2
votes

I'm calling this method and getting a 500 back from it.

In the debugger I'm able to step though it all the way to the return statement at the end. No problem, r is populated as expected after Response.build() is called, the status says 200 OK. But that's not what ends up getting produced. I've even told eclipse to break on any Exception.

@GET
@Path("/getAllAppMessagesAsXML")
@Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML})
public Response getAllAppMessagesXML(@QueryParam("applicationId")  String applicationId){
    ResponseList list = new ResponseList();
    ArrayList<XmlMessageBean> xmlmessages = new ArrayList<>();

    try {
        List<AppMessage> messages =  //Gets from a database
        for(AppMessage m : messages){
            XmlMessageBean xm = new XmlMessageBean();
            xm.setId(m.getId());
            xm.setApplicationId(m.getApplicationId());
            xm.setMessageBody(m.getMessageBody());
            xm.setMessageLevel(m.getMessageLevel());
            xm.setMessageTitle(m.getMessageTitle());
            xmlmessages.add(xm);
        }
    } catch (Exception e) {
        logger.error("ERROR Failed to save Message AppMessageService.saveAppMessage()", e);
        Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
    }   
    list.setList(xmlmessages);
    Response r = null;
    try{
        r = Response.status(Response.Status.OK).entity(list).build();
    }catch(Exception e){
        e.printStackTrace();
    }

    return r;
}

XmlMessageBean.java

@XmlRootElement(name="AppMessage")
@XmlAccessorType(XmlAccessType.FIELD)
public class XmlMessageBean {

    @XmlElement
    private Long id;
    @XmlElement
    private String applicationId;
    @XmlElement
    private String messageTitle;
    @XmlElement
    private String messageBody;
    @XmlElement
    private String messageLevel;

    public XmlMessageBean(){
    }

//getters and setters

}

ResponseList.java

@XmlRootElement(name = "ResponseList")
public class ResponseList {

    public ResponseList(){
    }

    @XmlElement(name="list")
    private List<XmlMessageBean> list;

    public List<XmlMessageBean> getList() {
        return list;
    }

    public void setList(List<XmlMessageBean> list) {
        this.list = list;
    }

}

I've got this all running in a jersey.servlet.ServletContainer I'm stumped. I can't figure out how to get it to produce any kind of error message other than a generic 500. I've tried setting up an exception mapper as some other posts have mentioned but this also isn't picking anything up.

1
Have you enabled logging for Jersey and your servlet container?T.D. Smith
I have. The logs are also silent.Mark D
Have you done a simple hello world round trip to verify network, firewall, etc?T.D. Smith
I'm doing some diving seeing IllegalAnnotationException: Class has two properties of the same name "list" Maybe I don't have my exception mapper configured right. I'd think I wouldn't have to work so hard for get that.Mark D

1 Answers

0
votes

IllegalAnnotationException: Class has two properties of the same name "list"

Look at your two model classes XmlMessageBean and ResponseList. Do you see any difference? The main difference (and the cause for the error), is the @XmlAccessorType(XmlAccessType.FIELD) annotation (or lack there of). JAXB by default will look for the public properties (JavaBean getters/setters). So that's one property. But then you define another property by using the @XmlElement annotation on the field. The reason it works for XmlMessageBean is that it overrides the default public property lookup by changing it to XmlAccessType.FIELD

So you can simply annotate the ResponseList with @XmlAccessorType(XmlAccessType.FIELD) and it should work. You could also simply get rid of all the @XmlElement annotations, and get rid of @XmlAccessorType(XmlAccessType.FIELD), and it will still work, as it will look up the JavaBean properties. Generally, for me I only use the @XmlElement annotations when I need to change the name of the property, and just put it on the getter, for example.

private String messageBody;

@XmlElement(name = "body")
public String getMessageBody(){
    return messageBody;l
}

Other than that, I normally leave out the annotation, and also the @XmlAccessorType annotation, and just let it resolve to the default behavior.