Java Platform, Enterprise Edition (Java EE) 8 The Java EE Tutorial

## The customer Example Application

This section describes how to build and run the `customer` example application. This application is a RESTful web service that uses JAXB to perform the create, read, update, delete (CRUD) operations for a specific entity.

The `customer` sample application is in the `_tut-install_/examples/jaxrs/customer/` directory. See Chapter 2, "Using the Tutorial Examples," for basic information on building and running sample applications.

The following topics are addressed here:

- Overview of the customer Example Application

- The Customer and Address Entity Classes

- The CustomerService Class

- Using the JAX-RS Client in the CustomerBean Classes

- Running the customer Example

### Overview of the customer Example Application

The source files of this application are at `_tut-install_/examples/jaxrs/customer/src/main/java/`. The application has three parts.

- The `Customer` and `Address` entity classes. These classes model the data of the application and contain JAXB annotations.

- The `CustomerService` resource class. This class contains JAX-RS resource methods that perform operations on `Customer` instances represented as XML or JSON data using JAXB. See The CustomerService Class for details.

- The `CustomerBean` session bean that acts as a backing bean for the web client. `CustomerBean` uses the JAX-RS client API to call the methods of `CustomerService`.

The `customer` example application shows you how to model your data entities as Java classes with JAXB annotations.

### The Customer and Address Entity Classes

The following class represents a customer’s address:

    @Entity
    @Table(name="CUSTOMER_ADDRESS")
    @XmlRootElement(name="address")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Address {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;

        @XmlElement(required=true)
        protected int number;

        @XmlElement(required=true)
        protected String street;

        @XmlElement(required=true)
        protected String city;

        @XmlElement(required=true)
        protected String province;

        @XmlElement(required=true)
        protected String zip;

        @XmlElement(required=true)
        protected String country;

        public Address() { }

        // Getter and setter methods
        // ...
    }

The `@XmlRootElement(name="address")` annotation maps this class to the `address` XML element. The `@XmlAccessorType(XmlAccessType.FIELD)` annotation specifies that all the fields of this class are bound to XML by default. The `@XmlElement(required=true)` annotation specifies that an element must be present in the XML representation.

The following class represents a customer:

    @Entity
    @Table(name="CUSTOMER_CUSTOMER")
    @NamedQuery(
        name="findAllCustomers",
        query="SELECT c FROM Customer c " +
              "ORDER BY c.id"
    )
    @XmlRootElement(name="customer")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Customer {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @XmlAttribute(required=true)
        protected int id;

        @XmlElement(required=true)
        protected String firstname;

        @XmlElement(required=true)
        protected String lastname;

        @XmlElement(required=true)
        @OneToOne
        protected Address address;

        @XmlElement(required=true)
        protected String email;

        @XmlElement (required=true)
        protected String phone;

        public Customer() {...}

        // Getter and setter methods
        // ...
    }

The `Customer` class contains the same JAXB annotations as the previous class, except for the `@XmlAttribute(required=true)` annotation, which maps a property to an attribute of the XML element representing the class.

The `Customer` class contains a property whose type is another entity, the `Address` class. This mechanism allows you to define in Java code the hierarchical relationships between entities without having to write an `.xsd` file yourself.

JAXB generates the following XML schema definition for the two preceding classes:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

      <xs:element name="address" type="address"/>
      <xs:element name="customer" type="customer"/>

      <xs:complexType name="address">
        <xs:sequence>
          <xs:element name="id" type="xs:long" minOccurs="0"/>
          <xs:element name="number" type="xs:int"/>
          <xs:element name="street" type="xs:string"/>
          <xs:element name="city" type="xs:string"/>
          <xs:element name="province" type="xs:string"/>
          <xs:element name="zip" type="xs:string"/>
          <xs:element name="country" type="xs:string"/>
        </xs:sequence>
      </xs:complexType>

      <xs:complexType name="customer">
        <xs:sequence>
          <xs:element name="firstname" type="xs:string"/>
          <xs:element name="lastname" type="xs:string"/>
          <xs:element ref="address"/>
          <xs:element name="email" type="xs:string"/>
          <xs:element name="phone" type="xs:string"/>
        </xs:sequence>
        <xs:attribute name="id" type="xs:int" use="required"/>
      </xs:complexType>
    </xs:schema>

### The CustomerService Class

The `CustomerService` class has a `createCustomer` method that creates a customer resource based on the `Customer` class and returns a URI for the new resource.

    @Stateless
    @Path("/Customer")
    public class CustomerService {
        public static final Logger logger =
                Logger.getLogger(CustomerService.class.getCanonicalName());
        @PersistenceContext
        private EntityManager em;
        private CriteriaBuilder cb;

        @PostConstruct
        private void init() {
            cb = em.getCriteriaBuilder();
        }
        ...
        @POST
        @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
        public Response createCustomer(Customer customer) {

            try {
                long customerId = persist(customer);
                return Response.created(URI.create("/" + customerId)).build();
            } catch (Exception e) {
                logger.log(Level.SEVERE,
                        "Error creating customer for customerId {0}. {1}",
                        new Object[]{customer.getId(), e.getMessage()});
                throw new WebApplicationException(e,
                        Response.Status.INTERNAL_SERVER_ERROR);
            }
        }
        ...
        private long persist(Customer customer) {
            try {
                Address address = customer.getAddress();
                em.persist(address);
                em.persist(customer);
            } catch (Exception ex) {
                logger.warning("Something went wrong when persisting the customer");
            }
            return customer.getId();
        }

The response returned to the client has a URI to the newly created resource. The return type is an entity body mapped from the property of the response with the status code specified by the status property of the response. The `WebApplicationException` is a `RuntimeException` that is used to wrap the appropriate HTTP error status code, such as 404, 406, 415, or 500.

The `@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})` and `@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})` annotations set the request and response media types to use the appropriate MIME client. These annotations can be applied to a resource method, a resource class, or even an entity provider. If you do not use these annotations, JAX-RS allows the use of any media type (`"*/*"`).

The following code snippet shows the implementation of the `getCustomer` and `findbyId` methods. The `getCustomer` method uses the `@Produces` annotation and returns a `Customer` object, which is converted to an XML or JSON representation depending on the `Accept:` header specified by the client.

        @GET
        @Path("{id}")
        @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
        public Customer getCustomer(@PathParam("id") String customerId) {
            Customer customer = null;

            try {
                customer = findById(customerId);
            } catch (Exception ex) {
                logger.log(Level.SEVERE,
                        "Error calling findCustomer() for customerId {0}. {1}",
                        new Object[]{customerId, ex.getMessage()});
            }
            return customer;
        }
        ...
        private Customer findById(String customerId) {
            Customer customer = null;
            try {
                customer = em.find(Customer.class, customerId);
                return customer;
            } catch (Exception ex) {
                logger.log(Level.WARNING,
                        "Couldn't find customer with ID of {0}", customerId);
            }
            return customer;
        }

### Using the JAX-RS Client in the CustomerBean Classes

Use the JAX-RS Client API to write a client for the `customer` example application.

The `CustomerBean` enterprise bean class calls the JAX-RS Client API to test the `CustomerService` web service:

    @Named
    @Stateless
    public class CustomerBean {
        protected Client client;
        private static final Logger logger =
                Logger.getLogger(CustomerBean.class.getName());

        @PostConstruct
        private void init() {
            client = ClientBuilder.newClient();
        }

        @PreDestroy
        private void clean() {
            client.close();
        }

        public String createCustomer(Customer customer) {
            if (customer == null) {
                logger.log(Level.WARNING, "customer is null.");
                return "customerError";
            }
            String navigation;
            Response response =
                    client.target("http://localhost:8080/customer/webapi/Customer")
                    .request(MediaType.APPLICATION_XML)
                    .post(Entity.entity(customer, MediaType.APPLICATION_XML),
                            Response.class);
            if (response.getStatus() == Status.CREATED.getStatusCode()) {
                navigation = "customerCreated";
            } else {
                logger.log(Level.WARNING, "couldn''t create customer with " +
                        "id {0}. Status returned was {1}",
                        new Object[]{customer.getId(), response.getStatus()});
                navigation = "customerError";
            }
            return navigation;
        }

        public String retrieveCustomer(String id) {
            String navigation;
            Customer customer =
                    client.target("http://localhost:8080/customer/webapi/Customer")
                    .path(id)
                    .request(MediaType.APPLICATION_XML)
                    .get(Customer.class);
            if (customer == null) {
                navigation = "customerError";
            } else {
                navigation = "customerRetrieved";
            }
            return navigation;
        }

        public List<Customer> retrieveAllCustomers() {
            List<Customer> customers =
                    client.target("http://localhost:8080/customer/webapi/Customer")
                    .path("all")
                    .request(MediaType.APPLICATION_XML)
                    .get(new GenericType<List<Customer>>() {});
            return customers;
        }
    }

This client uses the `POST` and `GET` methods.

All of these HTTP status codes indicate success: 201 for `POST`, 200 for `GET`, and 204 for `DELETE`. For details about the meanings of HTTP status codes, see `http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html`.

### Running the customer Example

You can use either NetBeans IDE or Maven to build, package, deploy, and run the `customer` application.

The following topics are addressed here:

- To Build, Package, and Deploy the customer Example Using NetBeans IDE

- To Build, Package, and Deploy the customer Example Using Maven

#### To Build, Package, and Deploy the customer Example Using NetBeans IDE

1. Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).

2. From the File menu, choose Open Project.

3. In the Open Project dialog box, navigate to:

       tut-install/examples/jaxrs

4. Select the `customer` folder.

5. Click Open Project.

6. In the Projects tab, right-click the `customer` project and select Build.

   This command builds and packages the application into a WAR file, `customer.war`, located in the `target` directory. Then, the WAR file is deployed to GlassFish Server.

7. Open the web client in a browser at the following URL:

       http://localhost:8080/customer/

   The web client allows you to create and view customers.

#### To Build, Package, and Deploy the customer Example Using Maven

1. Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).

2. In a terminal window, go to:

       tut-install/examples/jaxrs/customer/

3. Enter the following command:

       mvn install

   This command builds and packages the application into a WAR file, `customer.war`, located in the `target` directory. Then, the WAR file is deployed to GlassFish Server.

4. Open the web client in a browser at the following URL:

       http://localhost:8080/customer/

   The web client allows you to create and view customers.

Copyright © 2017, Oracle and/or its affiliates. All rights reserved.