Loading
EclipseLink Solutions Guide for EclipseLink
Release 2.4
  Go To Table Of Contents
Contents
 Search
Other Searches
 PDF
PDF
Comments
Comments

Introduction to the Solution

REpresentational State Transfer (REST) defines a set of architectural principles for distributed systems, in which Web Services are viewed as resources. Those resources are identified by URIs and can be addressed and transferred using the HTTP protocol. REST can be used with a number of technologies, including JPA. HTTP methods are used to access and perform operations on resources.

You can use the Java API for RESTful Web Services (JAX-RS) to develop applications that use the REST architecture, by using annotations to define resources and the actions that can be performed on those resources. The "RESTful Service Example" at http://wiki.eclipse.org/EclipseLink/Examples/REST/GettingStarted gives an example using this approach to interact with JPA persistence units.

However, EclipseLink provides an API that makes it easier to implement REST, without the need to use JAX-RS directly. EclipseLink Java Persistence API for RESTful Web Services (JPA-RS) can be used to interact with JPA persistence units and EJB session bean methods without explicitly writing JAX-RS code, thus providing a simple way to expose these Java EE capabilities through REST.

JPA-RS is made available via a web fragment, which extends the capabilities of a web application. The REST functionality is made available by including the JPA-RS jar in the WEB-INF/lib folder of a web application.

JPA-RS runtime provides access to all persistence units packaged in the same application that it is running in as well as any dynamic persistence unit that is provisioned within it.

Implementing the Solution

This section contains the following tasks for exposing JPA entities using JPA-RS:

Step 1: Prerequisites

To implement and use EclipseLink JPA-RS, you need:

  • Either of the following Java EE application servers:

    • Oracle WebLogic Server 12c Release 1 (12.1.2) or later.

    • Glassfish Server 3.1.2 or later.


      NoteNote:

      With Glassfish Server 3.1.2, you must upgrade the EclipseLink version to use the JPA-RS version shipped in EclipseLink 2.4.2 (and include DBWS). See http://www.eclipse.org/eclipselink/downloads/ for EclipseLink downloads.


    These servers include:

    • EclipseLink 2.4 or later, configured as the persistence provider.

    • Jersey, the reference implementation of the Java API for RESTful Web Services (JAX-RS) 1.0.

  • The org.eclipse.persistence.jpars_version.jar file. This file is included in the EclipseLink distributions from the Eclipse foundation, at http://www.eclipse.org/eclipselink/downloads/:

    • In the installer distribution, the file is located in eclipselink\jlib\jpa\.

    • In the bundles distribution, the file is located with the other bundles.

  • Any compliant Java Database Connectivity (JDBC) database, including Oracle Database, Oracle Database Express Edition (Oracle Database XE), or MySQL. These instructions are based on Oracle Database XE 11g Release 2.

    For the certification matrix, see

Step 2: Create and Configure the Application

JPA-RS is designed to function with a standard JPA application, with little extra work required beyond enabling JPA-RS, as described below:

  1. Develop an application using one or more standard JPA persistence units, package it in a WAR/EAR file, and deploy it normally.


    NoteNote:

    Weaving is required for several features to work: providing relationships as links, editing relationships, and dealing with lazy x-1 relationships. Either deploy to a Java EE compliant server or statically weave your classes.

    Lazy x-1 relationships are only supported when using the JPA RS default mapping strategy, which returns those mappings as links by using read-only mappings for the JSON/XML support and providing the links through a weaved attribute.


  2. Include the JPA-RS servlet in the EAR/WAR containing the application. (For instructions on downloading, see.Step 1: Prerequisites)


    NoteNote:

    The JPA-RS JAR file includes a web-fragment.xml file that identifies the JPA-RS servlet and defines the root URI for the RESTful service.


    Add the org.eclipse.persistence.jpars_version_no.jar file to the WAR/EAR containing the application, under WEB-INF/lib.

Step 3: Understand JPA-RS URI Basics

URIs used for making HTTP calls for JPA-RS follow these standard patterns:

  • The base URL for JPA-RS for an application is: http://server:port/application-name/persistence/

  • For base operations on the persistence unit, add the persistence unit name:

    /persistence/{unit-name}

  • For specific types of operations, add the type of operation, for example:

    • Entity operations: /persistence/{unit-name}/entity

    • Query operations: /persistence/{unit-name}/query

    • Single result query operations: /persistence/{unit-name}/querySingleResult

    • Metadata operations: /persistence/{unit-name}/metadata

For complete documentation on how to construct these URIs, see HTTP Request Reference for JPA-RS.

Step 4: Issue Client Calls for Operations on the Persistence Unit

Clients use HTTP calls to perform operations on persistence units in a deployed application. The requirements and options for constructing the calls are described HTTP Request Reference for JPA-RS.

Specify Media Format in the Header

This REST interface can handle both XML and JSON representations of data. The caller is responsible for using HTTP header values to indicate the format of the content:

  • Content-Type = application/json indicates that the content being sent is JSON

  • Content-Type = application/xml indicates that the content being sent is XML

  • Accept = application/json indicates that the expected format of the result is JSON

  • Accept = application/xml indicates that the expected format of the result is XML

If no header value is specified, JSON is used by default. If Content-type is specified and Accept is not specified, the returned format matches the Content-type passed in.


NoteNote:

In many REST utilities, the Accept value is defaulted to application/xml. In those cases, you must configure this value explicitly, if you want JSON.


About Logging

Messages related to JPA-RS operations are logged to a logger called org.eclipse.persistence.jpars. Most messages are logged at the FINE level. Exception stacks are logged at FINER.

Messages related to operations within EntityManagers, EntityManagerFactorys and JAXBContexts are logged in the same manner as other EclipseLink logging.

Step 5: Represent Entities Using JPA, JAXB, or JSON

Entities in JPA-RS are represented in two ways:

  • As JPA Entities - The mappings of the JPA entities must be represented in the typical EclipseLink JPA fashion, using either annotations or XML files. These mappings are used to interact with the data source.

  • As JAXB/JSON - No specific mapping information is required when using JAXB/JSON. By default, JPA-RS uses the JAXB defaults (defined in the JAXB specification) to map to JAXB/JSON. You can optionally provide JAXB annotations on the classes to alter the way the objects are mapped. Additionally, the persistence unit property eclipselink.jpa-rs.oxm can be specified in a persistence unit's persistence.xml to specify XML-defined JAXB mappings.

Relationships

In general, JAXB default mappings are sufficient to allow information exchange using JSON/JAXB. There are, however, some special cases when dealing with relationships.

Bidirectional Relationships and Cycles

Bidirectional relationships are typical in JPA and are easy to represent in a database using foreign keys. They are more difficult to represent in a XML or JSON document using standard JAXB. However, the EclipseLink JAXB implementation provides a way to define an inverse relationship. Inverse relationships are not directly written to XML or JSON but are populated when the XML or JSON is unmarshalled. The way this is handles is as follows:

JPA bidirectional relationships are defined to have an owning side and a non-owning side. JPA mapping provides a mapped-by attribute that defines which is which. JPA-RS defaults the owning side to be an inverse relationship. As a result, when an object with an owned-relationship is read or written, that relationship is ignored.

Consider the following pseudo-code:

  @Entity
  ClassA{
 
  @Id
  int id
 
  @OneToOne
  myB
 
}
 
 
  @Entity
  ClassB{
 
  @Id
  int id
 
  @OneToOne(mappedby="myB")
  myA
 
}

If the objects are identified as follows...

  • A1 with id=1 and myB = B1

  • B1 with id=11 and myA = A1

...the following JSON corresponds to those objects:

  A {
    id:1
  }
 
  B {
    id:11
    myA: {
      id: 1
    }
  }

Cycles can be difficult to detect, and JPA-RS requires that you provide JAXB mappings. That allows EclipseLink to resolve cycles in the cases where they can cause problems. In general, issues arise only when you try to create a group of new objects that include a cycle. To avoid problems in such cases, choose one of the mappings in the cycle and map it as XMLTransient.

Pass By Reference, Pass By Value

JPA-RS allows relationship objects to be passed either by value or by reference.

To pass an object by value, create typical JSON or XML that represents the object. The following JSON passes myA by value:

  B {
    id:11
    myA {
      id: 1
    }
  }

To pass an object by reference, use a link. The link represents the JPA-RS call necessary to get that object. The following JSON passes myA by reference:

  B {
    id:11
    myA {
      _link:{
          href: "http://localhost:8080/app/persistence/pu/entity/A/1"
          method: "GET"
          rel: "self"
      }
    }
  }

Lists can mix and match items represented by reference and by value.

JPA-RS read operations currently return all relationships by reference.

Sample JSON

The following example shows JSON that can be sent to JPA-RS in a regular-expression-like syntax:

  <code>
  {
    numericAttribute: 1
    stringAttribute: "auction1"
    dateAttribute: 12-09-16
    singleRelatedItem: RELATED_ITEM?
      listRelatedItem:
      {
          RELATED_ITEM*
      }
  }
 
 
  RELATED_ITEM =
 
      {
        numericAttribute: 11
        stringAttribute: "myName"
      }
 
  OR
 
      _link {
        rel="self", 
        href=LINK_HREF, 
        method="GET"
     }

The following JSON represents an entity called StaticAuction with several directly mapped fields and a collection of an entity called Bid.

  {
    "description": "Auction 1",
    "endPrice": 0,
    "id": 2,
    "image": "auction1.jpg",
    "name": "A1",
    "sold": false,
    "startPrice": 100,
    "_relationships": [
      {
        "_link": {
        "href": "http://localhost:8080/eclipselink.jpars.test/persistence/auction-static/entity/StaticAuction/2/bids",
        "rel": "bids"
        }
      }
      ],
    "bids": [
      {
        "_link": {
       "href": "http://localhost:8080/eclipselink.jpars.test/persistence/auction-static/entity/StaticBid/5",
        "method": "GET",
        "rel": "self"
      }
    },
    {
      "_link": {
        "href": "http://localhost:8080/eclipselink.jpars.test/persistence/auction-static/entity/StaticBid/6",
        "method": "GET",
        "rel": "self"
      }
    }
  ]
  }

Sample XML

XML representation mimics the JSON representation. The following is sample XML for an entity called StaticAuction, with several directly mapped attributes and a list of an entity called Bid.

  <staticAuction xmlns:atom="http://www.w3.org/2005/Atom">
    <description>Auction 1</description>
    <endPrice>0.0</endPrice>
    <id>2</id>
    <image>auction1.jpg</image>
    <name>A1</name>
    <sold>false</sold>
    <startPrice>100.0</startPrice>
    <_relationships>
      <_link href="http://localhost:8080/eclipselink.jpars.test/persistence/auction-static/entity/StaticAuction/2/bids" rel="bids" />
    </_relationships>
    <bids>
      <_link href="http://localhost:8080/eclipselink.jpars.test/persistence/auction-static/entity/StaticBid/5" method="GET" rel="self" />
    </bids>
    <bids>
      <_link href="http://localhost:8080/eclipselink.jpars.test/persistence/auction-static/entity/StaticBid/6" method="GET" rel="self" />
    </bids>
  </staticAuction> 

Step 6: Implement Security

Secure JPA-RS through typical REST security mechanisms.

Comments powered by Disqus