This basic example details how to use Eclipse to run/debug a minimum J2EE web application servlet using EclipseLink JPA as the persistence provider. The goal of this example is to detail the minimum steps required to run EclipseLink inside the IBM WebSphere Application Server 7.0 server using the Eclipse IDE. At this point no presentation/controller layer such as JSF, Spring or Struts will be used beyond a basic HttpServlet so we can concentrate on the the integration layer JPA setup.

The DALI project can be used to generate Entities from a schema with sequences already populated.

Tables can be populated by persisting an instance of the mode in an SE JPA persistence unit with DDL generation turned on.

The recommended configuration for running EclipseLink as the JPA provider on WebSphere 7 are the following container managed scenarios below.

OS

I am running this on both a 32-bit P630 2Gb machine and a Corei7 64-bit Windows7 12Gb machine - Note: installing the 32 bit version of WebSphere 7 on a 64-bit OS will require a full reboot of the server before you can start the container.

Note: Developing/Debugging an enterprise application works excellent if you use IBM Rational Developer as the Eclipse based IDE where 7.0 server support currently exists. However if you wish to debug from an unenhanced standard Eclipse 3.5 EE IDE you must run through some hoops and export your EAR manually, deploy/update it in the admin console and attach to the debuggable process manually. In other application servers such as WebLogic, OC4J, Glassfish, Tomcat and even WebSphere 6.0 this process is handled automatically for you via an eclipse plugin.

Prerequisites

Install Eclipse EE

I installed a clean version of Eclipse Galileo 3.5 SR2 EE Edition (32-bit) (April 2010) on a Window 7 64-bit install where the default JRE was the 64-Bit server version of the SUN JVM. I therefore needed to override the default java.exe by specifying the following shortcut override

Install a Database

We will be using a remote Oracle 11 instance as well as a localDerby 10.5.3.0 instance or the embedded Derby instance that comes with WebSphere.

Install WebSphere 7.0

I installed the commercial 7.0.0.0 version of IBM WebSphere 7 and then the 7.0.0.5fixpack in 7.0.0-WS-WAS-WinX32-FP0000005.pak using the 7.0.0.5-WS-UPDI-WinIA32.zip installer.

Install WebSphere Eclipse 3.4 Server Plugin - unusable

We will first see if the WebSphere 6.0 or 6.1 plugin works with WebSphere 7.0 - it fails on missing jar files that are not present in 7.0.
The WebSphere 6.1 Eclipse WTP server plugin is not shipped by default with Eclipse (WebSphere 6.0 for JEE 1.4 is).

We are not blocked from using Eclipse WTP to manage the WebSphere 6.1 server, but without this plugin we will need to attach manually to port 7781 of a running WebSphere server that was started in debug mode outside of the Eclipse IDE - we will use this alternate debug approach.

If you try to stub out the 73 jars required by the WebSphere 6.0 plugin to make it work with a WebSphere 7.0 server - you will get the following exception starting WebSphere from Eclipse. - so don't do it

com.ibm.ws.exception.ConfigurationError: java.lang.Exception: Cannot find BundleContext for service com.ibm.ws.runtime.config.ConfigServiceImpl
at com.ibm.ws.runtime.WsServerImpl.bootConfigService(WsServerImpl.java:335)
at com.ibm.ws.runtime.WsServerImpl.start(WsServerImpl.java:171)

WebSphere Configuration Changes

WebSphere configuration modifications can be done on the admin console .

Container Managed and Application Managed Scenarios

The steps below detail what needs to be done to migrate an existing JPA enterprise application to use a JPA provider other than the shipped OpenJPA - like the org.eclipse.persistence.jpa.PersistenceProvider provider.

The following table summarizes the type of test, server modifications and results for verious container managed and application managed EntityManager deployments on the IBM WebSphere 7 server.

Configuration

This section is currently undergoing review and minor editing as more deployment scenarios are tested today (20100419)

The following section details investigations on what configurations work when using the EclipseLink JPA provider on the IBM WebSphere 7 Application Server. The test deployments are configured around container managed EARs that require server modification such as creating a global shared library or placing the eclipselink.jar library directly in the %SERVER%/lib, and application managed EARs that do not require any server modification as they ship the required libraries as part of the EAR.

EAR Source

The following EAR attachment for bug# 309201 can be used as source until this project is checked into SVN.

Note: eclipselink.jar must be readded to the EAR in the position of EAR/APP-INF/lib/eclipselink.jar

EclipseLink library as Global Shared Library

Here a developer with access to the servers' console would add a global scope library that references an external eclipselink.jar.

This works the same as the option below.

EclipseLink library in Server/lib

Placing the eclipselink.jar library directly on the server in the %SERVER%/lib directory and restarting the server will allow container managed deployments of EclipseLink applications following the JPA 1.0 specification to inject and function correctly.

Container Managed EclipseLink library in EAR

This is an interesting use case where the eclipselink JPA library is included locally in the EAR (requiring no server modifications) but the persistence unit itself is container managed by @PersistenceContext EntityManager Proxy injection on a stateless session bean.

The following EAR attachment for bug# 309201 can be used as source until this project is checked into SVN.

Note: eclipselink.jar must be readded to the EAR in the position of EAR/APP-INF/lib/eclipselink.jar

Injected EntityManager on the SSB

We get a JPATxEntityManager@14001400 entityManager instance injected from the WebSphere container - this looks like a proxy wrapper for our EntityManagerImpl. - Normally I would debug this to verify but I am having difficulty attaching to port 7777 using my own instructions for WebSphere 6.1

Insertion/Persist Testing

after a read/ReadAllQuery of 5 existing entities and insertion/Persist of an additional 5...

inserting another 5 in a 2nd transaction using a different injected entityManager but the same JPAtxEntityManager proxy.

Configuration

Console Overrides

None - I did not override the Class Loader Order - it is still set to Classes loaded with parent class loader first.

EclipseLink library in EAR

org.eclipse.persistence.example.jpa.server.websphere.EnterpriseEAR

EarContent

APP-INF

lib

eclipselink.jar - note there is no eclipselink.jar on the server.

MANIFEST.MF

Place the following path to the included eclipselink.jar in your ejb.jar(s) ejbModule/META-INF/MANIFEST.MF file. This is the recommended approach where you update the manifest that is at the root of where your entities are - in this case as part of the ejb.jar.

In my example application, there are 3 MANIFEST.MF files, one on the WAR, one on the ejb.jar and one on the EAR.

EAR/META-INF/MANIFEST.MF

EJB/ejbModule/META-INF/MANIFEST.MF - update this one to point to the eclipselink.jar in the EAR/APP-INF/lib directory.

WAR/WebContent/META-INF/MANIFEST.MF

As a recommended test I removed all 3 manifest entries below and received an expected Injection failure - putting the ejb.jar(s) manifest back to reference eclipselink.jar allowed us to successully inject an EclipseLink JPA provider EntityManagerImpl instance instead of the default OpenJPA provider's instance.

Manifest-Version:1.0
Class-Path: APP-INF/lib/eclipselink.jar

Eclipse can be used to format your manifest file by selecting the eclipselink and other dependency libraries in the EJB project properties dialog

SE JPA app] - see the generic DDL generation project in SVN that has the same enties and will create your schema and propopulate your Derby database for you. Normally this is not an issue since the schema should be created by the DBA anyway.

No EclipseLink library on the Server or the EAR

This is not a valid configuration because the EclipseLink JPA provider library is needs to be added either on the server or via the APP-LIB directory of the EAR for Container or Application managed scenarios.

You will see the following exception if you attempt to use the org.eclipse.persistence.jpa.PersistenceProvider in this case. This forms a good base case failure test upon which the other valid scenarios can be verified against.

javax.ejb.EJBException: Injection failure; nested exception is: java.lang.IllegalStateException: EntityManagerFactory has not been created for PU : PuId=org.eclipse.persistence.example.jpa.server.websphere.EnterpriseEAR#org.eclipse.persistence.example.jpa.server.websphere.EnterpriseEJB.jar#example

Application Managed

The primary use case that requires an appplication managed entityManager is one where the application developer does not have access to the server to create global or local scope Shared Libraries. In this case all library configuration and classloader scope changes must be done inside the EAR itself.

For either the developer that has access to the deployment workflow on the WAS console - We can modify the classloader to load the parent last using the following procedure from DeveloperWorks.

EAR configuration

standard Persistence static bootstrap EMF on the servlet or @PersistenceUnit injection on the servlet with a non-JTA datasource or direct JDBC connection (in this case derby)

Eclipselink library in EAR

Static Persistence bootstrap EMF creation in WAR Servlet

Static Persistence bootstrap EMF creation in EJB Session Bean

20100420: this scenario may actually work if the MANIFEST.MF points to the correct APP-INF/lib/eclipselink.jar - I just need time to revert the testing EAR and verify this.

placing the eclipselink.jar in the EAR and attempting to use the SE Persistence bootstrap class to create an EMF on a Stateless Session Bean - in the EJB.jar - (on the EJB container instead of the WEB container) does not work because the classloader position of the eclipselink.jar is not visible to the JPA 1.0 persistence library that ships with the server higher up.

Console logs

The following logs show evidence of Weaving(bytecode instrumentation for change tracking and cache performance), EntityManagerFactory and EntityManagerEclipseLink JPA provider instances and their usage.

Browser Output

The following screen capture illustrates the fact that 5 entities were read from in this case a Derby 10.5.3.0 database using a RESOURCE_LOCAL @PersistenceUnit injected EMF on a Servlet client as part of the WAR in an EAR that contains the eclipselink.jar library embedded - essentially an SE application.

[4/16/1015:45:50:093 EDT] 00000016 SystemErr R com.ibm.ws.exception.RuntimeWarning: com.ibm.ws.metadata.MetaDataException: CWWJP0040E: The persistence.xml in application org.eclipse.persistence.example.jpa.server.websphere.EnterpriseEAR, module org.eclipse.persistence.example.jpa.server.websphere.EnterpriseWeb.war, has a syntax error at line number:20, column number:209.
[4/16/1015:45:50:093 EDT] 00000016 SystemErr R at com.ibm.ws.jpa.management.JPAApplInfo.processModulePUs(JPAApplInfo.java:185)[4/16/1015:45:49:250 EDT] 00000016 JPAPxmlInfo E CWWJP0040E: Incorrect syntax or error detected in the persistence.xml file in application: org.eclipse.persistence.example.jpa.server.websphere.EnterpriseEAR, module: org.eclipse.persistence.example.jpa.server.websphere.EnterpriseWeb.war, at line number:20, column number:209. The following associated error message occurred: javax.xml.bind.UnmarshalException- with linked exception:[org.xml.sax.SAXParseException: cvc-complex-type.3.1: Value '2.0' of attribute 'version' of element 'persistence' is not valid with respect to the corresponding attribute use. Attribute'version' has a fixed value of '1.0'.]
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:326)
Caused by: org.xml.sax.SAXParseException: cvc-complex-type.3.1: Value '2.0' of attribute 'version' of element 'persistence' is not valid with respect to the corresponding attribute use. Attribute'version' has a fixed value of '1.0'.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)

Also, if we try using JPA 2.0 API via a persistence.xml that is defined as JPA 1.0 so it passed deployment - we will still get an expected runtime exception when we try to use JPA 2.0 commands.

[4/16/1016:08:47:578 EDT] 0000001b servlet E com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0068E: Uncaught exception created in one of the service methods of the servlet FrontController in application org.eclipse.persistence.example.jpa.server.websphere.EnterpriseEAR. Exception created : java.lang.NoSuchMethodError: javax/persistence/EntityManager.getMetamodel()Ljavax/persistence/metamodel/Metamodel;
at org.eclipse.persistence.example.jpa.server.business.ApplicationManagedService.getMetamodel(ApplicationManagedService.java:139)

Persistence JAR location

Where does the standard library plugins/com.ibm.ws.jpa.jar and runtimes/com.ibm.ws.jpa.thinclient_7.0.0.jar fit in? Is this a JPA spec jar or an OpenJPA implementation?

JDBC JAR location

If you are using a JDBC provider other than the 3 provided by WebSphere, you must defined all of the JDBC Providers, the Data sources and the secondary JAAS-J2C authentication data sections in the admin console for your new datasource.

Remote Debugging EclipseLink in WebSphere 7.0 from Eclipse 3.4

The following procedure details how to attach to a debug version of IBM WebSphere 7.0 with the Eclipse 3.4 IDE.

Note: we will not be modifying startServer.bat. The java process in that script is only for server startup - if you need to debug this part of the server.

Modify console setup to start server in debug mode

Login to the console using your admin login or a default username like system