1

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!

Community
  • 1
  • 1
Niles11
  • 553
  • 1
  • 6
  • 17
  • Have you checked the server log to see what the error might be? – bdoughan Oct 23 '13 at 10:47
  • Yes I have. Unfortunatly, Glassfish enters no log of anything happening at the moment I call the REST-service. That's what makes the problem so difficult to solve. – Niles11 Oct 25 '13 at 22:01
  • which `JAX-RS` implementation are you using, I would say that `JAXB` is the wrong tool here, I usually use a Jackson plugin for the implementation and only use Jackson `JSON` annotations, the xml annotations have conflicts, that way what I am using that doesn't rely on `JAXB` and have no problems. –  Oct 29 '13 at 19:23
  • As far as I know, Jersey is the default implementation of JAX-RS when you use Java EE. I've never added another implementation, and the imports are all from javax.ws.rs. A method that is annotated with GET and Path-annotation should automatically marshall the returned POJO to XML or JSON right? (depending on the content-type) It always used to work like that for me anyway... – Niles11 Oct 29 '13 at 19:50

2 Answers2

2

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.

Community
  • 1
  • 1
Niles11
  • 553
  • 1
  • 6
  • 17
  • I faced the same 500 error with my resource method returning a POJO which is to be streamed as an XML. Spend around 30 minutes trying to figure out what caused the issue since the JAXB pojo was pretty straight forward. Your comment saved the day. I had apparently added a parameterised constructor for other classes to initialize the pojo in one step. Thanks a lot. And have an upvote. – NishM Aug 31 '15 at 06:21
1

I had the exact same problem but I did have no-arg constructors in the bean. For me, the solution was to remove a generic in the declaration of the bean. So, instead of returning Bean I had to return just Bean from the service. Then, magically, it all worked!