Monday, March 30, 2009

Digging into Jersey JAX-RS: 2. custom message body writers

I decided to start with something simple, like a service that simply returns a java POJO object.

So with that in mind, I created an EntryPoint that mapped to the root path of /.

Simple Service

@Path("/")
public class EntryPoint {
     @GET
     @Produces(MediaType.APPLICATION_XML)
     public Data getData() {
          final Data data = new Data();
          data.add("key1", "value1");
          data.add("key2", "value2");
          return data;
     }
}

And I tried to access the web application with my Safari, deployed to tomcat automatically with eclipse.

A message body writer for Java type, class me.kentlai.jaxrs.services.Data, and MIME media type, application/xml, was not found.

Hmm.. I wonder what are all the message body writers registered in the system. Other than the com.sun.jersey.server.impl.template.ViewableMessageBodyWriter in jersey-server, the following were found in jersey-core.

com.sun.jersey.core.impl.provider.entity.StringProvider
com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
com.sun.jersey.core.impl.provider.entity.FileProvider
com.sun.jersey.core.impl.provider.entity.InputStreamProvider
com.sun.jersey.core.impl.provider.entity.DataSourceProvider
com.sun.jersey.core.impl.provider.entity.RenderedImageProvider
com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider
com.sun.jersey.core.impl.provider.entity.FormProvider
com.sun.jersey.core.impl.provider.entity.FormMultivaluedMapProvider
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$App
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$Text
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$App
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$Text
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$App
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$Text
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
com.sun.jersey.core.impl.provider.entity.ReaderProvider
com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider
com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter

Ok to be fair, there are various ways to serialize xml. And various xml libraries. There are a few in-built xml providers, but they take in JAXB elements of DOM elements (as far as I can see. I am not an xml guru).

It is a good chance to experiment with my own provider. An xstream writer provider.

Custom XStream Message Body Writer

This is not an entry about how to use xstream. There are much better articles out there for xstream, so I will skim over the details.

I annotated my POJO with xstream annotations, to make the xml output prettier.

The xstream writer provider was rather simple to write. All it had to do was match the xml media type, and write the object out with an xstream instance. I am not using any xstream annotation here yet. Note also that I annotated it with javax.ws.rs.ext.Provider and com.sun.jersey.spi.resource.Singleton. The first allows the class to be picked up when Jersey scans the package for providers, and the second requests jersey to create only a single instance of the writer for the entire web application. This is a better option as readers/writers should be stateless and can be reused.

@Provider
@Singleton
public class XStreamMessageBodyWriter implements MessageBodyWriter<Object> {
     public long getSize(final Object t, final Class<?> type, final Type genericType,
               final Annotation[] annotations, final MediaType mediaType) {
          return -1;
     }
     public boolean isWriteable(final Class<?> type, final Type genericType,
               final Annotation[] annotations, final MediaType mediaType) {
          return mediaType.isCompatible(MediaType.APPLICATION_XML_TYPE) ||
               mediaType.isCompatible(MediaType.TEXT_XML_TYPE);
     }
     public void writeTo(final Object t, final Class<?> type, final Type genericType,
               final Annotation[] annotations, final MediaType mediaType,
               final MultivaluedMap<String, Object> httpHeaders,
               final OutputStream entityStream) throws IOException, WebApplicationException {
          xstream.processAnnotations(type);
          xstream.toXML(t, entityStream);
     }
     private final XStream xstream = new XStream();
}

And accessing the redeployed page gives me the following:

<data>
     <entry key="service1">
          <value>path1</value>
     </entry>
     <entry key="service2">
          <value>path2</value>
     </entry>
</data>

Cool! Now how about json?

Custom JSON Message Body Writer

Now change the javax.ws.rs.Produces to produce MediaType.APPLICATION_JSON instead.

A message body writer for Java type, class me.kentlai.jaxrs.services.Data, and MIME media type, application/json, was not found

That was expected. Now, to handle Json specifically with a JSON message body writer using json-lib.

@Provider
@Singleton
public class JSONMessageBodyWriter implements MessageBodyWriter<Object> {
     public long getSize(final Object t, final Class<?> type, final Type genericType,
               final Annotation[] annotations, final MediaType mediaType) {
          return -1;
     }
     public boolean isWriteable(final Class<?> type, final Type genericType,
               final Annotation[] annotations, final MediaType mediaType) {
          return mediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE);
     }
     public void writeTo(final Object t, final Class<?> type, final Type genericType,
               final Annotation[] annotations, final MediaType mediaType,
               final MultivaluedMap<String, Object> httpHeaders,
               final OutputStream entityStream) throws IOException, WebApplicationException {
          entityStream.write(serializer.toJSON(t).toString().getBytes());
     }
     private final JSONSerializer serializer = new JSONSerializer();
}

Accessing the page gives me the following:

{"data":[{"key":"key1","value":"value1"},{"key":"key2","value":"value2"}]}

End of this post

This is a simple post, with nothing overly hard to try nor implement.

Next up I will probably try to trace the flow of request through the components up to the response.

Update: My bad, I did not notice that if I annotated my POJO with a JAXB @XmlRootEntity/Type, it will trigger the JAXB writer.

Friday, March 27, 2009

Digging into Jersey JAX-RS: 1. setting up

So I started with a maven web application in Eclipse to do my test drive of jersey.

I added the repositories, and the jersey-server dependency (https://jersey.dev.java.net/source/browse/*checkout*/jersey/tags/jersey-1.0.2/jersey/dependencies.html)

I started out with a filter, instead of the servlet. I always prefer filters. I also added the following initialization parameters:

com.sun.jersey.config.property.packages: me.kentlai.jaxrs
com.sun.jersey.config.feature.Redirect: true
com.sun.jersey.config.feature.ImplicitViewables: true

com.sun.jersey.config.property.packages

I'm probably dumb, because I had a hard time finding out documentations for what these fields actually do. I do know that com.sun.jersey.config.property.packages tells jersey the package to find the resource classes, but all examples I saw specified only a single package.

Does it work for multiple packages? It did say packages..

The documentation did mention that the search is for the declared package and all sub-packages, so that would be fine. But how about two different packages?

I check in the source file. Multiple packages is detected by having the com.sun.jersey.config.property.packages. So how can I go about inserting multiple values?

So apparently, the documentation can be found in com.sun.jersey.spi.container.servlet.ServletContainer. Use ; as seperators.

I noticed two other properties mentioned:

com.sun.jersey.config.property.resourceConfigClass
javax.ws.rs.Application

I will probably look at them in a later date.

In conclusion: The value for com.sun.jersey.config.property.packages can be a ; seperated string value, as a list of packages to scan in. The scan works for sub-packages too.

com.sun.jersey.config.feature.Redirect

What is this? After doing a grep through the source, I found the documentation in com.sun.jersey.api.core.ResourceConfig. So apparently, what it does is this (when set to true)

request uri -> /test/abc
path declared -> /test/abc/

And the client will be redirected to /test/abc/. Hmm, seems no particular strong reason for me to turn that on. I'll keep it to false (default value) then.

I saw two other properties of interest in com.sun.jersey.api.core.ResourceConfig

com.sun.jersey.config.feature.NormalizeURI & com.sun.jersey.config.feature.CanonicalizeURIPath

They have a default value of false, and they seem to be about normalizing uri. For example, com.sun.jersey.config.feature.NormalizeURI would turn the request uri of a/b/../c into a/c. I'm not sure if it affects the routing, but I would not mind it turned on. Maybe some people like to check for intrusion attacks?

I'm not too sure what the second one does, but from what I understand after digging into the code, it seems to turn the request uri of ///a/b/c into /a/b/c. Guess it can be turned on as well.

I definitely need enlightenment on why some people might want this to be false.

It is also interesting to note that for com.sun.jersey.config.feature.CanonicalizeURIPath to take place, com.sun.jersey.config.feature.NormalizeURI must be true too.

The code to handle the normalization is found in com.sun.jersey.server.impl.container.filter.NormalizeFilter.

A filter?

Filters

Jersey supports filters! They are implemented in the two interfaces com.sun.jersey.spi.container.ContainerRequestFilter, com.sun.jersey.spi.container.ContainerResponseFilter, such that if your custom filter can care only before processing, or after processing, or if inclined, both. There are quite a few custom filters defined.

So where/how are they registered?

They seemed to be located by com.sun.jersey.server.impl.container.filter.FilterFactory (and it turns out that there are other filters like resource filter too), which the com.sun.jersey.server.impl.application.WebApplicationImpl will query and execute in order of declaration. Additional filters can be defined in the following init-params, which are executed before the apparently in-built filters:

com.sun.jersey.spi.container.ContainerRequestFilters
com.sun.jersey.spi.container.ContainerResponseFilters
com.sun.jersey.spi.container.ResourceFilters

The documentation of these can once again be found in com.sun.jersey.api.core.ResourceConfig. But in short, they are either a single string value, or a list of string values, which are fully qualitifed class names. It is interesting to note that the documentation and code will create these as singletons. That is, if you have a single class specified in all three filters, they are created as a single instance.

But where are the in-built filters defined? I had to dig deep, and found a com.sun.jersey.spi.service.ServiceFinder class. It is a way to locate services 'exported' by jars, as long as they have a folder META-INF/services in the jar, with the class files. So, opening the jersey-server jar, I found a single file with this value:

file: com.sun.jersey.spi.container.ContainerRequestFilters
values: com.sun.jersey.server.impl.container.filter.NormalizeFilter

There are more files in there, but for my current purpose, knowing this is sufficient.

There are more filters available too, like com.sun.jersey.api.container.filter.GZIPContentEncodingFilter, com.sun.jersey.api.container.filter.LoggingFilter, etc.

com.sun.jersey.config.feature.ImplicitViewables

This has to be on for jersey to resolve your jsp view implicitly. I'm curious on a few things.

1. The example had the jsp files in the root of the webapp. Convention had them inside WEB-INF. There should be a way to change that.

2. Is jsp the only option? Does it actually expose the ability to do other views like freemarker/velocity? There is mention of a com.sun.jersey.spi.template.TemplateProcessor, but how is it hooked up?

The magic seems to be in two places: com.sun.jersey.server.impl.model.ResourceClass and com.sun.jersey.server.impl.template.ViewableMessageBodyWriter.

The com.sun.jersey.server.impl.template.ViewableRule seems to be responsible for matching additional subpaths to the original resource. There is an additional match of empty/null subpath, and a match of an additional segment.

Eg, resource A with path /a/b. A request comes in as /a/b. The implicit view will be triggered. A request /a/b/c will be processed. But a request /a/b/c/d will not be processed by the resource A.

It iterates through the template processors from com.sun.jersey.spi.template.TemplateContext (it is injected, but what are the values?). And it only accepts HTTP GET method. What is the implications? I guess it would mean that if a request came in without a properly matched resource/path, it should not be redispatched to an implicit view. I am not too sure what it might really mean until I made experiments with HTTP POST.

A subclass com.sun.jersey.server.impl.template.TemplateFactory is created in com.sun.jersey.server.impl.application.WebApplicationImpl. This will then be injected into the com.sun.jersey.server.impl.template.ViewableRule. So there are two ways to have the com.sun.jersey.spi.template.TemplateProcessor hooked up. Services (as mentioned above), and providers. Providers seems to be classes marked with the annotation javax.ws.rs.ext.Provider.

Except that com.sun.jersey.server.impl.container.servlet.JSPTemplateProcessor is not marked with it! Mysterious..

But it turns out I missed out another way template processors can be injected. Via singleton instances registered with com.sun.jersey.api.core.ResourceConfig. And the creation and registration is done in com.sun.jersey.spi.container.servlet.WebComponent, which is the parent class of the jersey filter/servlet we usually registers.

Now on to com.sun.jersey.server.impl.container.servlet.JSPTemplateProcessor. It actually mentions, in the class, a configuration property used to lookup JSP files! com.sun.jersey.config.property.JSPTemplatesBasePath. Woo hoo!

Now back to com.sun.jersey.server.impl.template.ViewableMessageBodyWriter. Now that I am used to how things work, I check to see if there is a file javax.ws.rs.ext.MessageBodyWriter in the META-INF/services of the jar. Sure enough, there is one, with the entry com.sun.jersey.server.impl.template.ViewableMessageBodyWriter. And this is how it is injected into the application.

Looking at the writeTo code of com.sun.jersey.server.impl.template.ViewableMessageBodyWriter. It iterates through the template processors from com.sun.jersey.spi.template.TemplateContext again. It asks each template processor to resolve a path (which is the fully qualified class name, with . replaced with /, and append with 'index' if the path had been empty.

But wait.

The iteration does not stop with the first resolved template! All resolved template are written to! What could this mean? Potentially we could register two com.sun.jersey.spi.template.TemplateProcessor, and if both matches, could write its output out to the output stream? It does seem to indicate that..

To clarify more on that, we have to find out more about this com.sun.jersey.server.impl.template.ResolvedViewable mentioned in the class. It is the only exception to iterating over the available template processors. Who would set this?

Turns out we have to go back to look at com.sun.jersey.server.impl.template.ViewableRule. In its accept request check, it actually stops at the first resolved template processor, and set the response.

Things might be getting more confusing than required.

I will just dig into com.sun.jersey.server.impl.container.servlet.JSPTemplateProcessor first.

When asked to resolve a template, it actually attempts to locate the resource via the servlet context. If there is a perfect match, the template string is returned immediately. Otherwise it appends '.jsp' and try again. If there is still no match, a null string is returned. Pretty straightforward.

And writeTo basically commits the status/headers out to the response first, and then does a forward with the dispatcher to the new jsp.

While I'm here, I might as well find out what variables are exposed to the dispatched jsp. These are what I found and suspect what they mean (I gotta test it to find out)

1. _basePath: Original path to the resource

2. resource: Resource that handled the request

3. it: The resulting data

4. _request: Original request instance

5. _response: Original response instance

End of this post

This has been a long post (for my standard). I had approached this as a development and exploration diary, to pen down my discovery. All I had done so far has only been to figure out initialization parameters, and how the implicit view might flow.

I should stress that this is not meant to be an introduction on how to use Jersey. This is a post on understanding how Jersey works (even internally), in the hope to be able to use it more effectively. This is an exploration process, and as such, some of what was mentioned might be even wrong, different, or changed in future versions. And some of the exploration might be incomplete, but they are sufficient for the understanding I desired.

Coming up in the next post, I will follow up with a simple, barebone jersey web application with implicit views.

Wednesday, March 25, 2009

Jersey JAX-RS RI: An amazement

I took a longer harder look at Jersey, a JAX-RS Reference Implementation, and I was totally blown away.

Past

A background on the path to amazement.

I had heard about JAX-RS a while back. I think it was when I was playing around with Restlets. But I dismissed it off as I thought it was for web services.

I went around, playing with Wicket and Spring as well. I'll just round up my feelings. They might be outdated conclusions though.

Restlet: When I played with it, it was very much in the pre-annotations craze days. I had to add my restlets to an application router manually, and I had to extend Resource and Finder classes. I did not find out how to integrate with jsp at that time, so I was not sure if it supported it then (I did see freemarker/velocity support). But somehow, I did notice myself repeating a lot of code for different resources.

Wicket: It was a pleasant experience. Testing was easy too, and I felt very confident when developing the web application. There was no doubt, as my html and code are tested together. It was quite heavily session-based though, and turning off session/reducing the usage was harder than it was. Just when you felt used to a desktop-oriented way to developing with Wicket, you had to unlearn that and code session-less page.

Spring MVC: I tried it out with annotations, and it was truly wonderful. The resulting controller did not feel like a web-based java artifact, other than a minor hint of request/response/session here and there. Testing was easy too. But somehow, I am quite unsure of how generation of content other than html can be achieved for selected paths/resources. It felt like a tool for power user, actually.

Now

So fast forward to now. I actually took a look at Jersey again. This time I actually took a longer, harder look.

The code were really clean and simple. It was annotation-driven, with @Get and @Post and @Consume and @Produce. I just came from the Spring playground, and this felt really attractive. It was how Restlet should had been (and which they are now, as far as I know. I heard they currently had JAX-RS implementation within Restlet).

I knew I had to give it a go.

So I pondered about an implementation. I wonder if I had to go with html pages accessing JAX-RS with javascript. I wondered if I could get them to spit out html. I could, but if I had to make it annotation-driven, it would take quite a bit of effort. Then I wonder about which javascript framework would be suitable.

And as I was just going through the links on the jersey site, I saw this post: http://macstrac.blogspot.com/2009/01/jax-rs-as-one-web-framework-to-rule.html

Hmm.. so apparently, Jersey has this feature known as Implicit/Explicit views. That was really fascinating! And then I followed the link: http://blogs.sun.com/sandoz/entry/mvcj

Really very neat, it integrates with JSP! Not that I am a JSP fanboy though. I will get to that point later.

But anyway, all this is good, but I did noticed the issue James Strachan brought up, regarding Safari preferring Xml to Html. I also noticed that the Jersey implementation was registered as a Servlet with /* . That would not play well with static content. I thought to myself, that I probably could hack around a filter version later.

Today

And now, I saw on Paul Sandoz's blog about Jersey 1.0.2. Ok ok I know it was released in February. But I only got to know about it now. It added filter support, as well as ImplicitProduce!

I got excited. I decided to take a closer look at the implicit view now.

The documentation was sparse. There was nothing much on it. I had to download the samples to look at it. I checked out the bookstore sample.

The code was confusing. There was nothing much mentioned. I decided to run it.

And then it all made sense. And I was blew away.

The code was clean. Even annotations were kept to a minimal. It introduced some interesting way of resolving paths beyond the standard Path annotation.

I am really very impressed. I am going to give it a test drive now.

Summary

But to sum it up first, JAX-RS might have just become my preferred choice of web development framework (if it does not disappoint me in my test drive).

It is a very simple model. A very simple concept. Which means a very low entry barrier. I probably can introduce someone to JAX-RS development faster than Spring MVC. It would be even faster if there was a flow diagram of what components a request would go through, and what actors are involved.

And I will stick to JSP for a start, as it is also a low entry barrier choice. One might argue that velocity & freemarker are easy to pick up too, but given a handful of java web developers, there is a higher chance that you get someone who knows JSP than the other two.

I'll see if I can have a followup entry on my test-drive experience in the coming weeks.

Thursday, March 19, 2009

IBM to buy Sun, but what about Java?

Disclaimer: These are my personal opinion and is not representative of where I work

The rumors and news are spreading like fire, and there are lots of arguments on both sides. They talk about cloud strategies, hardware, existing customers, etc.

But what about Java?

First, I have to say my post here might be biased. I'm not exactly in favor of this buy over. I work in a small company which is a Sun partner, which means I do have quite a bit to lose in this buy over.

Anyway, about Java.

There are many companies with a lot of stakes in Java. There is IBM (the buyer), HP, Oracle, for the players that I can think of offhand. I'm sure I missed out many others, but I have limited exposure.

Java is open. It is run by JCR. Many would have argued. But Java is still very much associated with Sun, who is seen as a steward of Java. A protector. The hero against Microsoft and .NET (though, I do find .NET and C# to be quite appealing and nicely designed).

Sun own the trademark to Java afaik. One has to wonder what happen when IBM buys Sun.

Sun is a strong innovator. Sadly, they did not manage to capitalize on them too well. For example, for tools, IBM manage to overpower them with Eclipse back then. BEA WebLogic for Application Server.

Which is not exactly a bad thing I guess. Java is truly open. It is fair game.

Now, what happens if IBM buys over Sun. Will IBM take advantage of this and start steering Java to a direction which is advantagous to themselves? Gain an edge in the speed they push out Java Standards than the others? Will the others be playing catch up with IBM in terms of Java Standards?

These are just speculations of course.

On the other hand, what about the various Sun projects? Regardless if they are open-source or otherwise, they are still very much managed by existing Sun engineers. Glassfish, OpenESB, OpenSSO, MySQL, even OpenDS. I'm not all together familiar with IBM's portfolio, but I would think they have their own offerings of Application Server, SOA architecture, Directory Server, Single Sign On, Identity Management, a

Thursday, March 5, 2009

Spring TestContext Framework

It has been an exciting, and at the same time, frustrating time for the past few days.
For better or for worse, I decided to take a dive into Spring MVC and Spring Webflow, trying and playing around with it.

I walked away knowing more about Spring TestContext Framework instead.

Before I begin, I have to conclude that Spring MVC is really very neat. Webflows was interesting, and came with its own testing framework, which kinda irritates me... (they should all stick to Spring TestContext Framework instead). However, the inability to test the resulting view properly (without firing up Selenium) was a sore point for me..

So anyway, back to Spring TestContext Framework. It really is extensible.
Almost.

I could create custom TestExecutionListener, hook it up with the test class, and have it run before/after every test method!

So my first experiment was to do a MockTestExecutionListener. What it basically do is to create mocks of fields marked with @Mock (much like MockitoAnnotations). Pretty simple and easy. Then I hook it up to my test class.

The fastest way was to use @TestExcutionListeners, but I would have to declare DependencyInjectionTestExecutionListener as well, so that it would still remember to perform Spring Injection. Whatever classes declared in @TestExecutionListeners would override the default TestExecutionListener that Spring offers in SpringJunit4ClassRunner.

So instead, I extended SpringJUnit4ClassRunner, and added my TestExecutionListener in TestContextManager#getDefaultTestExecutionListenerClasses.

And then I got abit more adventurous.

I tried to reuse my mocks, and at the same time, verify that there were no more interactions in the afterTestMethod. So I kept track of my mocks in the given TestContext, and verify them.

The painful part was reusing the mocks. There is just no clean way to remove all interactions from mocks created from Mockito cleanly. Short of duplicating code from Mockito internals, cleaning delegates, blah blah blah. I'm trying to forget the ugly part of it.

So now, we have auto-mocking for our Spring Test!

And the next step. Wouldn't it be nice if some of my mocks are autowired to my Spring objects?

There is just no way it could be done nicely, especially if mocks are recreated for every test method execution.

A custom context loader can be provided, which can customize the loading of an application context.

Singletons are created and cached. And the application context are cached as well. So if two classes are using the same set of test configurations, the application context are cached across two class executions.

So it probably is out of the question.

And then I started playing with DbUnit. It is an excellent candidate for TestExecutionListener. It can auto locate a dataset xml file, initialize it for each test method invocation, and verify that the current state of the database match an expected dataset.

Only grip I had was in order to provide a DataSource to my TestExecutionListener, I had to locate it via the current test's application context.

Spring TestContext Framework is a very interesting framework, but it would be better if many methods are not made final, and better ability to declare custom classes instead of the in-built TestContext, TestContextManager, etc.