20 Exposing JPA Entities Through RESTful Data Services
This chapter includes the following sections:
Use Case
Expose persistent data model and application logic over REST for the development of Thin Server Architecture (TSA) clients including HTML5/JavaScript and mobile technologies.
Solution
Use RESTful Data Services to expose entities using a RESTful service, without writing JAX-RS code.
Components
-
A Java EE application server with the following:
-
TopLink 12c (12.1.2.0.0) or later.
Note:
TopLink's core functionality is provided by EclipseLink, the open source persistence framework from the Eclipse Foundation. EclipseLink implements Java Persistence API (JPA), Java Architecture for XML Binding (JAXB), and other standards-based persistence technologies, plus extensions to those standards. TopLink includes all of EclipseLink, plus additional functionality from Oracle.
-
EclipseLink 2.4 or later.
-
Support for Java API for RESTful Web Services (JAX-RS) 1.0, for example the JAX-RS reference implementation, Jersey (see
http://jersey.java.net/
).
-
-
A compliant Java Database Connectivity (JDBC) database, such as Oracle Database, Oracle Express, or MySQL
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.
The Java API for RESTful Web Services (JAX-RS) is an API designed to make it easy to develop Java applications that use the REST architecture. With JAX-RS, you use annotations to define resources and the actions that can be performed on those resources.
While it is possible to use JAX-RS directly to interact with JPA persistence units in a RESTful application, RESTful Data Services provide an API that makes it easier to implement REST for JPA persistence,. You can use this API to interact with JPA persistence units without explicitly writing JAX-RS code, thus providing a simple way to expose persistence units through REST.
Note:
For an example that uses JAX-RS directly to implement JPA persistence in a RESTful application, see "RESTful Service Example" at http://wiki.eclipse.org/EclipseLink/Examples/REST/GettingStarted
. For information about simplifying that process by using RESTful Data Services, continue reading this chapter.
RESTful Data Services are made available via a web fragment, which extends the capabilities of a web application. The REST functionality is made available by including the RESTful Data Services JAR file in the WEB-INF/lib
folder of a web application.
The RESTful Data Services runtime provides access to all persistence units packaged in the application in which it is running, as well as any dynamic persistence units that are provisioned within it.
Implementing the Solution
This section contains the following tasks for exposing JPA entities using RESTful Data Services:
Step 1: Prerequisites
To implement and use RESTful Data Services, you need:
-
Oracle WebLogic Server 12c (12.1.3) or later, which includes:
-
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 specification.
-
-
Either of the following Java EE application servers:
-
Oracle WebLogic Server 12c (12.1.3) or later.
-
Glassfish Server 3.1.2 or later.
Note:
With Glassfish Server 3.1.2, you must upgrade the EclipseLink version to use the version of the RESTful Data Services shipped in EclipseLink 2.4.2 (and must also include DBWS). See
http://www.eclipse.org/eclipselink/downloads/
for EclipseLink downloads.
Those servers include the following:
-
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 specification.
-
-
The
toplink-dataservices-web.jar
file. This file is included in the TopLink distribution underTOPLINK_HOME
\oracle_common\modules\oracle.toplink_
release_num
, whereTOPLINK_HOME
is the location where you installed TopLink, andrelease_num
is the TopLink release number, such asoracle.toplink_12.1.2
. -
The
org.eclipse.persistence.jpars_
version_num
.jar
file, whereversion_num
is the version of the jpars file, for example,org.eclipse.persistence.jpars_2.4.1.v20121003-ad44345.jar
. This file is included in the EclipseLink distributions from the Eclipse foundation, athttp://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
https://www.oracle.com/technetwork/middleware/toplink/overview/index.html
Step 2: Create and Configure the Application
RESTful Data Services are designed to function with standard JPA applications, with little extra work required beyond enabling the service, as described below:
Step 3: Understand RESTful Data Services URI Basics
URIs used for making REST calls for RESTful Data Services follow these standard patterns:
-
The base URI for an application is:
http://server:port/application-name/persistence/{version}
Note:
The version of RESTful Data Services in TopLink 12.1.2 is
v1.0
, and that version number should be used to make REST requests to RESTful Data Services. For example, the base URI for RESTful Data Services in an application using the current version of RESTful Data Services would be something likehttp://localhost:8080/exampleApp/persistence/v1.0
.Note:
As of EclipseLink 2.4.2, support for using RESTful Data Services URIs without a version number is deprecated and will be removed in future releases. The version of RESTful Data Services in EclipseLink 2.4.2 is
v1.0
, and that version number should be used to make REST requests to RESTful Data Services. -
For base operations on the persistence unit, add the persistence unit name:
/persistence/{version}/{unit-name}
-
For specific types of operations, add the type of operation, for example:
-
Entity operations:
/persistence/{version}/{unit-name}/entity
-
Query operations:
/persistence/{version}/{unit-name}/query
-
Single result query operations:
/persistence/{version}/{unit-name}/singleResultQuery
-
Persistence unit level metadata operations:
/persistence/{version}/{unit-name}/metadata
-
Base operations:
/persistence/{version}
-
For complete documentation on how to construct these URIs, see RESTful Data Services API Reference.
Step 4: Represent Entities Using JPA, JAXB, or JSON
Entities in RESTful Data Services are represented in two ways:
-
As JPA Entities - The mappings of the JPA entities must be represented in the typical 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, RESTful Data Services use 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'spersistence.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 an 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 handled is as follows:
JPA bidirectional relationships are defined to have an owning side and a non-owning side. The entity that has the table with a foreign key in the database is the owning entity. The other table--the one pointed to--is the inverse (non-owning) entity. JPA mapping provides a mapped-by attribute that defines which is which. The mappedBy
attribute must be on the inverse side. RESTful Data Services default 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
withid=1
andmyB = B1
-
B1
withid=11
andmyA = A1
...the following JSON corresponds to those objects:
A { id:1 } B { id:11 myA: { id: 1 } }
Passing By Value vs. Passing By Reference
RESTful Data Services allow relationship objects to be passed either by value or by reference in the REST request. JSON attributes hold resource references (see "Pass By Value"), while _relationship
s have "navigation" links (see "Pass By Reference").
Pass By Value
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 } }
Pass By Reference
To pass an object by reference, use a _link
. The link represents the RESTful Data Services call necessary to get that object. The following JSON passes myA
by reference:
B { id:11 myA { _link:{ href: "http://localhost:8080/app/persistence/v1.0/pu/entity/A/1" method: "GET" rel: "self" } } }
A link
consists of href
, method
and rel
attributes.
-
The
href
(Hypertext REFerence) is the URI of the entity linked to. Thehref
uniquely identifies the linked entity or attribute. -
The
method
identifies the operation thehref
is to be used for. -
The
rel
represents the relationship between the containing entity and the entity linked to.
Lists can mix and match items represented by reference and by value. The corresponding entity must exist if an item is represented by reference in a request; otherwise RESTful Data Services returns an error.
The following example shows JSON that can be sent to RESTful Data Services as a request, in a regular-expression-like syntax:
{ "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 Auction
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, "bids": [ { "_link": { "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/auction/entity/Bid/5", "method": "GET", "rel": "self" } }, { "_link": { "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/auction/entity/Bid/6", "method": "GET", "rel": "self" } } ] }
XML representation mimics the JSON representation. The following is sample XML for an entity called Auction
, with several directly mapped attributes and a list of an entity called Bid
.
<?xml version="1.0" encoding="UTF-8"?> <Auction> <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> <bids> <_link href="http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/auction/entity/Bid/5" method="GET" rel="self" /> </bids> <bids> <_link href="http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/auction/entity/Bid/6" method="GET" rel="self" /> </bids> </Auction>
Step 5: 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 in RESTful Data Services API Reference.
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.
Note:
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 RESTful Data Services 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 EntityManager
s, EntityManagerFactory
s and JAXBContext
s are logged in the same manner as other EclipseLink logging.
Step 7: Understand the Structure of RESTful Data Services Responses
The RESTful Data Services response messages, either in XML or in JSON, contain following categories:
-
Basic data types, such as
int
,double
,String
,Integer
,Double
,Boolean
, etc. -
Relationships (links and relationships)
The next sections explain the semantic and syntactic details of each category of data.
There is also a minor generic difference between the XML and JSON responses (other than format). The JSON responses do not include the root name of an entity, while XML responses do. See the employee
root/grouping name in the XML response below. The root name is derived from the name of the entity it represents.
JSON
{ "firstName":"John", "lastName": "Smith", … }
XML
<?xml version="1.0" encoding="UTF-8"?> <employee> <firstName>John</firstName> <lastName>Smith</lastName> … </employee>
Basic Data Types
In the RESTful Data Services responses, basic data types and primitives are presented as simple JSON or XML fields. For example:
JSON
{ "firstName":"John", "lastName": "Smith", … }
XML
<?xml version="1.0" encoding="UTF-8"?> <employee> <firstName>John</firstName> <lastName>Smith</lastName> … </employee>
Links and Relationships
RESTful Data Services operations return all relationships by reference, with the exception of JPA embeddables and element collections.
The relationships
are links pointing to the (JPA) relationships of an entity, such as one-to-one and one-to-many. For example, assume that an employee has multiple phone numbers (one-to-many). When the employee is read, the response will contain a relationship link pointing to the relationship between the employee and the phone entities, plus a list of the links, with each link pointing to a (unique) phone number that the employee owns. For example:
{ "firstName": "Jacob", "gender": "Male", "id": 743627, "lastName": "Smith", "version": 1, "_relationships": [ { "_link": { "href": "http://localhost:8080/eclipselink.jpars.test/persistence/hr/entity/Employee/743627/phoneNumbers", "rel": "phoneNumbers" } } ], "phoneNumbers": [ { "_link": { "href": "http://localhost:8080/eclipselink.jpars.test/persistence/hr/entity/PhoneNumber/743627+cell", "method": "GET", "rel": "self" } }, { "_link": { "href": "http://localhost:8080/eclipselink.jpars.test/persistence/hr/entity/PhoneNumber/743627+work", "method": "GET", "rel": "self" } } ] }
Embedded objects and element collections are strictly privately-owned (dependent) objects.They have no identity, and there is no cascade option on an ElementCollection
. The target objects are always persisted, merged, and removed with their parent. Therefore, RESTful Data Services embeds these objects directly in responses, rather than providing links to them. For example, assume the Employee
object has EmploymentPeriod
defined as Embedded
. When the Employee
is read, the response will contain EmploymentPeriod
as an embedded object, not a link to it. Relationships are currently not supported for embedded attributes. See the example below:
{ "firstName": "John", "lastName": "Smith", "employmentPeriod": { "startDate": "2010-04-23T14:12:03.905-04:00", "endDate": "2013-01-23T12:00:02.301-04:00", "_relationships": [] }, ... }
Similarly, element collections are also directly contained in RESTful Data Services responses as collections, not as links. For example, assume the Employee
object has a "certifications"
attribute defined as a collection of Certification
objects. When the Employee
is read, the response will contain list of Certification
objects, not links:
{ "firstName": "John", "lastName": "Smith", "certifications": [ { "issueDate": "2013-04-23T15:02:23.071-04:00", "name": "Java" }, { "issueDate": "2010-05-23T11:02:23.033-04:00", "name": "Weblogic" } ], ... }
Additional Resources
See the following resources for more information about the technologies and tools used to implement the solutions in this chapter:
-
"Building RESTful Web Services with JAX-RS" in The Java EE 6 Tutorial at
http://docs.oracle.com/javaee/6/tutorial/doc/giepu.html
. -
"RESTful Service Example" at
http://wiki.eclipse.org/EclipseLink/Examples/REST/GettingStarted
. -
JSR 311: JAX-RS: The Java API for RESTful Web Services" at
http://jcp.org/en/jsr/detail?id=311
-
Jersey project at
http://jersey.java.net/
.
RESTful Data Services API Reference
The following types of RESTful operations can be used with JPA via HTTP when using RESTful Data Services:
Entity Operations
Entity operations are those performed against a specific entity type within the persistence unit.
The base URI for entity operations is as follows:
/persistence/{version}/{unit-name}/entity/{type}/*
The {type}
value refers to the type name (descriptor alias).
Supported entity operations are:
FIND
HTTP Request Syntax
GET /persistence/{version}/{unit-name}/entity/{type}/{id}?{hints}
where:
-
{id}
is a string -
hints
are specified using HTTP query parameters, with the key being the name of the EclipseLink query hint
Example
GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo/1
Produces
JSON or XML
Response
-
OK
, with a payload containing the entity -
NOT_FOUND
if the entity does not exist
Usage
Composite Keys
Composite keys are supported. The +
character is reserved and therefore cannot be used in fields that represent keys. Composite keys are separated using the +
character and should be specified in an order corresponding to the Java default sorting of the attribute names.
For example, consider an entity Phone
, with attributes extB
=123
and extA
=321
. The URL to find the entity is:
http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Phone/321+123
The 321
comes before the 123
because extA
comes before extB
when sorted in Java.
Result Caching
Default EclipseLink and HTTP caching is enabled and configured through standard means.
Refresh
The EntityManager.refresh
operation can be invoked using the find
with the query hint for Refresh
.
Attributes
Navigating into the attributes of an entity (for example, to get the Address
entity associated with an employee in a single REST request) is supported to one level, for example:
/persistence/v1.0/{unit-name}/entity/{type}/{id}/{relationship}
will work
while
/persistence/v1.0/{unit-name}/entity/{type}/{id}/{relationship}/{index}/{relationship2
} will not
PERSIST
HTTP Request Syntax
PUT /persistence/{version}/{unit-name}/entity/{type}
Example
PUT http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo
Consumes
JSON or XML
Payload
Entity
Produces
JSON or XML
Response
Payload containing the entity returned by the persist operation
Usage
PUT
is required to be idempotent. 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
HTTP Request Syntax
POST /persistence/{version}/{unit-name}/entity/{type}
Example
POST http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo
Consumes
JSON or XML
Payload
Entity
Produces
JSON or XML
Response
Payload containing the entity returned by the merge operation.
Merge takes an object graph and makes it part of the persistence context through comparison. It compares the object and all related objects to the ones that already exist and issues INSERT
s, UPDATE
s, and DELETE
s to put the object in the persistence context.
Entity Operations on Relationships
The base URI for relationship operations is as follows:
/persistence/{version}/{unit-name}/entity/{entity}/{id}/{relationship}
Supported relationship operations are:
READ
Use this operation to get the values of a relationship.
HTTP Request Syntax
GET /persistence/{version}/{unit-name}/entity/{type}/{id}/{relationship}
where:
-
{id}
is a string. -
{relationship}
is the JPA name of the relationship.
Example
GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo/1/myRelationship
Produces
JSON or XML
Response
-
OK
, Payload containing an entity or a list of entities. -
NOT_FOUND
if the entity does not exist
ADD
Use this operation to add to a list or replace the value of a many-to-one relationship.
HTTP Request Syntax
POST /persistence/{version}/{unit-name}/entity/{type}/{id}/{relationship}?{partner}
Note:
partner
must be specified as a query parameter. Do not specify partner
as a matrix parameter.
Note:
As of EclipseLink 2.4.2, partner
should be specified as a query parameter. Specifying partner
as a matrix parameter is deprecated.
Examples
For unidirectional relationships, {partner}
is not required, for example:
POST http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo/1/myRelationship
For bi-directional relationships, you must provide the name of the attribute that makes up the opposite side of the relationship. For example, to update an Auction.bid
where the opposite side of the relationship is Bid.auction
, use the following:
POST http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo/1/myRelationship?partner=bid
Consumes
JSON or XML
Payload
Entity with the new value.
Note:
Relationship objects can be passed by value or by reference. See Passing By Value vs. Passing By Reference.
Produces
JSON or XML
Response
Payload containing the entity with the added element
REMOVE
Use this operation to remove a specific entity from the list or a null on a many-to-one relationship.
HTTP Request Syntax
DELETE /persistence/{version}/{unit-name}/entity/{type}/{id}/{relationship}?{relationshipListItemId}
where relationshipListItemId
is an optional query parameter. The relationshipListItemId
is meaningful only when the {relationship}
to be removed is a list. The relationshipListItemId
should be set to the id
of a member in the relationship list when only that member of the relationship list needs to be removed. The entire list specified by the {relationship}
will be removed when relationshipListItemId
is not specified.
Example
DELETE http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo/1/myRelationship
Consumes
JSON or XML
Note:
Relationship objects can be passed by value or by reference. See Passing By Value vs. Passing By Reference.
Produces
JSON or XML
Response
-
OK
-
Payload containing the entity with the removed element
Query Operations
The base URI for query operations is as follows:
GET /persistence/{version}/{unit-name}/query/{name}{params}
The following query operations are supported:
Named queries doing reads can be run two ways in JPA. Both are supported in the REST API. They are:
Query Returning List of Results
HTTP Request Syntax
GET /persistence/{version}/{unit-name}/query/{name};{parameters}? {hints}
where:
-
parameters
are specified using HTTP matrix parameters -
hints
are specified using HTTP query parameters and with the key being the name of the EclipseLink query hint
Examples
GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/query/Foo.findByName;name=myname
GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/query/Foo.findByName;name=myname?eclipselink.jdbc.max-results=500
Produces
JSON or XML
Response
A payload containing a list of entities. An XML response contains a List
as a grouping name for a collection of items and item
as a grouping name for each member of a collection returned. JSON responses use square brackets []
to encapsulate a collection and curly braces {}
to encapsulate each member of a collection. For example:
XML Example
<?xml version="1.0" encoding="UTF-8"?> <List> <item> <firstName>Miles</firstName> <lastName>Davis</lastName> <manager> <firstName>Charlie</firstName> <lastName>Parker</lastName> <gender>Male</gender> <id>26</id> </manager> </item> <item> <firstName>Charlie</firstName> <lastName>Parker</lastName> <manager> <firstName>Louis</firstName> <lastName>Armstrong</lastName> <gender>Male</gender> <id>27</id> </manager> </item> </List>
JSON Example
[ { "firstName": "Miles", "lastName": "Davis", "manager": { "firstName": "Charlie", "lastName": "Parker", "gender": "Male", "id": 26 } }, { "firstName": "Charlie", "lastName": "Parker", "manager": { "firstName": "Louis", "lastName": "Armstrong", "gender": "Male", "id": 27 } } ]
Update/Delete Query
HTTP Request Syntax
POST /persistence/{version}/{unit-name}/query/{name};parameters?hints
where:
-
parameters
are specified using HTTP matrix parameters -
hints
are specified using HTTP query parameters and with the key being the name of the EclipseLink query hint
Examples
POST http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/query/Foo.deleteAllByName;name=myname
POST http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/query/Foo.updateName;name=myname?eclipselink.jdbc.max-results=500
Produces
JSON or XML
Response
A payload containing the number of entities updated or deleted
Single Result Queries
HTTP Request Syntax
GET /persistence/{version}/{unit-name}/singleResultQuery/{name};{parameters}?{hints}
where:
-
parameters
are specified using HTTP matrix parameters -
hints
are specified using HTTP query parameters and with the key being the name of the EclipseLink query hint
Example
GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/singleResultQuery/Foo.findByName;name=myname
Produces
JSON, XML, or application/octet-stream
Response
A payload containing an entity
Base Operations
Base operations are:
List Existing Persistence Units
HTTP Request Syntax
GET /persistence/{version}
Example
GET http://localhost:8080/exampleApp/persistence/v1.0
Produces
JSON or XML
Response
A payload containing a list of persistence unit names and links to metadata about them. For example:
[ { "_link": { "href": "http://localhost:8080/exampleApp/persistence/v1.0/employee/metadata", "method": "application/json", "rel": "employee" } }, { "_link": { "href": "http://localhost:8080/exampleApp/persistence/v1.0/traveler/metadata", "method": "application/json", "rel": "traveler" } } ]
Metadata Operations
The following metadata operations are supported:
List Types in a Persistence Unit
HTTP Request Syntax
GET /persistence/{version}/{unit-name}/metadata
Example
GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/metadata
Produces
JSON
Response
-
OK
, with a payload containing a list of types, with links to more detailed metadata, for example:{ "persistenceUnitName": "hr", "types": [ { "_link": { "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/metadata/entity/Employee", "method": "application/json", "rel": "Employee" } }, { "_link": { "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/metadata/entity/PhoneNumber", "method": "application/json", "rel": "PhoneNumber" } } ] }
-
NOT_FOUND
if the persistence unit is not found
List Queries in a Persistence Unit
HTTP Request Syntax
GET /persistence/{version}/{unit-name}/metadata/query
Example
GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/metadata/query
Produces
JSON
Response
-
OK
with a payload containing a list of all available queries, for example:[ { "queryName": "Employee.count", "returnTypes": [ "Long" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.count", "rel": "execute" }, "jpql": "SELECT count(e) FROM Employee e" }, { "queryName": "EmployeeAddress.getRegion", "returnTypes": [ "String", "String", "String" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/EmployeeAddress.getRegion", "rel": "execute" }, "jpql": "SELECT u.postalCode, u.province, u.street FROM EmployeeAddress u" }, { "queryName": "Employee.getPhoneNumbers", "returnTypes": [ "String", "String", "PhoneNumber" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.getPhoneNumbers", "rel": "execute" }, "jpql": "SELECT e.firstName, e.lastName, pn FROM Employee e JOIN e.phoneNumbers pn" }, { "queryName": "EmployeeAddress.getPicture", "returnTypes": [ "byte[]" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/EmployeeAddress.getPicture;id={id}", "rel": "execute" }, "jpql": "SELECT u.areaPicture FROM EmployeeAddress u where u.id = :id" }, { "queryName": "EmployeeAddress.updatePostalCode", "returnTypes": [ "EmployeeAddress" ], "linkTemplate": { "method": "post", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/EmployeeAddress.updatePostalCode;postalCode={postalCode};id={id}", "rel": "execute" }, "jpql": "UPDATE EmployeeAddress u SET u.postalCode = :postalCode where u.id = :id" }, { "queryName": "Employee.salaryMax", "returnTypes": [ "int", "Object" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.salaryMax", "rel": "execute" }, "jpql": "SELECT e.id, max(e.salary) AS max_salary from Employee e GROUP BY e.id, e.salary" }, { "queryName": "EmployeeAddress.getAll", "returnTypes": [ "EmployeeAddress" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/EmployeeAddress.getAll", "rel": "execute" }, "jpql": "SELECT u FROM EmployeeAddress u" }, { "queryName": "EmployeeAddress.getById", "returnTypes": [ "EmployeeAddress" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/EmployeeAddress.getById;id={id}", "rel": "execute" }, "jpql": "SELECT u FROM EmployeeAddress u where u.id = :id" }, { "queryName": "Employee.getManagerById", "returnTypes": [ "String", "String", "Employee" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.getManagerById;id={id}", "rel": "execute" }, "jpql": "select u.firstName, u.lastName, u.manager from Employee u where u.id = :id" }, { "queryName": "Employee.findAll", "returnTypes": [ "Employee" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.findAll", "rel": "execute" }, "jpql": "SELECT e FROM Employee e ORDER BY e.id" }, { "queryName": "Employee.getManager", "returnTypes": [ "String", "String", "Employee" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.getManager", "rel": "execute" }, "jpql": "select u.firstName, u.lastName, u.manager from Employee u" } ]
-
NOT_FOUND
if persistence unit is not found
Describe a Specific Entity
HTTP Request Syntax
GET /persistence/{version}/{unit-name}/metadata/entity/
type
Example
GET http://localhost:8080/CustomerApp/persistence/v1.0/Inventory/metadata/entity/Customer
Produces
JSON
Response
-
OK
, with a payload containing details about the entity and available operations on it, for example,{ "name": "Employee", "attributes": [ { "name": "id", "type": "int" }, { "name": "firstName", "type": "String" }, { "name": "gender", "type": "Gender" }, { "name": "lastName", "type": "String" }, { "name": "salary", "type": "double" }, { "name": "version", "type": "Long" }, { "name": "period", "type": "EmploymentPeriod" }, { "name": "manager", "type": "Employee" }, { "name": "office", "type": "Office" }, { "name": "address", "type": "EmployeeAddress" }, { "name": "certifications", "type": "List<Certification>" }, { "name": "responsibilities", "type": "List<String>" }, { "name": "projects", "type": "List<Project>" }, { "name": "expertiseAreas", "type": "List<Expertise>" }, { "name": "managedEmployees", "type": "List<Employee>" }, { "name": "phoneNumbers", "type": "List<PhoneNumber>" } ], "linkTemplates": [ { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/entity/Employee/{primaryKey}", "rel": "find" }, { "method": "put", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/entity/Employee", "rel": "persist" }, { "method": "post", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/entity/Employee", "rel": "update" }, { "method": "delete", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/entity/Employee/{primaryKey}", "rel": "delete" } ], "queries": [ { "queryName": "Employee.count", "returnTypes": [ "Long" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.count", "rel": "execute" }, "jpql": "SELECT count(e) FROM Employee e" }, { "queryName": "Employee.getPhoneNumbers", "returnTypes": [ "String", "String", "PhoneNumber" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.getPhoneNumbers", "rel": "execute" }, "jpql": "SELECT e.firstName, e.lastName, pn FROM Employee e JOIN e.phoneNumbers pn" }, { "queryName": "Employee.salaryMax", "returnTypes": [ "int", "Object" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.salaryMax", "rel": "execute" }, "jpql": "SELECT e.id, max(e.salary) AS max_salary from Employee e GROUP BY e.id, e.salary" }, { "queryName": "Employee.getManagerById", "returnTypes": [ "String", "String", "Employee" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.getManagerById;id={id}", "rel": "execute" }, "jpql": "select u.firstName, u.lastName, u.manager from Employee u where u.id = :id" }, { "queryName": "Employee.findAll", "returnTypes": [ "Employee" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.findAll", "rel": "execute" }, "jpql": "SELECT e FROM Employee e ORDER BY e.id" }, { "queryName": "Employee.getManager", "returnTypes": [ "String", "String", "Employee" ], "linkTemplate": { "method": "get", "href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.getManager", "rel": "execute" }, "jpql": "select u.firstName, u.lastName, u.manager from Employee u" } ] }
-
NOT_FOUND
if the persistence unit is not found