1

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?
Alexander Rühl
  • 6,769
  • 9
  • 53
  • 96

1 Answers1

4

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.

Community
  • 1
  • 1
OndroMih
  • 7,280
  • 1
  • 26
  • 44
  • Thanks for the insights. Can you also tell me or direct me to suggestions on whether to use Java objects in a reponse and let the binding lib do the conversion or build JsonObjects manually? – Alexander Rühl Jan 18 '17 at 15:36
  • If you want to be Java EE compliant, the most straightforward way is to use JSON-processing (JsonObjects) to convert to JSON manually. You could, however, create a generic converter with this technique, and use it as a custom JAX-RS `MessageBodyWriter`. Here is an example of a [MessagebodyWriter converting to XML using JAXB](https://jersey.java.net/documentation/latest/message-body-workers.html#d0e6952) to get started. – OndroMih Jan 18 '17 at 18:40
  • Ok, then I think, I'd use JAX-B mapping where appropriate and hope for Java EE 8. – Alexander Rühl Jan 18 '17 at 19:43