Sunday, January 04, 2015

What Are RESTful Web Services? or RESTful Web Services Tutorial or Building a RESTful Web Service or RESTful Web Services with Java


The below article will show examples of building Simple RESTful Web Services, Restful web service for file upload, Restful web service for file download

  • Building RESTful Web Services with JAX-RS using Jboss rest easy API.
  • RESTful Web Services with Java
  • RESTful Java client with Jboss RESTEasy client framework
  • RESTEasy client for consuming REST APIs
  • Pure java client to invoke Restful web service
  • Using Firefox rest client for testing restful web services.
  • RestEasy client for file upload
  • RestEasy client for file download


I used Jboss rest easy API, You can also use Jersey api to build restful web services.
Lets say we need a restful web service which does the following

  • Employee service - To Create,Get,Update and Delete an employee object.
  • File Service - To upload and download a file.
  • Resteasy client  to download a file (ZIP, PDF...etc)
  • Resteasy client  to upload files (ZIP, PDF...etc)

Java code for building Employee Service

Lets build a java object for Employee object which is JAXB enabled. Let use JAXB annotations.

package com.rama.restful;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/*****
 *   XmlAccessType.NONE --> Tell JAXB not use field name as it's in the class. 
 *                         Instead we will give the names that as to be used  when generating XML. 
 *    
 *     Ideally keep this in common package so that you can share between java client and server                    
 ***/
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "employee")
public class Employee {


    @XmlAttribute(name = "id")
    private int Id;
 
    @XmlAttribute(name="uri")
    private String uri;
 
    @XmlElement(name = "firstName")
    private String firstName;
 
    @XmlElement(name = "lastName")
    private String lastName;
    
 public int getId() {
  return Id;
 }
 public void setId(int id) {
  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 String getUri() {
  return uri;
 }
 public void setUri(String uri) {
  this.uri = uri;
 }
 
 
 
}
A list of employee's is wrapped in a Employees Object as shown below.

package com.rama.restful;

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

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "employees")
public class Employees {

 //Will embed every object in the list with <employee> tag. 
 @XmlElement(name="employee") 
 private List<Employee> employees = new ArrayList<Employee>();

 public List<Employee> getEmployees() {
  return employees;
 }

 public void setEmployees(List<Employee> employees) {
  this.employees = employees;
 }
}

Now lets create EmployeeService which is the restful web service which will use the objects we created above.We will be adding the following methods which can be invoked on this web service.

  • public Response createEmployee(..)
  • public Response deleteEmployee(..)
  • public Employees getAllemployees()
  • public Employee getEmployeeById(..) - Returns XML respsonse.
  • public Employee getEmployeeByJsonId(..) - Returns JSON response
  • public EmployeeService getServiceInfo() - Returns basic info about this webservice
  • public Employee updateEmployee(..)
Frankly we don't need JAXB annotations (@XmlAccessorType and @XmlRootElement), Since getServiceInfo returns some info on this object as XML we added this tags to this class as well.
As you see the comments on each section you will see that each method is self explanatory.
Each method is marked by annotations which indicate the 
  • @Path - The url you need to access this method 
  • @GET,@PUT,@POST - Indicating the HTTP method type you need to use to access the give method
  • @Consumes -  Indicates if the method accepts XML or JSON
  • @Produces - Indicates if the method returns XML or JSON response.
These are key annotations that you need to know to build restful web services.

package com.rama.restful;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
* 
*  To test use this URL 
*  http://localhost:8081/RESTfulDemoApplication/employeeService/employees  ( Your port could be different)
*
**/
//For  fun we can make even this class JAXB enabled to list out the services...
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "employeeService")

@Path("/employeeService")
public class EmployeeService {
 
 @XmlElement(name = "employees")
 private String uri1 = "/employeeService/employees";
 
 
 
 public String getUri1() {
  return uri1;
 }

 public void setUri1(String uri1) {
  this.uri1 = uri1;
 }

 
 
 /**
  * Use the below url to access this
  * http://localhost:8081/RESTfulDemoApplication/employeeService ( Your port could be different)
  * 
  * 
  * OUTPUT: Just prints 
  * 
  * <employeeService>
  *    <employees>/employeeService/employees</employees>
  *    
  * </employeeService>
  * 
  **/
 @GET
 @Path("/")
 @Produces("text/xml;charset=UTF-8")
 public EmployeeService getServiceInfo() {
  return new EmployeeService();
 }

 
 
 
 /**
  * Use the below url to access this
  * http://localhost:8081/RESTfulDemoApplication/employeeService/employees ( Your port could be different)
  * 
  * OUTPUT:
  * 
   *  <employees>
    <employee id="1" uri="/employeeService/employees/1">
     <firstName>Rama</firstName>
     <lastName>chandra</lastName>
    </employee>
    <employee id="2" uri="/employeeService/employees/2">
     <firstName>John</firstName>
     <lastName>Smith</lastName>
    </employee>
   </employees>
  * 
  * 
  * 
  **/
 @GET
 @Path("/employees")
 @Produces("text/xml;charset=UTF-8")
 public Employees getAllemployees() {
  
  //Ideally you will go to database to pull this info..
  
  Employee employee1 = new Employee();
  employee1.setId(1);
  employee1.setFirstName("rama");
  employee1.setLastName("chandra");
  employee1.setUri("/employeeService/employees/1");

  Employee employee2 = new Employee();
  employee2.setId(2);
  employee2.setFirstName("John");
  employee2.setLastName("smith");
  employee2.setUri("/employeeService/employees/2");

  Employees employees = new Employees();
  employees.setEmployees(new ArrayList<Employee>());
  employees.getEmployees().add(employee1);
  employees.getEmployees().add(employee2);

  return employees;
 }

 /**
  * Use the below url to access this
  * http://localhost:8081/RESTfulDemoApplication/employeeService/employees/123 ( Your port could be different)
  * 
  * 
  * OUTPUT:
  *   <employee id="123" uri="/employeeService/employees/123">
   <firstName>demo</firstName>
   <lastName>employee</lastName>
   </employee>
  * 
  **/
 
 @GET
 @Path("/employees/{id}")
 @Produces("text/xml;charset=UTF-8")
 public Employee getEmployeeById(@PathParam("id") int id) {
  
  //Ideally you will go to database to pull this info..
  
  Employee employee = new Employee();
  employee.setId(id);
  employee.setFirstName("demo");
  employee.setLastName("employee");
  employee.setUri("/employeeService/employees/" + id);
  return employee;
 }

 
 
 /**
  * Use the below url to access this
  * http://localhost:8081/RESTfulDemoApplication/employeeService/employeesjson/123 ( Your port could be different)
  * 
  * OUTPUT:
  * 
   {
      "uri": "/employeeService/employees/123",
      "firstName": "demo",
      "lastName": "employee",
      "id": 123
    }

  **/
 @GET
 @Path("/employeesjson/{id}")
 @Produces("application/json")
 public Employee getEmployeeByJsonId(@PathParam("id") int id) {
  
  /* Pretend you are querying data base using this id and returning the results */
  
  Employee employee = new Employee();
  employee.setId(id);
  employee.setFirstName("demo");
  employee.setLastName("employee");
  employee.setUri("/employeeService/employees/" + id);
  return employee;
 }
 
 
 /**
  * Use the below url to access this
  * http://localhost:8081/RESTfulDemoApplication/employeeService/employeesjson2/123 ( Your port could be different)
  * 
  * OUTPUT:
   {
   
       "uri": "/employeeService/employees/123",
       "firstName": "Ram",
       "lastName": "Chandra",
       "id": 123
   }
  * 
  **/
 @GET
 @Path("/employeesjson2/{id}")
 @Produces("application/json")
    public Response getEmployeeById(@PathParam("id") Integer id)
    {
  //Pretend you are querying from database.
        Employee employee = new Employee();
        employee.setId(id);
        employee.setFirstName("Ram");
        employee.setLastName("Chandra");
        employee.setUri("/employeeService/employees/" + id);
        //Another way to send the response
        return Response.status(200).entity(employee).build();
    }
  
 
 /**
  * Use the below url to access this
  * http://localhost:8081/RESTfulDemoApplication/employeeService/employees ( Your port could be different)
  * Make sure you send the following custom http headers.
  * HTTP Headers:
  * =============
  *   Content-Type: text/xml
  *   allow-admin:true
  * 
  * 
  * And in the body the pay load:
  * ===================
  * 
  *    <employee id="1" uri="/employeeService/employees/1">
    <firstName>rama</firstName>
    <lastName>chandra</lastName>
   </employee>

  *  Http-Method:
  *   POST
  *   
  *   I used fire fox rest client add on  for testing.
  **/
 
 @POST
 @Path("/employees")
 @Consumes("text/xml;charset=UTF-8")
 @Produces("text/xml;charset=UTF-8")
 public Response createEmployee(Employee employee,@DefaultValue("false") @QueryParam("allow-admin") boolean allowAdmin)
   throws URISyntaxException {
  System.out.println(employee.getFirstName());
  System.out.println(employee.getLastName());
  return Response.status(201).contentLocation(new URI("/employeeService/employees/123")).build();
 }

 
 /**
  * Use the below url to update (Put method)
  * http://localhost:8081/RESTfulDemoApplication/employeeService/employees ( Your port could be different)
  * 
  *    Input:
  *    <employee id="1" uri="/employeeService/employees/1">
    <firstName>rama</firstName>
    <lastName>chandra</lastName>
   </employee>
  Set HTTP Headers:
  * ===================
  *   Content-Type: text/xml
  * 
  *   HTTP-Method : PUT 
  *   I used fire fox rest client add on  for testing.
  * 
  **/
 @PUT
 // @Path("/employees/{id: [0-9]*}")
 @Path("/employees/{id}")
 @Produces("text/xml;charset=UTF-8")
 @Consumes("text/xml;charset=UTF-8")
 public Employee updateEmployee(@PathParam("id") int id, Employee employee)throws URISyntaxException {
  employee.setId(id);
  employee.setFirstName(employee.getFirstName() + "updated");
  return employee;
 }

 
 
 /*****
  * Use the below url to delete (Delete method)
  * http://localhost:8081/RESTfulDemoApplication/employeeService/employees/1 ( Your port could be different)
  *   where 1 is the id.
  ****/
 @DELETE
 @Path("/employees/{id}")
 public Response deleteEmployee(@PathParam("id") int id)
   throws URISyntaxException {
  System.out.println(" Deleteing employee with id"+ id);
  //Add your magic code to delete 
  return Response.status(200).build();
 }
 
 
}


So how does rest webservice knows that EmployeeService is a Webservice. Well you nee to register that class as shown below.


package com.rama.restful;


import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
 

@ApplicationPath("/")
public class ApplicationConfig extends Application {
    @SuppressWarnings("unchecked")
    public Set<Class<?>> getClasses() {
     List<Class<?>> registeredServiceClassList = Arrays.asList(
       RESTEasyFileService.class,
          EmployeeService.class);
        return new HashSet<Class<?>>(registeredServiceClassList);
    }
}

And in you web.xml add the following



<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
 <display-name>Archetype Created Web Application</display-name>

 <context-param>
  <param-name>resteasy.scan</param-name>
  <param-value>true</param-value>
 </context-param>
 

 <listener>
  <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
 </listener>
 
 <servlet>
  <servlet-name>resteasy-servlet</servlet-name>
  <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
 </servlet>


 <servlet-mapping>
  <servlet-name>resteasy-servlet</servlet-name>
  <url-pattern>/*</url-pattern>
 </servlet-mapping>
</web-app>
This is all you need to set up the basic restful web service.

Now I will show you how to

Upload/Download File using RESTful Web service


In the same package where we added Employeeservice.java , add your RESTEasyFileService.java.
Needless to say you need to register this class with ApplicationConfig .java class as described above.

RESTEasyFileService.java

package com.rama.restful;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;

/**
 * 
 *   A simple class which you can use to upload files 
 *   or down load files..
 *   Source : 
 *     http://examples.javacodegeeks.com/enterprise-java/rest/resteasy/resteasy-file-upload-example/
 *   (Thanks to Nikos Maravitsas for File upload example)
 *     
 */
/**
 * @author twreddy
 *
 */
@Path("/files")
public class RESTEasyFileService {

 private static final String SERVER_UPLOAD_LOCATION_FOLDER = "C://RestFileUploadTest//";
 //Using same folder for testing ...
 private static final String SERVER_DOWNLOAD_LOCATION_FOLDER = "C://RestFileUploadTest//";  
 
 
 @GET
 @Path("/")
 @Produces("text/xml;charset=UTF-8")
 public String getServiceInfo() {
  return "<services>/upload" +
    "  For Upload use : http://localhost:8081/RESTfulDemoApplication/files/upload     Your port may differ \n" +
    "  For downloads use : http://localhost:8081/RESTfulDemoApplication/files/download/SpringAnnontationsCheatSheet.pdf  \n" +
    "  where SpringAnnontationsCheatSheet.pdf is the file you have on your server at SERVER_DOWNLOAD_LOCATION_FOLDER . You can use a different file \n" +
    "</services>";
 }
 
 
 
 /**
  *  Method that handles file Upload.
  *  
  *  Use sample html page to upload . The main content of the html page should look like this 
  *  
  *  
   <form action="http://localhost:8081/RESTfulDemoApplication/files/upload" method="post" enctype="multipart/form-data">
    <p>
     Select a file : <input type="file" name="file" size="50" />
    </p>
    <input type="submit" value="Upload It" />
   </form>
 
  *  
  **/
 @POST
 @Path("/upload")
 @Consumes("multipart/form-data")
 public Response uploadFile(MultipartFormDataInput input) {

  String fileName = "";

  Map<String, List<InputPart>> formParts = input.getFormDataMap();

  List<InputPart> inPart = formParts.get("file");

  for (InputPart inputPart : inPart) {

   try {

    // Retrieve headers, read the Content-Disposition header to
    // obtain the original name of the file
    MultivaluedMap<String, String> headers = inputPart.getHeaders();
    fileName = parseFileName(headers);
    // Handle the body of that part with an InputStream
    InputStream istream = inputPart.getBody(InputStream.class, null);
    fileName = SERVER_UPLOAD_LOCATION_FOLDER + fileName;
    saveFile(istream, fileName);

   } catch (IOException e) {
    e.printStackTrace();
   }

  }

  String output = "File saved to server location : " + fileName;

  return Response.status(200).entity(output).build();
 }

 
  
 /**
  *
  * http://localhost:8081/RESTfulDemoApplication/files/download/Test.pdf 
  * Where Test.pdf is the document I have stored under SERVER_DOWNLOAD_LOCATION_FOLDER path.
  * 
  */
 @GET
 @Path("/download/{fileName}")
 @Produces(MediaType.APPLICATION_OCTET_STREAM)
 public Response getFile(@PathParam("fileName") String fileName) {
     File file = new File(SERVER_DOWNLOAD_LOCATION_FOLDER+fileName);
     ResponseBuilder response = Response.ok((Object) file);
     response.header("Content-Disposition","attachment; filename="+fileName);
      return response.build();

 }
 
 
 /*
  *  Content-Disposition: form-data; name="file"; filename="AVD1.png"
  Content-Type: image/png

  */
 // Parse Content-Disposition header to get the original file name
 private String parseFileName(MultivaluedMap<String, String> headers) {
  String[] contentDispositionHeader = headers.getFirst("Content-Disposition").split(";");
  for (String name : contentDispositionHeader) {
   if ((name.trim().startsWith("filename"))) {
    String[] tmp = name.split("=");
    String fileName = tmp[1].trim().replaceAll("\"", "");
    return fileName;
   }
  }
  return "defaultFileName";
 }

 // save uploaded file to a defined location on the server
 private void saveFile(InputStream uploadedInputStream, String serverLocation) {

  try {
   OutputStream outpuStream = new FileOutputStream(new File(
     serverLocation));
   int read = 0;
   byte[] bytes = new byte[1024];

   outpuStream = new FileOutputStream(new File(serverLocation));
   while ((read = uploadedInputStream.read(bytes)) != -1) {
    outpuStream.write(bytes, 0, read);
   }
   outpuStream.flush();
   outpuStream.close();
  } catch (IOException e) {

   e.printStackTrace();
  }
 }
}

So this code now can handle both upload and download.

You can download the above server side Restful web service code at 


Rest easy web service clients

In your client package better to copy Employee.java before you add this client code.

Pure Java Restful Web service  Client

This code shows a simple java client that invokes getEmployee method  and prints the XML.

package com.rama.rest.ws.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import com.rama.restful.Employee;


/**
 * 
 * Pure java client example to test EmployeeService
 * @author twreddy
 *
 */
public class PureJavaClient  {
 public static void main(String[] args)throws Exception {
  try {
   getEmployeeByIDAsXML();

  } catch (MalformedURLException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  } 
 }
 
  
 private static void getEmployeeByIDAsXML()throws ProtocolException, IOException, JAXBException {
  
  // Not really a good idea to openconnection for each Request...
  URL url = new URL("http://localhost:8081/RESTfulDemoApplication/employeeService/employees/1");
  HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  
  conn.setRequestProperty("Content-Type", "text/plain; charset=utf-8");
  conn.setRequestMethod("GET");
  
  if (conn.getResponseCode() != 200) {
   throw new RuntimeException("Failed : HTTP error code : "+ conn.getResponseCode());
  }

  BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
  String responseStr = br.readLine();
  System.out.println("Response :"+responseStr);
  conn.disconnect();

  JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);
  Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
  Employee user = (Employee) jaxbUnmarshaller.unmarshal(new StringReader(responseStr));

  System.out.println(user.getId());
  System.out.println(user.getFirstName());
  System.out.println(user.getLastName());
 }
}

Jboss rest easy client

Here is the Jboss rest easy client API. Here all you need is to define an interface which more or less matches you webservice method signatures and then create Proxy using the Interface.
Don't worry once you see the below code it will be more clear.
More info @ 


Lets call the Rest easy client for EmployeeService as EmployeeServiceRestfulClient.java 

package com.rama.rest.ws.client;

import java.net.URISyntaxException;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

/**
 * 
 * Restful Client  which will be used by 
 * org.jboss.resteasy.client.ProxyFactory.
 * 
 * See  RestfulClientTest.java to see how to use this class.
 * 
 * BASEURL : http://localhost:8081/RESTfulDemoApplication/employeeService
 *   (your port may be different)
 * @author twreddy
 *
 */
public interface EmployeeServiceRestfulClient {

  @GET
     @Path("/")
     @Produces("text/xml;charset=UTF-8")
     String getServiceInfo();
  
  @GET
  @Path("/employees")
  @Produces("text/xml;charset=UTF-8")
  public String getAllemployees();
  
  
 @GET
 @Path("/employees/{id}")
 @Produces("text/xml;charset=UTF-8")
 public String getEmployeeById(@PathParam("id") int id);
 
 
 @GET
 @Path("/employeesjson/{id}")
 @Produces("application/json")
 public String getEmployeeByJsonId(@PathParam("id") int id);
 
 
 @GET
 @Path("/employeesjson2/{id}")
 @Produces("application/json")
    public Response getEmployeeById(@PathParam("id") Integer id);
 
 
 @POST
 @Path("/employees")
 @Consumes("text/xml;charset=UTF-8")
 @Produces("text/xml;charset=UTF-8")
 //Notice that we are sending Employee object as XML pay load.
 public Response createEmployee(String employee,@DefaultValue("false") @QueryParam("allow-admin") boolean allowAdmin)
   throws URISyntaxException;
 
 
 @PUT
 // @Path("/employees/{id: [0-9]*}")
 @Path("/employees/{id}")
 @Produces("text/xml;charset=UTF-8")
 @Consumes("text/xml;charset=UTF-8")
 public String updateEmployee(@PathParam("id") int id, String employee);
 
 @DELETE
 @Path("/employees/{id}")
 public Response deleteEmployee(@PathParam("id") int id);
 
}

Lets call the Rest easy client for RESTEasyFileService as RestEasyFileServiceRestfulClient.java 
package com.rama.rest.ws.client;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;

/**
 * @author twreddy
 *  
 *  
 * Restful Client  which will be used by 
 * org.jboss.resteasy.client.ProxyFactory.
 * 
 * See  RestfulClientTest.java to see how to use this class.
 * 
 *  BASE URL: 
 *  http://localhost:8081/RESTfulDemoApplication/files
 */
public interface RestEasyFileServiceRestfulClient {

 
 @GET
 @Path("/")
 @Produces("text/xml;charset=UTF-8")
 public String getServiceInfo();
 
 
 @POST
 @Path("/upload")
 @Consumes("multipart/form-data")
 public Response uploadFile(MultipartFormDataOutput  outPut);
 
 @GET
 @Path("/download/{fileName}")
 @Produces(MediaType.APPLICATION_OCTET_STREAM)
 public Response getFile(@PathParam("fileName") String fileName);
 
}
As you see we hardly have written any code to create the restful rest easy clients. 
Now lets make use of the above Restful clients as shown below.
I added both EmployeeServiceRestfulClient.java and RestEasyFileServiceRestfulClient.java   into same test class.Feel free to have separate testing code for each of them.

RestfulClientTest.java

The key in this class is the line which creates PROXY 
EmployeeServiceRestfulClient client = ProxyFactory.create(EmployeeServiceRestfulClient.class,baseUrl);
I have commented some code intentionally while testing. You can comment or uncomment whichever section you need.

package com.rama.rest.ws.client;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.jboss.resteasy.client.ProxyFactory;
import org.jboss.resteasy.client.core.BaseClientResponse;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;

/**
 * @author twreddy
 *
 * Comment or un comment which ever section you need for testing 
 */
public class RestfulClientTest {

 public static void main(String[] args) throws Exception {
  
  //Employee Service Test 
  String empServiceBaseUrl = "http://localhost:8081/RESTfulDemoApplication/employeeService";
  employeeServiceTest(empServiceBaseUrl);
  
  
  
  //RESTEasyFileService test 
  String fileServiceUrl = "http://localhost:8081/RESTfulDemoApplication/files";
  fileServiceTest(fileServiceUrl);
  
  
  
 }

 

 /**
  *  Employee Service Test . Comment or un comment which ever section you want to test.
  */
 private static void employeeServiceTest(String baseUrl ) {
  //NOTE: Dont re use the same client for different calls. 
  EmployeeServiceRestfulClient client = ProxyFactory.create(EmployeeServiceRestfulClient.class,baseUrl);
  
  /*  Get Employee test 
   
  String response = client.getEmployeeByJsonId(1);
  System.out.println("Response:" + response);
  
  Response responseObj = client.getEmployeeById(new Integer(10));
  System.out.println("Get by id="+ responseObj.getStatus());
  
  */
  
  
  /*  Create Employee  test 
   
  String empStr = "<employee id=\"1\" uri=\"/employeeService/employees/1\"><firstName>rama</firstName><lastName>chandra</lastName></employee>";
  Response responseObjForCreateEmp = client.createEmployee(empStr,true);
  System.out.println("Create Emp ="+responseObjForCreateEmp.getStatus());
  
  */
  
  
  /*  Update Employee test
  
  String empStr = "<employee id=\"1\" uri=\"/employeeService/employees/1\"><firstName>rama</firstName><lastName>chandra</lastName></employee>";
  String updatedEmpStr = client.updateEmployee(1,empStr);
  System.out.println("updatedEmpStr Emp ="+updatedEmpStr);
  
  */
  
  /* Delete Employee test */
  
  Response  responseObj = client.deleteEmployee(1);
  System.out.println("Deleted  Emp  status="+responseObj.getStatus());
 }

 
 
 
 /**
  * 
  * @param fileServiceUrl
  * @throws FileNotFoundException
  * @throws IOException
  */
 private static void fileServiceTest(String fileServiceUrl)
   throws FileNotFoundException, IOException {
  
  
  
  /*  File upload  Test  */
  /* 
   RestEasyFileServiceRestfulClient fileServiceClient = ProxyFactory.create(RestEasyFileServiceRestfulClient.class,fileServiceUrl);  
   MultipartFormDataOutput mdo = new MultipartFormDataOutput();
      mdo.addFormData("file", new FileInputStream(new File("c:\\Test.pdf")),MediaType.APPLICATION_OCTET_STREAM_TYPE);
      Response r = fileServiceClient.uploadFile(mdo);
      System.out.println("File upload Response="+ r.getStatus() +":"+ r.getMetadata());
    */
  
             
             
  /*  To Download a File...
   */
  RestEasyFileServiceRestfulClient fileServiceClient = ProxyFactory.create(RestEasyFileServiceRestfulClient.class,fileServiceUrl);
  BaseClientResponse response = (BaseClientResponse)fileServiceClient.getFile("ASD.zip");
  //You can get whatever  name the server sent
  System.out.println(response.getHeaders().getFirst("Content-Disposition"));  
  File s = (File)response.getEntity(File.class);
  File ff = new File("C:\\ASD.zip");
     s.renameTo(ff);
     FileWriter fr = new FileWriter(s);
     fr.flush();
  System.out.println("FileDownload Response = "+ response.getStatus());
 }
 
 
}

A simple HMTL client for testing File upload


<html>
<head>
<title>Form Page</title>
</head>
<body>
 <h1>Upload a File</h1>

 <form action="http://localhost:8081/RESTfulDemoApplication/files/upload " method="post" enctype="multipart/form-data">
  <p>
   Select a file : <input type="file" name="file" size="50" />
  </p>
  <input type="submit" value="Upload It" />
 </form>

</body>
</html>

FIREFOX Restful Webservice Client:

Now I will show you some screen shots as how you can test restful web services with just firefox rest client .

1. CreateEmployee - This is how you can test createEmployee.You need to add two http headers
allow-admin:true
Content-Type:text/xml
and choose the method as POST as shown.



2. UpdateEmployee - Choose method as "PUT" and http header as "Content-Type:text/xml"



3. GetEmployee 



4.  FileDownload - Just type the full url in browser ( http://localhost:8081/RESTfulDemoApplication/files/download/SpringAnnontationsCheatSheet.pdf )
where "SpringAnnontationsCheatSheet.pdf" was the document that was already present on the server


Hope this article gives you enough info for writing restful webcservices and testing them with different clients.

You can download the client code at  RestFullWebserviceClients.zip
Leave your comments if you have any below.