Order Entry System

Creating a REST Web service based Order Entry System 
In the earlier lectures we have seen the introduction to Web services, the different flavours of them(SOAP vs REST) and made them greet us with a simple HelloWorld Application. As an introduction it is good. Now it is time to take a deep dive and build a working example and learn more about JAX-RS as we develop the example. From now on the discussion is going to be primarily on REST web services only.

Order entry system

Lets say we are building an e-commerce system. There are different products that are sold. Each product has id, name and cost. There are Customers who gets registered, update their profiles, cancel their registration. Each registered customer will have an id. Registered customers can place orders. Each order will have an id and one or more LineItems. Each LineItem will have an id and product id and quantity of the product. The object model for this system will look like

Identifying the resources in the system
In the introduction to REST we said http concepts are heavily used in REST design. One of the primary concept used is seeing each service exposed as a resource and assigning URL for the resources. In our Order entry system we have the below entities.

  • Customer
  • Order
  • LineItem
  • Product


There will be a service associated with each entity that service should have methods to add, update, delete, get the current state of entity. For e.g the system should have a CustomerService which supports addCustomer, updateCustomer etc and a ProductService which support operations like addProduct, deleteProduct etc. We expose these services as resources and assign them urls.

Creating the RESTFul CustomerService
Let us start with CustomerService.

  • Create a Dynamic Web project called OrderEntrySystem. 
  • Make this a maven project by Right clicking on the project -> Configure -> Convert to Maven project
  • Once converted to maven project put these lines in the pom.xml


Pom.xml

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>OrderEntrySystem</groupId>
 <artifactId>OrderEntrySystem</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>war</packaging>
 <properties>
  <jersey2.version>2.19</jersey2.version>
  <jaxrs.version>2.0.1</jaxrs.version>
 </properties>
 <build>
  <sourceDirectory>src</sourceDirectory>
  <plugins>
   <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
     <source>1.8</source>
     <target>1.8</target>
    </configuration>
   </plugin>
   <plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.4</version>
    <configuration>
     <warSourceDirectory>WebContent</warSourceDirectory>
     <failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
   </plugin>
  </plugins>
 </build>
 <dependencies>
  <!-- JAX-RS -->
  <dependency>
   <groupId>javax.ws.rs</groupId>
   <artifactId>javax.ws.rs-api</artifactId>
   <version>${jaxrs.version}</version>
  </dependency>
  <!-- Jersey 2.19 -->
  <dependency>
   <groupId>org.glassfish.jersey.containers</groupId>
   <artifactId>jersey-container-servlet</artifactId>
   <version>${jersey2.version}</version>
  </dependency>
  <dependency>
   <groupId>org.glassfish.jersey.core</groupId>
   <artifactId>jersey-server</artifactId>
   <version>${jersey2.version}</version>
  </dependency>
  <dependency>
   <groupId>org.glassfish.jersey.core</groupId>
   <artifactId>jersey-client</artifactId>
   <version>${jersey2.version}</version>
  </dependency>
  <dependency>
   <groupId>org.glassfish.jersey.media</groupId>
   <artifactId>jersey-media-multipart</artifactId>
   <version>${jersey2.version}</version>
  </dependency>
  <dependency>
   <groupId>com.fasterxml.jackson.jaxrs</groupId>
   <artifactId>jackson-jaxrs-json-provider</artifactId>
   <version>2.4.1</version>
  </dependency>
  <dependency>
   <groupId>org.glassfish.jersey.media</groupId>
   <artifactId>jersey-media-json-jackson</artifactId>
   <version>${jersey2.version}</version>
  </dependency>
 </dependencies>
</project>

Lets start adding the source code for our OrderEntrySystem.
Customer.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.example;

import javax.xml.bind.annotation.XmlRootElement;

/**
 * @author Santosh
 *
 */
@XmlRootElement
public class Customer {

 private int id;
 private String name;
 private String address;

 /**
  * @return the id
  */
 public int getId() {
  return id;
 }

 /**
  * @param id
  *            the id to set
  */
 public void setId(int id) {
  this.id = id;
 }

 /**
  * @return the name
  */
 public String getName() {
  return name;
 }

 /**
  * @param name
  *            the name to set
  */
 public void setName(String name) {
  this.name = name;
 }

 /**
  * @return the address
  */
 public String getAddress() {
  return address;
 }

 /**
  * @param address
  *            the address to set
  */
 public void setAddress(String address) {
  this.address = address;
 }

}

CustomerServiceImpl.java

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package com.example.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
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.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.example.Customer;

/**
 * @author Santosh
 *
 */

@Path("/customers")
public class CustomerService {

 private Map<Integer, Customer> customerDB = new ConcurrentHashMap<Integer, Customer>();

 private AtomicInteger idCounter = new AtomicInteger();

 public CustomerService() {
  // add some 5 dummy customers
  int limit = 5;
  int id = idCounter.getAndIncrement();

  while (id < limit) {
   Customer c = new Customer();
   c.setId(id);
   c.setName("Cust" + c.getId());
   c.setAddress("Some Address");
   System.out.println("Created a dummy customer with id:" + id);
   id = idCounter.getAndIncrement();

  }
 }

 @GET
 @Produces(MediaType.APPLICATION_XML)
 public List<Customer> getAllCustomers() throws WebApplicationException {
  List<Customer> customers = new ArrayList<>();
  for (Customer customer : customerDB.values()) {
   customers.add(customer);
  }
  return customers;
 }

 @Path("/{id}")
 @GET
 @Produces(MediaType.APPLICATION_XML)
 public Customer getCustomers(@PathParam("id") int id)
   throws WebApplicationException {

  if (customerDB.get(id) == null) {
   // no such customer exists
   throw new WebApplicationException(Response.Status.NOT_FOUND);
  } else {
   return customerDB.get(id);

  }
 }

 @PUT
 @Produces(MediaType.APPLICATION_XML)
 @Consumes(MediaType.APPLICATION_XML)
 public Customer updateCustomer(Customer cust)
   throws WebApplicationException {
  if (customerDB.get(cust.getId()) == null) {
   throw new WebApplicationException(Response.Status.NOT_FOUND);
  } else {
   customerDB.put(cust.getId(), cust);
   return customerDB.get(cust.getId());
  }

 }

 @POST
 @Produces(MediaType.APPLICATION_XML)
 @Consumes(MediaType.APPLICATION_XML)
 public Customer addCustomer(Customer cust) throws WebApplicationException {
  if (cust == null) {
   throw new WebApplicationException(Response.Status.BAD_REQUEST);
  } else {
   int id = idCounter.getAndIncrement();
   cust.setId(id);
   customerDB.put(id, cust);
   return customerDB.get(id);
  }
 }

 @DELETE
 @Produces(MediaType.APPLICATION_XML)
 @Consumes(MediaType.APPLICATION_XML)
 public Customer deleteCustomer(Customer cust)
   throws WebApplicationException {
  if (customerDB.get(cust.getId()) == null) {
   throw new WebApplicationException(Response.Status.NOT_FOUND);
  } else {
   customerDB.remove(cust.getId());
   return customerDB.get(cust.getId());
  }

 }

}

ShoppingApplication.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
 * 
 */
package com.example.service;

/**
 * @author Santosh
 *
 */

import java.util.HashSet;
import java.util.Set;

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

@ApplicationPath("/services")
public class ShoppingApplication extends Application {
 private Set<Object> singletons = new HashSet<Object>();
 private Set<Class<?>> empty = new HashSet<Class<?>>();

 public ShoppingApplication() {
  singletons.add(new CustomerService());
 }

 @Override
 public Set<Class<?>> getClasses() {
  return empty;
 }

 @Override
 public Set<Object> getSingletons() {
  return singletons;
 }
}

Web.xml



<web-app id="WebApp_ID" version="2.4"
 xmlns="http://java.sun.com/xml/ns/j2ee" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 <display-name>OrderEntrySystem</display-name>

</web-app>    



Testing the application built so far
Using eclipse servers tab add this web app and start tomcat. Once successfully deployed we will test the services using postman app.
Once the application is deployed the customer service should be reachable at
http://localhost:<port>/<webapp name>/<application path>/<service path>. For e.g in my local machine the path is http://localhost:8090/OrderEntrySystem/services/customers
                                                                                  
Getting List of Customers



GET operation on http://localhost:8090/OrderEntrySystem/services/customers gets all customers. Once the application start there are no customers. Hence the operation did not give any customer results.

Adding a Customer
For adding a customer we should invoke post operation on http://localhost:8090/OrderEntrySystem/services/customers with request body containing an xml representation of a new customer object
  <customer>
<name>cust1</name>
<address>Some address</address>
</customer>


The response returned by this call will be a Customer object with id field populated.


Updating Customer details
This operation will be same as Adding customer except that invoke PUT on the url and also pass customer id as part of the input customer object

<customer>
<id>0</id>
<name>cust1</name>
<address>Some other address</address>
</customer>


The response for this operation would be a updated customer object.


Deleting a customer

This will be same as Updating a customer except that you will call DELETE on the same url.



The response for delete operation is 

No comments:

Post a Comment