Jump to: navigation, search

Difference between revisions of "EclipseLink/Development/2.4.0/JPA-RS/REST-API"

(Persistence Unit Operations)
(Persistence Unit Operations)
Line 54: Line 54:
 
This REST interface deals with XML and JSON representations of the data equally well. The caller is responsible for using the HTTP header values to indicate the format of the content it is sending (Content-Type = application/json or application/xml) as well as indicating the format of the result it expects (Accept = application/json or application/xml).
 
This REST interface deals with XML and JSON representations of the data equally well. The caller is responsible for using the HTTP header values to indicate the format of the content it is sending (Content-Type = application/json or application/xml) as well as indicating the format of the result it expects (Accept = application/json or application/xml).
 
NOTE: In many REST utilities the accept value is defaulted to application/xml making it the users responsibility to configure this value explicitly.
 
NOTE: In many REST utilities the accept value is defaulted to application/xml making it the users responsibility to configure this value explicitly.
 
===HTTP Header Fields ===
 
 
'''Standard HTTP'''
 
* If-Match - conditional
 
* Warning
 
 
'''EclipseLink JPA-RS'''
 
* Refresh
 
 
=== Multi-Tenancy ===
 
 
When using EclipseLink's multi-tenancy features developers can choose to isolate their tenant's data by schema/table (@Multitenant(TABLE_PER_TENANT) - EclipseLink 2.4) or within a shared table (@Multitenant(SINGLE_TABLE) - EclipseLink 2.3). In order to access a persistence unit that supports concurrent access by multiple tenants the persistence context must specify tenant discriminator values within its properties. To support this usage within JPA-RS the tenant identifier values will be supplied using matrix parameters within the persistence unit portion of the URI.
 
 
<pre>
 
/persistence/{unit-name};mysports.league=HTHL/
 
</pre>
 
  
 
=== Logging ===
 
=== Logging ===

Revision as of 14:30, 30 October 2012

JAX-RS: A RESTful API for JPA

History Date Author Description 01/10/11 dclarke Initial Version

Date Author Description
Oct 1, 2011 dclarke Initial Version
Nov 9, 2011 dclarke Moved to wiki for community review and feedback.
Jan-Mar, 2012 tware updates and additions to REST API descriptions

Overview

This specification will define a RESTful API for dealing with JPA. The intent is to simplify how JPA persistence units can be accessed using REST with JSON or XML formatted messages. A JPA-RS runtime will provide 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.

Using JPA-RS

JPA-RS comes in two parts and is available starting with our 2.4.0 release.

  1. Server side - The majority of code is written in EclipseLink and should be run server-side there are two ways you can get this functionality
    1. If you are on a server that distributes with the full EclipseLink jar or on our 2.4.0 or 2.4.1 release, no changes are needed
    2. If you are on our 2.4.2 or a later release and on a server that uses our OSGi bundles, you will have to ensure that you have the org.eclipse.persistence.dbws bundle (e.g. GlassFish ships with the OSGi bundles. You will need to ensure our org.eclipse.persistence.dbws bundle is available to GlassFish)
  2. Client Side - A small web-fragment called org.eclipse.persistence.jpars is used to enable JPA-RS. This web-fragment should be included with your application.

Although there is no reason the web service cannot be enabled on any fairly recent container that contains Jersey, initial development and testing was done on GlassFish 3.1.2 and this description will assume you are using GlassFish 3.1.2 or better.

JPA-RS uses "/persistence" as its path. (i.e. The base URL for JPA-RS for a particular application is: http://<server>:<port>/<applicationName>/persistence)

Persistence Unit Operations

The JPA-RS URI structure then requires a persistence unit name: /persistence/{unit-name}. Assuming this is a valid persistence unit in the given JPA-RS application context the following high level operations are available.

  • BASE /persistence/{unit-name}
  • ENTITY: /persistence/{unit-name}/entity
  • QUERY: /persistence/{unit-name}/query
  • SINGLE_RESULT_QUERY: /persistence/{unit-name}/singleResultQuery
  • METADATA: /persistence/{unit-name}/metadata

Data Formats: JSON or XML

This REST interface deals with XML and JSON representations of the data equally well. The caller is responsible for using the HTTP header values to indicate the format of the content it is sending (Content-Type = application/json or application/xml) as well as indicating the format of the result it expects (Accept = application/json or application/xml). NOTE: In many REST utilities the accept value is defaulted to application/xml making it the users responsibility to configure this value explicitly.

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 withing EntityManagers, EntityManagerFactories and JAXBContexts are logged in the same manner as other EclipseLink logging.

Deployment Requirements

Weaving is required for several features to work (providing relationships as links, editing relationships, dealing with LAZY x-1 relationships). You should either deploy to a Java EE compliant server or statically weave you classes.

Note: Lazy x-1 relationships are only supported when using JPA RS's 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.

Entity Operations: /persistence/{unit-name}/entity/*

Entity operations are those performed against a specific entity type within the persistence unit. The {type} value refers to the type name (descriptor alias).

FIND


EntityManager.find API:

public <T> T find(Class<T> entityClass, Object primaryKey);
public <T> T find(Class<T> entityClass, Object primaryKey, Map<String, Object> properties);


Composite Key

Composite keys are supported. In the initial implementation, the character '+' will be reserved and not available for use in fields that represent keys. Composite keys will be separated using the '+' character and should be specified in an order cooresponding to java default sorting of the attribute names.

Imagine this entity:

  • Foo
    • idB=1
    • idA=2

The URL to find this entity would be as follows:

http://localhost:8080/persistence/ExamplePU/entity/Foo/2+1

Notice that the '2' comes before the '1' because "idA" comes before "idB" when sorted in java.

Result Caching

Default EclipseLink and HTTP caching will be enabled and configured through standard means.

REFRESH

The EntityManager.refresh operation can be invoked using the find with the query hint for Refresh. See the Query section of the document for how to use hints.

Attributes

Navigating into the attributes of an Entity (e.g. get the Address entity associated with a particular employee in a single URL) is initially only supported to one level:

e.g. /persistence/{unit-name}/entity/{type}/{id}/{relationship} will work

/persistence/{unit-name}/entity/{type}/{id}/{relationship}/{index}/{relationship2} will not

Relationships

To make use of Entities with relationships, the persistence unit classes MUST be weaved. JPA-RS relies on Fetch groups to implement its relationships maintenance. PUT/POST operations on relationships for non-weaved classes is an error condition

Relationships are, by default, represented as links. Reading and writing to relationships is done through that link. See the Relationships section below.

Private-Owned(orphan removal in JPA) relationships are inlined and hence an object model with only Private-Owned relationships does not need to be weaved.

PERSIST

PUT is required to be itempotent. As a result, it will fail if called with an object that expects the server to provide an ID field. Typically this will occur if the metadata specifies a generated key and the field that contains that key is unpopulated.

MERGE


DELETE

Relationships: /persistence/{unit-name}/entity/{entity}/{id}/{relationship}

READ

To get the values of a relationship

ADD

To add to a list or replace the value of a X-1 Relationship

REMOVE

To remove a specific entity from the list or null on an X-1 Relationship

Query Operations

  • Named Query: GET /persistence/{unit-name}/query/{name}{params}

Named Query

Named queries doing reads can be run two ways in JPA. Both are supported in the REST API.

List of Results

Single Result

Update/Delete Query

Session Beans

A restful API is provided to make a call into a SessionBean

  • POST /persistence
    • payload: A SessionBeanCall JSON or XML object containing the following information:
      • jndiName: The JNDI name of the SessionBean
      • methodName: The name of the SessionBean method to call
      • context: (optional) The JPA RS context to use to unmarshall parameters and marshall return values. If not provided, return values are returned as is
      • parameters: A list of parameter Object with the following information
        • typeName: The name of the java class of the parameter, or the name of the entity type in JPA RS
        • value: The value of the parameter
  • Produces: */*
  • Response
    • NOT_FOUND is the context is not found or the Session bean cannot be found on lookup
    • OK on succes with:
      • Payload: Return value of SessionBean method

Metadata Operations

  • GET /persistence
  • GET /persistence/{unit-name}/metadata
  • GET /persistence/{unit-name}/metadata/entity/{type}
  • GET /persistence/{unit-name}/metadata/query

List Existing Persistence Units

Example:

[
  {
    "rel": "auction",
    "type": "application/json",
    "href": "http://localhost:8080/HenleyAvatarModel/jpa-rs/auction/metadata"
  },
  {
    "rel": "DataAppLibraryPU",
    "type": "application/json",
    "href": "http://localhost:8080/HenleyAvatarModel/jpa-rs/DataAppLibraryPU/metadata"
  }
]

List Types in a Persistence Unit

Example:

{
  "persistence-unit-name": "auction",
  "types": [
    {
      "rel": "User",
      "type": "application/json",
      "href": "http://localhost:8080/HenleyAvatarModel/jpa-rs/auction/metadata/entity/User"
    },
    {
      "rel": "Auction",
      "type": "application/json",
      "href": "http://localhost:8080/HenleyAvatarModel/jpa-rs/auction/metadata/entity/Auction"
    },
    {
      "rel": "Bid",
      "type": "application/json",
      "href": "http://localhost:8080/HenleyAvatarModel/jpa-rs/auction/metadata/entity/Bid"
    }
  ]
}

List Queries in a Persistence Unit

Example:

[
  {
    "query-name": "User.all",
    "reference-type": "jpars.app.auction.model.User",
    "jpql": "SELECT u from User u",
    "link-template": {
      "rel": "execute",
      "method": "get",
      "href": "http://localhost:8080/HenleyAvatarModel/jpa-rs/auction/query/User.all/{parameters}"
    }
  },
  {
    "query-name": "User.updateName",
    "reference-type": "jpars.app.auction.model.User",
    "jpql": "UPDATE User u SET u.name = :name WHERE u.id = :id",
    "link-template": {
      "rel": "execute",
      "method": "post",
      "href": "http://localhost:8080/HenleyAvatarModel/jpa-rs/auction/query/User.updateName/{parameters}"
    }
  }
]

Describe a specific entity

Example:

{
  "name": "User",
  "type": "jpars.app.auction.model.User",
  "link-templates": [
    {
      "rel": "find",
      "type": "application/json",
      "method": "get",
      "href": "http://localhost:8080/HenleyAvatarModel/jpa-rs/auction/entity/Bid/{primaryKey}"
    },
    {
      "rel": "persist",
      "type": "application/json",
      "method": "put",
      "href": "http://localhost:8080/HenleyAvatarModel/jpa-rs/auction/entity/Bid"
    },
    {
      "rel": "update",
      "type": "application/json",
      "method": "post",
      "href": "http://localhost:8080/HenleyAvatarModel/jpa-rs/auction/entity/Bid"
    },
    {
      "rel": "delete",
      "type": "application/json",
      "method": "delete",
      "href": "http://localhost:8080/HenleyAvatarModel/jpa-rs/auction/entity/Bid/{primaryKey}"
    }
  ],
  "attributes": [
    {
      "name": "id",
      "type": "java.lang.Integer"
    },
    {
      "name": "name",
      "type": "java.lang.String"
    }
  ],
  "queries": [
    {
      "query-name": "User.all",
      "reference-type": "jpars.app.auction.model.User",
      "jpql": "SELECT u from User u"
    },
    {
      "query-name": "User.updateName",
      "reference-type": "jpars.app.auction.model.User",
      "jpql": "UPDATE User u SET u.name = :name WHERE u.id = :id"
    }
  ]
}

Entity Representation

Interaction in REST is done through XML and JSON and makes use of EclipseLink's MOXy functionality which provides a JAXB implementation and also leverages that implementation to produce JSON based on the JAXB mappings. Objects are mapped to XML using standard JAXB mapping rules including JAXB defaults and use of a JAXB mappings file. Since all the configuration is in the JPA persistence unit, the JAXB mappings file can be named in the Persistence Unit property called: "eclipselink.jpa-rs.oxm".

Relationships

Sample JSON

The following provides some sample JSON with some regular-expression-like notation.

<code>
{
  numericAttribute: 1
  stringAttribute: "auction1"
  dateAttribute: 12-09-16
  singleRelatedItem: RELATED_ITEM?
    listRelatedItem:
    {
        RELATED_ITEM*
    }
}


RELATED_ITEM =

    {
      numericAttribute: 11
      stringAttribute: "myName"
    }

OR

    {
      rel="self", 
      href=LINK_HREF, 
      method="GET"
    }

Notice: When an entity is the target of a relationship, it can either be completely represented in the JSON, or it can be represented as a Link.

As a rule, JPA RS will marshal relationships using links from GET calls unless they are private-owned in which case the object will be embedded

When using PUT/POST new objects should be embedded and existing object should be supplied using links.

Bidirectional Relationships and Cycles

in progress

XML

in progress

Future Development

http://wiki.eclipse.org/EclipseLink/Development/JPA-RS