JAX-RS 2.0 has brought lots of improvement over previous version. One of major improvement is client API which was completely missing in JAX-RS 1.0. While it was easy to write a portable JAX-RS service, each JAX-RS implementation defined their own proprietary API. JAX-RS 2.0 fills in this gap with a fluent, low-level, request building API. Here’s a simple example:
Client client = ClientFactory.newClient(); WebTarget target = client.target("http://localhost:8080/howtodoinjava"); Form form = new Form().param("customer", "Bill").param("product", "book"); Response response = target.request().post(Entity.form(form)); Order order = response.readEntity(Order.class);
Above code is JAX-RS 2.0 specific and uses JAX-RS classes. If you are using latest RESTEasy (version 3) build then you can use these lower level JAX-RS 2.0 APIs from RESTEasy abstraction provided by its client API.
JAX-RS RESTEasy APIs
Let’s take an example web-service APIs which we will access in our client code:
@GET @Path("/users") @Produces("application/vnd.com.demo.user-management.users+xml;charset=UTF-8;version=1") public Users getAllUsers() { User user1 = new User(); user1.setId(1); user1.setFirstName("demo"); user1.setLastName("user"); user1.setUri("/user-management/users/1"); User user2 = new User(); user2.setId(2); user2.setFirstName("Mark"); user2.setLastName("Dwain"); user2.setUri("/user-management/users/2"); Users users = new Users(); users.setUsers(new ArrayList<User>()); users.getUsers().add(user1); users.getUsers().add(user2); return users; } @POST @Path("/users") @Consumes("application/vnd.com.demo.user-management.user+xml;charset=UTF-8;version=1") public Response createUser(User user, @DefaultValue("false") @QueryParam("allow-admin") boolean allowAdmin) throws URISyntaxException { System.out.println(user.getFirstName()); System.out.println(user.getLastName()); return Response.status(201) .contentLocation(new URI("/user-management/users/123")).build(); }
Client code
Now let’s access these APIs using new client code:
package test.jaxrs2; import javax.ws.rs.client.Entity; import javax.ws.rs.core.Response; import org.jboss.resteasy.client.jaxrs.ResteasyClient; import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; import com.demo.rest.model.User; import com.demo.rest.model.Users; public class Demo_JAXRS_2_Example { public static void main(String[] args) { getExample_one(); getExample_two(); postExample(); } private static void getExample_one() { ResteasyClient client = new ResteasyClientBuilder().build(); ResteasyWebTarget target = client.target("http://localhost:8080/RESTEasyApplication/user-management/users"); Response response = target.request().get(); //Read output in string format String value = response.readEntity(String.class); System.out.println(value); response.close(); } private static void getExample_two() { ResteasyClient client = new ResteasyClientBuilder().build(); ResteasyWebTarget target = client.target("http://localhost:8080/RESTEasyApplication/user-management/users"); Response response = target.request().get(); //Read the entity Users users = response.readEntity(Users.class); for(User user : users.getUsers()){ System.out.println(user.getId()); System.out.println(user.getLastName()); } response.close(); } private static void postExample() { User user = new User(); user.setFirstName("john"); user.setLastName("Maclane"); ResteasyClient client = new ResteasyClientBuilder().build(); ResteasyWebTarget target = client.target("http://localhost:8080/RESTEasyApplication/user-management/users"); Response response = target.request().post(Entity.entity(user, "application/vnd.com.demo.user-management.user+xml;charset=UTF-8;version=1")); //Read output in string format System.out.println(response.getStatus()); response.close(); } } Output in console: <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <users> <user id="1" uri="/user-management/users/1"><firstName>demo</firstName><lastName>user</lastName></user> <user id="2" uri="/user-management/users/2"><firstName>demo</firstName><lastName>user</lastName></user> </users> 1 user 2 Dwain 201
Maven Configuration
I have used below Maven configuration to run these examples.
<repositories> <repository> <id>jboss</id> <url>https://repository.jboss.org/maven2/</url> </repository> </repositories> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- core library --> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxrs</artifactId> <version>3.0.2.Final</version> </dependency> <!-- JAXB support --> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxb-provider</artifactId> <version>3.0.2.Final</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>jaxrs-api</artifactId> <version>3.0.2.Final</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-client</artifactId> <version>3.0.2.Final</version> </dependency> <dependency> <groupId>net.sf.scannotation</groupId> <artifactId>scannotation</artifactId> <version>1.0.3</version> </dependency> </dependencies>
To download the source code of above example, follow below link.
Download sourcecode
Happy Learning !!
Alex Terrance
What if I want to send Json instead of XML? When I change the media type to application/json, I receive an error “Caused by: javax.ws.rs.ProcessingException: could not find writer for content-type application/json type”, but when I stay with XML, everything works fine.
Lokesh Gupta
If server support the media-type, you can send it.
Alex Terrance
Ok, It is working. I was missing some dependencies.
antonin
What about HATEOS ? I always see server implementations saying that client implementations will be easier using it…. But I really see no client implementation using HATOAS even in your sample. Has someone found such resource somewhere ?
Lokesh Gupta
You are right. In theory, that’s how a REST API should be designed. But in practical, I also see very less usage.
RAvish
How to access the https urls?
Aashish
I am getting this error when I ran your example-
———————————————————————————————
Error404 – Not Found
Exception in thread “main” javax.ws.rs.ProcessingException: Unable to find a MessageBodyReader of content-type text/html and type class com.demo.rest.model.Users
at org.jboss.resteasy.core.interception.ClientReaderInterceptorContext.throwReaderNotFound(ClientReaderInterceptorContext.java:39)
at org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.getReader(AbstractReaderInterceptorContext.java:73)
at org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:50)
at org.jboss.resteasy.plugins.interceptors.encoding.GZIPDecodingInterceptor.aroundReadFrom(GZIPDecodingInterceptor.java:59)
at org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:53)
at org.jboss.resteasy.client.jaxrs.internal.ClientResponse.readFrom(ClientResponse.java:244)
at org.jboss.resteasy.client.jaxrs.internal.ClientResponse.readEntity(ClientResponse.java:178)
at org.jboss.resteasy.specimpl.BuiltResponse.readEntity(BuiltResponse.java:217)
at test.jaxrs2.Demo_JAXRS_2_Example.getExample_two(Demo_JAXRS_2_Example.java:40)
at test.jaxrs2.Demo_JAXRS_2_Example.main(Demo_JAXRS_2_Example.java:19)
————————————————————————————————————————————————————
Savani
Hey Do you got any solution for this issue?
Thanks,
Savani
Lokesh Gupta
Make sure you are sending correct content-type in request.
Krishna
Sir, Could u please explain about @POST annotation method which is below……….
@POST
@Path(“/users”)
@Consumes(“application/vnd.com.demo.user-management.user+xml;charset=UTF-8;version=1”)
public Response createUser(User user,
@DefaultValue(“false”) @QueryParam(“allow-admin”) boolean allowAdmin)
throws URISyntaxException {
System.out.println(user.getFirstName());
System.out.println(user.getLastName());
return Response.status(201).contentLocation(new URI(“/user-management/users/123”)).build();
}
Lokesh Gupta
Whenever you will send a HTTP POST request to URL /users?allow-admin=true, this method will be called. Request body should be like
<user><firstName>demo</firstName><lastName>user</lastName></user>
and “content-type” header should be exactly “application/vnd.com.demo.user-management.user+xml;charset=UTF-8;version=1”
tbellinTiziano
Sorry : I modified the version of scannotation from 1.0.3 to 1.0.2. I found that version 1.0.3 has as org.scannotation.
Something wrong?
Harika
Hi Lokesh,
line Response response = target.request().post(Entity.entity(user, “application/vnd.com.demo.user-management.user+xml;charset=UTF-8;version=1″));
will I be able to get the user entity as xml?? instead of a Java object?
to be more clear, does the post method accept xml file??
Lokesh Gupta
Post method will accept “XML Content/Body”, not XML file to be specific.
As JAXB plays as middleman, you will get a populated User instance (java object) from response; after jaxb unmarshal the response XML to java object.
Richard
line: Response response = target.request().post(Entity.entity(user, “application/vnd.com.demo.user-management.user+xml;charset=UTF-8;version=1”));
erro: The method entity(User, String) is undefined for the type
Entity
Lokesh Gupta
Make sure you are using: javax.ws.rs.client.Entity