So, does it work as advertised? Well I started with the README file on Github and a working Apache Felix configuration. I tend to gravitate toward Felix just because the footprint tends to be smaller, I get most of the same features, the web console is nice and, well am just used to it. Here's the bundle list I started with.
org.apache.felix.bundlerepository-1.4.2.jar org.apache.felix.configadmin-1.2.4.jar org.apache.felix.dependencymanager-2.0.1.jar org.apache.felix.dependencymanager.shell-2.0.1.jar org.apache.felix.eventadmin-1.0.0.jar org.apache.felix.fileinstall-2.0.8.jar org.apache.felix.http.api-2.0.4.jar org.apache.felix.http.bundle-2.0.4.jar org.apache.felix.http.jetty-2.0.4.jar org.apache.felix.http.proxy-2.0.4.jar org.apache.felix.http.whiteboard-2.0.4.jar org.apache.felix.log-1.0.0.jar org.apache.felix.metatype-1.0.4.jar org.apache.felix.prefs-1.0.4.jar org.apache.felix.scr-1.4.0.jar org.apache.felix.shell-1.4.1.jar org.apache.felix.shell.tui-1.4.1.jar org.apache.felix.webconsole-2.0.4.jar
Then I added the bundles listed on Github, the Jersey core and server bundles and the extender bundle itself. I added my simple service and got it to work just as Neil outlined (you have to remember to add the JAX-RS-Alias and JAX-RS-Classes properties to the bundle manifest file).
jersey-core-1.4.jar jersey-server-1.4.jar name.njbartlett.osgi.jaxrsextender-0.0.0.jar
This works for services that return "text/plain" but the services I deal in nearly all consume and produce JSON and if I change the "@Produces" attribute to "application/json" you'll get a runtime exception when Jersey processes the request. So now you need to add a few more bundles, luckily they're all from the jersey site so you don't have to dig around for them, and you'll be set. There are a few here, basically there's a dependency chain such that we really want jersey-json, but that depends on jackson which in turn depends on jettison.
jersey-json-1.4.jar jackson-core-asl-1.5.5.jar jackson-jaxrs-1.5.5.jar jackson-mapper-asl-1.5.5.jar jackson-xc-1.5.5.jar jettison-1.1.jar
The final result is a nice clean service shown below, we define a specific class that is our domain object, return it from our API and define the content type and let Jersey do the rest.
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("/sysprop")
public class SampleService {
@GET
@Produces("application/json")
public PlatformProperties getSystemProperties() {
...
}
}
One final thing that tripped me up was that by default the JSON mappers included above don't process "unadorned" classes, they need a hint to know where to start the serialization so you need to add the "@XmlRootElement" attribute to the domain object.
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class PlatformProperties {
...
With this type of scheme, is there a way to wrap the call with something like a counter service that would be provided via OSGi? Or would I need to invoke the counter service inside the getSystemProperties() method?
ReplyDeleteSweet: "I am a huge OSGi fan" :-)
ReplyDelete