Niles11 Niles11 - 2 days ago 5
Java Question

Jackson JSON generates HTTP status 500, XML works

I am currently using Jackson to serialize Java objects to JSON and XML as the response for a REST webservice. I have the following annotated Java object:

@XmlRootElement(name = "Product")
@XmlAccessorType(XmlAccessType.FIELD)
public class ProductDetailsView {

@XmlElement
private int id;
@XmlElement
private long EAN;
@XmlElement
private String manufacturer;
@XmlElement
private String modelname;
@XmlElementWrapper(name = "onlineCompetitors")
@XmlElement(name = "competitor")
private List<OnlineCompetitorView> onlineCompetitors;


Now, the first few fields are primitive types and those work perfectly in both JSON and XML (in fact, there are a lot more primitive fields). However, from the moment I added the list of OnlineCompetitorView's the JSON serialization no longer works, and causes the application to generate a HTTP status of 500 ('Internal Server Error'). But, when I use application/xml as the accepted content type it works flawlessly.

The correct XML response:

<Product>
<id>1</id>
<EAN>5901234123457</EAN>
<manufacturer>Samsung</manufacturer>
<onlineCompetitors>
<competitor>
<id>1</id>
<shopname>Shop1</shopname>
<rating>4</rating>
<productPrice>488.95</productPrice>
<stock>7</stock>
</competitor>
<competitor>
<id>2</id>
<shopname>Shop2</shopname>
<rating>5</rating>
<productPrice>498.95</productPrice>
<stock>12</stock>
</competitor>
</onlineCompetitors>
</product>


So the XML works fine, but when I request application/json from the service it (GlassFish 4.0) creates an internal server error. This is how the OnlineCompetitorView is annotated:

@XmlAccessorType(XmlAccessType.FIELD)
public class OnlineCompetitorView {

@XmlElement
private final int id;
@XmlElement
private final String shopname;
@XmlElement
private final int rating;
@XmlElement
private final double productPrice;
@XmlElement
private final int stock;


I've tried adding the @XmlRootElement-annotation the OnlineCompetitorView as well, but this doesn't change anything. As I'm not getting any error from GlassFish I really don't know how to fix the problem. The simple webservice looks like this:

@GET
@Path("/get/product/{ean}")
@Produces({"application/xml", "application/json"})
public ProductDetailsView getProduct(@PathParam("ean") Long EAN) {
ProductDetailsView pdv = service.getProductDetailsView(EAN);
return pdv;
}


So how is it possible that XML works fine, while JSON creates an internal server error?
Could someone help me out with this problem? Any help is greatly appreciated!




EDIT!

As I still don't know why JSON isn't working, while XML does I went on developping my application. In doing so, I stumbled upon a new problem, probably relating to the first one so that's why I update my question.

I created a small and simple test which returns back a very simple annotated POJO and it doesn't work with either XML or JSON (while the much more complex 'Product'-POJO is working, albeit only with XML).

Now, the error log still shows no errors but glassfish returns me something:

FINE: Trying to locate com/eid/instoreapp/JSONView/jaxb.properties
FINE: not found
FINE: Checking system property javax.xml.bind.context.factory
FINE: not found
FINE: Checking system property javax.xml.bind.JAXBContext
FINE: not found
FINE: OSGi environment detected


I've been doing some research about this and apparently JAXB needs some sort of properties file. Now, i've build a lot more REST applications like this and I never had to add a properties file or whatsoever, and it always worked.

Some people on the internet suggest that it is a problem with classloader (like here) but, once again, I never had to set some classloader and because I use Java EE this marshalling and unmarshalling of XML/JSON objects should work automatically. Also, the solution proposed in the hyperlink (adding the class-loader XML attribute) doesn't work for me.

I don't understand why the system is so inconsistent. Some of the RESTful methods work in both XML and JSON. Some of them work only with XML and some of them don't work at all (within the same application!).

I really hope anyone can help me find a solution to this problem!

Answer

For those who have the same sort of problem as I had, and can't figure out why: I found the solution myself. I wasn't fully aware of the fact that the POJO-objects that are to be serialized to XML/JSON need to have a zero-arguments constructor. That includes collections used in the original object.

So in my case: my 'ProductDetailsView'-object has a list of 'OnlineCompetitorView'-objects. Both the ProductDetailsView and the OnlineCompetitorView need to have a zero-argument constructor. For some it might be obvious, but I thought it would be wise to share this information. I found this information, accidently, in the opening post in this link, so I want to give some credit to that.

Comments