I am very new to building rest API application. Here I was trying to make a simple method return a response xml of a model object Message
Here is my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.rest.messenger.service</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/webapi/*</url-pattern>
</servlet-mapping>
</web-app>
I have a service class that returns a hard-coded list of Message
objects.
package com.rest.messenger.service;
import java.util.ArrayList;
import java.util.List;
import com.rest.messenger.model.Message;
public class MessageService {
public List<Message> getAllMessages(){
Message m1 = new Message(1L, "message1", "mt");
Message m2 = new Message( 2L, "message 2", "pt");
List<Message> messages = new ArrayList<Message>();
messages.add(m1);
messages.add(m2);
return messages;
}
}
The Message
object is defined as follows ( here I used @XmlRootElement
annotation to let jaxb convert this into xml, as I wanted an xml response to be returned by resource):
package com.rest.messenger.model;
import java.util.Date;
import jakarta.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Message {
private long id;
private String message;
private String author;
private Date created;
public Message() {
}
public Message(long id, String message, String author) {
super();
this.id = id;
this.message = message;
this.author = author;
this.created = new Date();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
}
I mapped the incoming GET
request to a resource as follows:
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/messages")
public class MessageResource {
public MessageService messageService = new MessageService();
@GET
@Produces(MediaType.APPLICATION_XML)
public List<Message> getMessages() {
return messageService.getAllMessages();
}
}
Now when I run this and try to access the resource at URL http://localhost:8080/messenger.service/webapi/messages
I get the following internal server error:
May 06, 2020 1:28:14 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Jersey Web Application] in context with path [/messenger.service] threw exception [java.lang.NullPointerException] with root cause
java.lang.NullPointerException
at jakarta.xml.bind.ContextFinder.handleClassCastException(ContextFinder.java:114)
at jakarta.xml.bind.ContextFinder.newInstance(ContextFinder.java:254)
at jakarta.xml.bind.ContextFinder.newInstance(ContextFinder.java:240)
at jakarta.xml.bind.ContextFinder.find(ContextFinder.java:375)
at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:691)
at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:632)
at org.glassfish.jersey.jaxb.internal.AbstractJaxbProvider.getStoredJaxbContext(AbstractJaxbProvider.java:288)
at org.glassfish.jersey.jaxb.internal.AbstractJaxbProvider.getJAXBContext(AbstractJaxbProvider.java:273)
at org.glassfish.jersey.jaxb.internal.AbstractJaxbProvider.getMarshaller(AbstractJaxbProvider.java:240)
at org.glassfish.jersey.jaxb.internal.AbstractJaxbProvider.getMarshaller(AbstractJaxbProvider.java:207)
at org.glassfish.jersey.jaxb.internal.AbstractCollectionJaxbProvider.writeTo(AbstractCollectionJaxbProvider.java:243)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:242)
The tutorial that I followed used javax and I believe it is now migrated to jakarta.
Not sure if it has to do with @XmlRootElement
I also added dependencies in pom.xml
as suggested on:
jersey return 500 when trying return an XML
I used the modifiers for fields of model object to be private, as was suggested.( the default XML accessor type used jaxb is able to work on private fields)
Can anyone please suggest on this?