REST client, CXF server : JAX-RS or SPRING-MVC ?

Hi reader,

If you’ve read my previous article you know I had to provide a POC for a REST architecture.
The target is : simple REST invocation with an even simpler implementation.

The POC, a maven multi-project, includes :
– core : entities, exceptions, service (jar packaging)
– server : service implementation including a custom in-memory repository, service exposition with Apache CXF (war packaging)
– server-test : uses the server artifact, runs it in a jetty container, exposes the service. A JAX-WS client consumes and tests the webservice (CRUD tests).
– JAX-RS client : consumes the webservice and exposes REST urls. Renders JSON with jackson.
– JAX-RS client test : consumes JAX-RS client thanks to HttpClient. The rest framework used is Jersey.
– SPRING-MVC client : consumes the webservice and exposes REST urls.
– SPRING-MVC client test : consumes SPRING-MVC client thanks to RestTemplate. Renders JSON with jackson. Renders XML with xstream.


What I couldn’t get to work :
– with both technologies I have no proven method to manage properly exceptions.
– with spring-mvc and RestTemplate : I can’t manage properly 404 in case of resource not found (wrong id provided in a GET request for example).

I came up with the following rough conclusions. They are no absolute truth, they only reflect my understanding of the subject so far.

Every sharp review will be more than welcome.

jax-rs pros and cons :
– pro : ResponseBuilder is a real fun to use, it is powerful enough to do whatever you want with the response.
– pro : Easy to handle HTTP return code.
– con : ContentNegotiation is not a built-in feature. You have to provide your HttpMessageConverters.

spring-mvc pros and cons :
– pro : @ResponseBody builds the body for you. You just focus on your business.
– pro : ContentNegotiation is a built-in feature. No need to implement it. There is an exhaustive set of HttpMessageConverters shiped with spring-webmvc.
– con : without RestTemplate it is not that easy to send the right request (HTTP methods and header are often tricky to deal with, I guess I lack a good REST Reference)
– con : RestTemplate forces you to return not null object on a *ForObject method, thus making it hard to properly handle null returns (404 not found equivalent).

I posted below some code excerpts and you can download the full example here.

NOTE : I found useful information here, there and there

Hope this will help anybody interested in a working example on REST and WEBSERVICES.

— excerpts from jax-rs client test —
ProductResourceTest.java

package org.diveintojee.poc.rest.client.jaxrs;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.type.TypeFactory;
import org.diveintojee.poc.rest.domain.Product;
import org.diveintojee.poc.rest.domain.services.ProductService;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.webapp.WebAppContext;
import org.mortbay.thread.QueuedThreadPool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * @author louis.gueye@gmail.com
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {Constants.TESTS_CONTEXT})
public class ProductResourceTest {

   HttpClient httpClient;

   @Autowired
   ObjectMapper mapper;

   private static final String BASE_URL = ResourceBundle.getBundle(Constants.CONFIG_BUNDLE_NAME).getString(Constants.REST_POC_CLIENT_URL_KEY);
   private static final String JETTY_PORT = ResourceBundle.getBundle(Constants.CONFIG_BUNDLE_NAME).getString(Constants.JETTY_PORT_KEY);
   private static final String CLIENT_MODULE_CONTEXT = ResourceBundle.getBundle(Constants.CONFIG_BUNDLE_NAME).getString(Constants.CLIENT_MODULE_CONTEXT_KEY);
   private static final String SERVER_MODULE_CONTEXT = ResourceBundle.getBundle(Constants.CONFIG_BUNDLE_NAME).getString(Constants.SERVER_MODULE_CONTEXT_KEY);

   private static final int PRODUCTS_INITIAL_SIZE = 5;

   @Autowired
   @Qualifier("productServiceProxy")
   private ProductService productService;

   private static Server server;

   /**
    * @throws Throwable
    */
   @BeforeClass
   public static void beforeClass() throws Throwable {

      server = new Server();

      QueuedThreadPool threadPool = new QueuedThreadPool();
      threadPool.setMaxThreads(100);
      server.setThreadPool(threadPool);

      SelectChannelConnector connector = new SelectChannelConnector();
      connector.setPort(Integer.valueOf(JETTY_PORT));
      connector.setMaxIdleTime(30000);
      connector.setConfidentialPort(8443);
      server.setConnectors(new Connector[] {connector});

      WebAppContext restPocClientWebApp = new WebAppContext();
      restPocClientWebApp.setWar("../rest-poc-client-jaxrs/target/rest-poc-client-jaxrs.war");
      restPocClientWebApp.setContextPath("/" + CLIENT_MODULE_CONTEXT);
      server.addHandler(restPocClientWebApp);

      WebAppContext restPocServerWebApp = new WebAppContext();
      restPocServerWebApp.setWar("../rest-poc-server/target/rest-poc-server.war");
      restPocServerWebApp.setContextPath("/" + SERVER_MODULE_CONTEXT);
      server.addHandler(restPocServerWebApp);

      server.start();

      server.setStopAtShutdown(true);

      server.setSendServerVersion(true);
   }

   /**
    * @throws Throwable
    */
   @AfterClass
   public static void afterClass() throws Throwable {

      server.stop();
      server.join();

   }

   /**
    * 
    */
   @Before
   public void before() {

      assertNotNull(productService);

      setUpNewProductRepository();

      httpClient = new HttpClient();

   }

   /**
    * @throws Throwable
    */
   @Test
   public final void testList() throws Throwable {

      List<Product> products = listProducts();

      assertNotNull(products);

      assertEquals(PRODUCTS_INITIAL_SIZE, products.size());

   }

   /**
    * @throws Throwable
    */
   @Test
   public void testAdd() throws Throwable {

      String name = "doliprane";

      String description = "Ce médicament est un antalgique et un antipyrétique qui contient du paracétamol."
            + "\nIl est utilisé pour faire baisser la fièvre et dans le traitement des affections douloureuses.";

      Long id = addProduct(name, description);

      assertNotNull(id);

      Product product = getProduct(id);

      assertNotNull(product);

      assertEquals(name, product.getName());

      assertEquals(description, product.getDescription());
   }

   /**
    * @throws Throwable
    */
   @Test
   public void testFindByDescription() throws Throwable {

      String name = "doliprane";

      String description = "Ce médicament est un antalgique et un antipyrétique qui contient du paracétamol."
            + "\nIl est utilisé pour faire baisser la fièvre et dans le traitement des affections douloureuses.";

      addProduct(name, description);

      assertEquals(PRODUCTS_INITIAL_SIZE + 1, listProducts().size());

      String term = "description";

      assertEquals(PRODUCTS_INITIAL_SIZE, findByDescription(term).size());

   }

   /**
    * @throws Throwable
    */
   @Test
   public void testUpdate() throws Throwable {

      String uri = null;

      HttpMethod httpMethod = null;

      NameValuePair[] queryString = null;

      int statusCode;

      String name = "doliprane";

      String description = "Ce médicament est un antalgique et un antipyrétique qui contient du paracétamol."
            + "\nIl est utilisé pour faire baisser la fièvre et dans le traitement des affections douloureuses.";

      Long id = addProduct(name, description);

      assertNotNull(id);

      String newName = "prozac";

      String newDescription = "Ce médicament est un antidépresseur de la famille des inhibiteurs de la recapture de la sérotonine.";

      newDescription += "Il est utilisé chez l'adulte dans le traitement : -des états dépressifs ; \n-des troubles obsessionnels compulsifs ;";

      newDescription += "\n- de la boulimie (en complément d'une psychothérapie). ;";

      uri = "/product/update/" + id;

      httpMethod = new PostMethod(BASE_URL + uri);

      httpMethod.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

      queryString = new NameValuePair[] {new NameValuePair("name", newName), new NameValuePair("description", newDescription)};

      httpMethod.setQueryString(queryString);

      statusCode = httpClient.executeMethod(httpMethod);

      assertEquals(HttpStatus.SC_OK, statusCode);

      Product p = getProduct(id);

      assertNotNull(p);

      assertEquals(newName, p.getName());

      assertEquals(newDescription, p.getDescription());
   }

   /**
    * @throws Throwable
    */
   @Test
   public void testDelete() throws Throwable {

      String uri = null;

      HttpMethod httpMethod = null;

      int statusCode;

      String name = "doliprane";

      String description = "Ce médicament est un antalgique et un antipyrétique qui contient du paracétamol."
            + "\nIl est utilisé pour faire baisser la fièvre et dans le traitement des affections douloureuses.";

      Long id = addProduct(name, description);

      assertNotNull(id);

      uri = "/product/delete/" + id;

      httpMethod = new GetMethod(BASE_URL + uri);

      statusCode = httpClient.executeMethod(httpMethod);

      assertEquals(HttpStatus.SC_OK, statusCode);

      uri = "/product/" + id;

      httpMethod = new GetMethod(BASE_URL + uri);

      statusCode = httpClient.executeMethod(httpMethod);

      assertEquals(HttpStatus.SC_NOT_FOUND, statusCode);

   }

   /**
    * 
    */
   private void setUpNewProductRepository() {

      productService.clear();

      for (int i = 0; i < PRODUCTS_INITIAL_SIZE; i++) {

         Product p = new Product();

         String name = "name" + i;

         String description = "description" + i;

         p.setName(name);

         p.setDescription(description);

         productService.add(p);

      }

   }

   /**
    * @param name
    * @param description
    * @return
    * @throws Throwable
    */
   private Long addProduct(String name, String description) throws Throwable {

      String uri = null;

      HttpMethod httpMethod = null;

      NameValuePair[] queryString = null;

      int statusCode;

      byte[] responseBody = null;

      uri = "/product/add";

      httpMethod = new PostMethod(BASE_URL + uri);

      httpMethod.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

      queryString = new NameValuePair[] {new NameValuePair("name", name), new NameValuePair("description", description)};

      httpMethod.setQueryString(queryString);

      statusCode = httpClient.executeMethod(httpMethod);

      responseBody = httpMethod.getResponseBody();

      assertEquals(HttpStatus.SC_OK, statusCode);

      Long id = mapper.readValue(new ByteArrayInputStream(responseBody), Long.class);

      return id;

   }

   /**
    * @param id
    * @return
    * @throws Throwable
    */
   private Product getProduct(Long id) throws Throwable {

      String uri = null;

      HttpMethod httpMethod = null;

      int statusCode;

      byte[] responseBody = null;

      uri = "/product/" + id;

      httpMethod = new GetMethod(BASE_URL + uri);

      statusCode = httpClient.executeMethod(httpMethod);

      responseBody = httpMethod.getResponseBody();

      assertEquals(HttpStatus.SC_OK, statusCode);

      Product product = mapper.readValue(new ByteArrayInputStream(responseBody), Product.class);

      return product;

   }

   /**
    * @return
    * @throws Throwable
    */
   private List<Product> listProducts() throws Throwable {

      String uri = "/product/list";

      HttpMethod method = new GetMethod(BASE_URL + uri);

      int statusCode = httpClient.executeMethod(method);

      assertEquals(HttpStatus.SC_OK, statusCode);

      byte[] responseBody = method.getResponseBody();

      List<Product> products = mapper.readValue(new ByteArrayInputStream(responseBody), TypeFactory.collectionType(ArrayList.class, Product.class));

      return products;
   }

   /**
    * @param term
    * @return
    * @throws Throwable
    */
   private List<Product> findByDescription(String term) throws Throwable {

      String uri = "/product/find/by/description/term/" + term;

      HttpMethod method = new GetMethod(BASE_URL + uri);

      int statusCode = httpClient.executeMethod(method);

      assertEquals(HttpStatus.SC_OK, statusCode);

      byte[] responseBody = method.getResponseBody();

      List<Product> products = mapper.readValue(new ByteArrayInputStream(responseBody), TypeFactory.collectionType(ArrayList.class, Product.class));

      return products;
   }

}

rest-poc-client-jaxrs-test.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
        <property name="locations" value="classpath:config.properties" /> 
    </bean> 

    <jaxws:client id="productServiceProxy"
                  serviceClass="org.diveintojee.poc.rest.domain.services.ProductService"
                  address="${rest-poc-server.url}"/>
                  
    <bean id="jsonMapper" class="org.codehaus.jackson.map.ObjectMapper"/>

</beans>

— excerpts from spring-mvc client test —
ProductResourceTest.java

package org.diveintojee.poc.rest.client.springmvc;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.ResourceBundle;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.diveintojee.poc.rest.domain.Product;
import org.diveintojee.poc.rest.domain.services.ProductService;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.webapp.WebAppContext;
import org.mortbay.thread.QueuedThreadPool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;

/**
 * @author louis.gueye@gmail.com
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {Constants.TESTS_CONTEXT})
public class ProductResourceTest {

   @Autowired
   RestTemplate restTemplate;

   private static final String BASE_URL = ResourceBundle.getBundle(Constants.CONFIG_BUNDLE_NAME).getString(Constants.REST_POC_CLIENT_URL_KEY);

   private static final String JETTY_PORT = ResourceBundle.getBundle(Constants.CONFIG_BUNDLE_NAME).getString(Constants.JETTY_PORT_KEY);

   private static final String CLIENT_MODULE_CONTEXT = ResourceBundle.getBundle(Constants.CONFIG_BUNDLE_NAME).getString(Constants.CLIENT_MODULE_CONTEXT_KEY);

   private static final String SERVER_MODULE_CONTEXT = ResourceBundle.getBundle(Constants.CONFIG_BUNDLE_NAME).getString(Constants.SERVER_MODULE_CONTEXT_KEY);

   private static final int PRODUCTS_INITIAL_SIZE = 5;

   @Autowired
   @Qualifier("productServiceProxy")
   private ProductService productService;

   private static Server server;

   /**
    * @throws Throwable
    */
   @BeforeClass
   public static void beforeClass() throws Throwable {

      server = new Server();

      QueuedThreadPool threadPool = new QueuedThreadPool();
      threadPool.setMaxThreads(100);
      server.setThreadPool(threadPool);

      SelectChannelConnector connector = new SelectChannelConnector();
      connector.setPort(Integer.valueOf(JETTY_PORT));
      connector.setMaxIdleTime(30000);
      connector.setConfidentialPort(8443);
      server.setConnectors(new Connector[] {connector});

      WebAppContext restPocClientWebApp = new WebAppContext();
      restPocClientWebApp.setWar("../rest-poc-client-springmvc/target/rest-poc-client-springmvc.war");
      restPocClientWebApp.setContextPath("/" + CLIENT_MODULE_CONTEXT);
      server.addHandler(restPocClientWebApp);

      WebAppContext restPocServerWebApp = new WebAppContext();
      restPocServerWebApp.setWar("../rest-poc-server/target/rest-poc-server.war");
      restPocServerWebApp.setContextPath("/" + SERVER_MODULE_CONTEXT);
      server.addHandler(restPocServerWebApp);

      server.start();

      server.setStopAtShutdown(true);

      server.setSendServerVersion(true);
   }

   /**
    * @throws Throwable
    */
   @AfterClass
   public static void afterClass() throws Throwable {

      server.stop();
      server.join();

   }

   /**
    * 
    */
   @Before
   public void before() {

      assertNotNull(productService);

      setUpNewProductRepository();

   }

   /**
    * @throws Throwable
    */
   @Test
   public final void testList() throws Throwable {

      List<Product> products = listProducts();

      assertNotNull(products);

      assertEquals(PRODUCTS_INITIAL_SIZE, products.size());

   }

   /**
    * @throws Throwable
    */
   @Test
   public void testAdd() throws Throwable {

      String name = "doliprane";

      String description = "Ce médicament est un antalgique et un antipyrétique qui contient du paracétamol."
            + "\nIl est utilisé pour faire baisser la fièvre et dans le traitement des affections douloureuses.";

      Long id = addProduct(name, description);

      assertNotNull(id);

      Product product = getProduct(id);

      assertNotNull(product);

      assertEquals(name, product.getName());

      assertEquals(description, product.getDescription());
   }

   /**
    * @throws Throwable
    */
   @Test
   public void testFindByDescription() throws Throwable {

      String name = "doliprane";

      String description = "Ce médicament est un antalgique et un antipyrétique qui contient du paracétamol."
            + "\nIl est utilisé pour faire baisser la fièvre et dans le traitement des affections douloureuses.";

      addProduct(name, description);

      assertEquals(PRODUCTS_INITIAL_SIZE + 1, listProducts().size());

      String term = "description";

      assertEquals(PRODUCTS_INITIAL_SIZE, findByDescription(term).size());

   }

   /**
    * @throws Throwable
    */
   @Test
   public void testUpdate() throws Throwable {

      String uri = null;

      String name = "doliprane";

      String description = "Ce médicament est un antalgique et un antipyrétique qui contient du paracétamol."
            + "\nIl est utilisé pour faire baisser la fièvre et dans le traitement des affections douloureuses.";

      Long id = addProduct(name, description);

      assertNotNull(id);

      String newName = "prozac";

      String newDescription = "Ce médicament est un antidépresseur de la famille des inhibiteurs de la recapture de la sérotonine.";

      newDescription += "Il est utilisé chez l'adulte dans le traitement : -des états dépressifs ; \n-des troubles obsessionnels compulsifs ;";

      newDescription += "\n- de la boulimie (en complément d'une psychothérapie). ;";

      uri = "/product/update/" + id;

      Product product = new Product();

      product.setId(id);

      product.setDescription(newDescription);

      product.setName(newName);

      restTemplate.put(BASE_URL + uri, product);

      Product p = getProduct(id);

      assertNotNull(p);

      assertEquals(newName, p.getName());

      assertEquals(newDescription, p.getDescription());
   }

   /**
    * @throws Throwable
    */
   @Test
   public void testDelete() throws Throwable {

      String uri = null;

      String name = "doliprane";

      String description = "Ce médicament est un antalgique et un antipyrétique qui contient du paracétamol."
            + "\nIl est utilisé pour faire baisser la fièvre et dans le traitement des affections douloureuses.";

      Long id = addProduct(name, description);

      assertNotNull(id);

      uri = "/product/delete/" + id;

      restTemplate.delete(BASE_URL + uri);

      uri = "/product/" + id;

      Product product = restTemplate.execute(BASE_URL + uri, HttpMethod.GET, new RequestCallback() {

         @Override
         public void doWithRequest(ClientHttpRequest request) throws IOException {
         }

      }, new ResponseExtractor<Product>() {

         @Override
         public Product extractData(ClientHttpResponse response) throws IOException {

            // TODO : should be 404 ... change server to return 404;
            assertEquals(HttpStatus.OK, response.getStatusCode());

            InputStream body = response.getBody();

            assertNotNull(body);

            List<String> content = IOUtils.readLines(body);

            assertEquals(0, CollectionUtils.size(content));

            return null;

         }

      });

      assertNull(product);

   }

   /**
    * 
    */
   private void setUpNewProductRepository() {

      productService.clear();

      for (int i = 0; i < PRODUCTS_INITIAL_SIZE; i++) {

         Product p = new Product();

         String name = "name" + i;

         String description = "description" + i;

         p.setName(name);

         p.setDescription(description);

         productService.add(p);

      }

   }

   /**
    * @param name
    * @param description
    * @return
    * @throws Throwable
    */
   private Long addProduct(String name, String description) throws Throwable {

      String uri = null;

      uri = "/product/add";

      Product product = new Product();

      product.setName(name);

      product.setDescription(description);

      Long id = restTemplate.postForObject(BASE_URL + uri, product, Long.class);

      return id;

   }

   /**
    * @param id
    * @return
    * @throws Throwable
    */
   private Product getProduct(Long id) throws Throwable {

      String uri = null;

      uri = "/product/" + id;

      Product product = restTemplate.getForObject(BASE_URL + uri, Product.class);

      return product;

   }

   /**
    * @return
    * @throws Throwable
    */
   private List<Product> listProducts() throws Throwable {

      String uri = "/product/list";

      @SuppressWarnings("unchecked")
      List<Product> products = restTemplate.getForObject(BASE_URL + uri, List.class);

      return products;

   }

   /**
    * @param term
    * @return
    * @throws Throwable
    */
   private List<Product> findByDescription(String term) throws Throwable {

      String uri = "/product/find/by/description/term/" + term;

      @SuppressWarnings("unchecked")
      List<Product> products = restTemplate.getForObject(BASE_URL + uri, List.class);

      return products;

   }

}

rest-poc-client-springmvc-test.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
        <property name="locations" value="classpath:config.properties" /> 
    </bean> 

    <jaxws:client id="productServiceProxy"
                  serviceClass="org.diveintojee.poc.rest.domain.services.ProductService"
                  address="${rest-poc-server.url}"/>
                  
    <bean id="httpClientParams" class="org.apache.commons.httpclient.params.HttpClientParams">
        <property name="connectionManagerClass"
                  value="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager"/>
    </bean>
    
    <bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
        <constructor-arg ref="httpClientParams"/>
    </bean>
    <bean id="httpClientFactory" class="org.springframework.http.client.CommonsClientHttpRequestFactory">
        <constructor-arg ref="httpClient"/>
    </bean>

    <bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
        <constructor-arg ref="httpClientFactory"/>

        <property name="messageConverters">
            <list>
                <!-- Default converters -->
                <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>

                <bean id="xmlHttpMessageConverter"
                    class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
                    <constructor-arg>
                        <bean class="org.springframework.oxm.xstream.XStreamMarshaller" />
                    </constructor-arg>
                </bean>
                <bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
                
                <!-- Converter for images -->
                <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
                
            </list>
        </property>
    </bean>

</beans>

Advertisements

4 thoughts on “REST client, CXF server : JAX-RS or SPRING-MVC ?

  1. I actually want to take note of this specific posting, “REST client, CXF server :
    JAX-RS or SPRING-MVC ? | Diving deep into JEE” on
    my personal site. Would you mind if perhaps I reallydo it?
    Thanks ,Agustin

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s