I have declared two REST web services. One which simply returns a object. And other which accepts an object and returns another object. POJO Order.java is used.
@XmlRootElement
public class Order {
private String id;
private String description;
public Order() {
}
@XmlElement
public String getId() {
return id;
}
@XmlElement
public String getDescription() {
return description;
}
// Other setters and methods
}
Webservice is defined as
@Path("/orders")
public class OrdersService {
// Return the list of orders for applications with json or xml formats
@Path("/oneOrder")
@GET
@Produces({MediaType.APPLICATION_JSON})
public Order getOrder_json() {
System.out.println("inside getOrder_json");
Order o1 = OrderDao.instance.getOrderFromId("1");
System.out.println("about to return one order");
return o1;
}
@Path("/writeAndIncrementOrder")
@GET
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
public Order writeAndIncrementOrder(Order input) {
System.out.println("inside writeAndIncrementOrder");
Order o1 = new Order();
o1.setId(input.getId()+1000);
o1.setDescription(input.getDescription()+"10000");
System.out.println("about to return one order");
return o1;
}
I could write client code to call the web service that does not accept anything but returns object. Client code is as follows
import java.net.URI;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.jersey.client.ClientConfig;
public class Test {
public static void main(String[] args) {
WebTarget target2 = client.target(getBaseURI()).path("rest").path("orders");
String o2 = target2.path("oneOrder").request().accept(MediaType.APPLICATION_JSON).get(String.class);
System.out.println(o2);
}
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost:8090/FirstRESTProject").build();
}
But I do not understand how to call other service which accepts as well as returns object. I tried different solutions given on internet. But nothing worked for me. Some solution works only for sending object and some works only for accepting. But none worked for doing both in one call.
EDIT As suggested in below answer I registered JacksonJaxbJsonProvider.class But auto-conversion into Order object is not happening.
String o2 = target2.path("oneOrder").request().accept(MediaType.APPLICATION_JSON).get(String.class);
client.register(JacksonJaxbJsonProvider.class);
Order o4 = target2.path("oneOrder").request().accept(MediaType.APPLICATION_JSON).get(Order.class);
In above program I successfully get string as {"id":"1","description":"This is the 1st order"} But getting direct object throws error MessageBodyReader not found for media type=application/json, type=class shopping.cart.om.Order, genericType=class shopping.cart.om.Order.
You should use POST or PUT instead GET
try this code
If you take a little bit of time to understand the
WebTarget
API, as well as the different types returned from calls toWebTarget
's method, you should get a better understanding of how to make calls. It may be a little confusing, as almost all the example use method chaining, as it's a very convenient way, but doing this, you miss all the actual classes involved in create and sending the request. Let break it down a bitWebTarget.path()
simply returns theWebTarget
. Nothing interesting there.WebTarget.request()
returnsInvocation.Builder
Invocation.Builder.accept(..)
returnsInvocation.Builder
Invocation.Builder.get()
calls its super class'sSyncInvoker.get()
, which makes the actual request, and returns a type, based on the argument we provide toget(Class returnType)
What you're doing with
get(String.class)
is saying that the response stream should be deserialized into a Sting type response. This is not a problem, as JSON is inherently just a String. But if you want to unmarshal it to a POJO, then you need to have aMessageBodyReader
that knows how to unmarshal JSON to your POJO type. Jackson provides aMessageBodyReader
in it'sjackson-jaxrs-json-provider
dependencyMost implementations will provider a wrapper for this module, like
jersey-media-json-jackson
for Jersey orresteasy-jackson-provider
for Resteasy. But they are still using the underlyingjackson-jaxrs-json-provider
.That being said, once you have that module on the classpath, is should be automatically registered, so the
MessageBodyReader
will be available. If not you can register it explicitly with the client, likeclient.register(JacksonJaxbJsonProvider.class)
. Once you have the Jackson support configured, then you can simply do something likeAs for posting/sending data, you can again look at the different
Invocation.Builder
methods. For instanceIf we want to post, look at the different
post
methods available. We can useResponse post(Entity<?> entity)
- Our request might look something likeYou'll notice the
Entity
. All thepost
methods accept anEntity
, and this is how the request will know what type the entity body should be, and the client will invoke the approriateMessageBodyWriter
as well as set the appropriate header<T> T post(Entity<?> entity, Class<T> responseType)
- There's another overload, where we can specify the type to unmarshal into, instead of getting back aResponse
. We could doNote that with
Response
, we call itsreadEntity(Class pojoType)
method to read from theResponse
, the entity body. The advantage of this, is that theResponse
object comes with a lot of useful information we can use, like headers and such. Personally, I always get theResponse
As an aside, for your particular code you are showing, you most likely want to make it a
@POST
method. Remember@GET
is mainly for retrieving data,PUT
for updating, andPOST
for creating. That is a good rule of thumb to stick to, when first starting out. So you might change the method toThen you can do