Monday, February 28, 2011

Spring 3: REST Web Service Provider and Client Tutorial (Part 2)

In this tutorial we'll create a Spring MVC REST client that uses Spring 3's RestTemplate. Our client is able to communicate via XML and JSON. It also has basic support for retrieving images. This tutorial is Part 2 of our Spring 3: REST Web Service Provider and Client Tutorial series. If you haven't read Part 1, please read it first (See here).

What is REST in Spring 3?
For a great introduction, please see the following links:
- REST in Spring 3: @MVC
- REST in Spring 3: RestTemplate

What is RestTemplate?
The central class for client-side HTTP access. It simplifies communication with HTTP servers, and enforces RESTful principles. It handles HTTP connections, leaving application code to provide URLs (with possible template variables) and extract results.

Source: Spring 3 Reference: RestTemplate

Development

Our client application is unique because it doesn't need a Service layer. We only need the Domain and the Controller layers. We also need a couple of JSP pages to display the records.

Domain Layer

We'll be declaring two domain objects: Person and PersonList. These are the same class declarations we had in the REST provider application.

Person.java
package org.krams.tutorial.domain;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="person")
public class Person {

 private Long id;
 private String firstName;
 private String lastName;
 private Double money;
 
 public Long getId() {
  return id;
 }
 public void setId(Long id) {
  this.id = id;
 }
 public String getFirstName() {
  return firstName;
 }
 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }
 public String getLastName() {
  return lastName;
 }
 public void setLastName(String lastName) {
  this.lastName = lastName;
 }
 public Double getMoney() {
  return money;
 }
 public void setMoney(Double money) {
  this.money = money;
 }
}
Person is a simple POJO consisting of three properties. Notice we've annotated the class name with @XmlRootElement(name="person"). Its purpose is to help JAXB (the one responsible for marshalling/unmarshalling to XML) determine the root of our POJO.

PersonList.java
package org.krams.tutorial.domain;

import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="persons")
public class PersonList {

 @XmlElement(required = true)
 public List<person> data;

 @XmlElement(required = false)
 public List<person> getData() {
  return data;
 }

 public void setData(List<person> data) {
  this.data = data;
 }
}
PersonList is another simple POJO. It's purpose is to wrap a list of Person objects.

Ideally we should be able to return a List instead of a PersonList. However, JAXB has difficulties processing java.util.List. A simple Google search verifies this unwanted behavior, for example, http://stackoverflow.com/questions/298733/java-util-list-is-an-interface-and-jaxb-cant-handle-interfaces

To resolve this issue with JAXB, we wrap our List with another object. To learn more about JAXB please visit the following link: http://download.oracle.com/javaee/5/tutorial/doc/bnazf.html

Controller Layer

The controller layer is the most important section of the client application because here's where we communicate with the REST provider. It's also responsible for displaying the JSP pages.

ProviderController.java
package org.krams.tutorial.controller;

import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.krams.tutorial.domain.Person;
import org.krams.tutorial.domain.PersonList;
import org.krams.tutorial.util.Writer;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletResponse;

/**
 * REST service client
 */
@Controller
public class RestClientController {

 protected static Logger logger = Logger.getLogger("controller");
 
 private RestTemplate restTemplate = new RestTemplate();
 
 /**
  * Retrieves an image from the REST provider
  * and writes the response to an output stream.
  */
 @RequestMapping(value = "/getphoto", method = RequestMethod.GET)
 public void getPhoto(@RequestParam("id") Long id, HttpServletResponse response) {
  logger.debug("Retrieve photo with id: " + id);
  
  // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.IMAGE_JPEG);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  HttpEntity<String> entity = new HttpEntity<String>(headers); 
  
  // Send the request as GET
  ResponseEntity<byte[]> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/person/{id}", HttpMethod.GET, entity, byte[].class, id);
  
  // Display the image
  Writer.write(response, result.getBody());
 }
 
 /**
  * Retrieves all records from the REST provider
  * and displays the records in a JSP page
  */
 @RequestMapping(value = "/getall", method = RequestMethod.GET)
 public String getAll(Model model) {
  logger.debug("Retrieve all persons");
  
  // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_XML);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  HttpEntity<Person> entity = new HttpEntity<Person>(headers);

  // Send the request as GET
  try {
   ResponseEntity<PersonList> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/persons", HttpMethod.GET, entity, PersonList.class);
   // Add to model
   model.addAttribute("persons", result.getBody().getData());
   
  } catch (Exception e) {
   logger.error(e);
  }
  
  // This will resolve to /WEB-INF/jsp/personspage.jsp
  return "personspage";
 }
 
 /**
  * Retrieves a single record from the REST provider
  * and displays the result in a JSP page
  */
 @RequestMapping(value = "/get", method = RequestMethod.GET)
 public String getPerson(@RequestParam("id") Long id, Model model) {
  logger.debug("Retrieve person with id: " + id);
  
  // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_XML);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  HttpEntity<Person> entity = new HttpEntity<Person>(headers);

  // Send the request as GET
  try {
   ResponseEntity<Person> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/person/{id}", HttpMethod.GET, entity, Person.class, id);
   // Add to model
   model.addAttribute("person", result.getBody());
   
  } catch (Exception e) {
   logger.error(e);
  }
  
  // This will resolve to /WEB-INF/jsp/getpage.jsp
  return "getpage";
 }
 
 /**
     * Retrieves the JSP add page
     */
 @RequestMapping(value = "/add", method = RequestMethod.GET)
 public String getAddPage(Model model) {
  logger.debug("Received request to show add page");

  // Create new Person and add to model
  // This is the formBackingOBject
  model.addAttribute("personAttribute", new Person());

  // This will resolve to /WEB-INF/jsp/addpage.jsp
  return "addpage";
 }
 
 /**
  * Sends a new record to the REST provider
  * based on the information submitted from the JSP add page.
  */
 @RequestMapping(value = "/add", method = RequestMethod.POST)
 public String addPerson(@ModelAttribute("personAttribute") Person person,
       Model model) {
  logger.debug("Add new person");
  
  // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_XML);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  // Pass the new person and header
  HttpEntity<Person> entity = new HttpEntity<Person>(person, headers);

  // Send the request as POST
  try {
   ResponseEntity<Person> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/person", HttpMethod.POST, entity, Person.class);
  } catch (Exception e) {
   logger.error(e);
  }
  
  // This will resolve to /WEB-INF/jsp/resultpage.jsp
  return "resultpage";
 }
 
 /**
     * Retrieves the JSP update page
     */
    @RequestMapping(value = "/update", method = RequestMethod.GET)
    public String getUpdatePage(@RequestParam(value="id", required=true) Integer id,  
              Model model) {
     logger.debug("Received request to show edit page");
    
     // Retrieve existing Person and add to model
     // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_XML);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  HttpEntity<Person> entity = new HttpEntity<Person>(headers);

  // Send the request as GET
  try {
   ResponseEntity<Person> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/person/{id}", HttpMethod.GET, entity, Person.class, id);
   // Add to model
   model.addAttribute("personAttribute", result.getBody());
   
  } catch (Exception e) {
   logger.error(e);
  }
     
     // This will resolve to /WEB-INF/jsp/updatepage.jsp
     return "updatepage";
 }
 
 /**
  * Sends an update request to the REST provider
  * based on the information submitted from the JSP update page.
  */
    @RequestMapping(value = "/update", method = RequestMethod.POST)
 public String updatePerson(@ModelAttribute("personAttribute") Person person,
      @RequestParam(value="id",  required=true) Long id,
      Model model) {
  logger.debug("Update existing person");
  
  // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_XML);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  // Pass the new person and header
  HttpEntity<Person> entity = new HttpEntity<Person>(person, headers);
  
  // Send the request as PUT
  ResponseEntity<String> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/person/{id}", HttpMethod.PUT, entity, String.class, id);

  // This will resolve to /WEB-INF/jsp/resultpage.jsp
  return "resultpage";
    }
    
    /**
  * Sends a delete request to the REST provider
  */
    @RequestMapping(value = "/delete", method = RequestMethod.GET)
 public String deletePerson(@RequestParam("id") Long id,
          Model model) {
     logger.debug("Delete existing person");
     
  // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_XML);
  
  // Prepare header
     HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  HttpEntity<String> entity = new HttpEntity<String>(headers); 
  
  // Send the request as DELETE
  ResponseEntity<String> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/person/{id}", HttpMethod.DELETE, entity, String.class, id);
  
  // This will resolve to /WEB-INF/jsp/resultpage.jsp
  return "resultpage";
    }
}
Notice our controller is our typical Spring MVC 3 controller.

Let's dissect our controller and analyze each methods.

getPhoto() method

The getPhoto() method retrieves an image as a byte array from the REST provider. It displays the image by writing it to the output stream using a helper class: Writer
/**
  * Retrieves an image from the REST provider
  * and writes the response to an output stream.
  */
 @RequestMapping(value = "/getphoto", method = RequestMethod.GET)
 public void getPhoto(@RequestParam("id") Long id, HttpServletResponse response) {
  logger.debug("Retrieve photo with id: " + id);
  
  // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.IMAGE_JPEG);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  HttpEntity<String> entity = new HttpEntity<String>(headers); 
  
  // Send the request as GET
  ResponseEntity<byte[]> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/person/{id}", HttpMethod.GET, entity, byte[].class, id);
  
  // Display the image
  Writer.write(response, result.getBody());
 }

Writer.java
package org.krams.tutorial.util;

import java.io.ByteArrayOutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;

/**
 * Writes the report to the output stream
 * 
 * @author Krams at {@link http://krams915@blogspot.com}
 */
public class Writer {

 private static Logger logger = Logger.getLogger("service");
 /**
  * Writes the report to the output stream
  */
 public static void write(HttpServletResponse response, ByteArrayOutputStream bao) {
  
  logger.debug("Writing report to the stream");
  try {
   // Retrieve the output stream
   ServletOutputStream outputStream = response.getOutputStream();
   // Write to the output stream
   bao.writeTo(outputStream);
   // Flush the stream
   outputStream.flush();
   // Close the stream
   outputStream.close();

  } catch (Exception e) {
   logger.error("Unable to write report to the output stream");
  }
 }
 
 /**
  * Writes the report to the output stream
  */
 public static void write(HttpServletResponse response, byte[] byteArray) {
  
  logger.debug("Writing report to the stream");
  try {
   // Retrieve the output stream
   ServletOutputStream outputStream = response.getOutputStream();
   // Write to the output stream
   outputStream.write(byteArray);
   // Flush the stream
   outputStream.flush();
   // Close the stream
   outputStream.close();
   
  } catch (Exception e) {
   logger.error("Unable to write report to the output stream");
  }
 } 
}

To call this method, we have to use the following URL:
http://localhost:8081/spring-rest-client/krams/getphoto?id=1
Notice the port number is 8081. That's because I'm using two versions of Tomcat. For the REST provider, I use port 8080. For the REST client, I use port 8081. Depending on how you setup your server, please modify the URL accordingly.

Running the URL displays the following image:

I think you know who this person is (and it just so happen this is the photo I have in my desktop). Notice whatever id you use the application will show the same image. That's because the provider uses a fix image from the classpath. Anyway the point of this exercise is how to retrieve a byte array using RestTemplate.

getAll() method

The getAll() method sends a request to retrieve all records from the REST provider. Once the result has arrived, it is added to the model to be displayed in a JSP page.

/**
  * Retrieves all records from the REST provider
  * and displays the records in a JSP page
  */
 @RequestMapping(value = "/getall", method = RequestMethod.GET)
 public String getAll(Model model) {
  logger.debug("Retrieve all persons");
  
  // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_XML);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  HttpEntity<Person> entity = new HttpEntity<Person>(headers);

  // Send the request as GET
  try {
   ResponseEntity<PersonList> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/persons", HttpMethod.GET, entity, PersonList.class);
   // Add to model
   model.addAttribute("persons", result.getBody().getData());
   
  } catch (Exception e) {
   logger.error(e);
  }
  
  // This will resolve to /WEB-INF/jsp/personspage.jsp
  return "personspage";
 }

To call this method, we have to use the following URL:
http://localhost:8081/spring-rest-client/krams/getall

Running the URL shows the following page:

getPerson() method

The getPerson() method retrieves a single record based on the id from the REST provider. Once the result has arrived, it is added to the model to be displayed in a JSP page.

/**
  * Retrieves a single record from the REST provider
  * and displays the result in a JSP page
  */
 @RequestMapping(value = "/get", method = RequestMethod.GET)
 public String getPerson(@RequestParam("id") Long id, Model model) {
  logger.debug("Retrieve person with id: " + id);
  
  // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_XML);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  HttpEntity<Person> entity = new HttpEntity<Person>(headers);

  // Send the request as GET
  try {
   ResponseEntity<Person> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/person/{id}", HttpMethod.GET, entity, Person.class, id);
   // Add to model
   model.addAttribute("person", result.getBody());
   
  } catch (Exception e) {
   logger.error(e);
  }
  
  // This will resolve to /WEB-INF/jsp/getpage.jsp
  return "getpage";
 }

To call this method, we have to use the following URL:
http://localhost:8081/spring-rest-client/krams/get?id=1
Alternatively we can click the Get link from the getAll page.

Running the URL shows the following page:

getAddPage() and addPerson() methods

The getAddPage() method returns a JSP form where the user can add a new record.

     /**
     * Retrieves the JSP add page
     */
 @RequestMapping(value = "/add", method = RequestMethod.GET)
 public String getAddPage(Model model) {
  logger.debug("Received request to show add page");

  // Create new Person and add to model
  // This is the formBackingOBject
  model.addAttribute("personAttribute", new Person());

  // This will resolve to /WEB-INF/jsp/addpage.jsp
  return "addpage";
 }

To call this method, we have to use the following URL:
http://localhost:8081/spring-rest-client/krams/add?id=1
Alternatively we can click the Add link from the getAll page

Running the URL shows the following page:

When the form is submitted, the addPerson() method takes control. Its purpose is to send a new record by sending a POST request to the REST provider.

/**
  * Sends a new record to the REST provider
  * based on the information submitted from the JSP add page.
  */
 @RequestMapping(value = "/add", method = RequestMethod.POST)
 public String addPerson(@ModelAttribute("personAttribute") Person person,
       Model model) {
  logger.debug("Add new person");
  
  // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_XML);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  // Pass the new person and header
  HttpEntity<Person> entity = new HttpEntity<Person>(person, headers);

  // Send the request as POST
  try {
   ResponseEntity<Person> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/person", HttpMethod.POST, entity, Person.class);
  } catch (Exception e) {
   logger.error(e);
  }
  
  // This will resolve to /WEB-INF/jsp/resultpage.jsp
  return "resultpage";
 }
To see the new record, please refresh the getAll page.

getUpdatePage() and updatePerson() methods

The getUpdatePage() method returns a JSP form where the user can edit an existing record.

 /**
     * Retrieves the JSP update page
     */
    @RequestMapping(value = "/update", method = RequestMethod.GET)
    public String getUpdatePage(@RequestParam(value="id", required=true) Integer id,  
              Model model) {
     logger.debug("Received request to show edit page");
    
     // Retrieve existing Person and add to model
     // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_XML);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  HttpEntity<Person> entity = new HttpEntity<Person>(headers);

  // Send the request as GET
  try {
   ResponseEntity<Person> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/person/{id}", HttpMethod.GET, entity, Person.class, id);
   // Add to model
   model.addAttribute("personAttribute", result.getBody());
   
  } catch (Exception e) {
   logger.error(e);
  }
     
     // This will resolve to /WEB-INF/jsp/updatepage.jsp
     return "updatepage";
 }

To call this method, we have to use the following URL:
http://localhost:8081/spring-rest-client/krams/update?id=1
Alternatively we can click the Edit link from the getAll page

Running the URL shows the following page:

When the form is submitted, the updatePerson() method takes control. Its purpose is to send an updated record by sending a PUT request to the REST provider.

/**
  * Sends an update request to the REST provider
  * based on the information submitted from the JSP update page.
  */
    @RequestMapping(value = "/update", method = RequestMethod.POST)
 public String updatePerson(@ModelAttribute("personAttribute") Person person,
      @RequestParam(value="id",  required=true) Long id,
      Model model) {
  logger.debug("Update existing person");
  
  // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_XML);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  // Pass the new person and header
  HttpEntity<Person> entity = new HttpEntity<Person>(person, headers);
  
  // Send the request as PUT
  ResponseEntity<String> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/person/{id}", HttpMethod.PUT, entity, String.class, id);

  // This will resolve to /WEB-INF/jsp/resultpage.jsp
  return "resultpage";
    }
To see updated record, please refresh the getAll page.

deletePerson() method

The deletePerson() method sends a DELETE request to delete an existing record based on the submitted id.

    /**
  * Sends a delete request to the REST provider
  */
    @RequestMapping(value = "/delete", method = RequestMethod.GET)
 public String deletePerson(@RequestParam("id") Long id,
          Model model) {
     logger.debug("Delete existing person");
     
  // Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_XML);
  
  // Prepare header
     HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  HttpEntity<String> entity = new HttpEntity<String>(headers); 
  
  // Send the request as DELETE
  ResponseEntity<String> result = restTemplate.exchange("http://localhost:8080/spring-rest-provider/krams/person/{id}", HttpMethod.DELETE, entity, String.class, id);
  
  // This will resolve to /WEB-INF/jsp/resultpage.jsp
  return "resultpage";
    }

To call this method, we have to use the following URL:
http://localhost:8081/spring-rest-client/krams/delete?id=1
Alternatively we can click the Delete link from the getAll page

When you run the URL it will automatically send a request. To see the results, please refresh the getAll page.

Configuration

The application's configuration is quite trivial. It's just a basic Spring MVC configuration. To spare some space, I will not post the XML configurations here. Instead, you can look at them by checking the source code at the end of this tutorial.

Considerations

Notice in the header of each request we set the media type to APPLICATION_XML. We can equally change it to APPLICATION_JSON to accept JSON objects.

APPLICATION_XML
// Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_XML);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  // Pass the new person and header
  HttpEntity<Person> entity = new HttpEntity<Person>(person, headers);

APPLICATION_JSON
// Prepare acceptable media type
  List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
  acceptableMediaTypes.add(MediaType.APPLICATION_JSON);
  
  // Prepare header
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(acceptableMediaTypes);
  // Pass the new person and header
  HttpEntity<Person> entity = new HttpEntity<Person>(person, headers);

For JSON to work, you need to have the Jackson library in your classpath. Make sure to check the pom.xml!

Conclusion

That's it. We've managed to create a REST client using Spring 3's RestTemplate. We've exchanged information with the provider via XML and displayed the result in a JSP page using Spring MVC.

Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring-rest-guide/

You can download the project as a Maven build. Look for the spring-rest-client.zip in the Download sections.

You can run the project directly using an embedded server via Maven.
For Tomcat: mvn tomcat:run
For Jetty: mvn jetty:run

If you want to learn more about Spring MVC and integration with other technologies, feel free to read my other tutorials in the Tutorials section.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring 3: REST Web Service Provider and Client Tutorial (Part 2) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share