[Part 1] Websphere Liberty Profile: OSGi and JPA

Part 1 of 4 Part Series: JPA, JAX-RS, Blueprint, BPM

OSGi and JPA


Forward: 

Leading me towards Websphere Liberty was the need for rapid integration development on BPM projects. Though Websphere is an excellent enterprise-class server, it was a little too big for development and unit testing at the desktop level. This isn't to say that my desktop wasn't up to the challenge... However, Websphere just can't beat the average 300ms turnaround on deployments directly from Eclipse (server configuration set for "automatic deployment").

Additionally, given Libery's discrete run-time configuration (relatively) I'm able to easily deploy and propagate reference applications accross my development team. With Liberty running at the desktop, there's no longer a need for deploy/restart cycles on a shared Websphere server platform. And Liberty's minimal configuration requirements significantly reduces training overhead.

Finally... Liberty runs OSGi bundles!

There are other OSGi capable platforms. But, IBM provides Eclipse tooling for new developers to help them quickly ramp-up on this technology. And most importantly, OSGi bundles built for Liberty port to Websphere Application Server (unless we have Liberty running in production - an ideal solution but this may take some additional time for adoption).



Development Platform and Tools: 
(see "resources" for additional equipment)
- Windows 7-64
- Eclipse Indigo SR2 (see requirements on Liberty tools download page)
- WebSphere® Application Server tools,  V8.5 Liberty Profile
- Liberty server v8.5.0.2: wlp-developers-8.5.0.2.jar 
- Database: Derby 10.10.1.1 (using Networked configuration)

NOTE: Though the new, extended beta (refresh) had many nice features... (i.e. CXF?) I ran into a few issues that required that I drop back to the GA release. I'll demonstrate the new beta-refresh in another write-up. 



Reference:

Apache ARIES Blueprint tutorial
http://aries.apache.org/documentation/tutorials/blueprinthelloworldtutorial.html 

Blueprint Services by Guillaume Nodet (slideshare)
http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=blueprintservices-090622184559-phpapp01&stripped_title=osgi-blueprint-services-1622424 

OSGi JAX-RS and bnd declerative service
http://stackoverflow.com/questions/10200347/osgi-jax-rs-and-bnd-declerative-service 



Resources:

Download: WebSphere® Application Server Developer Tools 
https://www.ibm.com/developerworks/community/blogs/wasdev/entry/download_wdt?lang=en 

Download: WebSphere Application Server Liberty Profile 
https://www.ibm.com/developerworks/community/blogs/wasdev/entry/download_wlp?lang=en 

BairTail (win tail utility)
http://www.baremetalsoft.com 



OSGi and JPA on Liberty Profile


1) Create a Database and Eclipse Database Connection
Need this for the JPA eclipse plugi-in

I'm using Derby 10.10.1.1 with the "networked" client configuration
- Networked setup allowed me to use both Eclipse and DBVisualizer

Pitfall: Make sure to create a schema matching the DB user-name used in Liberty "datasource" and Eclipse database connection. JPA likes to default to the logged in user's schema. I wasn't able to set to a different "default schema" 





2) Create Eclipse Database Connection


Eclipse Database Connection
Make sure to use an eclipse database connection name that matches your eventual Liberty datasource JNDI name. For example, if you're Liberty datasource jndi name is "jdpc/jpa_test" then name the eclipse database connection "jpa_test". 

Pitfall: JPA plug-in likes to use the Eclipse database connection name for the JNDI name (and will switched this back after you've corrected it in "persistence.xml". So, make sure to use a database connection name that will exactly match your Liberty datasource JNDI name. 

Database Connection


Connection Properties




3) Create Liberty JDBC Driver and Datasource

Snippet from the "server.xml" configuration
See appendix for full "server.xml" configuration
<jdbcDriver id="jdpc_driver_derby_for_jpa">
   <library id= "DerbyLib2">
        <fileset dir="O:\derby\db-derby-10.10.1.1-bin\db-derby-10.10.1.1-bin\lib" includes="derbyclient.jar" />
   </library>
</jdbcDriver >
<dataSource id="DerbyJPA_TEST" jdbcDriverRef="jdpc_driver_derby_for_jpa" jndiName="jdbc/JPA_TEST" >
  <properties.derby.client databaseName= "jpa_test" password="{xor}NS8+ACs6LCs=" serverName="babe" user= "jpa_test"/>
</dataSource >


4) Create JPA OSGi Bundle Project

Top-menu: File -> New -> Other -> filter Wizard on "osgi" ->OSGi Bundle Project


OSGi Bundle Project
Project name: osgi_jpa_03 (yes... 3rd attempt. Ran into a few issues and discoveries)
Target runtime: Liberty (I'm using v8.5.0.2)
Add persistence Support: checked, JPA 2.0
-> Next


Java: Leave defaults
-> Next


JPA Facet
Platform: Generic 2.0
JPA implementation: Library Provided by Target Runtime (our RT is Liberty 8.5.0.2)
Persistent class management: Discover annotated classes automatically
-> Next


OSGi Bundle
Version: 1.0.0
-> Finish


JPA OSGi Project Ready to Create Entities




5) Create JPA Entities from Tables


Before we start: 
make sure the Eclipse Data Source Explorer has an open connection to the database


Right-click osgi_jpa project (the one we created above)
-> JPA Tools -> Generate Entites from Tables


Select Tables
JPA tooling fetches DB information from DataSource.
- Select our table (example: colors)
- Update class list in persistence.xml: checked
-> Next


Table Associations 
none for this example
-> Next



Customize Default Entity Generation
Key generator: none
Entity access: Field
Associations fetch: default
Collections properties type: java.util.List (my preference) 
Alweays generate optioanl JPA Annotations [...]: unchecked

source folder: osgi_jpa_3/src (default)
Package: model

-> Next


Customize Individual Entities
Leave defaults
-> Finish


Wizard leaves Java entity with a minor error
- we'll fix this in next step




6) Configure JPA Entities 


Right-click jpa bundle project
-> JPA Tools -> Configure JPA Entities



Configure JPA Entities
- Select the Entity (we're using "color")
-> Next



Primary Key: colorCode



Relationships: none


Named Queries
Click "add"



Add Named Query
- Select colorCode and colorName
- Order results by colorCode

The Query statement should look something like below (it's generated)
-> OK


Concurrency Coordinator
Not our focus at this stage: leave defaults


Other
Convert Java Set objects to Java List objects: checked
Automatically set up initial values for JDBC Deployment: unchecked
-> Finish


The "no primary key" error should now clear 

Snippet from Color.java
Note the NamedQuery we created earlier.
/**
 * The persistent class for the COLORS database table.
 *
 */
@Entity
@Table(name= "COLORS")
@NamedQuery(name = "getColor" , query = "SELECT c FROM Color c ORDER BY c.colorCode")
public class Color implements Serializable {
     private static final long serialVersionUID = 1L;

     @Column(name="COLOR_CODE")
     @Id
     private String colorCode;

     @Column(name="COLOR_NAME")

I also added an additional constructor to include properties:
public Color(String colorCode, String colorName) {
            super();
            this. colorCode = colorCode;
            this. colorName = colorName;
     }



7) Create Entity Manager (e.g. JPA Bean Manager) 

The "Entity Manager" is a wrapper class intended to hide some of the details from model consumers (JAX-RS service later uses this JPA  model)

--------

ColorManager Interface:
Please refer to implementation for detailed discussion
---------
package model;

import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;

public interface ColorManager {
     
     public EntityManager getEntityManager();
     
     public String createColor(Color color) throws Exception;
     
     public String deleteColor(Color color) throws Exception;
     
     public String updateColor(Color color) throws Exception;
     
     public Color findColorByColorCode(String colorCode);
     
     public Color getNewColor();
     
     public List<Color> getColor();
     
     public void startUp();
     
     public void onRegisterService(ColorManager colorManager, Map props);

     public void onUnRegisterService(ColorManager colorManager, Map props);
     
     public void referenceBind(ColorManager colorManager);
     
     public void referenceUnBind(ColorManager colorManager);

}
---------

ColorManagerImpl Implementation:
NOTE: "getColor()" is the only tested/used method
---------
package model;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;
import javax.transaction.UserTransaction;

@SuppressWarnings("unchecked" )
public class ColorManagerImpl implements ColorManager {
     
     @PersistenceUnit(unitName= "osgi_jpa_03")
     private EntityManagerFactory emf;
     @Resource
     private UserTransaction utx;

     public ColorManagerImpl() {
           System. out.println( "*** ColorManagerImpl()");
     }
     
     public EntityManager getEntityManager() {
            /**
           if (this.emf == null) {
                System.out.println("*** ColorManagerImpl.getEntityManager found NULL emf");
                System.out.println("*** IBM workaround... ");           
                try {
                      this.emf = (EntityManagerFactory) new InitialContext().lookup("osgi:service/javax.persistence.EntityManagerFactory/(osgi.unit.name=jpa_test_03)");
                } catch (NamingException e) {
                      // TODO Auto- generated catch block
                      e.printStackTrace();
                }
           }
           **/
            return emf.createEntityManager();
     }
     
     void setEmf(EntityManagerFactory emf) {
           System. out.println( "*** ColorManagerImpl.setEmf()");
           System. out.println( "*** ColorManagerImpl.setEmf()- emf tostring: "+emf.toString());
            this. emf = emf;
     }
     
     /* (non-Javadoc)
      * @see model.ColorManager#createColor(model.Color)
      */
     @Override
     public String createColor(Color color) throws Exception {
           EntityManager em = getEntityManager();
            try {
                 utx.begin();
                em.joinTransaction();
                em.persist(color);
                 utx.commit();
           } catch (Exception ex) {
                 try {
                       utx.rollback();
                } catch (Exception e) {
                      ex.printStackTrace();
                       throw e;
                }
                 throw ex;
           } finally {
                em.close();
           }
            return "";
     }

     @Override
     public String deleteColor(Color color) throws Exception {
           EntityManager em = getEntityManager();
            try {
                 utx.begin();
                em.joinTransaction();
                color = em.merge(color);
                em.remove(color);
                 utx.commit();
           } catch (Exception ex) {
                 try {
                       utx.rollback();
                } catch (Exception e) {
                      ex.printStackTrace();
                       throw e;
                }
                 throw ex;
           } finally {
                em.close();
           }
            return "";
     }

     @Override
     public String updateColor(Color color) throws Exception {
           EntityManager em = getEntityManager();
            try {
                 utx.begin();
                em.joinTransaction();
                color = em.merge(color);
                 utx.commit();
           } catch (Exception ex) {
                 try {
                       utx.rollback();
                } catch (Exception e) {
                      ex.printStackTrace();
                       throw e;
                }
                 throw ex;
           } finally {
                em.close();
           }
            return "";
     }

     @Override
     public Color findColorByColorCode(String colorCode) {
           Color color = null;
           EntityManager em = getEntityManager();
            try {
                color = (Color) em.find(Color. class, colorCode);
           } finally {
                em.close();
           }
            return color;
     }

     @Override
     public Color getNewColor() {

           Color color = new Color();
     
            return color;
     }

     @Override
     public List<Color> getColor() {
           EntityManager em = getEntityManager();
           List<Color> results = null;
            try {
                Query query = em.createNamedQuery( "getColor");
                results = (List<Color>) query.getResultList();
           } catch(Exception e){
                e.printStackTrace();
           }
            finally {
                em.close();
           }
            return results;
     }
     
     public String testDbConnection() {
           System. out.println( "*** ColorManagerImpl.testDbConnection()");
           String result = "error";
           List<Color> list = null;
            try {
                list = this.getColor();
           } catch (Exception e) {
                e.printStackTrace();
           }
           
            for (Color color : list) {
                System. out.println( "*** color code: "+ color.getColorCode());
           }
            if (list.size() > 0) {
                result = "connects";
           }
           System. out.println( "*** ColorManagerImpl.testDbConnection() result: "+result);
            return result;
     }

     @Override
     public void startUp() {
           System. out.println( "*** ColorManagerImpl.startUp()");
           
            // NOT A GOOD IDEA to attempt testing in startup method
            //   - this can lead to trouble when the testing, itself, interferes with bean startup
            //   - additionally, the bean isn't yet ready for testing - not yet "registered".
            /**
           List <Color> list = null;
           try {
                list = this.getColor();
           } catch (Exception e) {
                e.printStackTrace();
           }
           
           for (Color color : list) {
                System.out.println("color code: "+ color.getColorCode());
           }
           **/
           
     }

     @Override
     public void onRegisterService(ColorManager colorManager, Map props) {
           System. out.println( "*** ColorManagerImpl.onRegisterService()");
            // this.testDbConnection();
           
     }

     @Override
     public void onUnRegisterService(ColorManager colorManager, Map props) {
           System. out.println( "*** ColorManagerImpl.onUnRegisterService()");
           
     }
     
     public void referenceBind(ColorManager colorManager) {
           System. out.println( "*** ColorManagerImpl.referenceBind()");
     }
     
     public void referenceUnBind(ColorManager colorManager) {
           System. out.println( "*** ColorManagerImpl.referenceUnBind()");
     }
     
}
---------------------------------------------
ColorManagerImpl Review: 
NOTE: Only covering the interesting bits
---------------------------------------------
@PersistenceUnit(unitName= "osgi_jpa_03")
private EntityManagerFactory emf;

I have the option of setting the EntityManagerFactory directly (shown above) or via blueprint. Given I was wrestling with a couple of blueprint concepts I opted to set the unitName directly in code (we'll cover using the blueprint later). 

Assign unitName to the value set in "persistence.xml"
<?xml version="1.0" encoding= "UTF-8"?>
<persistence version= "2.0" [schema omitted for readability] 
     <persistence-unit name ="osgi_jpa_03" transaction-type="JTA">
            <jta-data-source >jdbc/JPA_TEST</ jta-data-source>
            <class >model.Color </class >
     </persistence-unit >
</persistence>

---------------------------------------------
public List<Color> getColor ()

     public List<Color> getColor() {
           EntityManager em = getEntityManager();
           List<Color> results = null;
            try {
                Query query = em.createNamedQuery("getColor");
                results = (List<Color>) query.getResultList();
           } catch(Exception e){
                e.printStackTrace();
           }
            finally {
                em.close();
           }
            return results;
     }

The named query, "getColor" was set in the Color entity via JPA "Entity Configuration" 
Color.java
@NamedQuery (name = "getColor", query = "SELECT c FROM Color c ORDER BY c.colorCode")

Queries the DB for a list of color entities... returns a list of <Color>

Usage example:
from ColorManagaerImple.testDbConnection(): 
               List<Color> list = null;
            try {
                list = this.getColor();
           } catch (Exception e) {
                e.printStackTrace();
           }
           
            for (Color color : list) {
                System. out.println( "*** color code: "+ color.getColorCode());
           }
output:
color code: BLUE
color code: ORANGE
color code: WHITE
color code: YELLOW


---------------------------------------------
Event Callbacks referenced in blueprint: 
I'll cover these events in more detail on the next section on blueprint (just listing here for reference)

All of these methods, more or less, are simply reporting status. I found them extremely helpful in both learning and debugging OSGi blueprint activity. 

public void startUp()

public void onRegisterService(ColorManager colorManager, Map props)

public void onUnRegisterService(ColorManager colorManager, Map props)

public void referenceBind(ColorManager colorManager)

public void referenceUnBind(ColorManager colorManager)



8) Create Blueprint for JPA Bundle Project


right-click project
new -> other -> wizard filter "blue" -> select Blueprint File
-> Next


New Blueprint File
select folder under OSGI-INF (default)


Add or Remove Blueprint Namespaces
Select support for:
- JPA
- Transaction 
- Resource Reference


Blueprint file created




9) Create a blueprint-defined ColorManagerImpl bean and service

The ColorManager service provides  List<Color> to the JAX-RS/ReST bundle. 

Create Bean
Add -> Bean



Create a Blueprint Bean for ColorManagerImpl
click Browse and type in "model." to get a list of classes
-> select "ColorManagerImple" from the osgi_pja_03 project

Pitfall: Be careful not to select a class outside of the project



Leave default values for Bean ID
(helps avoid the confusion that will follow)
-> OK


Register Initialization method: startUp


Create a Service
Select "blueprint"
click "add" -> Service
-> OK



Browse for service interface
click "Browse" -> choose type name: "model."
select ColorManager interface from project "osgi_jpa_03
Careful not to select an interface outside of our project! 



Bean Reference
click Browse -> select the ID from the bean we created previous step



Auto-fills in the Service ID
Leave generated name as-is


Relationship between implementation bean and service 
The service "reference" value is set to implementation bean's ID value

ColorManagerImpleBean ID = 
     ColorManagerImleBeanServce Reference



Source View (blueprint.xml)

The new service should also now be visible in the project explorer


Create a Registration listener for ColorManagerImpleBleanService
NOTE: This listener is very helpful in tracking exactly when the ColorManager service becomes available in the application. This event not reporting means there's been an error somewhere during invocation (useful for learning and debugging blueprint)

Select ColorManagerImpleBleanService -> add -> REgistration listener
-> OK


Select Registration Listener -> Reference, click Browser
-> Select the ColorManagerImplBean
-> OK


Add registration and unregistration methods for listener
NOTE: We use these methods to help us track blueprint activity - very helpful for debugging! 
From ColorManagerImpl source:

Fill in method names


Blueprint source view
Registration listener references ColorManagerImplBean ID

Sample log output (using BareTail to highlight messages)
Note the order shows that "startup" is called prior to registration! 



Pitfall:
 Avoid attempting to use a service prior to registration. This was my mistake early in development and this error lead to nullpointers... 


10) Create OSGi Application Project for JPA bundle

Create OSGi Application Project
(top level menu) File -> new -> other -> Wizards, type "osgi"
-> select OSGi Application Project
-> Next


OSGI Application Project Details
Project name: osgi_jpa_o3_app (note: adding an "app" postfix helps identify)
Target Runtime: Liberty
-> Next


Contained OSGi Bundles and Composite Bundles
Select the osgi_jpa project we created above
-> Finish





11) Deploy and Test the JPA OSGi Application

Add a test method to onRegisterService
testDbConnection prints to log results from the "getColor" query

     public void onRegisterService(ColorManager colorManager, Map props) {
           System. out.println( "*** ColorManagerImpl.onRegisterService()");
            this.testDbConnection();  // added a discrete test method
           
     }

snippet from testDbConnection():

               try {
                list = this.getColor();
           } catch (Exception e) {
                e.printStackTrace();
           }


Deploy application to Liberty
When Liberty loads the bundle, blueprint should invoke the beans which will eventually call onRegisterService... and this is where we have the test waiting. 

Log should read:
Note the order...
1) ColorManagerImpl instantiates
2) ColorManagerImpl.startUp
3) ColorManagerImpl.onRegsterService
4) ColorManagerImpl.referenceBind - JAX-RS connects! We'll cover this event during JAX-RS writeup 
5) ColorManagerImpl.testDbConnection

We'll cover details later regarding the other events listed below




** DONE **