Search code examples
javajax-rsjava-ee-7wildfly-10payara

WildFly vs. Payara JSON response - what is standard behavior?


In a small demo JAX-RS application, I had the following POJO:

public class Book {
    private String title;
    private String author;
    private int year;

    // only this constructor, no default
    public Book(String title, String author, int year) {
        this.title = title;
        this.author = author;
        this.year = year;
    }

    // getters for members, no setters
    ...
}

I used this as a response within a REST operation:

@GET
@Path("books")
@Produces(MediaType.APPLICATION_JSON)
public List<Book> getBooks() {
    List<Book> books = new ArrayList<>();
    // add some books via Book constructor
    ...
    return books;
}

The application ran perfectly on WildFly 10, producing a JSON output of the book objects.

The very same war deployed on a recent Payara, got me an exception in server log:

MessageBodyWriter not found for media type=application/json

After adding a default constructor and @XmlAccessorType(XmlAccessType.FIELD) (or setters, which I ommited for fuctional design reasons), it worked.

All this lead me to 2 questions:

  • Why is the behavior different and which container does something non-standard or additionally?
  • Is there a recommended way for either using data objects such as my Book class as responses and let it convert to JSON automatically (with of course an additionally http response code) or like shown in many examples instead building the JSON response object manually?

Solution

  • Unfortunately, the mapping of Java objects to/from JSON is not defined yet in Java EE, therefore both WildFly and Payara Server behavior is by definition not standard. It is planned to be defined by the JSON-Binding JSR, which will be included in Java EE 8. Most of the implementations right now use JAX-B for mapping, but that was designed for mapping between Java and XML and doesn't work without issues for JSON.

    By default, Payara Server uses Moxy to map to/from JSON. You can force using Jackson for example, if you add Jackson to your app and add JacksonFeature into JAX-RS classes: Force Glassfish4 to use Jackson instead of Moxy

    If you want your application behave in standard way all the time, you would need to configure JAX-RS to use your own MessageBodyWriter/Reader.