Tuesday, October 30, 2012

Easy way to access JPA with REST (JSON / XML)

With the release of EclipseLink 2.4, JPA persistence units can be accessed using REST with JSON or XML formatted messages. The 2.4 version supports JPA-RS which is a RESTful API for dealing with JPA. In this blogpost I will show you what is possible with JPA-RS, how easy it is and howto setup your own EclipseLink REST service. This is also possible when you want to expose database tables as SOAP Web Service, for more information on this topic see my blog about Eclipselink DBWS.

To test these REST Services I added the Dev HTTP Client extension to my Google Chrome browser.  Here you can download my testcases which I used in this blogpost and it is possible to import these in the Dev HTTP Client extension.

It is very important with every invocation to set the Accept HTTP Header property with application/json or application/xml as value, else you will get an error and EclipseLink won't know the requested response format.

We can start with HTTP GET and http://localhost:8080/HR-JPA-RS/persistence/ as url , This will show you all the JPA persistence units.  persistence is the mapping of the JPA-RS Servlet ( it's a web-fragment in the JPA-RS eclipselink jar ) and HR-JPA-RS is the context url of my GlassFish web application.


Now we know the Persistence Units we can ask for all the Entities of this particular HRLocal Persistence Unit. Use http://localhost:8080/HR-JPA-RS/persistence/HRLocal/metadata
This gives us the Department, Location and Employee entities of the Oracle HR Demo schema.


Next step is to retrieve the metadata of the Departments Entity. Here you can see all the entity attributes and relationships to the other entities, the supported Rest operations plus the Named Queries you can call.
http://localhost:8080/HR-JPA-RS/persistence/HRLocal/metadata/entity/Departments



We can call for example the findAll namedquery http://localhost:8080/HR-JPA-RS/persistence/HRLocal/query/Departments.findAll , a particular record http://localhost:8080/HR-JPA-RS/persistence/HRLocal/entity/Departments/190 or localhost:8080/HR-JPA-RS/persistence/HRLocal/query/Departments.findById;departmentId=200



To retrieve the manager of this department we can add manager to this url.  http://localhost:8080/HR-JPA-RS/persistence/HRLocal/entity/Departments/190/manager


When we want XML as response instead of JSON we can set the Accept HTTP Header to application/xml




Click here for more information what is possible with JPA-RS

Next step of this blogpost is about howto setup this eclipselink environment. For this I used OEPE ( Oracle Eclipse ) as IDE and GlassFish 3.12 as J2EE server. ( You can also use WebLogic 12c )

First we need to update the EclipseLink version of GlassFish to at least version 2.4.1. See this Oracle blogpost how to replace the current version of eclipselink . Also had to add org.eclipse.persistence.jpa.jpql.jar to this module folder.

This is my workspace overview. It contains a JPA and Web project and off course the EAR project.

In the web project I added the org.eclipse.persistence.jpars_2.4.xxx.jar to the lib folder of the WEB-INF.
The meta-inf folder inside this jar contains the web-fragment xml and this will automatically added to your web.xml ( if its support version 3.0 of the web-app )

The last step is to set the Persistence Units to Local Resource instead of JTA Datasource, else it won't work.

Here you can download the eclipse projects.

5 comments:

  1. Thanks for the tutorial, but I think that some of the files in the eclipse projects are missing...

    ReplyDelete
    Replies
    1. Hi,

      thanks,

      what are you missing, I didn't export the whole space and the .metadata folder.

      Delete
    2. You're right, I was running the application on Tomcat and I had to manually copy the content of web-fragment.xml to web.xml.

      Really cool way to expose RESTful APIs!

      Delete
  2. Does JPA-RS support dynamically exposing projection queries of entities. For example obtaining only the email and lastName of an employee by ID, without it being an already defined @NamedQuery?

    ReplyDelete
    Replies
    1. Hi,

      I don't think so, I did not see this feature.

      I know with coherence Rest you got something like this.
      http://url/Department/100;p=departmentId,departmentName

      http://biemond.blogspot.nl/2013/08/coherence-1212-rest-application-build.html

      Thanks

      Delete