Blog Archives

December 4th, 2009
5:09 pm
Using JPA Annotations with XML

Posted under JPA
Tags , ,

It is possible to use both annotations and descriptors in orm.xml to define entity mappings with JPA. The debate on which way to go has become very heated, but in my opinion there is a strong case for both.

  1. Annotations are best for metadata which you would consider closely bound to the code. This promotes clarity, as elements which are closely bound together are also in close proximity, promoting clarity and maintainability.
  2. XML is best for metadata which may change independantly of the code, and provides the ability to isolate platform specific issues from the code, for example to enhance persistence provider independance.

The OO design principle “Separate what changes from what stays the same” comes to mind clearly here.

I found the following simple example helpful in this context. The ID for the entity is defined via annotations in the code. However, I have defined the ID generator seperately in orm.xml. The generator name is fixed and referred to by the @GeneratedValue annotation, but the actual generator is in orm.xml and may be specified either as a table generator (which is database independant), or as a sequence generator which allows me to take advantage of Oracle’s sequences for primary key generation. Either generator may be defined in orm.xml, but the code does not change. This gives database independance, whilst still allowing leverage of the enhanced features of a specific database platform. In the example below, for illustration, orm.xml contains both generators and one has been commented out.

Note that to enable sequence generation in Oracle for this example to work, the correct properties must be set in persistence.xml, as by default Eclipselink will use table based ID generation even if you turn sequence generation on. The way to do this is detailed in this post here.

Class UserInfo

package uk.co.salientsoft.jpatest.domain;
import java.io.Serializable;
import javax.persistence.*;

@Entity
public class UserInfo implements Serializable {

 @Id
 @GeneratedValue(generator="UserID")
 private long userID;

 private String userName;
 private static final long serialVersionUID = 1L; 

 public UserInfo() {
  super();
 }  
 public long getUserID() {
   return this.userID;
 }
 public void setUserID(long userID) {
  this.userID = userID;
 }   
 public String getUserName() {
   return this.userName;
 }
 public void setUserName(String userName) {
  this.userName = userName;
 }
}

 

orm.xml

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings version="1.0" xmlns="http://java.sun.com/xml/ns/persistence/orm"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
    http://java.sun.com/xml/ns/persistence/orm_1_0.xsd">

 <!--<table-generator name="UserID" />-->

 <sequence-generator name="UserID" sequence-name="UserID"/>

</entity-mappings>

No Comments »

December 4th, 2009
3:33 pm
Configuring Libraries for Eclipse Plugins

Posted under Eclipse
Tags , , , ,

If you want to configure the libraries for use with a particular Eclipse plugin, this can seem rather a mystery at first. The traditional way in Eclipse to configure libraries for a project is to open the project properties for a project, select Java Build Path in the list on the left, and visit the libraries tab in the pane on the right. You can then use the “Add Jars” or “Add External Jars” to add jars to the project. To improve project portability across different development platforms, you can also add Classpath Variables which can be defined appropriately for each platform to isolate a project from platform specific jar locations etc. An example of this screen, with the JSF and ICEfaces entries expanded, is here :-

However, whilst you will see entries for plugins such as Eclipslink and ICEfaces on this screen, it does not provide any means of configuring them. Libraries for such plugins use an Eclipse feature called a Classpath Container. This allows the library configuration to be completely dynamic, as it is handled in code via a class. This allows the configuration to change at any time in response to project changes, as every reference to the classpath container is handled via the code rather than being static. To configure plugin libraries, therefore, you need to visit the dialogs for the Project Facets, which is where plugins are configured for the project. This post here, which details how to create a JPA-enabled EJB, shows this in action for JPA.

Another example would be to configure the  libraries for JSF and ICEfaces. You can do this as follows :-

Open the Project Properties dialog for the project, and select the Java Server Faces option under Project Facets in the left hand pane. This lists all the JSF and ICEfaces libraries available which may be selected/deselected.

The buttons on the right of the libraries frame allow management and downloading of the libraries. Clicking the Manage Libraries button allows configuration of the libraries available for selection in the project facets dialog above.

This is for example where you would upgrade ICEfaces libraries to a new version. You can leave both versions, or remove the old ones once you don’t need them any more. You can then select the new versions for that particular project in the parent Project Facets dialog.

Note that one particular issue arises when creating a new Eclipse workspace, as it is useful to migrate all the library definitions to the new workspace to avoid having to set them up manually or download them again. This post describes how you can do this by exporting and importing workspaces preferences. The post also discusses the issue of library location when sharing libraries – this is important as by default you would end up with one workspace sharing libraries within the folder structure of another workspace. My typical development folder structure is detailed at the end of this post.

If you subsequently return to view the libraries on the Libraries tab of the Java Build Path screen, you will then see the results of your efforts – the libraries for the plugins will have changed in accordance with your actions.

The dialogs used for plugin configuration do vary and are certainly not always intuitive or consistent – in these examples JPA was configured via the Java Persistence dialog in the project properties or via a link on the JPA facet screen which is not always present. In contrast, the JSF libraries (including the ICEfaces libraries) are configured via the Java Server Faces option under Project Facets. Even though there is an ICEfaces option under project facets, in my 3.5 Galileo Eclipse this displays “unknown library configuration”. However, the configuration is all there if you are willing to hunt around a bit for it!

No Comments »

December 3rd, 2009
3:14 pm
Create a JPA EJB using Eclipse/Eclipselink/Glassfish

Posted under Eclipse
Tags , , ,

This simple example was performed with Eclipse Galileo 3.5.1

1/ Project Creation Dialog

From the menus in eclipse, select File/New/EJB project. On the resulting dialog, name the project. You can pick other options at this stage such as EAR membership but this can be done later if desired. Note that we are not amending the configuration section (via the modify button) at this stage to add JPA faceting (more on this later).

Click Finish and your EJB project will be created.

2/Project Facets

Right click your new project, and select Project Facets on the left. Tick the box marked Java Persistence in the middle pane, and you will be presented with the following screen :-

3/ JPA Facets

Now Click the “Further configuration available” link at the bottom. This will display the JPA Facet dialog as follows. On this screen you should do the following :-

  1. Select the correct platform version and library type – typically these will be Eclipselink 1.1 or later version if available.
  2. Untick the box marked “Include libraries with this application”.  The  latest Eclipselink.jar  library should be deployed separately to Glassfish, and stored in the $GLASSFISH_HOME/lib directory. To clarify, Eclipselink is available as a single jar, non-OSGI deployment, or split up into multiple jars for OSGI deployment. The OSGI jars have the long names with the OSGI packaging prefixes such as “org.eclipse.persistence.core” followed by name and version number information. They are a finer grained breakdown of the classes to allow more selectivity/flexibility in use. You can copy the OSGI jars to $GLASSFISH_HOME/lib directory – this will also work but is unnecessarily complex for non-OSGI use. This post here contains a brief overview of OSGI and links to detailed information about it.
  3. Select the database connection to be used. If it is not already present, click the Add connection link to create a new one. This also allows you to add a new JDBC provider for a given database type, and point to the jar file(s) for the provider. Note that you will also need to add the JDBC provider jar to GLASSFISH_HOME/lib. To clarify, this database connection is used by eclipse to validate the persistent entities and mappings in the project during development. It is not used by Glassfish at run time. The run time connection (data source) will be created in Glassfish, and persistence.xml will be configured to use the datasource that you created in Glassfish.
  4. Next, you can select whether your annotated persistent classes will be discovered automatically, or whether they must be listed explicitly in persistence.xml. To ensure portatbility, you should take the manual option as  automatic discovery is not guarrranteed to be portable.
  5. Finally you can select whether or not to create orm.xml. You can always create it later if you need it – if you are using annotations entirely you won’t. This post here describes how you can combine both annotations and orm.xml in order to both take advantage of features like sequences in Oracle whilst still retaining database independance.

Click OK on the JPA Facet dialog, and then OK on the project facets screen. This will complete the creation of your project.

Note that as already stated, it is possible to click the modify button in the configuration section of the dialog in stage 1, which will also display the project facet screen. However, this version of the project facet screen is different to the one displayed if you select Project Facets after creating the project. In particular it does not have the “Further configuration available” option, and so does not allow you to display the JPA Facet dialog to modfy the options there. It assumes defaults for these options instead.

It is possible to  reconfigure the project JPA Facet settings subsequently, by selecting the “Java Persistence” option which appears in the list on the left of the project properties dialog (this only appears for projects with the JPA facet selected). This displays the “Java Persistence” dialog which has the same options as the “JPA Facets” dialog. Instead, you can also untick Java Persistence on the Project Facets screen, applying the changes, and retick the option. This will reveal the “Further Configuration Available” option to allow access to the JPA Facet dialog as well. In the example above, we added the Java persistence facet after saving the project which gave us immediate access to the JPA Facets dialog.

No Comments »

November 30th, 2009
1:40 pm
JPA Web Tutorials

Posted under JPA
Tags , , , , , , , ,

Update 08/09/2022

Another interesting and helpful post on primary key generation may be found on Baeldung here.

Original Post

There are a number listed on eclipse.org, oracle.com, and Sun.com. The eclipse ones are often not all complete but still useful.

  1. A general list of Eclipse tutorials is here
  2. Eclipse/JPA/Tomcat web tutorial
  3. Eclipselink/JPA/JSF web tutorial (looks incomplete and is missing the source code).
  4. Eclipselink/JPA/Glassfish V2 Web Tutorial – also a work in progress.
  5. Oracle – Build a Web Application (JSF) Using JPA
  6. Oracle – Example: Web Application (JSF) Using JPA (another article using the same code example as the previous one)
  7. The Sun Java ee 5 tutorial contains a JPA example.

No Comments »

November 30th, 2009
1:34 pm
Optimising tree structures in JPA

Posted under JPA
Tags ,

Interesting post by Nick Johnson about how to optimise lazy fetches and avoid loading the whole tree.
http://spatula.net/blog/2007/03/optimizing-message-tree-with-jpa.html

No Comments »

November 30th, 2009
1:11 pm
JPA Tutorial /EJB3/Glassfish/Derby

Posted under JPA
Tags , , ,

This one is from Web Age Solutions and is a good basic tutorial building on their earlier “simple session bean” one:-
http://www.webagesolutions.com/knowledgebase/javakb/jkb006/index.html

No Comments »

November 25th, 2009
5:53 pm
Eclipse/JPA outside container/Glassfish example

Posted under JPA
Tags , , ,

JPA Eclipse + GlassFish + Oracle XE – Outside EJB Container

Introduction

This example details the configuration of JPA running in Eclipse, using EclipseLink and GlassFish 2.1 and Oracle XE.
Eclipselink therefore overrides the built in TopLink Essentials JPA in GlassFish 2.1.

 

Installation

  1. Install the latest Java JDK 1.6 release
  2. Install the Eclipse Galilieo Java EE package (includes EclipseLink)
  3. Install GlassFish 2.1
  4. Install the GlassFish Eclipse Plugin (see web notes about downloading/installing this)
  5. Download and install Oracle XE

 

 Database Creation

In the Oracle XE database home page, click on Administration, then Manage Database Users, create database user. For testing purposes, you can give the user all roles and privileges, however you would not do this in a production environment. Note that in Oracle, creating a database user also creates an empty database schema, as the two terms are synonymous. A single Oracle XE database installation can have any number of schemas (users), all as distinct logical databases in the same database instance (container).

 

 Connection Pool / JDB Resource Creation

Open the GlassFish administration web page (by default this is at http://localhost:4848) and log in (default is admin/adminadmin). Open Resources, JDBC, and click on Connection Pools – the text, not the adjacent arrow. This will display the connection pools in the RHS pane. Click on New. Name the pool JPATestPool. Select a resource type of javax.sql.datasource, and select Oracle as the database vendor. Click Next, then in the additional properties, set the following values :-

Property Name

Value

User Your XE database username
Password Your XE database password
URL jdbc:oracle:thin:@localhost:1521:xe

 
Click Save to save the new connection pool.

Click on JDBC Resources in the left hand pane (again, the wording not the arrow), and click new to create a new resource. Select the conncetion pool just created in the dropdown list. For the JNDI name, enter jdbc/JPATestPool and click OK to save. Note that the JNDI name given must match the name given in the <non-jta-data-source> element value in persistence.xml.

 

Project Creation

  1. Create a new JPA project with the wizard. Select “GlassFish v2.1 Java EE 5” as the target runtime.
  2. Select either Default, Utility, or minimal for the configuration – this determines which facets are added to the project. Facets can be added later via the “Project Facets” page in the project properties.
    All of the above configurations worked.
  3. Following this, a connectivity driver (for Oracle in this case) needs adding to Eclipse and then to the project as follows :-
    Download ojdbc14.jar from Oracle.com here :-
    http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/htdocs/jdbc_10201.html
  4. Copy the file to the glassfish\lib folder under the GlassFish installation directory and Restart GlassFish.
    N.B. the jar file must be placed in this location
  5. Click on Window, preferences, and select Data Management, Connectivity, Driver Definitions in the left pane.
  6. Click Add, and assuming Oracle XE is in use, select “Oracle Thin Driver” for Oracle 10.
  7. Click on the Jar List tab. ojdbc14.jar should be listed. Browse for the above location where the actual jar was placed (<GlassFish_Home>\glassfish\lib) and select the jar from there.
    The properties tab allows defaults to be set up for database connectivity, but these values will be added in GlassFish when the data source is created.
  8.  Select Java Build Path in the project properties for the project you created above. Pick the libraries tab, and click Add Library. Click “Add Library” and select “Connectivity Driver Definitions” from the list. Select “Oracle thin Driver” from the drop down. If it is not present (i.e. because you did not create it correctly as above), you can click the button/icon to the right of the drop down and add the connectivity driver to Eclipse from there. Once done, you select it in the drop down then click finish to add it to the project.

 

 Creating the Source Code

Create the following java classes in Eclipse by right clicking the “src” folder of the project and selecting New,  Class. For the package name, enter uk.co.salientsoft.jpatest.domain. For the UserInfo class (which is the persisted class), the combined package and classname must match the value given in the <class> element in persistence.xml.

Class: JPATest

package uk.co.salientsoft.jpatest.domain;
import javax.persistence.*;
public class JPATest {

 private static final String PERSISTENCE_UNIT_NAME = "JPATest";
 private EntityManagerFactory factory;
 
 public static void main(String[] args) {
  JPATest jpaTest = new JPATest();
  jpaTest.addEntries();
 }

 public JPATest() {
  factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
 }
 
 public void addEntries() {
  EntityManager em = factory.createEntityManager();

  // Begin a new local transaction so that we can persist a new entity
  em.getTransaction().begin();

  // Read the existing entries
  Query q = em.createQuery("select u from UserInfo u");

  // Do we have entries?
  boolean createNewEntries = (q.getResultList().size() == 0);

  // No, so lets create new entries
  if (createNewEntries) {

   UserInfo userInfo;   
   
   userInfo = new UserInfo();
   userInfo.setUserName("Bilbo.Baggins");
   em.persist(userInfo);
   userInfo = new UserInfo();
   userInfo.setUserName("Frodo.Baggins");
   em.persist(userInfo);        
  }

  // Commit the transaction, which will cause the entity to
  // be stored in the database
  em.getTransaction().commit();
  
  // It is always good practice to close the EntityManager so that
  // resources are conserved.
  em.close();
 } 
}

Class: UserInfo

package uk.co.salientsoft.jpatest.domain;
import java.io.Serializable;
import javax.persistence.*;

/**
 * Entity implementation class for Entity: UserInfo
 *
 */
@Entity
public class UserInfo implements Serializable {
 
 @Id
 @GeneratedValue(strategy=GenerationType.AUTO)
 private long userID;
 private String userName;
 private static final long serialVersionUID = 1L; 
 public UserInfo() {
  super();
 }
 
 public long getUserID() {
   return this.userID;
 }

 public void setUserID(long userID) {
  this.userID = userID;
 }
   
 public String getUserName() {
   return this.userName;
 }

 public void setUserName(String userName) {
  this.userName = userName;
 }
}
 

Persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<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="JPATest" transaction-type="RESOURCE_LOCAL">
  <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
  <non-jta-data-source>jdbc/JPATestPool</non-jta-data-source>
  <class>uk.co.salientsoft.jpatest.domain.UserInfo</class>
  <properties>
   <property name="eclipselink.target-server" value="None" />
   <property name="eclipselink.logging.level" value="FINEST" />
   <property name="eclipselink.session-name" value="JPATestSession" />

   <!-- EclipseLink should create the database schema automatically -->
   <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
   <property name="eclipselink.ddl-generation.output-mode" value="database" />

  </properties>
 </persistence-unit>
</persistence>

 

Notes  on Persistence.xml

 <persistence-unit name="JPATest" transaction-type="RESOURCE_LOCAL">

The persistence unit defines a related grouping of classes, metadata etc. which are being persisted .

 NOTE – ensure that the value matches the one passed to createEntityManagerFactory in the code, or the call causes a stack trace citing no persistence provider found – all the available persistence providers are tried and listed and they all return null. They are all tried to see if they support the given persistence unit  (i.e. are they listed as the provider for that persistence unit in persistence.xml) hence the error.

 Transaction-type needs to be ”RESOURCE_LOCAL” if jpa is used outside the EJB container, in which case the datasource is defined as a <non-jta-data-source>. Note that the datasource in this case is still defined in GlassFish.

The alternative for jpa usage inside the conainer , e.g. from a session bean, would be to defined transaction-type as “JTA” and the datasource as a <jta-data-source>.

<property name="eclipselink.target-server" value="None" />

 

Note  that with JPA inside the container, the above property would have the following value :-

<property name="eclipselink.target-server" value="SunAS9" />

 

When set to “SunAS9”, you must use a JTA data source and JTA transaction type or you get an error. When you use “None” you can use <non-jta-data-source> and “RESOURCE_LOCAL”, but note that you can still refer to the data source defined in GlassFish, or you can define one explicitly in persistence.xml. You could define one explicitly in persistence.xml as follows :-

 <property name="eclipselink.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
 <property name="eclipselink.jdbc.user" value="jpatest"/>
 <property name="eclipselink.jdbc.password" value="jpatest"/>
 <property name="eclipselink.jdbc.driver" value="oracle.jdbc.OracleDriver"/>

 

The mechanism used to drop and create the tables automatically (“drop-and-create-tables” value) is jpa provider dependant (and may not always be available). When it is used with EclipseLink as above, a stack trace with a number of errors is dumped when it tries to drop non existant tables etc., and due to other issues. If you check in Oracle XE and can see the tables and the data, the errors can be ignored. The drop and create only needs to be done once to create the tables. You can remove this property from persistence.xml to prevent the tables being dropped and created each time. Note that this can also be done directly from Eclipse via the project context menu, as detailed here.
 

Running the application

  1. In Eclipse, select Window, Show View, Servers. If GlassFish is not listed, right click the server window and select New Server. Then Select GlassFish 2.1 Java EE 5. Click Next, and browse for the <GlassFish_Home>\glassfish directory (leave the JRE as the default).
  2. Right click the server in the servers view, then select start to start it if it is not running.
  3. Right click on JPATest.java and select Run as, then Java application.
  4. The application should then run and populate the database. Log in to the XE database home page as the user/schema you created, and click on the object browser.
  5. Click on the UserInfo table and you should see the rows which were created.

No Comments »