Reputation: 3
Creating an restful application but it is not returning the response in XML. Even there is no log on the console when hitting the URL "http://localhost:8080/message/webapi/messages".
I am returning a list and using @Produces(MediaType.APPLICATION_XML) to return the response in XML.
MessageResource.java
package org.porwal.restful.message.resources;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.porwal.restful.message.model.Message;
import org.porwal.restful.message.service.MessageService;
@Path("/messages")
public class MessageResource {
MessageService ms = new MessageService();
@GET
@Produces(MediaType.APPLICATION_XML)
public List<Message> getMessage(){
return ms.getAllMessage();
}
}
Message.java
package org.porwal.restful.message.model;
import java.util.Date;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement( name = "Message" )
public class Message {
public long id;
public String message;
public Date created;
public String author;
public Message() {
}
public Message(long id, String message, String author) {
this.id = id;
this.message = message;
this.author = author;
this.created = new Date();
}
public long getId() {
return id;
}
@XmlElement (name = "ID")
public void setId(long id) {
this.id = id;
}
public String getMessage() {
return message;
}
@XmlElement (name = "Message")
public void setMessage(String message) {
this.message = message;
}
public Date getCreated() {
return created;
}
@XmlElement (name = "Created")
public void setCreated(Date created) {
this.created = created;
}
public String getAuthor() {
return author;
}
@XmlElement (name = "Author")
public void setAuthor(String author) {
this.author = author;
}
}
This is working if i do not use @XMLRootElement annotation and TEXT_PLAIN is returned well through the URL. I also tried to remove @XmlElement for each fields but no luck. When i remove @XMLRootElement then MessageBodyWriter error can be seen in logs on eclipse console but when includes @XMLRootElement then no logs on eclipse console and URL "http://localhost:8080/message/webapi/messages" throws the error:
Error in case of @XmlRootElement is missing.
org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor aroundWriteTo SEVERE: MessageBodyWriter not found for media type=application/xml, type=class java.util.ArrayList, genericType=java.util.List<org.porwal.restful.message.model.Message>. This exception comes only when i commented the line "//@XmlRootElement( name = "Message" )".
HTTP Status 500 – Internal Server Error
Can someone please tell what i am missing here?
Upvotes: 0
Views: 1275
Reputation: 209092
You need to make all your fields in the Message
class private. If you leave them as public, then JAXB will treat it as a property, and will consider it duplicate properties as you also haves JavaBean properties (getters/setters).
@XmlRootElement( name = "Message" )
public class Message {
private long id;
private String message;
private Date created;
private String author;
// ...
}
How I figured this out was by using a generic ExceptionMapper
@Provider
public class DebugExceptionMapper implements ExceptionMapper<Exception> {
@Override
public Response toResponse(Exception exception) {
exception.printStackTrace();
return Response.serverError().entity(exception.getMessage()).build();
}
}
You can register this with your application and it will catch unmapped exceptions and you can do whatever you want with it. Here we just print the stack trace. If we don't handle it, it will just get swallowed up and we will never know what happened.
When running the app with the ExceptionMapper, here's the error message I got.
Caused by: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 4 counts of IllegalAnnotationExceptions
Class has two properties of the same name "author"
this problem is related to the following location:
at public java.lang.String com.example.Message.getAuthor()
at com.example.Message
this problem is related to the following location:
at public java.lang.String com.example.Message.author
at com.example.Message
Class has two properties of the same name "created"
this problem is related to the following location:
at public java.util.Date com.example.Message.getCreated()
at com.example.Message
this problem is related to the following location:
at public java.util.Date com.example.Message.created
at com.example.Message
Class has two properties of the same name "id"
this problem is related to the following location:
at public long com.example.Message.getId()
at com.example.Message
this problem is related to the following location:
at public long com.example.Message.id
at com.example.Message
Class has two properties of the same name "message"
this problem is related to the following location:
at public java.lang.String com.example.Message.getMessage()
at com.example.Message
this problem is related to the following location:
at public java.lang.String com.example.Message.message
at com.example.Message
You can clearly see what the problem is. And aside from avoiding this error, this is how encapsulation is supposed to work anyway; the fields should be private and exposed via getters and setters.
Upvotes: 1