By kswaughs | Thursday, November 26, 2015

How to read headers from REST response with Apache CXF

In my previous post, I have explained how to pass headers to RESTful services using Apache CXF.

CXF Rest client passing headers to request

For the same example, we will see how to read/parse headers from the REST response.

There are two ways to read/parse the headers from REST response

  • Example 1 - Using getHeaderString method of Response object to read a single header value
  • Example 1 - Using MultivaluedMap to read all header values

Using getHeaderString method of Response

Example 1
package com.example.cxfrs;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.core.Response;

import com.example.cxfrs.beans.UserRequest;
import com.example.cxfrs.beans.UserResponse;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class CXFRestPostClient {

 public static void main(String[] args) {

  // Adding JacksonJsonProvider to convert JSON String to Java object
  List<Object> providers = new ArrayList<Object>();
  providers.add(new JacksonJsonProvider());

  // Build REST request
  UserRequest req = new UserRequest();
  req.setId("1234578");
  req.setName("kswaughs");

  // Create WebClient 
  WebClient client = WebClient.create(
    "http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add",
    providers);

  // Adding headers
  client = client.accept("application/json").type("application/json")
    .header("consumer_id", "StandAloneRestClient")
    .header("consumer_location", "US");

  // Call the REST service
  Response r = client.post(req);
  
  //Read/parse the response headers
  System.out.println("date:"+ r.getHeaderString("Date"));
  
  // Read/parse the response
  UserResponse resp = r.readEntity(UserResponse.class);
  
  System.out.println(resp);
 }

Server log - Response

ID: 5
Response-Code: 200
Content-Type: application/json
Headers: {Content-Type=[application/json], Date=[Fri, 27 Nov 2015 06:50:34 GMT]}
Payload: {"id":"1234578","status":"Success"}

Output is

date:Fri, 27 Nov 2015 06:50:34 GMT
UserResponse [status=Success, id=1234578]

Using MultivaluedMap to read all header values

Example 2
package com.example.cxfrs;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;

import com.example.cxfrs.beans.UserRequest;
import com.example.cxfrs.beans.UserResponse;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class CXFRestPostClient {

 public static void main(String[] args) {

  // Adding JacksonJsonProvider to convert JSON String to Java object
  List<Object> providers = new ArrayList<Object>();
  providers.add(new JacksonJsonProvider());

  // Build REST request
  UserRequest req = new UserRequest();
  req.setId("1234578");
  req.setName("kswaughs");

  // Create WebClient 
  WebClient client = WebClient.create(
    "http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add",
    providers);

  // Adding headers
  MultivaluedMap<String, String> reqHeaders = new MultivaluedHashMap<String, String>();
  reqHeaders.add("consumer_id", "StandAloneRestClient");
  reqHeaders.add("consumer_location", "US");
  
  client = client.accept("application/json")
                 .type("application/json")
                 .headers(reqHeaders);

  // Call the REST service
  Response r = client.post(req);
  
  //Read/parse the response headers
  MultivaluedMap<String, String> respHeaders = r.getStringHeaders();
  System.out.println("respHeaders:\n" + respHeaders);
  
  // Read/parse the response
  UserResponse resp = r.readEntity(UserResponse.class);
  
  System.out.println(resp);
 }
}

Output is

respHeaders:
{content-type=[application/json], Date=[Fri, 27 Nov 2015 07:13:16 GMT], Server=[Apache-Coyote/1.1], transfer-encoding=[chunked], Content-Type=[application/json]}

UserResponse [status=Success, id=1234578]

Recommend this on


How to pass headers to REST request with Apache CXF

In my previous posts, I have explained how to call RESTful services using Apache CXF.

CXF Rest client to call POST method using WebClient

CXF Rest client to call GET method using WebClient

For the same example, we will see how to add custom headers to the REST request.

There are two ways to add the headers.

  • Example 1 - Chained method calls of header(key, value) on WebClient object
  • Example 1 - Using MultivaluedMap to pass multiple headers

Using header(key, value) method on WebClient object

Example 1
package com.example.cxfrs;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.core.Response;

import com.example.cxfrs.beans.UserRequest;
import com.example.cxfrs.beans.UserResponse;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class CXFRestPostClient {

 public static void main(String[] args) {

  List<Object> providers = new ArrayList<Object>();
  providers.add(new JacksonJsonProvider());

  UserRequest req = new UserRequest();
  req.setId("1234578");
  req.setName("kswaughs");

  WebClient client = WebClient.create(
          "http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add",
          providers);

  client = client.accept("application/json").type("application/json")
    .header("consumer_id", "StandAloneRestClient")
    .header("consumer_location", "US");

  Response r = client.post(req);
  UserResponse resp = r.readEntity(UserResponse.class);

  System.out.println(resp);
 }
}

Using MultivaluedMap to pass multiple headers

Example 2
package com.example.cxfrs;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;

import com.example.cxfrs.beans.UserRequest;
import com.example.cxfrs.beans.UserResponse;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class CXFRestPostClient {

 public static void main(String[] args) {

  List<Object> providers = new ArrayList<Object>();
  providers.add(new JacksonJsonProvider());
  
  UserRequest req = new UserRequest();
  req.setId("1234578");
  req.setName("kswaughs");

  WebClient client = WebClient.create(
       "http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add", 
       providers);
  
  MultivaluedMap<String, String> headers = 
       new MultivaluedHashMap<String, String>();
  
  headers.add("consumer_id", "StandAloneRestClient");
  headers.add("consumer_location", "US");
  
  client = client.accept("application/json").
                  type("application/json").
                  headers(headers);
  
  Response r = client.post(req);
  UserResponse resp = r.readEntity(UserResponse.class);

  System.out.println(resp);
 }
}

In the server console, See the passed header values highlighted in bold

ID: 1
Address: http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add
Encoding: ISO-8859-1
Http-Method: POST
Content-Type: application/json
Headers: {Accept=[application/json], cache-control=[no-cache], connection=[keep-alive], consumer_id=[StandAloneRestClient], consumer_location=[US], Content-Length=[34], content-type=[application/json], host=[127.0.0.1:8080], pragma=[no-cache], user-agent=[Apache CXF 3.1.2]}
Payload: {"id":"1234578","name":"kswaughs"}

Recommend this on


By kswaughs | Wednesday, November 25, 2015

CXF Rest Client to call POST method

I have a sample REST service with POST method running in my local system. This method is used to add user details.

The URL is 'http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add'

Request is

{ "id" : "12346" , "name":"kswaughs" }

Response is

{
   "id": "12346",
   "status": "Success"
}

Create a POJO class to send the request

Request Object - UserRequest
package com.example.cxfrs.beans;

public class UserRequest {

 private String id;

 private String name;

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }
}

Create a POJO class to parse the JSON response into java object

Response Object - UserResponse
package com.example.cxfrs.beans;

public class UserResponse {

 private String status;

 private String id;

 public String getStatus() {
  return status;
 }

 public void setStatus(String status) {
  this.status = status;
 }

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 @Override
 public String toString() {
  StringBuilder builder = new StringBuilder();
  builder.append("UserResponse [status=");
  builder.append(status);
  builder.append(", id=");
  builder.append(id);
  builder.append("]");
  return builder.toString();
 }
}

A simple stand-alone client code using WebClient and JacksonJsonProvider.

Sample Client code to call POST Method
package com.example.cxfrs;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.core.Response;

import com.example.cxfrs.beans.UserRequest;
import com.example.cxfrs.beans.UserResponse;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class CXFRestPostClient {

 public static void main(String[] args) {

  List<Object> providers = new ArrayList<Object>();
  providers.add(new JacksonJsonProvider());
  
  UserRequest req = new UserRequest();
  req.setId("1234578");
  req.setName("kswaughs");

  WebClient client = WebClient
    .create("http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add", providers);
  
  client = client.accept("application/json").type("application/json");
  
  Response r = client.post(req);
  UserResponse resp = r.readEntity(UserResponse.class);
  System.out.println(resp);
 }
}

Output is

UserResponse [status=Success, id=1234578]

Use Below maven dependency in your pom.xml to use CXF Client

<!-- To use WebClient API -->
<dependency>
 <groupId>org.apache.cxf</groupId>
 <artifactId>cxf-rt-rs-client</artifactId>
 <version>3.1.2</version>
</dependency>
<!-- To parse JSON String to Java objects --> 
<dependency>
 <groupId>org.codehaus.jackson</groupId>
 <artifactId>jackson-jaxrs</artifactId>
 <version>1.9.0</version>
</dependency> 

If you dont provide JacksonJsonProvider to WebClient, You will get below JSON parsing error.

 
org.apache.cxf.jaxrs.utils.JAXRSUtils logMessageHandlerProblem
SEVERE: No message body writer has been found for class org.example.cxfrs.beans.UserRequest, ContentType: application/json
Nov 25, 2015 3:00:48 PM org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging
WARNING: Interceptor for {http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add}WebClient has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: No message body writer has been found for class org.example.cxfrs.beans.UserRequest, ContentType: application/json
 at org.apache.cxf.jaxrs.client.WebClient$BodyWriter.doWriteBody(WebClient.java:1227)
 at org.apache.cxf.jaxrs.client.AbstractClient$AbstractBodyWriter.handleMessage(AbstractClient.java:1052)
 at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
 at org.apache.cxf.jaxrs.client.AbstractClient.doRunInterceptorChain(AbstractClient.java:636)
 at org.apache.cxf.jaxrs.client.WebClient.doChainedInvocation(WebClient.java:1091)
 at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:894)
 at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:865)
 at org.apache.cxf.jaxrs.client.WebClient.invoke(WebClient.java:331)
 at org.apache.cxf.jaxrs.client.WebClient.post(WebClient.java:340)
 at org.example.cxfrs.CXFRestPostClient.main(CXFRestPostClient.java:30)
Caused by: javax.ws.rs.ProcessingException: No message body writer has been found for class org.example.cxfrs.beans.UserRequest, ContentType: application/json
 at org.apache.cxf.jaxrs.client.AbstractClient.reportMessageHandlerProblem(AbstractClient.java:754)
 at org.apache.cxf.jaxrs.client.AbstractClient.writeBody(AbstractClient.java:485)
 at org.apache.cxf.jaxrs.client.WebClient$BodyWriter.doWriteBody(WebClient.java:1222)
 ... 9 more

Exception in thread "main" javax.ws.rs.ProcessingException: org.apache.cxf.interceptor.Fault: No message body writer has been found for class org.example.cxfrs.beans.UserRequest, ContentType: application/json
 at org.apache.cxf.jaxrs.client.WebClient.doResponse(WebClient.java:1147)
 at org.apache.cxf.jaxrs.client.WebClient.doChainedInvocation(WebClient.java:1092)
 at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:894)
 at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:865)
 at org.apache.cxf.jaxrs.client.WebClient.invoke(WebClient.java:331)
 at org.apache.cxf.jaxrs.client.WebClient.post(WebClient.java:340)
 at org.example.cxfrs.CXFRestPostClient.main(CXFRestPostClient.java:30)
Caused by: org.apache.cxf.interceptor.Fault: No message body writer has been found for class org.example.cxfrs.beans.UserRequest, ContentType: application/json
 at org.apache.cxf.jaxrs.client.WebClient$BodyWriter.doWriteBody(WebClient.java:1227)
 at org.apache.cxf.jaxrs.client.AbstractClient$AbstractBodyWriter.handleMessage(AbstractClient.java:1052)
 at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
 at org.apache.cxf.jaxrs.client.AbstractClient.doRunInterceptorChain(AbstractClient.java:636)
 at org.apache.cxf.jaxrs.client.WebClient.doChainedInvocation(WebClient.java:1091)
 ... 5 more
Caused by: javax.ws.rs.ProcessingException: No message body writer has been found for class org.example.cxfrs.beans.UserRequest, ContentType: application/json
 at org.apache.cxf.jaxrs.client.AbstractClient.reportMessageHandlerProblem(AbstractClient.java:754)
 at org.apache.cxf.jaxrs.client.AbstractClient.writeBody(AbstractClient.java:485)
 at org.apache.cxf.jaxrs.client.WebClient$BodyWriter.doWriteBody(WebClient.java:1222)
 ... 9 more

Related Links
Apache Camel SOAP Service Client
Apache CXF Rest Client to call GET method

Recommend this on


CXF Rest Client to call REST service - GET method

I have a sample REST service with GET method running in my local system. This method is used to fetch user details..

The URL is 'http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/details/123'

Response is

{
   "status": "Success",
   "id": "123",
   "name": "kswaughs"
}

Create a model object to parse JSON response into java object.

Response Object - User
package com.example.cxfrs.beans;

public class User {

 private String status;

 private String id;

 private String name;

 public String getStatus() {
  return status;
 }

 public void setStatus(String status) {
  this.status = status;
 }

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 @Override
 public String toString() {
  StringBuilder builder = new StringBuilder();
  builder.append("User [status=");
  builder.append(status);
  builder.append(", id=");
  builder.append(id);
  builder.append(", name=");
  builder.append(name);
  builder.append("]");
  return builder.toString();
 } 
}

A simple stand-alone client code using WebClient and JacksonJsonProvider.

Sample Client code to call get Method
package com.example.cxfrs;

import java.util.ArrayList;
import java.util.List;

import com.example.cxfrs.beans.User;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class CXFRestClient {

 public static void main(String[] args) {

  List<Object> providers = new ArrayList<Object>();
  providers.add(new JacksonJsonProvider());

  WebClient client = WebClient
    .create("http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/details", providers);
  
  User user = client.accept("application/json").type("application/json")
    .path("123").get(User.class);

  System.out.println(user);
 }
}

Output is

User [status=Success, id=123, name=kswaughs]

Use Below maven dependency in your pom.xml to use CXF Client

<!-- To use WebClient API -->
<dependency>
 <groupId>org.apache.cxf</groupId>
 <artifactId>cxf-rt-rs-client</artifactId>
 <version>3.1.2</version>
</dependency>
<!-- To parse JSON String to Java objects --> 
<dependency>
 <groupId>org.codehaus.jackson</groupId>
 <artifactId>jackson-jaxrs</artifactId>
 <version>1.9.0</version>
</dependency> 

If you dont provide JacksonJsonProvider to WebClient, You will get below error while parsing the JSON response.

 
org.apache.cxf.jaxrs.utils.JAXRSUtils logMessageHandlerProblem
SEVERE: No message body reader has been found for class com.example.cxfrs.beans.User, ContentType: application/json
Exception in thread "main" javax.ws.rs.client.ResponseProcessingException: No message body reader has been found for class org.apache.camel.example.cxfrs.beans.User, ContentType: application/json
 at org.apache.cxf.jaxrs.impl.ResponseImpl.reportMessageHandlerProblem(ResponseImpl.java:433)
 at org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:384)
 at org.apache.cxf.jaxrs.client.AbstractClient.readBody(AbstractClient.java:512)
 at org.apache.cxf.jaxrs.client.WebClient.handleResponse(WebClient.java:1173)
 at org.apache.cxf.jaxrs.client.WebClient.doResponse(WebClient.java:1156)
 at org.apache.cxf.jaxrs.client.WebClient.doChainedInvocation(WebClient.java:1092)
 at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:894)
 at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:865)
 at org.apache.cxf.jaxrs.client.WebClient.invoke(WebClient.java:428)
 at org.apache.cxf.jaxrs.client.WebClient.get(WebClient.java:611)
 at com.example.cxfrs.CXFRestClient.main(CXFRestClient.java:21)

Recommend this on