Friday, December 2, 2011

RESTful: Part 1 - Introduction to RESTful Web Services

Extend or add functionality into your applications with RESTful Web services.

This article, the first of a three part series, demonstrates how to create a Java Platform, Enterprise Edition (Java EE) application integrating Representational State Transfer (REST) Web services.

I will use the NetBeans 7.0.1 IDE and Java EE 6 to create the application and Oracle GlassFish Server 3.1 to deploy it.

Part 2 covers managing the answers sent by a Web service using the JavaScript Object Notation (JSON) framework, while Part 3 focuses on the integration of Java API for XML Web Services (JAX-WS). These articles highlight methods for increasing application agility.

What Are Web Services?
Web services provide a standard means of interoperating among software applications that run on a variety of platforms or frameworks.

In other words, Web services are the best and standard way to extend your application in order to make it interoperable with other systems via HyperText Transfer Protocol (HTTP) using Extensible Markup language (XML). Web services allow you to mask the complexity of each application included in the exchange and achieve complex operation.

Web services are more than the sum of the technologies used to deploy an application. They are a method for carving out services from business functionalities that are then exposed to be consumed by client applications.

Why RESTful Web Services?
Java EE 6 provides natively all mechanisms for REST via the Java API for RESTful Web Services” (JAX-RS), JSR-311. There are many good reasons to choose REST to add the Web services into your system.

Here are some examples:

The most important reason is that RESTful Web services are easy to learn, easy to build, and easy to deploy.
  • REST provides a uniform interface between the producers and the consumers of the services.
  • RESTful Web services provide support for a variety of message formats (XML, JSON, HTML, and more).
  • RESTful Web services are easy to integrate into existing applications in order to extend or add new functionality.
  • REST is just an architectural style, not a technology. That is why there is a specification, JSR-311, to describe how REST should be implemented in Java. There have been several implementations of this standard. Jersey is the official reference implementation and the one that is most widely used in development and production. Jersey is open source and backed by Oracle.
However, REST might have some limitations when it comes to big Web services. This will be discussed in Part 3 of the series.

Prerequisites

The following software was used to develop the application described in this article:
  1. NetBeans IDE.
  2. Jersey (included in NetBeans): It is the open source, production- quality reference implementation for a Java EE specification
  3. (JAX-RS JSR-311) for building RESTful Web services. 
Note: This article was tested using NetBeans IDE 7.0.1.

Real-Life Application

In this practical section, we will build a real-life application step by step so that you can learn quickly the basics of the RESTful Web services.

The application is an online auction place (like eBay). Sellers post their items in listings, and buyers bid on the items. A seller can post one or many items, and a buyer can bid on one or many items. To simplify, we will consider the following entities: Seller, Item, and Bid.

Now lets code this application in five minutes using NetBeans and JavaServer Faces.

1.    Generate the initial NetBeans project:
a.    Launch NetBeans and create a new project.
b.    From the File menu, choose New Project.
c.    From Categories, select Java Web.
d.    From Projects, select Web Application.
e.    Click Next.
f.     Type a project name, AuctionApp, and click Next.
g.    Make sure the Server is GlassFish Server (or similar wording).
h.    Click Finish.

The AuctionApp is created with a simple index.xhtml.

2.    Right-click the project and select Run. The default page, as seen in Figure 1, will be displayed with the simple message, Hello from Facelets.

Figure 1
3.    Create the entities:
a.    Right-click the AuctionApp project and select New; then select Entity class.
b.    Type Seller in the Class Name field, type com.tm.rs.auctionApp in the Package field, and click Next.
c.    From the Provider and Database, select EclipseLink (JPA 2.0) (default).
d.    Choose one of the datasources provided by NetBeans. Click Finish.
e.      Repeat Step 3 for each entity. NetBeans generates the Seller.java, Item.java, and Bid.java files.

Now we are going to add properties in the entities using the NetBeans wizard.

1.    Open the Seller.java file, right-click anywhere in the code, and select Insert code.
2.    Select Add property and add the seller properties (String firstName, String lastName, and String email).
3.    Open the Item.java file and add the item properties (String title, String description, Double initialPrice, and Seller seller).
4.    Click the NetBeans warning to define the entity relationship (bidirectional ManyToOne). This action creates a list of items in the Seller entity.
5.    Open the Bid.java file and add the item properties (String bidderName, Double amount, and item).
6.    Click the NetBeans warning to define the entity relationship (bidirectional ManyToOne). This action creates a list of bids in the Item entity.
7.    Generate the Getters and Setter, respectively, for the list of items and bids created in the Seller and Item entities.

At this point, your Seller.java file will look like Listing 1.
Listing 1
@Entity
public class Seller implements Serializable {
    @OneToMany(mappedBy = "seller")
    private List<Item> items;
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    protected String firstName;
    protected String lastName;
    protected String email;

    public List getItems() {
        return items;
    }

    public void setItems(List<Item> items) {
        this.items = items;
    }

8.    Add the RESTful capacities in the initial NetBeans project:
  1. Right-click the AuctionApp project and select New; then select RESTful Web Services from Entity Classes.
  2. From Entity Classes, click Add all; then click Next.
  3. Two names need to be specified: a Resource Package name such as com.tm.rs.auctionApp.resource and a Converter Package name, com.tm.rs.auctionApp.converter.
  4. Click Finish.
New resources classes (that use JAXRS annotations to define the representation of the entities) and converters classes (that use JAXB annotations such as @XmlElement and @XmlAttribute to define the way to marshal and unmarshal the data) are added to the project. Now the AuctionApp has RESTful capacities.

Take a look at the BidConverter.java code in Listing 2.
Listing 2
@GET
@Produces({"application/xml", "application/json"})
public BidConverter get(@QueryParam("expandLevel")@DefaultValue("1")int expandLevel) {
        return new BidConverter(getEntity(), 
        uriInfo.getAbsolutePath(), expandLevel);
    }
@PUT
@Consumes({"application/xml", "application/json"})
public void put(BidConverter data) {
   updateEntity(getEntity(), data.resolveEntity(em));
}

NetBeans has generated methods that use GET and PUT annotation for retrieving or updating an instance of Bid identified by ID in XML format.

Notice:
·         The @Produces({"application/xml", "application/json"}) annotation allows JAX-RS to specify XML format and JSON as the types of representations a resource can produce.
·         The @Consumes({"application/xml", "application/json"}) annotation allows JAX-RS to specify XML format and JSON as the types of representations a resource can consume.

Take a look at the BidConverter.java code in Listing 3.
Listing 3

@XmlElement
public Long getId() {
    return (expandLevel > 0) ? entity.getId() : null;
}
@XmlAttribute
public URI getUri() {
    return uri;
}

NetBeans has generated Getter methods that use XmlElement annotation to map the field of Bid entity to
XML format.

·         The @XmlElement annotation tells JAXB to map the id to a <id> element of the XML document.
·         The @XmlAttribute annotation tells JAXB to map the uri to an uri attribute on the the XML document.

In Figure 2, you can see the XML representation of your resources in the browser by typing this URL in your browser: http://localhost:8080/AuctionApp/resources/bids.

Figure 2
If you see this result, it means your RESTful services are working correctly.

But to test it correctly, we need to use Oracles JavaServer Faces. So we are going to quickly build a JavaServer Faces front end to allow us to create data.

1.    Create the JavaServer Faces pages:
a.    Right-click the Web Pages node of the AuctionApp project and select New; then select Folder.
b.    Type a Folder Name, such as ui. Click Finish.
c.    Right-click the AuctionApp project and select New; then select JSF Pages from Entity Classes.
d.    From Entity Classes, click Add all; then click Next.
e.    Type a Session Bean Package name, such as com.tm.rs.auctionApp.facade, and a JSF Classes Package name, com.tm.rs.auctionApp.presentation.
f.     Click Browse to select the ui folder as the JSF pages folder.
g.    Click Finish.

2.    Run the AuctionApp and add the data:
a.    Right-click the AuctionApp project and select Run.

As seen in Figure 3, the home page is displayed and shows the links to create, update, or delete the entities.

Figure 3
b.    From the home page, click on Show All Seller Items; then click Create New Seller and add a new seller, as seen in Figure 4.

Figure 4
3.    Test the RESTful Web services availability:
      a.    Open your browser and type the resource URL http://localhost:8080/AuctionApp/resources/sellers.

As seen in Listing 4, the XML representation of the resource (Seller) is displayed. You can see all Sellers you already created in XML format.
Listing 4

<sellers uri="http://localhost:8080/AuctionApp/resources/sellers">
<seller uri="http://localhost:8080/AuctionApp/resources/sellers/1/">
 <firstName>Bonbhel</firstName>
  <id>1</id>
  <items uri=
      "http://localhost:8080/AuctionApp/resources/sellers/1/items/" /> 
  <lastName>Max</lastName>
</seller>
<seller uri="http://localhost:8080/AuctionApp/resources/sellers/2/">
  <firstName>Oddet</firstName> 
  <id>2</id>
  <items uri=
      "http://localhost:8080/AuctionApp/resources/sellers/2/items/" />
  <lastName>Rossi</lastName>
</seller>
<seller uri="http://localhost:8080/AuctionApp/resources/sellers/3/">
  <firstName>Malonga</firstName>
  <id>3</id>
  <items uri=
      "http://localhost:8080/AuctionApp/resources/sellers/3/items/" /> 
  <lastName>Chrisbel</lastName>
</seller>
</sellers>
  
Conclusion
We have seen how NetBeans can help to quickly develop a Java EE application that features RESTful Web services as well as an interface based on JavaServer Faces. The integration of REST with Jersey has shown how Web services can make functionality reusable and the system as a whole more flexible.

In Part 2, I will discuss Web services and the JSON framework.


Reference: Java Magazine 2011 by MAX BONBHEL.

3 comments :

  1. When creating RESTful Web Services from Entity Classes, in Netbeans 7.1 I cannot find
    "Converter Package name" to specify.
    Any idea how to do this in 7.1?

    ReplyDelete
  2. In netbeans version 7.1, when creating RESTful Web Services from Entity Classes there are no converters will be created.

    you can use the entity classes directly as return types instead of converters, be bear in mind the XML annotations on entity classes to be exposed as xml contents.

    @GET
    @Produces({"application/xml", "application/json"})
    public Bid get(@QueryParam("expandLevel")@DefaultValue("1")int expandLevel) {
    return new Bid(uriInfo.getAbsolutePath(), expandLevel);
    }

    Also take care of cycle object notation as Seller has list of items and each item has object of seller, this will raise an exception CyclicDetectionException when calling the services.

    ReplyDelete
  3. How is this done: "Click the NetBeans warning to define the entity relationship "? There is no explanation.
    What warning? Should I see a warning, is warning a pulldown from somewhere. I have no idea how to proceed.

    ReplyDelete