Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

EclipseLink/Examples/OSGi/Developing with EclipseLink OSGi in PDE

< EclipseLink‎ | Examples‎ | OSGi
Revision as of 17:27, 15 June 2010 by Shaun.smith.oracle.com (Talk | contribs) (Environment Setup)

Developing with EclipseLink OSGi in PDE

EclipseLink is the the only comprehensive Java persistence framework that is designed for OSGi. EclipseLink is available as a set of OSGi bundles that can be used with any OSGi framework. Support is also available for byte code weaving of Entities when using Equinox.

This example illustrates how to develop a simple OSGi hello database application using Eclipse's Plug-in Development Environment (PDE) and EclipseLink.

Environment Setup

  • Download Eclipse IDE with PDE
    • A number of distributions include PDE including the Java EE, RCP, and Classic distributions.
  • Obtain and Install Database driver--we'll used the embedded Apache Derby database in this example
    • Download Apache Derby (org.apache.derby) bundle from Orbit.
    • Place the org.apache.derby bundle into your ECLIPSE_HOME\dropins folder.
      EclipseLinkExamplesOSGiDeveloping with EclipseLink OSGi in PDE-2v2.png

Building a JPA application in OSGi

Now that the environment is setup, you can proceed to building an application.

Create a Plug-in Project

  • Use the New>Project dialog to select a new "Plug-in Project" and call it "hello.jpa". For the target platform select "an OSGi Framework" and "standard" and click Next.
    EclipseLinkExamplesOSGiDeveloping with EclipseLink OSGi in PDE-5.png
  • On the Content panel of the New Project wizard set the Execution Environment to "J2SE-1.5" as JPA requires at least Java 5.
  • Select "Generate an Activator.." and accept the default Activator class name "hello.jpa.Activator" and click Finish.
    EclipseLinkExamplesOSGiDeveloping with EclipseLink OSGi in PDE-6.png

Create a JPA Entity

  • Create a new "hello.jpa.Person" class as illustrated below.
package hello.jpa;
 
public class Person {
	private int id;
	private String name;
 
	public int getId() {
		return id;
	}
 
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
  • We can make Person a JPA Entity by adding few annotations but first we need to adjust the hello.jpa bundle manifest to import JPA's javax.persistence packages. Open the Manifest.mf and go to the Dependencies tab and add imported package "javax.persistence".
    EclipseLinkExamplesOSGiDeveloping with EclipseLink OSGi in PDE-7.png
  • Now we can add the JPA annotations we need to our Person.
package hello.jpa;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
 
@Entity
public class Person {
	@Id
	@GeneratedValue
	private int id;
	private String name;
 
	public int getId() {
		return id;
	}
 
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

Create a persistence.xml

  • In your source folder, create a META-INF folder and in that folder create a new persistence.xml file. The persistence.xml below defines a persistence unit called "hello.jpa" with a single Person Entity along with an Apache Derby embedded database connection. It instructs EclipseLink to drop and create the tables implied by the Entities in the project and it tweaks the logging level and verbosity. These and other EclipseLink persistence unit properties are documented on the Using EclipseLink JPA Extensions page of the EcilpseLink User Guide.
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    <persistence-unit name="hello.jpa">
        <class>hello.jpa.Person</class>
        <properties>
            <!-- Embedded Derby Login -->
            <property name="eclipselink.target-database" value="Derby"/>
            <property name="eclipselink.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
            <property name="eclipselink.jdbc.url" value="jdbc:derby:comics;create=true"/>
            <property name="eclipselink.jdbc.read-connections.min" value="1"/>
            <property name="eclipselink.jdbc.write-connections.min" value="1"/>
            <property name="eclipselink.jdbc.batch-writing" value="JDBC"/>
 
            <!-- Database Schema Creation -->
            <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
            <property name="eclipselink.ddl-generation.output-mode" value="database"/>
 
            <!-- Logging Settings -->
            <property name="eclipselink.logging.level" value="FINE" />
            <property name="eclipselink.logging.thread" value="false" />
            <property name="eclipselink.logging.session" value="false" />
            <property name="eclipselink.logging.exceptions" value="true" />
            <property name="eclipselink.logging.timestamp" value="false"/>            
        </properties>
    </persistence-unit>
</persistence>

Notice that we've told EclipseLink to use org.apache.derby.jdbc.EmbeddedDriver as our driver. However our bundle doesn't import org.apache.derby.jdbc. PDE can't detect the missing dependency because it doesn't understand EclipseLink's persistence unit properties. What we have to do is add an import for org.apache.derby.jdbc to our bundle Manifest.mf as we did previously for javax.persistence.
EclipseLinkExamplesOSGiDeveloping with EclipseLink OSGi in PDE-8.png

JPA Client Code

For this example, we'll put our "application code" in the start() method of our Activator. This is just standard JPA code as in Java SE. The complete hello.jpa.Activator

package hello.jpa;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
 
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
 
public class Activator implements BundleActivator {
 
	public void start(BundleContext context) throws Exception {
		EntityManagerFactory emf = Persistence
				.createEntityManagerFactory("hello.jpa");
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		Person bob = new Person();
		bob.setName("Bob");
		em.persist(bob);
		em.getTransaction().commit();
		em.close();
		emf.close();
	}
 
	public void stop(BundleContext context) throws Exception {
	}
}

Declaring your Persistence Unit

  • In your Manifest.mf you need to declare that your bundle provides a persistence unit so it can be found by EclipseLink. Add the following entry to your Manifest.mf:
JPA-PersistenceUnits: hello.jpa

Running your Application

Now that we have all the code and configuration in place we can create a PDE run configuration for our application.

  • Select Run>Run Configurations.. to open the Run Configurations dialog.
  • Select "OSGi Framework" as your run configuration type on the left and create a new configuration named "hello.jpa"
  • Since this example uses EclipseLink JPA and Apache Derby you'll need to include them and their associated bundles (illustrated below) in your configuration.
    EclipseLinkExamplesOSGiDeveloping with EclipseLink OSGi in PDE-9.png
  • Configure javax.persistence to auto-start at start level 1 and org.eclipse.persistence.jpa to auto-start at level 2. These bundles each provide OSGi services that must be started before application code.
  • Configure the hello.jpa bundle to auto-start at the default level, which is 4.
  • Press the "Validate Bundles" button to ensure you have no unsatisfied bundle dependencies.
  • Press "Run" to launch your application.

Understanding the Output

Let's look at the output produced by running the example. First we see javax.persistence and org.eclipse.persistence.jpa start their services.

osgi> Persistence bundle starting...
Persistence bundle started.
ProviderTracker: New service detected...
ProviderTracker: Added service org.eclipse.persistence.jpa.osgi.PersistenceProviderOSGi

With logging set to FINE, EclipseLink logs the JPA mappings that are being defaulted.

[EL Config]: The access type for the persistent class [class hello.jpa.Person] is set to [FIELD].
[EL Config]: The alias name for the entity class [class hello.jpa.Person] is being defaulted to: Person.
[EL Config]: The table name for entity [class hello.jpa.Person] is being defaulted to: PERSON.
[EL Config]: The column name for element [private int hello.jpa.Person.id] is being defaulted to: ID.
[EL Config]: The column name for element [private java.lang.String hello.jpa.Person.name] is being defaulted to: NAME.
[EL Info]: EclipseLink, version: Eclipse Persistence Services - 1.1.2.v20090526-r4309

EclipseLink logs into Derby.

[EL Config]: Connection(21350489)--connecting(DatabaseLogin(
	platform=>DerbyPlatform
	user name=> ""
	datasource URL=> "jdbc:derby:comics;create=true"
))
[EL Config]: Connection(16426320)--Connected: jdbc:derby:comics
	User: APP
	Database: Apache Derby  Version: 10.3.1.4 - (561794)
	Driver: Apache Derby Embedded JDBC Driver  Version: 10.3.1.4 - (561794)
[EL Config]: Connection(24864323)--connecting(DatabaseLogin(
	platform=>DerbyPlatform
	user name=> ""
	datasource URL=> "jdbc:derby:comics;create=true"
))
[EL Config]: Connection(23376028)--Connected: jdbc:derby:comics
	User: APP
	Database: Apache Derby  Version: 10.3.1.4 - (561794)
	Driver: Apache Derby Embedded JDBC Driver  Version: 10.3.1.4 - (561794)
[EL Info]: bundleresource://1.fwk15020296/-hello.jpa login successful

As configured in the persistence.xml, EclipseLink drops and creates the database schema for the persistence unit. Note that the first time you run your application you may see messages indicating that the as yet non-existent tables cannot be dropped. The next time you run you will not see these messages.

[EL Fine]: Connection(16426320)--DROP TABLE PERSON
[EL Fine]: Connection(16426320)--CREATE TABLE PERSON (ID INTEGER NOT NULL, NAME VARCHAR(255), PRIMARY KEY (ID))
[EL Fine]: Connection(16426320)--CREATE TABLE SEQUENCE (SEQ_NAME VARCHAR(50) NOT NULL, SEQ_COUNT DECIMAL(15), PRIMARY KEY (SEQ_NAME))
...

We see an INSERT for "Bob", the person we created in our application.

[EL Fine]: Connection(23376028)--INSERT INTO PERSON (ID, NAME) VALUES (?, ?)
[EL Fine]: Connection(23376028)--	bind => [1, Bob]

And we see logout messages as we shutdown.

[EL Config]: Connection(16426320)--disconnect
[EL Info]: bundleresource://1.fwk15020296/-hello.jpa logout successful
[EL Config]: Connection(21350489)--disconnect
[EL Config]: Connection(23376028)--disconnect

Shutting Down Equinox

If you didn't adjust any of the Equinox launch parameters then after your application runs Equinox is still running and the console is ready to take commands in the Eclipse Console view. If you type "ss" (for short status) in the Console you should see something like:

osgi> ss

Framework is launched.

id	State       Bundle
0	ACTIVE      org.eclipse.osgi_3.5.0.v20090520
1	ACTIVE      hello.jpa_1.0.0.qualifier
2	ACTIVE      org.eclipse.persistence.antlr_1.1.2.v20090526-r4309
3	ACTIVE      org.eclipse.persistence.asm_1.1.2.v20090526-r4309
4	ACTIVE      org.eclipse.persistence.core_1.1.2.v20090526-r4309
5	ACTIVE      org.eclipse.persistence.jpa_1.1.2.v20090526-r4309
6	ACTIVE      org.apache.derby.core_10.3.1.4
7	ACTIVE      javax.persistence_1.99.0

osgi> 

You'll need to manually shut down Equinox with the "exit" command. If you don't, and you try to run your application again you'll get an exception. This is because the embedded Derby database only allows one process to access it at a time and you still have a running application with it open. The second or third instance of your application will fail. So "exit" and you're ready to roll again. If you want Equinox to automatically shut down then go to the Arguments tab of your Run Configuration and change the VM argument osgi.noShutdown to false.

-Dosgi.noShutdown=false

Back to the top