Friday, March 13, 2015

Grizzly scanning JAX-RS Providers?

Spent half a day troubleshooting issue where Jersey serialization was not working; evidently my RuntimeTypeAdapterFactory that was supposed to be registered as a GSON adapter -- through the following registration path: RuntimeTypeAdapterFactory --> javax.ws.rs.ext.MessageBodyWriter<Object> --> org.glassfish.jersey.client.ClientConfig --> org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory -- wasn't evidently since breakpoints in the MessageBodyWriter weren't getting hit. I was working in Eclipse and had set the project as a higher order dependency via both the project "Order and Export" and the run configuration classpath. Still SOME MessageBodyWriter was registered since I saw its log4j debug output. The funny thing is that the breakpoint in my development MessageBodyWriter was getting hit in the constructor, but not the writeTo method. So that tells me both classes -- the old one and the new one (in a different package) were getting loaded into the classpath and mine was definitely getting created and registered per the above registration path. Could the issue be due to caching? No. Tried clean project, restart Eclipse, etc. Then I started fiddling with the registration path, inserting a test writer from another package. This time that test writer produced writeTo output. But switching back to my desired dev version did not "reset" any cache whether Grizzly or Jersey if there is such a thing. I did not see my dev version getting hit. Then I deleted the test version AND moved the dev version of the MessageBodyWriter to the same project as the Grizzly server and that did the trick. This was inherited code and I started looking at it for clues as to the explanation. Being new to Jersey and JAX-RS I hadn't noticed that one of the annotations on the MessageBodyWriter was @javax.ws.rs.ext.Provider. A quick google search for GSON Jersey integration took me to the following blog http://eclipsesource.com/blogs/2012/11/02/integrating-gson-into-a-jax-rs-based-application/ where it explains that the server scans for @Providers to use. Sure enough, removing the @Provider annotation on the test MessageBodyWriter caused it to not replace my target MessageBodyWriter. So evidently Grizzly tries to behave like a JEE container and scans like one or perhaps it's just following spec (but if it were, then it should have at least produced a warning I believe). Either way, moral of the story is, if you are registring a provider with Grizzly manually via some programmatic registration path such as the one above, DO NOT annotate the providers with @Provider or else you won't know which one is actually being used to do the serialization at runtime!