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:
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
.