I am writing a Jersey 2 Restful web service. Here is the service class:
package com.Test.PS;
import java.io.IOException;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.QueryParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import com.Test.Exchange.*; // Here class UserInfo is defined
@Path("/ps")
public class TestService {
private UserInfo ui;
public TestService () throws IOException {
ui = new UserInfo();
}
public TestService (String uid) throws IOException {
UserInfo ui = ObjectFileStore.serializeDataIn(uid);
}
public TestService (UserInfo ui) throws IOException {
this.ui = ui;
ObjectFileStore.serializeDataOut(ui);
}
@GET
@Produces(MediaType.TEXT_HTML)
public String sayHelloHTML(@QueryParam("uid") String uid) {
String resource="<h1> Hi '" + uid + "'. </h1>";
return resource;
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public UserInfo postNK(@QueryParam("asid") String asid, UserInfo u) {
return ui;
}
}
Here is the maven dependencies:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>${version.jersey}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>${version.jersey}</version>
</dependency>
<!-- JSON Support (MOXy) -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>${version.jersey}</version>
</dependency>
Finaly, this is my web.xml file:
<display-name>Test-PS</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Test-PS</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.Test.PS</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Test-PS</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
I am getting the following error when cosuming the post method using the following code:
UserInfo n2k = new UserInfo();
ClientConfig config = new ClientConfig(MOXyJsonProvider.class);
Client client = ClientBuilder.newClient(config);
String targetUrl = "http://localhost:8081/Test-PS";
WebTarget target = client.target(targetUrl);
Invocation.Builder invocationBuilder = target.path("rest").path("ps").queryParam("asid", ASID).request(MediaType.APPLICATION_JSON);
Response response = invocationBuilder.post(Entity.entity(n2k, MediaType.APPLICATION_JSON));
UserInfo ui = response.readEntity(UserInfo.class);
response.close();
client.close();
On the console screen, I see:
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/html;charset=utf-8, type=class com.Exchange.UserInfo, genericType=class com.Exchange.UserInfo.
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:232)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:156)
org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1091)
org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:808)
org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:321)
org.glassfish.jersey.client.InboundJaxrsResponse$1.call(InboundJaxrsResponse.java:115)
org.glassfish.jersey.internal.Errors.process(Errors.java:316)
org.glassfish.jersey.internal.Errors.process(Errors.java:298)
org.glassfish.jersey.internal.Errors.process(Errors.java:229)
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:389)
org.glassfish.jersey.client.InboundJaxrsResponse.runInScopeIfPossible(InboundJaxrsResponse.java:264)
org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:112)
com.AS.AuthenticatorService.Authenticate(AuthenticatorService.java:79)
org.apache.jsp.JSP.Authenticate_jsp._jspService(Authenticate_jsp.java:128)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:458)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
The server logs says: "POST /Test-PS/rest/ps?asid=AS1 HTTP/1.1" 500 1081
I have tried lots of solutions provided for this error but non of them works!!!
I want also to add that if the POST method returns a primitive type, e.g., String, instead of the user defined one, i.e., UserInfo, it works! UserInfo is a serialized class with fields like: username, date of birth, etc..
Oh, finally I got the issue. It is realy a strange one. There is a method in the UserInfo class called setUserInfo that accepts a parameter of the same class type as shown in the code bellow:
public void setUserInfo(UserInfo ui) {
this.firstName = ui.getFirstName();
this.lastName = ui.getFirstName();
this.dateOfBirth = ui.getDateOfBirth();
this.homeAddress = ui.getHomeAddress();
}
If I delete it, everything works smoothly. Once I re-add it, I got the same exception. It seems that it is forbidden for a class to have a method which accepts a parameter of its type if this class will be sent as a Jersey JSON response.
I do not know why, but this was the issue as I tried it several times and evertime the method is added, the same exception is raised!!! It can be a bug!!!
You may try it as well