By Duncan Mills on Feb 20, 2014
From time to time we all make silly mistakes which lead to much head scratching and time being wasted. This is a short missive about just such a mistake that I made yesterday which then had me totally stumped (for a a few minutes at least!) this morning.
So, here's the story. I was taking a long flight back to the UK from California yesterday and had wanted to keep working on a client UI for a RESTful service provided by our build infrastructure. As you can imagine, it's not going to work very well to access those services in flight, so I spent the wait time in the lounge building out a quick mock implementation of the data structure using the same POJOs so I could switch to that and continue with the UI development offline. As part of this I thoughtlessly added a new constructor into my main POJO that the REST service JSON structure mapped in to. All was well.
This morning I'm back online, so I switch the implementation of my UI data provider back to the real service to see what the UI now looks like with more data - it fails? Huh? OK back to the test client - it also fails:
Exception in thread "main" org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=class com.groundside.model.Orchestration, genericType=class com.groundside.model.Orchestration. at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:207) at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:139) at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1109) at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:853) at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:785) at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:267) at org.glassfish.jersey.client.InboundJaxrsResponse$1.call(InboundJaxrsResponse.java:111) at org.glassfish.jersey.internal.Errors.process(Errors.java:315) at org.glassfish.jersey.internal.Errors.process(Errors.java:297) at org.glassfish.jersey.internal.Errors.process(Errors.java:228) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:397) at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:108)
So now I spin round and make all the checks I can think of. The libraries are all unchanged, perhaps the shape of the service has been changed overnight? - nope, every thing is the same. The mime type coming from the service is still application/json as well.
So I'm pretty confused. Back to first principles though. Has really nothing changed? Well in fact yes there was a change - just one little, tiny thing, that new constructor. Of course that was it. One of the requirements for the JAX-RS unmarshalling is that the entity class should have an empty constructor. Before it was implicit, but now I'd added that new constructor for the mocking which included arguments and that replaced the implicit empty constructor and broke the above requirement to boot. So it was simple to fix in the end just annoying. Hey ho...