0

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..

mksoi
  • 131
  • 3
  • 13
  • For som reason, you are getting back HTML (and not the JSON response) from the server. Maybe an error is occurring on the server and you are getting an error page back. Why don't you check the status code on the response. If it is not a 200, then get the String response and print it. See what it is. `response.readEntity(String.class)` – Paul Samsotha Aug 27 '18 at 20:16
  • If it is an error, check the server log, are there any exception being thrown? If not, maybe it is being swallowed up, Try registering a [generic ExceptionMapper](https://stackoverflow.com/a/45758691/2587435) to see if you can catch the exception and print the stack trace. – Paul Samsotha Aug 27 '18 at 20:19
  • Thank you Paul. I will do so tomorrow as I have no access to the code right now, however, I would like to say that I have already checked the server logs as I said. It seems that the correct method were called but there is an error code 500. Please check the post again to see the server logs. – mksoi Aug 27 '18 at 20:29
  • Is the `UserInfo` class annotated with `@XmlRootElement`? – Paul Samsotha Aug 27 '18 at 20:35
  • No, it's just serialised. No annotations – mksoi Aug 27 '18 at 20:41
  • It needs that annotation. – Paul Samsotha Aug 27 '18 at 21:29
  • I tried, it did not work :( – mksoi Aug 28 '18 at 09:26
  • You tried _everything_ I mentioned above (in _all_ my comments)? – Paul Samsotha Aug 28 '18 at 18:57
  • Yes, everything – mksoi Aug 28 '18 at 20:54
  • And did you see a stack trace with the ExceptionMapper? – Paul Samsotha Aug 28 '18 at 21:23
  • And did you check the content of the response? What was it? Was it actually HTML? If so, what did it say? – Paul Samsotha Aug 28 '18 at 23:18
  • I have not tried ExceptionMapper before, I would appreciate if you can provide a link about it. How can I check the content of the response if there is an exception? If you mean the error code, then it is 500. – mksoi Aug 29 '18 at 09:42
  • I've answered both of your questions in my previous comments. – Paul Samsotha Aug 29 '18 at 10:40
  • Yes, sorry. Anyway I got the issue. Thank you for your help. – mksoi Aug 29 '18 at 15:50

2 Answers2

0

You are combining to things. Your GET method can use query params but POST don't. Change your post method like this:

@POST("{asid}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public UserInfo postNK(@PathParam("asid") String asid, UserInfo u) {
    return ui;
}

Then

Invocation.Builder invocationBuilder = target.path("rest").path("ps/" + ASID).request(MediaType.APPLICATION_JSON);

I used to build rest api with jax-rs so I guess there should be another way to add the ASID param.

Wilder Valera
  • 986
  • 9
  • 11
  • I do not think so. Anyway I will try it. Thank you. – mksoi Aug 28 '18 at 09:34
  • POST can use path param but not query params thats why the @POST("{asid}") – Wilder Valera Aug 28 '18 at 13:52
  • As I told in my question, the code works fine if the returned class is a Java primitave class, e.g., String. So no issue with the POST accessing query params. You can try it – mksoi Aug 29 '18 at 10:16
0

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

mksoi
  • 131
  • 3
  • 13