Using Java Persistence API(JPA) in bluemix with EJBs

This article will demonstrate how to deploy a typical JPA application into the BlueMix cloud.It makes use of a JPA Sample Application, bound to a db2 database, driven by either EJBs or Servlets.

JPA (Java Persistence API) is a set of APIs that is used for reading and writing data to databases via Java objects.

An EJB (Enterprise Java Bean) is a server side Java object that contains business logic with special qualities of service (collaborators) such as transactions and security.

The article provides code snippets for EJBs and JPA, and a sample application. It explains how to push this application to BlueMix, making use of the auto-config support to connect to a DB2 database. Auto-config is a feature of the BlueMix runtime that facilitates the connection of an application to a back end resource, such as a database, shielding the customer from the complexity of configuring resource XML stanzas or even creating the database itself.

Overview

1. Importing the Sample into Eclipse2. EJBs3. JPA4. Persistence Units, persistence.xml and mapping to the database for JPA5. Explanation of Auto-config6. Pushing the standalone war file7. Running the Application

1. Importing the Sample into Eclipse

Next if you want to examine the source and run the sample application yourself, you can get it from here: JPABlueMixProjectRead instructions in the README.MD file to get the project set up with the CF plugin in Eclipse.

2. EJBs (Enterprise Java Beans)The sample uses annotations to create callable handles to EJBs that are invoked from servlets.Annotations (e.g. @EJB ListDBEJB listEJB; ) simplify the process of creating these callable handles to EJBs by justspecifying the EJB class name (e.g. ListDBEJB) followed by the instance name (e.g. listEJB):

input.setSql(Boolean.parseBoolean(request.getParameter("isMySQL"))); // set the DB type into // input objectoutput = listEJB.list(input); // call the ejb and get the results in output instance

EJB definition in the EJB’s java file containing your business logic:

@Stateless // annotation for stateless session EJB bean
@LocalBean // local ejb, can only be called from within same JVM, as per ejbLite feature
public class ListDBEJB {
// your methods and business logic here
}

The ListDB functions lists out the customers in the database table using a named query (query invoked from a servlet or EJB, but the query itself is defined in the JPA entity):

EntityManager em = emfToUse.createEntityManager(); // get an entity manager handle
OpenJPAQuery q = OpenJPAPersistence.cast(em
.createNamedQuery("listCustomers")); // run the named query
Collection coll = null;
coll = q.getResultList(); // gather up the result set into a java collection
if (coll != null) { // if we have results
Iterator it = coll.iterator(); // get the collection into a java iterator
CustomerAcct[] cas = new CustomerAcct[8]; // set up an array for the results
int i = 0;
CustomerAcct ca = null;
while (it.hasNext()) { //iterate through the results of the query
ca = (CustomerAcct) it.next(); // get the next result
System.out.println("customer acct from result set: "+ca);
cas[i] = ca;
i++;
}
ob.setCustomerAccts(cas); //set array of customers into output object
}

4. Persistence Units, persistence.xml and mapping to the database for JPA

Persistence units specify the persistent unit names, dataSources and JPA entity name(s) necessary to access the database table.The persistence.xml, which describes the persistence units, is under the src/META-INF folder.

The business logic of an application can inject a Persistence Unit (via annotation: @PersistenceUnit) and use it to to gain access to a database table which automatically maps that table to a JPA entity, easing accessing to the database table:

Example annotation to inject a persistent unit: (as used in the business logic/java code of all of the EJBs and Servlets in this sample)

If you prefer to using the command line you can get the war file: JPABlueMixProject.war and push the sample application using CF Commands, creating and binding the required services (dataSource in this case):

[ERROR ] CWWJP0013E: The server cannot locate the jdbc/MyDataSourceDB2 data source for the CustomerQueryDB2 persistence unit because it has encountered the following exception: javax.naming.NameNotFoundException: Intermediate context does not exist: jdbc/MyDataSourceDB2.
[ERROR ] CNTR0020E: EJB threw an unexpected (non-declared) exception during invocation of method “list” on bean “BeanId(myapp#myapp#ListDBEJB, null)”. Exception data: org.apache.openjpa.persistence.ArgumentException: The persistence provider is attempting to use properties in the persistence.xml file to resolve the data source. A Java Database Connectivity (JDBC) driver or data source class name must be specified in the openjpa.ConnectionDriverName or javax.persistence.jdbc.driver property. The following properties are available in the configuration: “WsJpaJDBCConfigurationImpl@a004b24f: PDQ disabled: AccessIntent Task=disable”.

I had posted another comment about an exception I get when I try to run application but it seems that was never published. Here is the detail which I had posted last time.

I get following exception when I try to run application to ‘populate database’ or ‘list database content’ with either EJB or Servlet option event though I do have SQLDB service called “MyDataSourceDB2″ associated with my application.

[ERROR ] CWWJP0013E: The server cannot locate the jdbc/MyDataSourceDB2 data source for the CustomerQueryDB2 persistence unit because it has encountered the following exception: javax.naming.NameNotFoundException: Intermediate context does not exist: jdbc/MyDataSourceDB2.
[ERROR ] CNTR0020E: EJB threw an unexpected (non-declared) exception during invocation of method “list” on bean “BeanId(myapp#myapp#ListDBEJB, null)”. Exception data: org.apache.openjpa.persistence.ArgumentException: The persistence provider is attempting to use properties in the persistence.xml file to resolve the data source. A Java Database Connectivity (JDBC) driver or data source class name must be specified in the openjpa.ConnectionDriverName or javax.persistence.jdbc.driver property. The following properties are available in the configuration: “WsJpaJDBCConfigurationImpl@a004b24f: PDQ disabled: AccessIntent Task=disable”.
at org.apache.openjpa.jdbc.schema.DataSourceFactory.newDataSource(DataSourceFactory.java:72)
at org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl.createConnectionFactory(JDBCConfigurationImpl.java:849)

I have found a Tech Note from IBM stating that it is defect in WAS and fix is available in WAS 8.5.0.1. Has anyone tried to run this application recently? Or have I missed something obvious which is causing exception in my application?

I had noticed the case sensitive name of the datasource when I was first building my app and I had used ‘MyDataSourceDB2′ instead of ‘MyDataSourcedb2′ and still I was getting the error I mentioned earlier.

I suspect when you ( or other people) had build and run this application then it might be using different version of Java Liberty. I guess if you try to run same application now then you might get same error as I am getting.

Thanks a lot Dave, I have everything working now, however I will like to use postgreSql or MySql instead of DB2, as far as I understand I should modify the server.xml, however I don´t know if is possible just to modify the file without creating a new Liberty server. In the case I have to create the server do I setup one locally, test everything local and then upload to bluemix?

Hi Dave. Your explanation of the project is really good. I can’t deny getting benefited from it. But I have a doubt here-

How can I know what is the database schema being used for creation of the table. I tried to search the table name CUSTOMERACCT in the IBM Managed Database Service console. But I couldn’t get it. Can you please let me know, how can I search for the table in console, and is there any way to specify my own schema name.

Please note that MANISH is the schema name and EMPLOYEE is the table name.
I googled this error. I understand that this error says that it couldn’t find the table. But then why is this condition arising.

Do you have a create statement in your code? Or preferably you should have something like this in your persistence.xml to create the table (you can see this in the persistence.xml for the sample that goes with this article):

I would like to build the app locally in my Eclipse with Derby and then push to BlueMix and use SQLDB. However persistence.xml only allows single per file. What is the best practice to deal with this? Shall I create two persistence.xml files on a side and rebuild the project before I do cf push with a different persistence.xml file?

If I used JDBC then all configuration can be done via VCAPS programmatically in the code – is there any way to do this programmatically when using JPA?