Blog Archives

December 18th, 2009
12:24 pm
Eclipse JPA Generate Tables From Entities “Unable to identify VM” error

Posted under Eclipse
Tags , , ,

This error was caused by importing Eclipse projects from another configuration. The projects had a different JRE library configured, which eclipse listed as “Unbound” as it was not present.

Simply adding the default JRE system library and removing the unbound definition solved the problem. To do this, right click the project, and select Build Path/Configure Build Path. Select the libraries tab on the right hand pane and add/remove from there.

Strangely, this problem did not stop projects running completely – eclipse still allowed a number of small test projects to run even with the “unbound” jre configured. The problem only appeared to manifest itself when trying to create the database schema from the entities via right clicking on the project and selecting JPA Tools/Generate Tables from Entities, wherupon the error occurred.

No Comments »

December 18th, 2009
11:33 am
Java Dev setup – Eclipse/Eclipselink/ICEfaces/Glassfish/Tomcat

Posted under Java
Tags , , , , ,

  1. Decide on component versions to be used by building a cross compatibility matrix. Generally you will want to install the latest production builds of all components consistent with full cross compatibility. Also to be considered are the various tool bundles available, which can simplify installation and configuration by allowing multiple tools to be installed from a single kit. However, many of the bundles overlap, so this needs to be taken into account (in addition to the compatibility matrix)  so that you do not end up installing multiple versions of the same tool – for example, Java EE can come with the JDK or with Eclipse. In my case, I am using an Eclipse bundle which includes Java EE.
  2. Download and install the chosen Java SE JDK.
  3. Download and install Glassfish (Eclipse has a plugin for, and therefore a dependency on, Glassfish so we do the latter first).
  4. Download and install Eclipse. My bundle included Java EE 5 and Eclipselink and all the web tools.
  5. Install the Glassfish Plugin for Eclipse.
  6. Download ICEfaces (e.g. v1.8.x). This just needs unzipping to any desired target folder (e.g. E:\ICEfaces-1.8.x). The distribution contains full documentation for getting started, running tutorials, and development.
  7. Download and Install the Eclipse ICEfaces plugin.
  8. Download Tomcat if required. You may just want to use Glassfish as your servlet container, but in my case some development projects will use JSF/ICEfaces/Tomcat without Java EE. I have in the past used the windows service installer version, which is a self installing .exe and installs/runs Tomcat as a service. However note that this does not work under Windows 64-bit if you are using a 32 bit JVM. See here for a manual install process from the zip kit to give you all the functionality of the windows installer version, including run as a service, configuration utility, and system tray monitor/utility.

No Comments »

December 17th, 2009
4:15 pm
Using Eclipse/JSF/JPA with Tomcat 6

Posted under JPA
Tags , , , , , ,

I’ve found that this is useful for prototyping/mockups of apps that are targetted for GlassFish. It is possible to run JPA with Eclipselink outside an EJB container, so a JSF/JPA app can be run under Tomcat, resulting in less overhead and faster turnaround of changes. For a while I’ve had to use a PC which is RAM limited, and so developing/prototyping with Eclipse and Glassfish has been slow. Turning around deployments/changes around takes time, and I’ve found the synchronisation between Eclipse and Glassfish to be a bit fussy – sometimes Eclipse misunderstands the state of Glassfish, needing a Glassfish restart which again takes valuable time.

Note the following points on doing this:-

1/ My application stack looks similar to the ‘real’ one, but my Service layer/domain objects are just POJOs which are explicitly created or injected via faces_config.xml. This Oracle Example details the various IOC features of the JSF. managed bean facility.

2/ Persistence.xml needs setting up differently to run JPA outside the container. I have found it easiest to specify the database connection explicitly, rather than using a data source. In Eclipse, you can use the persistence.xml editor to populate the connection properties directly from the one Eclipse uses for its entity validation. Whilst you can do JNDI lookups of a data source stored in Tomcat, the naming context used is different, as it makes use of the Enterprise Naming Context (ENC), i.e. “java:comp/env”. This example details how to do it if you want to go that way. A sample persistence.xml follows (with entries commented out where they have been replaced for use with Tomcat) :- 

<?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="SentryPrototype" transaction-type="JTA">-->
 <persistence-unit name="SentryPrototype" transaction-type="RESOURCE_LOCAL">

   <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>

   <!--<jta-data-source>jdbc/JPATestPool</jta-data-source>-->

   <class>uk.co.salientsoft.jpatest.domain.UserInfo</class>
   <properties>
    <property name="eclipselink.logging.level" value="INFO" />

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

    <property name="eclipselink.session-name" value="SentryPrototypeSession" />
    <property name="eclipselink.target-database" value="Oracle" />   
    <property name="eclipselink.ddl-generation.output-mode" value="database" />

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

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

 

3/ Ref this eclipse tutorial :-
Tomcat does not have an EJB container so you must add EJB 3.0/JPA 1.0 capability for EclipseLink JPA by placing the specification persistence.jar into the container lib directory $TOMCAT_HOME/lib.
It is recommended to put persistence_1_0.xsd there as well.  It is not recommended that the WAR include its own version of persistence.jar. Your eclipse project should reference but not include this jar and xsd.

The eclipselink.jar should be placed off of the container lib directory $TOMCAT_HOME/lib.
Since Tomcat does not include an EJB container, you may put eclipselink.jar in the web applications’s lib directory or higher up in the classloader by putting it off of Tomcats’ lib directory, where all web applications can access it.
Do not split the eclipselink.jar from the javax.persistence jar – keep them together – preferably in $TOMCAT_HOME/lib

 4/ Tomcat has its own dependencies on the Expression Language (EL) web libraries. These should be removed from WEB_INF/lib when deploying to Tomcat as pointed out here. (If you do not do this, the application will crash with duplicate class loading exceptions.) This may be done in eclipse on the Java Server Faces facet page – open the project properties for the project, and select Java Server Faces under Project Facets. Untick the entry for Standardized EL Library v1.0.

Then save the changes and redeploy the application.

For more information, the eclipse tutorial referenced in 3/ goes into greater depth on the subject. You can also find a list of the available eclipse JPA tutorials here.

5/ When running xxxxxx

Comments Off on Using Eclipse/JSF/JPA with Tomcat 6

December 15th, 2009
11:09 am
Accessing JPA Entity Metadata

Posted under JPA
Tags , ,

It is often useful to access the entity definition metadata. A classic example would be to access the actual maximum defined length of a string column from the code. Such a definition should be centralised to avoid multiple definitions of a constant value, which would otherwise require multiple changes if the value were increased. There are several approaches to this, but unfortunately not an obvious ‘silver bullet’ which is straightforward and also performant.

1/ Access Database Metadata via JDBC

You can access the actual database definitions via a JDBC connection. This would have a performance penalty, but would make sense if the database is your master definition source, i.e. you are starting with a database defninition and then creating entities based on the database. You can get a JDBC connection from JPA via the code below, as described at the end of this post here :-

JPA 2.0

entityManager.getTransaction().begin();
java.sql.Connection connection = entityManager.unwrap(java.sql.Connection.class);
...
entityManager.getTransaction().commit();

 

JPA 1.0

entityManager.getTransaction().begin();
UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)((JpaEntityManager)entityManager.getDelegate()).getActiveSession();
unitOfWork.beginEarlyTransaction();
java.sql.Connection connection = unitOfWork.getAccessor().getConnection();
...
entityManager.getTransaction().commit();

 

  This post here  details how to get metadata from a connection. The sample code from the post follows :-

Get Column Size

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class Main {
  public static void main(String[] argsthrows Exception {
    Connection conn = getMySqlConnection();
    System.out.println("Got Connection.");
    Statement st = conn.createStatement();
    st.executeUpdate("drop table survey;");
    st.executeUpdate("create table survey (id int,name varchar(30));");
    st.executeUpdate("insert into survey (id,name ) values (1,'nameValue')");

    ResultSet rsColumns = null;
    DatabaseMetaData meta = conn.getMetaData();
    rsColumns = meta.getColumns(null, null, "survey"null);
    while (rsColumns.next()) {
      String columnName = rsColumns.getString("COLUMN_NAME");
      System.out.println("column name=" + columnName);
      String columnType = rsColumns.getString("TYPE_NAME");
      System.out.println("type:" + columnType);
      int size = rsColumns.getInt("COLUMN_SIZE");
      System.out.println("size:" + size);
      int nullable = rsColumns.getInt("NULLABLE");
      if (nullable == DatabaseMetaData.columnNullable) {
        System.out.println("nullable true");
      else {
        System.out.println("nullable false");
      }
      int position = rsColumns.getInt("ORDINAL_POSITION");
      System.out.println("position:" + position);
      
    }

    st.close();
    conn.close();
  }

  private static Connection getHSQLConnection() throws Exception {
    Class.forName("org.hsqldb.jdbcDriver");
    System.out.println("Driver Loaded.");
    String url = "jdbc:hsqldb:data/tutorial";
    return DriverManager.getConnection(url, "sa""");
  }

  public static Connection getMySqlConnection() throws Exception {
    String driver = "org.gjt.mm.mysql.Driver";
    String url = "jdbc:mysql://localhost/demo2s";
    String username = "oost";
    String password = "oost";

    Class.forName(driver);
    Connection conn = DriverManager.getConnection(url, username, password);
    return conn;
  }

  public static Connection getOracleConnection() throws Exception {
    String driver = "oracle.jdbc.driver.OracleDriver";
    String url = "jdbc:oracle:thin:@localhost:1521:caspian";
    String username = "mp";
    String password = "mp2";

    Class.forName(driver)// load Oracle driver
    Connection conn = DriverManager.getConnection(url, username, password);
    return conn;
  }
}

 

2/ Access JPA Annotations via Reflection

Alternatively, you could try using Reflection to read the JPA annotations via introspection.  This post here describes how to read annotations with Reflection, but note that this is not a JPA example – it is a ‘roll your own persistance provider’ example, but the introspection techniques should work the same way. The downside of this technique is that all that introspection just seems laborious and slow performing if all you want is the length of a few string columns.

 

3/ Use Constants in Inner Classes to roll your own master Metadata Definitions

Another way, which makes sense if the entity defninitions are the ‘master’ and you are creating the database tables from the entities, is just to define some inner classes in the entity class containing static constants for the metadata you need access to. You can then use these definitions as the master, and refer to them both in the annotations and the calling code. You can also use an inheritance hierachy to standardise the metadata you are using, and centralise common definitions. As you are rolling your own metadata, you do not have to stick to the jpa annotations, you are free to invent any other constants that you need to tell you something about your entities/columns. The example which follows demonstrates column metadata, but you could of course apply the same technique to entity (table) level metadata if required.

In this example, a number of entities have Code fields containing a coded string which might be 30 characters, and description fields which might be 255 characters. The definitions for “Code” and “Description” can be centralised in a common superclass. In each Entity, for all the fields for which you want to expose the metadata, you define a public  inner class named <FieldName>Meta just above the field and annotation declarations. You can then access the constants in the inner class statically from outside the entity. (If required, you could also provide a statically initialised field containing a reference to the <FieldName>Meta class, and create a getter for it, if you need getter access as well, e.g. for managed access via a framework such as JSF, although this involves non static access to a static value which eclipse/java will winge about). The following code samples illustrate the technique:-

Class ColumnMeta

package uk.co.salientsoft.jpa;

/* This base class defines the metadata used. */

public abstract class ColumnMeta {
 public static final String NAME = null;
 public static final int LENGTH = 255;
}

 

Class ColumnMetaCode

package uk.co.salientsoft.test.domain;
import uk.co.salientsoft.jpa.ColumnMeta;

public abstract class ColumnMetaCode extends ColumnMeta {
 public static final String NAME = "Code";
 public static final int LENGTH = 30;
}

 

Class ColumnMetaDescription

package uk.co.salientsoft.test.domain;
import uk.co.salientsoft.jpa.ColumnMeta;

public abstract class ColumnMetaDescription extends ColumnMeta {
 public static final String NAME = "Description";
 public static final int LENGTH = 255;
}

 

Entity Class AppRole

package uk.co.salientsoft.test.domain;

import java.io.Serializable;
import java.lang.String;
import javax.persistence.*;

@Entity
public class AppRole implements Serializable {

 private static final long serialVersionUID = 1L;

 @Id
 @GeneratedValue(generator="AppRoleID")
 private long AppRoleID;
 private long AppID;

 public class CodeMeta extends ColumnMetaCode {};
 @Column(length=CodeMeta.LENGTH)
 private String Code;
 
 public class DescriptionMeta extends ColumnMetaDescription {};
 @Column(length=DescriptionMeta.LENGTH)
 private String Description;

 public AppRole() {
  super();
 }  
 public long getAppRoleID() {
  return this.AppRoleID;
 }
 public void setAppRoleID(long AppRoleID) {
  this.AppRoleID = AppRoleID;
 }  
 public long getAppID() {
  return this.AppID;
 }
 public void setAppID(long AppID) {
  this.AppID = AppID;
 }  
 public String getCode() {
  return this.Code;
 }
 public void setCode(String Code) {
  this.Code = Code;
 }  
 public String getDescription() {
  return this.Description;
 }
 public void setDescription(String Description) {
  this.Description = Description;
 }
}

 

Example MetaData References

codeLength = AppRole.CodeMeta.LENGTH;
descLength = AppRole.DescriptionMeta.LENGTH;

Comments Off on Accessing JPA Entity Metadata

December 9th, 2009
6:45 pm
Creating database tables from Entities in Eclipse

Posted under JPA
Tags , , ,

This can be done a couple of different ways :-

  1. From the Project context menu, select JPA Tools/Create Tables from Entities. This will drop and create the whole schema based on the entity definitions.
  2. Alternatively, you can configure persistence.xml to drop and create the whole schema before each run as detailed in the example file here.

Comments Off on Creating database tables from Entities in Eclipse

December 9th, 2009
6:06 pm
Using Oracle Specific features in JPA with Eclipselink

Posted under JPA
Tags , , ,

To use Oracle specific features in JPA with Eclipselink, such as using sequences for ID generation as described in this example here, it is necessary to set the correct property in persistence.xml to ensure that JPA/Eclipselink knows that an Oracle database is in use. By default, it does not discover this automatically and resorts to using table based ID generation even if you turn sequences on as per the above example.

A sample persistence.xml with the correct properties follows :-

<?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>
  <mapping-file>META-INF/orm.xml</mapping-file>
  <class>uk.co.salientsoft.jpatest.domain.UserInfo</class>
  <properties>
   <property name="eclipselink.target-server" value="SunAS9" />
   <property name="eclipselink.logging.level" value="FINEST" />
   <property name="eclipselink.session-name" value="JPATestSession" />

   <!-- Ensure Eclipselink knows we have an Oracle Database
        so that Oracle specific features work correctly -->
   <property name="eclipselink.target-database" value="Oracle"/>

   <!-- This will cause EclipseLink to create the database schema
        automatically on every run.
        You can also do this from the JPA Tools/Create Tables from Entities
        project context menu option in Eclipse, which may well be preferrable-->
   <!--
   <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
   <property name="eclipselink.ddl-generation.output-mode" value="database" />
   -->

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

Comments Off on Using Oracle Specific features in JPA with Eclipselink

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 »