3
votes

I'm trying to create my own RESTful WS application using Jersey 2.12 based from this article. I want to return an XML representation of a class depending on the id been passed from the url, however, I'm getting a 500 response code when trying from either Advanced Rest Client Application (google chrome app) or browser. Below are the details:

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-
    app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>WS_RESTful_Practice</display-name>
  <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <!-- Register resources and providers under com.vogella.jersey.first package. -->
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>test.services</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
 </servlet-mapping>
</web-app> 


TestRestModel.java

package test.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class TestRestModel{

    /**
     * 
     */
    private static final long serialVersionUID = -8391589100962515747L;
    private String name;
    private String content;

    public TestRestModel(String name, String content){
        this.name = name;
        this.content = content;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}


TestResource.java

package test.services;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import test.dao.TestModelDao;
import test.model.TestRestModel;

@Path("/test")
public class TestResource {

    @GET
    @Path("{id}")
    public Response getModel(@PathParam("id") String id){
        return Response.ok().entity(TestModelDao.instance.getModel().get(id)).build();
    }
}


TestModelDao.java

package test.dao;

import java.util.HashMap;
import java.util.Map;
import test.model.TestRestModel;

public enum TestModelDao {
    instance;

    private Map<String, TestRestModel> container = new HashMap<String, TestRestModel>();

    private TestModelDao(){

        TestRestModel model = new TestRestModel("a", "this is first");
        container.put("1", model);
        model = new TestRestModel("b", "this is second");
        container.put("2", model);
        model = new TestRestModel("c", "this is third");
        container.put("3", model);
    }

    public Map<String, TestRestModel> getModel(){
        return container;
    }
}

I'm totally new to Jersey and REST. And I don't know how to log error from Jersey yet.

4
Pls provide the stack trace of your 500 ...zyexal
@zyexal thanks for the feedback. i don't know where to get the stacktrace and the web server doesn't print it neither.anonymouse
If you start your server from your IDE (for example Eclipse) in debug mode, you should see something in you console view. Also you should be able to go through the code step by step then. So, try to enable debugging and report back afterwards ...zyexal
@zyexal thanks. but that's the problem, the stacktrace doesnt print in the console. it just shows the server is started.anonymouse

4 Answers

15
votes

This happens when you don't provide a default no arg constructor to your JAXB bean. So in your case you should amend the class by adding one:

  public TestRestModel(){

    }

This is due to a requirement in the JSR-222:

existing types, authored by users, are required to provide a no arg constructor. The no arg constructor is used by an unmarshaller during unmarshalling to create an instance of the type.

10
votes

Stuff below is not the answer, but will probably help Johne to find out, whats up.

Out of the comments I've extract, that the main problem is, that you don't have any noticeable debug output in your console. So you are not able to find the issue by yourself, rather than give us some logs which would help to find out, what the exact problem could be.

Therefore pls implement an ExceptionMapper first, which will force console output of the stacktrace:

Example:

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider
public class HelpMeExceptionMapper implements ExceptionMapper<Exception> {

    @Override
    public Response toResponse(Exception e) {
        e.printStackTrace();
        return Response
                    .status(Status.INTERNAL_SERVER_ERROR)
                    .type(MediaType.APPLICATION_JSON)
                    .entity(e.getCause())
                    .build();
    }

}

The ExceptionMapper has to be in a subpackage of your resource-config/providers path test.services:

<init-param>
    <param-name>jersey.config.server.provider.packages</param-name>
    <param-value>test.services</param-value>
</init-param>

As i didn't implement your/vogellas code i would like to recommend you, to debug this step by step to find out whats up.

I reckon, that you miss to import something. But who knows ...

Have a nice day ...

0
votes

To the ones with the same problem, I had something like it but in my case it was a List that i wanted in my response. The source of the problem was that the object had a lazy load relationship and when I used GenericEntity> to return my list the same problem as occurred to me. Just change to null the relationship or bring the lazy load relation to the object before create GenericEntity> and it will be fine.

0
votes

We need to understand this problem first Jersey returns 500 when trying to return an XML response. This issue is coming because of missing dependency in pom.xml and that is:

<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.2.11</version>
</dependency>  

But this is not enough. This will resolve the 500 Error but one more error will come, while using endpoint.

javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.NoClassDefFoundError: com/sun/xml/bind/v2/model/annotation/AnnotationReader

To resolve this you need to add following dependencies too into pom.xml

<!-- https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-core -->
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.3.0.1</version>
</dependency>

        <!-- https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-impl -->
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.1</version>
</dependency>

So this is the complete solution, to make your Jersey webApp work