Skip to Main Content

Java EE (Java Enterprise Edition) General Discussion

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

JAXB Based JSON support not working with Jersey JAX-RS

873896May 1 2013 — edited May 8 2013
Do I make something wrong using JAXB based JSON support with the Jersey 1.17 Client API?
The code below delivers
415
[text/html;charset=utf-8]
Mai 01, 2013 8:23:30 AM com.sun.jersey.api.client.ClientResponse getEntity
SEVERE: A message body reader for Java class client.Pair, and Java type class client.Pair, and MIME media type text/html; charset=utf-8 was not found
Mai 01, 2013 8:23:30 AM com.sun.jersey.api.client.ClientResponse getEntity
SEVERE: The registered message body readers compatible with the MIME media type are:
*/* ->
com.sun.jersey.core.impl.provider.entity.FormProvider
com.sun.jersey.core.impl.provider.entity.StringProvider
com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
com.sun.jersey.core.impl.provider.entity.FileProvider
com.sun.jersey.core.impl.provider.entity.InputStreamProvider
com.sun.jersey.core.impl.provider.entity.DataSourceProvider
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
com.sun.jersey.core.impl.provider.entity.ReaderProvider
com.sun.jersey.core.impl.provider.entity.DocumentProvider
com.sun.jersey.core.impl.provider.entity.SourceProvider$StreamSourceReader
com.sun.jersey.core.impl.provider.entity.SourceProvider$SAXSourceReader
com.sun.jersey.core.impl.provider.entity.SourceProvider$DOMSourceReader
com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$General
com.sun.jersey.json.impl.provider.entity.JSONArrayProvider$General
com.sun.jersey.json.impl.provider.entity.JSONObjectProvider$General
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$General
com.sun.jersey.core.impl.provider.entity.EntityHolderReader
com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$General
com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$General
com.sun.jersey.json.impl.provider.entity.JacksonProviderProxy

Exception in thread "main" com.sun.jersey.api.client.ClientHandlerException: A message body reader for Java class client.Pair, and Java type class client.Pair, and MIME media type text/html; charset=utf-8 was not found
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:561)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:517)
at client.ComputeConcat.main(ComputeConcat.java:39)



package server;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/**
*
* calling with data as JSON serialization
* $ curl -X POST --data-binary "{ \"first\":\"Hello, \", \"second\":\"World.\" }" \
* -H "Content-Type: application/json" -H "Accept: application/json" \
* --user exampleuser:changeit \
* http://localhost:8080/JAXRSServer/rs/concatEngine/concat
* delivers
* { "first":"Hello, World." }
*/
@Path("/concatEngine")
public class ConcatEngine {
@POST
@Path("/concat")
// MediaType.APPLICATION_XML,
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public Pair concat(Pair data) {
Pair res = new Pair();
res.setFirst(data.getFirst() + data.getSecond());
return res;
}
}



package server;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Pair {
protected String first;
protected String second;

public Pair() {
}

public String getFirst() {
return first;
}

public void setFirst(String first) {
this.first = first;
}

public String getSecond() {
return second;
}

public void setSecond(String second) {
this.second = second;
}
}



package client;

import javax.ws.rs.core.MediaType;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;

public class ComputeConcat {

private static WebResource getHttpResource() {
ClientConfig config = new DefaultClientConfig();
// config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
// config.getClasses().add(JSONRootElementProvider.class);
Client client = Client.create(config);
return client.resource(
"http://localhost:8080/JAXRSServer/rs/concatEngine/concat");
}


public static void main(String[] args) {
Pair pair = new Pair();
pair.setFirst("Hello, "); pair.setSecond("World!");

WebResource resource = getHttpResource();

// resource.accept(MediaType.APPLICATION_XML);
resource.accept(MediaType.APPLICATION_JSON);
resource.type(MediaType.APPLICATION_JSON);
// resource.header("content-type", MediaType.APPLICATION_JSON);

ClientResponse response = resource.post(ClientResponse.class, pair);
System.out.println(response.getStatus());
System.out.println(response.getHeaders().get("Content-Type"));
Pair res = response.getEntity(Pair.class);
System.out.println(res.getFirst());
}

}


My web.xml (under Tomcat) if that should be of interest:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

<display-name>JAXRSServer</display-name>

<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>server</param-value>
</init-param>
<!-- init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rs/*</url-pattern>
</servlet-mapping>
</web-app>



If changing @Consumes({MediaType.APPLICATION_JSON}) to @Consumes({MediaType.APPLICATION_XML}) for the concat method, then the code operates. However, the input pair is sent as XML and not as JSON serialization. It seems like the Jersy Client does not automatically serialize the pair object to JSON but only to XML, although imho it should.

Any ideas? Thank you!

Comments

gimbal2
The error seems really off to me.
A message body reader for Java class client.Pair, and Java type class client.Pair, and MIME media type text/html; charset=utf-8
Jersey seems to be either expecting or getting HTML content as a response. I'm wondering if the JAX-RS service you are invoking is actually doing what you are thinking it should be doing.
873896
Jersey seems to be either expecting or getting HTML content as a response. I'm wondering if
the JAX-RS service you are invoking is actually doing what you are thinking it should be doing
Please note that the first 2 lines are output of my client programm. The http error code is 415. That means that only the error message is text/html. If only using MediaType.APPLICATION_XML on the various occurences instead of ...JSON the program works perfect! Also in its current form using curl as indicated in the comment of the server class, it works with JSON perfectly.

The problem is imho the client of Jersey, which does not perfomr the right (JSON) serialization.
gimbal2
de-serialization since the crash seems to happen in getEntity(). The post request you send seems to work just fine, so the serialization part must work.

I have no clue what could be wrong. If you get no other responses I would try the jersey user mailing list:

https://java.net/projects/jersey/lists
873896
Posted on the user list and created an entry to the issues database of Jersey:

https://java.net/jira/browse/JERSEY-1879

However, I neither way I get some response. Seems that either nobody cares or that my question is somehow ridiculous. Btw. I am not the only one:

http://stackoverflow.com/questions/12630917/posting-json-via-jersey

The hints provided in this posting do not operate, or at least I cannot Interpret them correctly.
873896
I found the error:

resource.type(MediaType.APPLICATION_JSON);
resource.accept(MediaType.APPLICATION_JSON);
ClientResponse response = resource.post(ClientResponse.class, pair);

The methods of WebResource (ie post) always create new WebResource.Builder objects. That is setting the type to MediaType.APPLICATION_JSON is done in an object for the garbage collector, and not the one which issues
post.

The following code operates.

WebResource resource = getHttpResource();
WebResource.Builder builder = resource.getRequestBuilder();
builder.accept(MediaType.APPLICATION_JSON_TYPE);
builder.type(MediaType.APPLICATION_JSON_TYPE);
ClientResponse response = builder.post(ClientResponse.class, pair);

However, this behavior is poorly documented and contrintuitive. For chaining/fluent API the passed objects better should be changed and a reference to them returned.

Hower, many thanks for your help.
gimbal2
This strikes me as something very curious and potentially wrong. I would expect that this internally constructed builder would adopt the resource settings and apparently you have now proven this is not the case. At least not in the version of Jersey you're using. On the other hand I have not worked with the JAX-RS API long enough yet to fully understand its inner workings, perhaps I'm just making false claims.

Nice catch by the way, and thanks for posting back a solution.
r035198x
The builder pattern is used here so you must use
response = resource.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).post(ClientResponse.class, pair);
Edited by: r035198x on May 8, 2013 7:00 AM
1 - 7
Locked Post
New comments cannot be posted to this locked post.

Post Details

Locked on Jun 5 2013
Added on May 1 2013
7 comments
19,279 views