Tuesday Jan 22, 2013

Default DataSource in Java EE 7: Lesser XML and More Defaults (TOTD #196)


Section E.5.5.20 in the Java EE 7 Platform specification defines a new Default Data Source that must be provided by a Java EE 7-compliant runtime. This pre-configured data source can be used by application for accessing the associated database. It is accessible to the application under the JNDI name:
java:comp/DefaultDataSource

This can be accessed in the application as:
@Resource(name="myDataSource", lookup="java:comp/DefaultDataSource")
DataSource myDS;

If the binding is not specified, the mapping of the reference will default to this default data source. So the above fragment is equivalent to:
@Resource(name="myDataSource")
DataSource myDS;

Section 8.2.1.5 in the JPA 2.1 specification says

If neither jta-data-source and non-jta-data-source elements are specified, the deployer must specify a JTA data source at deployment or a JTA data source must be provided by the container, and a JTA EntityManagerFactory will be created to correspond to it.

Per.book
This means a Java EE 7 application can have the following persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
<persistence-unit name="myPU" transaction-type="JTA">
<jta-data-source>java:comp/DefaultDataSource</jta-data-source>
</persistence-unit>
</persistence>

This is semantically equivalent to:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
<persistence-unit name="movieplex7PU" transaction-type="JTA"/>
</persistence>

Notice, no jta-data-source.

In both cases, the default data source will be provisioned and available to the application. In GlassFish 4, this is bound to the JDBC resource jdbc/__default.

And this can be verified by giving the command:
./bin/asadmin list-jdbc-resources
jdbc/sample
jdbc/__TimerPool
jdbc/__default
Command list-jdbc-resources executed successfully.

Lesser XML and more defaults makes Java EE 7 more lightweight and user friendly!

Download GlassFish 4.0 promoted build and try it today!

Friday Jan 18, 2013

JPA 2.1 Implementation - EclipseLink M6 integrated in GlassFish 4 (TOTD #195)

As TOTD #187 explained, one of the new features in JPA 2.1 is Schema Generation. It refers to generation of database artifacts like tables, indexes, and constraints in a database schema. Read TOTD #187 for more details. This Tip Of The Day (TOTD) will explain how to use this feature in GlassFish 4.

JPA 2.1 is implemented in EclipseLink and the status shows that a decent progress is made. EclipseLink Milestone builds shows the dates when milestones are released. It typically takes a few days for the milestone to be integrated in GlassFish 4 after the release.

How do you know which milestone is integrated in GlassFish 4 ?

Issue the following commmand in glassfish/modules directory:
unzip -p org.eclipse.persistence.core.jar META-INF/MANIFEST.MF | grep Bundle-Version
to see an output as:
Bundle-Version: 2.5.0.v20130110-d839ca4
If we break the version string then it shows this is version 2.5.0 and dated 20130110 in the format YYYYMMDD, that would be Jan 10, 2013. Based upon the milestone release dates, this indicates M6 is integrated.

I tried this with the latest nightly build (dated Jan 18). By the time you read this blog, a newer version may be integrated and so the version string may look different.

Now lets see this in action!

The sample code explained below can be downloaded here and run on GlassFish 4 1/17 nightly. A promoted build after this nightly should work too.

Create an Entity class as:
@Entity
@Table
@NamedQueries({
@NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e")
})
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;

@Column(length=40)
private String name;
This is a simple Employee entity that has two fields id and name. A trivial @NamedQuery is defined to retrieve the list of employees.

The associated persistence.xml looks like:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
<persistence-unit name="MyPU" transaction-type="JTA">
<jta-data-source>jdbc/sample</jta-data-source>
<properties>
<property name="javax.persistence.schema-generation-action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation-target" value="database"/>
<property name="eclipselink.deploy-on-startup" value="true"/>
</properties>
</persistence-unit>
</persistence>

Other than the usual elements like <persistence-unit> and <jta-data-source>, the newly introduced properties - javax.persistence.schema-generation-action and javax.persistence.schema-generation-target define the action and target for the schema generation. The action is to drop and create the tables. The target defines to perform the action in the database. These properties control the behavior of schema generation and their meaning is defined in TOTD #187. Notice, the third property is EclipseLink specific and is specified to eagerly initialize the Persistence Unit. This will ensure that the schema is generated during the application deployment itself. Otherwise it is generated when the PU is first accessed.

This will generate the table in the database defined by jdbc/sample JDBC resource. This resource is pre-defined for JavaDB that is already bundled with GlassFish 4.

After this, you can write a simple EJB as:

@Stateless
public class EmployeeBean {

@PersistenceContext
EntityManager em;

public void persist(Employee e) {
em.persist(e);
}

public List<Employee> get() {
return em.createNamedQuery("Employee.findAll", Employee.class).getResultList();
}
}

And invoke it from a Servlet as:

for (int i=0; i<5; i++) {
bean.persist(new Employee("Name" + i));
}
for (Employee e : bean.get()) {
out.println(e.getName() + "<br>");
}

A different set of properties may be specified as:

<properties>
<property name="javax.persistence.schema-generation-action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation-target" value="scripts"/>
<property name="javax.persistence.ddl-create-script-target" value="createfoo.sql"/>
<property name="javax.persistence.ddl-drop-script-target" value="dropfoo.sql"/>
<property name="eclipselink.deploy-on-startup" value="true"/>
<property name="eclipselink.application-location" value="/tmp"/>
</properties>
These properties specify the action as "drop-and-create", i.e. drop and create the tables. The target specifies the the action to be performed in a script. The *.script-target property specifies the name of the files for create and drop DDL. The following scripts are generated:

more /tmp/createfoo.sql 
CREATE TABLE EMPLOYEE (ID INTEGER NOT NULL, NAME VARCHAR(40), PRIMARY KEY (ID))
CREATE TABLE SEQUENCE (SEQ_NAME VARCHAR(50) NOT NULL, SEQ_COUNT DECIMAL(15), PRIMARY KEY (SEQ_NAME))
INSERT INTO SEQUENCE(SEQ_NAME, SEQ_COUNT) values ('SEQ_GEN', 0)
CREATE TABLE SEQUENCE (SEQ_NAME VARCHAR(50) NOT NULL, SEQ_COUNT DECIMAL(15), PRIMARY KEY (SEQ_NAME))
INSERT INTO SEQUENCE(SEQ_NAME, SEQ_COUNT) values ('SEQ_GEN', 0)

more /tmp/dropfoo.sql
DROP TABLE EMPLOYEE
DELETE FROM SEQUENCE WHERE SEQ_NAME = 'SEQ_GEN'

By default, the scripts are generated in glassfish/domains/domain1 directory. In this case, an EclipseLink-specific property to identify the base location of the generated files is specified.

As TOTD #187 explains, you can bundle DDL and DML scripts to generate and populate the database. Are you ready to test drive JPA 2.1 implemented using EclipseLink 2.5 in GlassFish 4 ?

JPA 2.1 Public Review specification has been available for a few days now. The Appendix A in the specification provide revision history in case you want to focus on the newly added features only.  If you are a JUG member, you may consider adopting this JSR and provide feedback!

Tuesday Apr 10, 2012

Java EE 6 and NoSQL/MongoDB on GlassFish using JPA and EclipseLink 2.4 (TOTD #175)


TOTD #166 explained how to use MongoDB in your Java EE 6 applications. The code in that tip used the APIs exposed by the MongoDB Java driver and so requires you to learn a new API. However if you are building Java EE 6 applications then you are already familiar with Java Persistence API (JPA). Eclipse Link 2.4, scheduled to release as part of Eclipse Juno, provides support for NoSQL databases by mapping a JPA entity to a document. Their wiki provides complete explanation of how the mapping is done.

This Tip Of The Day (TOTD) will show how you can leverage that support in your Java EE 6 applications deployed on GlassFish 3.1.2.

Before we dig into the code, here are the key concepts ...
  • A POJO is mapped to a NoSQL data source using @NoSQL or <no-sql> element in "orm.xml".
  • A subset of JPQL and Criteria query are supported, based upon the underlying data store
  • Connection properties are defined in "persistence.xml"
Now, lets lets take a look at the code ...
  1. Download the latest EclipseLink 2.4 Nightly Bundle. There is a Installer, Source, and Bundle - make sure to download the Bundle link (20120410) and unzip.
  2. Download GlassFish 3.1.2 zip and unzip.
  3. Install the Eclipse Link 2.4 JARs in GlassFish
    • Remove the following JARs from "glassfish/modules":
      org.eclipse.persistence.antlr.jar
      org.eclipse.persistence.asm.jar
      org.eclipse.persistence.core.jar
      org.eclipse.persistence.jpa.jar
      org.eclipse.persistence.jpa.modelgen.jar
      org.eclipse.persistence.moxy.jar
      org.eclipse.persistence.oracle.jar
    • Add the following JARs from Eclipse Link 2.4 nightly build to "glassfish/modules":
      org.eclipse.persistence.antlr_3.2.0.v201107111232.jar
      org.eclipse.persistence.asm_3.3.1.v201107111215.jar
      org.eclipse.persistence.core.jpql_2.4.0.v20120407-r11132.jar
      org.eclipse.persistence.core_2.4.0.v20120407-r11132.jar
      org.eclipse.persistence.jpa.jpql_2.0.0.v20120407-r11132.jar
      org.eclipse.persistence.jpa.modelgen_2.4.0.v20120407-r11132.jar
      org.eclipse.persistence.jpa_2.4.0.v20120407-r11132.jar
      org.eclipse.persistence.moxy_2.4.0.v20120407-r11132.jar
      org.eclipse.persistence.nosql_2.4.0.v20120407-r11132.jar
      org.eclipse.persistence.oracle_2.4.0.v20120407-r11132.jar
  4. Start MongoDB
    1. Download latest MongoDB from here (2.0.4 as of this writing).
    2. Create the default data directory for MongoDB as:
      sudo mkdir -p /data/db/
      sudo chown `id -u` /data/db
      Refer to Quickstart for more details.
    3. Start MongoDB as:
      arungup-mac:mongodb-osx-x86_64-2.0.4 <arungup> ->./bin/mongod
      ./bin/mongod --help for help and startup options
      Mon Apr  9 12:56:02 [initandlisten] MongoDB starting : pid=3124 port=27017 dbpath=/data/db/ 64-bit host=arungup-mac.local
      Mon Apr  9 12:56:02 [initandlisten] db version v2.0.4, pdfile version 4.5
      Mon Apr  9 12:56:02 [initandlisten] git version: 329f3c47fe8136c03392c8f0e548506cb21f8ebf
      Mon Apr  9 12:56:02 [initandlisten] build info: Darwin erh2.10gen.cc 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386 BOOST_LIB_VERSION=1_40
      Mon Apr  9 12:56:02 [initandlisten] options: {}
      Mon Apr  9 12:56:02 [initandlisten] journal dir=/data/db/journal
      Mon Apr  9 12:56:02 [initandlisten] recover : no journal files present, no recovery needed
      Mon Apr  9 12:56:02 [websvr] admin web console waiting for connections on port 28017
      Mon Apr  9 12:56:02 [initandlisten] waiting for connections on port 27017
  5. Check out the JPA/NoSQL sample from SVN repository. The complete source code built in this TOTD can be downloaded here.
  6. Create Java EE 6 web app
    1. Create a Java EE 6 Maven web app as:
      mvn archetype:generate
      -DarchetypeGroupId=org.codehaus.mojo.archetypes
      -DarchetypeArtifactId=webapp-javaee6
      -DgroupId=model -DartifactId=javaee-nosql
      -DarchetypeVersion=1.5 -DinteractiveMode=false
    2. Copy the model files from the checked out workspace to the generated project as:
      cd javaee-nosql
      cp -r ~/code/workspaces/org.eclipse.persistence.example.jpa.nosql.mongo/src/model src/main/java
    3. Copy "persistence.xml"
      mkdir src/main/resources
      cp -r ~/code/workspaces/org.eclipse.persistence.example.jpa.nosql.mongo/src/META-INF ./src/main/resources
    4. Add the following dependencies:
      <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>org.eclipse.persistence.jpa</artifactId>
      <version>2.4.0-SNAPSHOT</version>
      <scope>provided</scope>
      </dependency>
      <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>org.eclipse.persistence.nosql</artifactId>
      <version>2.4.0-SNAPSHOT</version>
      </dependency>
      <dependency>
      <groupId>org.mongodb</groupId>
      <artifactId>mongo-java-driver</artifactId>
      <version>2.7.3</version>
      </dependency>

      The first one is for the EclipseLink latest APIs, the second one is for EclipseLink/NoSQL support, and the last one is the MongoDB Java driver.

      And the following repository:
      <repositories>
      <repository>
      <id>EclipseLink Repo</id>
      <url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;file=/rt/eclipselink/maven.repo</url>
      <snapshots>
      <enabled>true</enabled>
      </snapshots>
      </repository> 
      </repositories>
    5. Copy the "Test.java" to the generated project:
      mkdir src/main/java/example
      cp -r ~/code/workspaces/org.eclipse.persistence.example.jpa.nosql.mongo/src/example/Test.java ./src/main/java/example/
      This file contains the source code to CRUD the JPA entity to MongoDB. This sample is explained in detail on EclipseLink wiki.
    6. Create a new Servlet in "example" directory as:
      package example;

      import java.io.IOException;
      import java.io.PrintWriter;
      import javax.servlet.ServletException;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;

      /**
      * @author Arun Gupta
      */
      @WebServlet(name = "TestServlet", urlPatterns = {"/TestServlet"})
      public class TestServlet extends HttpServlet {

      protected void processRequest(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      response.setContentType("text/html;charset=UTF-8");
      PrintWriter out = response.getWriter();
      try {
      out.println("<html>");
      out.println("<head>");
      out.println("<title>Servlet TestServlet</title>");
      out.println("</head>");
      out.println("<body>");
      out.println("<h1>Servlet TestServlet at " + request.getContextPath() + "</h1>");
      try {
      Test.main(null);
      } catch (Exception ex) {
      ex.printStackTrace();
      }
      out.println("</body>");
      out.println("</html>");
      } finally {
      out.close();
      }
      }

      @Override
      protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      processRequest(request, response);
      }

      @Override
      protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      processRequest(request, response);
      }
      }
  7. Build the project and deploy it as:

    mvn clean package
    glassfish3/bin/asadmin deploy --force=true target/javaee-nosql-1.0-SNAPSHOT.war
  8. Accessing http://localhost:8080/javaee-nosql/TestServlet shows the following messages in the server.log:

    connecting(EISLogin(
    platform=> MongoPlatform
    user name=> ""
    MongoConnectionSpec()
    ))
    . . .

    Connected:
    User:
    Database: 2.7  Version: 2.7

    . . .

    Executing MappedInteraction()
    spec => null
    properties => {mongo.collection=CUSTOMER, mongo.operation=INSERT}
    input => [DatabaseRecord(
    CUSTOMER._id => 4F848E2BDA0670307E2A8FA4
    CUSTOMER.NAME => AMCE)]

    . . .


    Data access result: [{TOTALCOST=757.0, ORDERLINES=[{DESCRIPTION=table,
    LINENUMBER=1, COST=300.0}, {DESCRIPTION=balls, LINENUMBER=2, COST=5.0},
    {DESCRIPTION=rackets, LINENUMBER=3, COST=15.0}, {DESCRIPTION=net,
    LINENUMBER=4, COST=2.0}, {DESCRIPTION=shipping, LINENUMBER=5,
    COST=80.0}, {DESCRIPTION=handling, LINENUMBER=6, COST=55.0},
    {DESCRIPTION=tax, LINENUMBER=7, COST=300.0}], SHIPPINGADDRESS=
    [{POSTALCODE=L5J1H7, PROVINCE=ON, COUNTRY=Canada, CITY=Ottawa,
    STREET=17 Jane St.}], VERSION=2, _id=4F848E2BDA0670307E2A8FA8,
    DESCRIPTION=Pingpong table, CUSTOMER__id=4F848E2BDA0670307E2A8FA7,
    BILLINGADDRESS=[{POSTALCODE=L5J1H8, PROVINCE=ON, COUNTRY=Canada,
    CITY=Ottawa, STREET=7 Bank St.}]}]

    You'll not see any output in the browser, just the output in the console. But the code can be easily modified to do so.

Once again, the complete Maven project can be downloaded here.

Do you want to try accessing relational and non-relational (aka NoSQL) databases in the same PU ?

Monday Jan 23, 2012

JPA 2.1 Early Draft Explained - Java EE 7 making progress

Java Persistence API 2.1 Early Draft has been available for about a month now. JPA2 was one of the first JSRs to be filed as part of Java EE 7. Several other specifications in Java EE 7 have released early drafts as well (JavaServer Faces 2.0, JAX-RS 2.0, CDI 1.1, more coming as well) and I'll cover them in later blogs.

Here are the main highlights of JPA 2.1:
  • Support for Stored Procedures: Added support for the invocation of predefined database functions and user-defined database functions to the Java Persistence query language.

    There are different variants of EntityManager.createXXXStoredProcedureQuery methods that return a StoredProcedureQuery for executing a stored procedure.  Just liked @NamedQuery, there is @NamedStoredProcedureQuery that specifies and names a stored procedure, its parameters, and its result type. This annotation can be specified on an entity or mapped superclass. The name specified in the annotation is then used in EntityManager.createNamedStoredProcedureQuery. The IN, OUT, and INOUT parameters can be set and used to retrieve values passed back from the procedure. For example:

    @Entity
    @NamedStoredProcedureQuery(name="topGiftsStoredProcedure", procedureName="Top10Gifts")
    public class Product {
     . . .
    }


    // In your client

    StoredProcedreQuery query = EntityManager.createNamedStoredProcedureQuery("topGiftsStoredProcedure");
    query.registerStoredProcedureParameter(1, String.class, ParameterMode.INOUT);
    query.setParameter(1, "top10");
    query.registerStoredProcedureParameter(2, Integer.class, ParameterMode.IN);
    query.setParameter(2, 100);
    // there are other setParameter methods for defining the temporal type of a parameter
    . . .
    query.execute();
    String response = query.getOutputParameterValue(1);


    The section 3.8.6 provide more details.
  • Bul update/delete using Criteria: Added CriteriaUpdate, CriteriaDelete, CommonAbstractQuery interfaces, refactored AbstractQuery interface.

    Here is a sample for CriteriaUpdate from section 6.5.15:

    CriteriaUpdate<Customer> q = cb.createCriteriaUpdate(Customer.class);
    Root<Customer> c = q.from(Customer.class);
    q.set(c.get(Customer_.status), "outstanding")
     .where(cb.lt(c.get(Customer_.balance), 10000));

    with the equivalent JPQL of:

    UPDATE Customer c
    SET c.status = 'outstanding'
    WHERE c.balance < 10000

    This query can then be executed as:

    @PersistenceContext EntityManager em;
    Query query = em.createQuery(q);
    query.executeUpdate();

    Here is a sample for CriteriaDelete from section 6.5.15:

    CriteriaDelete<Customer> q = cb.createCriteriaDelete(Customer.class);
    Root<Customer> c = q.from(Customer.class);
    q.where(cb.equal(c.get(Customer_.status), "inactive"),
            cb.isEmpty(c.get(Customer_.orders)));

    with the equivalent JPQL of:

    DELETE FROM Customer c
    WHERE c.status = 'inactive'
    AND c.orders IS EMPTY


    This query can then be executed in similar way as earlier:

    @PersistenceContext EntityManager em;
    Query query = em.createQuery(q);
    query.executeUpdate();

  • New reserved keywords: Added the following to Java Persistence query language reserved identifiers: FUNCTION, ON, TREAT.
    • Pre-defined and user-defined functions using FUNCTION: JPQL provide several in-built functions which may be used in the SELECT, WHERE or HAVING clause of a query such as CONCAT, SUBSTRING, TRIM, LENGTH, ABS, SQRT, and CURRENT_DATE. The section 4.6.17.3 define invocation of predefined and user-defined database functions using the FUNCTION operator. The FUNCTION is used to invoke predefined database functions or user-defined database functions. An example from the section is:

      SELECT c
      FROM Customer c
      WHERE FUNCTION(‘hasGoodCredit’, c.balance, c.creditLimit)

    • Downcasting using TREAT: TREAT is supported for downcasting within path expressions in the FROM and WHERE clauses. Use of the TREAT operator allows access to subclass-specific state. An example from section 4.4.9 is:

      SELECT b.name, b.ISBN
      FROM Order o JOIN TREAT(o.product AS Book) b


      In this example, the join is performed between Order and Product but name and ISBN are attributes of the Book class which is a subclass of the Product class. Another example is:

      SELECT e FROM Employee e
      WHERE TREAT(e AS Exempt).vacationDays > 10
      OR TREAT(e AS Contractor).hours > 100


      Here again vacationDays are attributes for Exempt employees only and hours only for Contractor.

    • Join condition using ON: The ON clause in SQL is used to specify the relationship between the tables. It is different from the WHERE clause which specifies the criteria for the rows to be picked. An example from the section 4.4.5.2 shows the JPQL as:

      SELECT s.name, COUNT(p)
      FROM Suppliers s LEFT JOIN s.products p
      ON p.status = 'inStock'
      GROUP BY s.name


      The mapped SQL for this will be:

      SELECT s.name, COUNT(p.id)
      FROM Suppliers s LEFT JOIN Products p
      ON s.id = p.supplierId AND p.status = 'inStock'
      GROUP BY s.name


      The s.id = p.supplierId condition is generated becase of the LEFT JOIN. The additional JOIN condition of p.status = 'inStock' is also added to the generated SQL because of the ON clause in the JPQL. The result of this query will include all suppliers (with possibly NULL values). This is different from the query below:

      SELECT s.name, COUNT(p)
      FROM Suppliers s LEFT JOIN s.products p
      WHERE p.status = 'inStock'
      GROUP BY s.name


      The result of this query will not include suppliers that have no products in stock.

      Additional methods are also added to Fetch, Join, CollectionJoin, SetJoin, ListJoin, and MapJoin interfaces to support the ON clause.
  • Entity listeners using CDI: Entity Listeners allow to handle cross-cutting lifecycle events in a non-persistent listener class. In JPA 2.1, entity listeners will support dependency injection through CDI. The usual lifecycle callback methods of @PrePersist, @PostPersist, @PreUpdate, and @PreRemove can be used for entities. The entity listeners can also be annotated with @PostConstruct and @PreDestroy for their own lifecycle. The section 3.5.1 provides more details on this.

    Read more details on jsr338-experts alias archive and users@jpa-spec.
  • Synchronization of persistence contexts: In JPA 2, the persistence context is synchronized with the underlying resource manager. Any updates made to the persistence context are propagated to the resource manager. JPA 2.1 introduces the concept of unsynchronized persistence contenxt. Here is how you can create a container-managed unsynchronized persistence context:

    @PersistenceContext(synchronization=SynchronizationType.UNSYNCHRONIZED) EntityManager em;

    The section 7.6.1 provide more details.
  • Several clarifications in text and javadocs

The Appendix in the specification provide a comprehensive list of changes in this version of the specification. And there are change bars through out as well allowing you to see what has changed since JPA 2.

Here are some final set of references for you:

And of course, it'll all be delivered as part of GlassFish 4.0!


Tuesday Jan 11, 2011

JAX-RS 2.0 and JPA 2.1 JSRs filed ... Java EE 7 moves forward!

JSR 338 (JPA 2.1) and JSR 339 (JAX-RS 2.0) are the first formal steps in moving Java EE 7 platform forward!

The key features considered in scope of JPA 2.1 are:

  • Support for the use of custom types and transformation methods in object/relational mapping.
  • Support for the use of "fetch groups" and/or "fetch plans" to provide further control over data that is fetched, detached, copied, and/or used in merging.
  • Support for the specification of immutable attributes and readonly entities.
  • Support for user-configurable naming strategies for use in O/R mapping and metamodel generation.
  • More flexibility in the use of generated values; support for UUID generator type.
  • Additional mapping metadata to provide better standardization for schema generation.
  • Support for multitenancy.
  • Additional event listeners and callback methods; availability of entity manager to callbacks.
  • Methods for dirty detection.
  • Improved ability to control persistence context synchronization.
  • Additional unwrap methods to support use of vendor extensions.
  • Support for dynamic definition of persistence unit, including object/relational mapping information.
  • Extension of metamodel API to object/relational mapping information.
  • Improvements to the Java Persistence query language and criteria APIs

More details in JSR 338. Click here if you are interested in joining this Expert Group.

The key features considered in scope of JAX-RS 2.0 are:

  • Client API - a low-level using a builder pattern and a higher level leveraging the former one
  • Hypermedia processing on client and server
  • MVC architecture compatible with JAX-RS programming model
  • Integration with Bean Validation for parameter validation
  • Tighter integration with JSR 330 annotations, such as @Inject
  • Asynchronous request processing
  • Sophisiticated server-side content negotiation
  • More ease-of-development following DRY principles

More details in JSR 339. Click here if you are interested in joining this Expert Group. This Expert Group will have a public observer alias to monitor discussions.

The JSR ballot closes on Jan 24, 2011. After the JSRs are approved the Expert Groups start discussion on each and every item of the proposal. And you'll start seeing the promoted builds and integrations into GlassFish after that.

Stay tuned to hear details as Java EE 7 continues its march forward. In the meanwhile, you can download GlassFish 3.1 promoted build (soon to be final) that provides full Java EE 6 functionality along with centralized administration and high availability.

Technorati: javaee7 glassfish jaxrs jpa restful persistence

Wednesday Nov 17, 2010

TOTD #150: Collection of GlassFish, NetBeans, JPA, JSF, JAX-WS, EJB, Jersey, MySQL, Rails, Eclipse, and OSGi tips

This is the 150th tip published on this blog so decided to make it a collection of all the previous ones. Here is a tag cloud (created from wordle.net/create) from title of all the tips:

As expected GlassFish is the most prominent topic. And then there are several entries on NetBeans, JRuby/Rails, several Java EE 6 technologies like JPA, JAX-WS, JAX-RS, EJB, and JSF, and more entries on Eclipse, OSGi and some other tecnhologies too. Here is a complete collection of all the tips published so far:

Just for fun, here is another tag cloud:

You can access all the tips here. And keep those suggestions coming!

Technorati: totd glassfish netbeans jpa jsf jaxws jersey mysql rails osgi eclipse

Wednesday May 05, 2010

TOTD #133: JPA2 (JPQL & Criteria), JavaDB, and embedded GlassFish - perfect recipe for testing

TOTD #132 explained how to use embedded GlassFish for deploying/testing a simple Servlet. As mentioned in that blog, this Tip Of The Day (TOTD) will extend that entry and show how to create a simple test that:

  • Creates a JDBC Connection Pool using GlassFish APIs
  • Creates a JDBC Resource using that Connection Pool, again programmatically
  • Persists and Queries an entity in that database using JPQL and the newly introduced Criteria APIs in JPA 2

This application uses a "Games" entity with two simple fields - "id" for the primary key and "name" for the name of a game. The test persists 3 entries in the database and then retrieves them by issuing a JPQL statement and Criteria API. There are four tests:

  • The first test consists of creating a JDBC Connection Pool & a JDBC Resource using that pool in the embedded GlassFish instance
  • The second test stores 3 entities in the database using the JDBC resource
  • The third test queries the database using JPQL
  • The fourth test queries the database using Criteria API

The entire source code is available here and "mvn test" is all you need to see the action. The updated directory structure from TOTD #132 is:

src
src/main
src/main/java
src/main/java/org
src/main/java/org/glassfish
src/main/java/org/glassfish/embedded
src/main/java/org/glassfish/embedded/samples
src/main/java/org/glassfish/embedded/samples/App.java
src/main/java/org/glassfish/embedded/samples/Games.java
src/main/resources
src/main/resources/META-INF
src/main/resources/META-INF/persistence.xml
src/test
src/test/java
src/test/java/org
src/test/java/org/glassfish
src/test/java/org/glassfish/embedded
src/test/java/org/glassfish/embedded/samples
src/test/java/org/glassfish/embedded/samples/AppTest.java

The newly added files are highlighted in the bold. "Games.java" is the new entity class and "persistence.xml" provides the definition of Persistence Unit.

Here is our simple entity class:

package org.glassfish.embedded.samples;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/\*\*
 \* @author arungupta
 \*/
@Entity
@Table
public class Games implements Serializable {
    @Id
    int id;

    @Column
    String name;

    public Games() { }

    public Games(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Adding "@Entity" and "@Table" annotation on this POJO makes it an JPA Entity Bean. In addition, the primary key is defined using the "@Id" annotation on the field and an additional column is marked using "@Column"annotation.

In "AppTest.java", add a new method to create and test for JDBC connection pool and a JDBC resource using that pool as shown below:

public void testJDBCPoolAndResource() throws Throwable {
    Server.Builder builder = new Server.Builder("server");
    server = builder.build();
    server.createPort(8080);

    // add the required containers
    server.addContainer(ContainerBuilder.Type.web);
    server.addContainer(ContainerBuilder.Type.jpa);

    // Create a JDBC connection pool
    ParameterMap params = new ParameterMap();
    params.add("datasourceclassname", "org.apache.derby.jdbc.EmbeddedDataSource");
    params.add("property",
       "databaseName=games:connectionAttributes=\\\\;create\\\\=true");
    params.add("jdbc_connection_pool_id", JDBC_POOL);
    executeCommand("create-jdbc-connection-pool", server, params);
    System.out.println("JDBC Connection Pool successfully created.");

    // Assert the JDBC connection pool
    List<MessagePart> messageParts = 
        executeCommand("list-jdbc-connection-pools", server);
    assertInArray(messageParts, JDBC_POOL);

    // Create a JDBC resource
    System.out.println("Creating JDBC resource ...");
    ParameterMap params2 = new ParameterMap();
    params2.add("connectionpoolid", "MyPool");
    params2.add("jndi_name", JDBC_RESOURCE);
    executeCommand("create-jdbc-resource", server, params2);

    // Assert the JDBC resource
    messageParts = executeCommand("list-jdbc-resources", server);
    assertInArray(messageParts, JDBC_RESOURCE);
}

A disk representation of the database is created in the current directory by using "databaseName=games". Using in-memory JavaDB would've avoided the directory creation but facing issues with that (more on this at the end).

Here are convenience methods to execute an "asadmin"-equivalent command and used in the method above ...

private List executeCommand(String command, Server server) throws Throwable {
    return executeCommand(command, server, null);
}

private List executeCommand(String command, Server server, ParameterMap params) 
    throws Throwable {
    CommandRunner runner = server.getHabitat().getComponent(CommandRunner.class);
    ActionReport report = server.getHabitat().getComponent(ActionReport.class);
    if (params == null)
        runner.getCommandInvocation(command, report).execute();
    else
        runner.getCommandInvocation(command, report).parameters(params).execute();
    if (report.hasFailures()) {
        report.writeReport(System.out);
        throw report.getFailureCause();
    }

    return report.getTopMessagePart().getChildren();
}   

The error messages are shown on the console. Add another method for asserting on the created JDBC connection pool and resource as:

private void assertInArray(List messageParts, String resource) throws Throwable {
    boolean found = false;

    for (MessagePart part : messageParts) {
        if (part.getMessage().equals(resource)) {
            found = true;
            break;
        }
        System.out.println(part.getMessage());
    }

    if (!found)
        throw new Throwable("\\"" + resource + "\\" resource not found");
}

Here is a method to insert new values in the database using standard JPA calls:

public void testInsert() throws Throwable {
    EntityManagerFactory emf = 
        Persistence.createEntityManagerFactory("webtier2-PU");
    EntityManager em = emf.createEntityManager();

    // list of games to be added
    String[] games = {
               "Super Mario Galaxy",
               "Super Mario Brothers",
               "Mario Kart" };

    // create a transaction
    EntityTransaction utx = em.getTransaction();
    System.out.println("Persisting " + games.length + " games ...");
    utx.begin();
    for (int i=0; i<games.length; i++) {
        em.persist(new Games(i, games[i]));
        System.out.println("\\t " + games[i]);
    }
    utx.commit(); // and commit
    System.out.println("Committed.");
}

The method to query the database using JPQL ...

public void testJPQL() throws Throwable {
    EntityManagerFactory emf = 
        Persistence.createEntityManagerFactory("webtier2-PU");
    EntityManager em = emf.createEntityManager();

    // now query them
    List list = em.createQuery("select g from Games g").getResultList();
    assertEquals("Games retrieved", 3, list.size());
    System.out.println("Found " + list.size() + " games (using JPQL) ...");
    for (Object o : list) { // and dump
        System.out.println("\\t" + ((Games)o).getName());
    }
}

And finally a method to query the database using JPA 2 Critieria API ...

public void testCriteria() throws Throwable {
    EntityManagerFactory emf = 
        Persistence.createEntityManagerFactory("webtier2-PU");
    EntityManager em = emf.createEntityManager();

    CriteriaBuilder cb = emf.getCriteriaBuilder();
    CriteriaQuery<Games> criteria = cb.createQuery(Games.class);

    // FROM clause
    Root<Games> games = criteria.from(Games.class);

    // SELECT clause
    criteria.select(games);

    // No WHERE clause - pick all

    // FIRE
    List<Games> list = em.createQuery(criteria).getResultList();
    assertEquals("Games retrieved", 3, list.size());
    System.out.println("Found " + list.size() + " games (using Criteria) ...");
    for (Object o : list) { // and dump
       System.out.println("\\t" + ((Games)o).getName());
    }
 }

And here is the "persistence.xml"

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
   <persistence-unit name="webtier2-PU" transaction-type="JTA">
       <jta-data-source>jdbc/MyResource</jta-data-source>
       <properties>
           <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
       </properties>
       <class>org.glassfish.embedded.samples.Games</class>
   </persistence-unit>
</persistence>

The Persistence Unit is referring to "jdbc/MyResource" JDBC Resource created earlier. The table creation strategy is "drop-and-create-tables" and this can be "create-tables" if in-memory JavaDB is used instead.

The version of "glassfish-embedded-all" dependency in "pom.xml" is changed from "3.0" to "3.1-SNAPSHOT" so that latest updates are picked. The updated dependency looks like:

<dependency>
   <groupId>org.glassfish.extras</groupId>
   <artifactId>glassfish-embedded-all</artifactId>
   <version>3.1-SNAPSHOT</version>
</dependency>

Change the source version of "maven-compiler-plugin" from "1.5" to "1.6", the updated entry looks like:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.0.2</version>
    <configuration>
       <source>1.6</source>
       <target>1.6</target>
    </configuration>
</plugin>


And now when you fire "mvn clean test", a test output is shown as ...

INFO: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolver.
[EL Info]: 2010-05-05 13:49:28.339--ServerSession(149074043)--file:/Users/arungupta/samples/v3/
embedded/webtier2/target/classes/_webtier2-PU login successful
Persisting 3 games ...
         Super Mario Galaxy
         Super Mario Brothers
         Mario Kart
Committed.
Found 3 games (using JPQL) ...
        Mario Kart
        Super Mario Galaxy
        Super Mario Brothers
Found 3 games (using Criteria) ...
        Mario Kart
        Super Mario Galaxy
        Super Mario Brothers

You may see the following exception during the test run:

May 5, 2010 1:49:24 PM com.sun.logging.LogDomains$1 log
SEVERE: loader.asurlclassloader_malformed_url
java.util.zip.ZipException: error in opening zip file
        at java.util.zip.ZipFile.open(Native Method)
        at java.util.zip.ZipFile.(ZipFile.java:114)
        at java.util.jar.JarFile.(JarFile.java:133)
        at java.util.jar.JarFile.(JarFile.java:97)

This occurs because no URL is specified in the connection properties. This error message can be ignored as sufficient information is available to resolve the database otherwise.

Using the in-memory JavaDB is causing some sort of race condition in the test path and throwing an exception at random runs. After trying the configuration on couple of Macs, Windows 7 and Ubuntu and still not able to detect the cause of randomness, no formal issue is logged yet but its still being followed with the required folks.

In the meanwhile, enjoy the power of embedded GlassFish with JPA and Java DB.

Technorati: totd glassfish v3 javaee embedded servlet jpa persistence javadb

Thursday Feb 11, 2010

TOTD #123: f:ajax, Bean Validation for JSF, CDI for JSF and JPA 2.0 Criteria API - all in one Java EE 6 sample application

Taking TOTD #120 forward, we'll add the following features to our application:

  • Add database access using Java Persistence API 2.0
  • Show type-safe Criteria API from JPA 2.0
  • Use Context & Dependency Injection for JSF managed beans
  • Add Ajax effects from Java Server Faces 2.0
  • Add Bean Validation to the JSF managed bean

Lets get started!

  1. Use the Maven project created in TOTD #120 and update the directory such that it looks like:
    src
    src/main
    src/main/java
    src/main/java/org
    src/main/java/org/glassfish
    src/main/java/org/glassfish/samples
    src/main/java/org/glassfish/samples/SakilaBean.java
    src/main/java/org/glassfish/samples/SimpleBean.java
    src/main/java/org/glassfish/samples/SimpleEJB.java
    src/main/java/org/glassfish/samples/SimpleServlet.java
    src/main/webapp
    src/main/webapp/index.jsp
    src/main/webapp/index.xhtml
    src/main/webapp/sakila.xhtml
    src/main/webapp/show.xhtml
    src/main/webapp/WEB-INF
    src/main/webapp/WEB-INF/beans.xml
    src/main/webapp/WEB-INF/web.xml
    
    
    The key differences are:

    1. "beans.xml" is an empty file to enable Context & Dependency Injection bean discovery.
    2. The JPA Persistence Unit is copied and installed in local Maven repository as explained in TOTD #122.
    3. "web.xml" is added to bootstrap the Java Server Faces runtime. This is required because "@ManagedBean" annotation on "SimpleBean" class is now changed to "@javax.inject.Named". The JSF runtime is automatically registered and booted if any bean in the webapp is annotated with "@ManagedBean" or one of the JSF common classes (such as Converter, Validator, or Renderer) is implemented or extended. If none of these "hints" are available in the application, and it's required, then it needs to enabled explicitly.

Here are the updated files, changes are highlighted in bold and explained after each fragment:

index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtm
l1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:ui="http://java.sun.com/jsf/facelets"
 xmlns:h="http://java.sun.com/jsf/html">
 <h:head>
 <title>Enter Name &amp; Age</title>
 </h:head>
 <h:body>
 <h1>Enter Name &amp; Age</h1>
<h:form>
 <h:panelGrid columns="3">
 <h:outputText value="Name:"/>
 <h:inputText value="#{simplebean.name}" title="name" id="name" required="true"/>
 <h:message for="name" style="color: red"/>
 <h:outputText value="Age:"/>
 <h:inputText value="#{simplebean.age}" title="age" id="age" required="true"/>
 <h:message for="age" style="color: red"/>
 </h:panelGrid>
 <h:commandButton action="show" value="submit"/>
 </h:form>
 </h:body>
</html>

Changed the panelGrid from "2" columns to "3". This allows for any validation messages to be displayed right next to the source. Also added "<h:message .../>" to display the validation messages.



SimpleBean.java

package org.glassfish.samples;

import javax.inject.Named;
import javax.enterprise.context.RequestScoped;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.constraints.Min;

@Named("simplebean")
@RequestScoped
public class SimpleBean {
 @NotNull
 @Size(min=2, message="Name must be at least 2 characters")
 private String name;

 @NotNull
 @Min(5)
 private int age;

 public String getName() { return name; }
 public void setName(String name) { this.name = name; }

 public int getAge() { return age; }
 public void setAge(int age) { this.age = age; }
}

The changes to the above code are listed below:

  • Replaced "@ManagedBean" with "@Named" annotation defined in JSR 330 and used by CDI.
  • Using constraints defined by Bean Validation APIs (JSR 303) to check for
    • Both bean properties to be non-null
    • Name to be at least 2 characters
    • A minimum age of 5
    • There are several other pre-defined constraints in "javax.validation.constraints" package and new constraints can be easily defined as well.

SakilaBean.java

package org.glassfish.samples;

import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.faces.event.ActionEvent;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceUnit;
import javax.persistence.EntityManagerFactory;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import sakila.Actor;

@Named("sakilabean")
@RequestScoped
public class SakilaBean {
 @PersistenceUnit(unitName="SakilaPU")
 EntityManagerFactory emf;

 private List<Actor> actors;
 private int length;
 private int totalActors;

 // getters & setters
 public List<Actor> getActors() { return actors; }
 public void setActors(List<Actor> actors) { this.actors = actors; }
 public int getLength() { return length; }
 public void setLength(int length) { this.length = length; }
 public int getTotalActors() { return totalActors; }
 public void setTotalActors(int totalActors) { this.totalActors = totalActors; }

 public void findActors(ActionEvent evt) {
   EntityManager em = emf.createEntityManager();

   CriteriaBuilder cb = emf.getCriteriaBuilder();
   CriteriaQuery<Actor> criteria = cb.createQuery(Actor.class);

   // FROM clause
   Root<Actor> actor = criteria.from(Actor.class);

   // SELECT clause
   criteria.select(actor);

   // WHERE clause
   criteria.where(cb.greaterThan(
     cb.length(actor.get("firstName").as(String.class)), length));

   // FIRE
   actors = em.createQuery(criteria).getResultList();
   totalActors = actors.size();
 }
}

The key points:

  • This is a CDI bean marked by @Named and used in the JSF view (shown next), with the name "sakilabean"
  • EntityManagerFactory is injected using @PersistenceUnit
  • "findActors" method builds the query using Criteria API. Returns actors' names limited by the number of characters in their first name.
  • Queries "Actor" table from the database and set bean properties "actors" and "totalActors".
  • Uses "length" bean property (set from the JSF view) to restrict the number of characters in the name.

sakila.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtm
l1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html">
  <h:head>
    <title>Sakila - Actors Listing</title>
  </h:head>
  <h:body>
    <h1>Sakila - Actors Listing</h1>
    <h:form>
    <h:outputText value="Show actors with first name's length &lt;"/>
    <h:inputText value="#{sakilabean.length}" id="length" required="true" size="5"/>
    <h:commandButton actionListener="#{sakilabean.findActors}" value="submit">
      <f:ajax execute="length" render="actorTable totalActors"/>
    </h:commandButton><br/>
     Total actors found: <h:outputText value="#{sakilabean.totalActors}" id="totalActors"/><p/>
     <h:dataTable var="actor" value="#{sakilabean.actors}" border="1" id="actorTable">
       <h:column><h:outputText value="#{actor.firstName}"/>, <h:outputText value="#{actor.lastName}"/></h:column>
     </h:dataTable>
   </h:form>
 </h:body>
</html>

Key points:

  • This JSF view shows a form that accepts a number used for restricting the length of actors' first name. The value of this attribute is bound to "length" property of the underlying bean.
  • Command Button is tied to a JSF Action Listener which is then bound to "findActors" method in the bean. This method executes the JPA query explained above.
  • "f:ajax" is a newly introduced tag in JSF 2.0 and means an Ajax request is performed on the "onClick" event of the rendered button, "findActors" method in the bean in this case. The tag also specifies other tags in the page, "actorTable" and "totalActors" in this case, that needs to be rendered after the request is completed. The input parameter to the Ajax request is specified using "execute" attribute. Read more about this tag here or section 10.4.1.1 of the JSF 2 specification.

Package and deploy the application as:

mvn clean package
./bin/asadmin deploy --force=true ~/samples/javaee6/simplewebapp/target/simplewebapp-1.0-SNAPSHOT.war

The application is now accessible at "http://localhost:8080/simplewebapp-1.0-SNAPSHOT/sakila.jsf" and looks like:

Enter a value of "4" in the text box and hit "Submit":

Only the HTML table of names and the total count of actors is refreshed showcasing partial page refresh.

Now enter a value of "8" and hit "Submit":

Enjoy!

More Java EE 6 features to be shown in subsequent blogs.

Technorati: totd javaee glassfish v3 javaserverfaces ajax jpa cdi beanvalidation

Tuesday Feb 09, 2010

TOTD #122: Creating a JPA Persistence Unit using NetBeans 6.8

Taking TOTD #121 forward, this blog explains how to create a JPA Persistence Unit for a MySQL sample database and package it as a library. This JAR file can then be easily included in other web applications.

Lets get started!

  1. Configure GlassFish for using the MySQL sample database (sakila) as described in TOTD #121.
  2. Add the GlassFish instance in NetBeans IDE using "Services" panel.
  3. Create JPA entities using NetBeans IDE.
    1. Create a Java class library:



      Our ultimate goal is to create a reusable JAR file and that's why this project type is chosen.
    2. Specify the name of project as "SakilaPU":


    3. Right-click on the project and select "New", "Entity Classes from Database ..." to initiate the process of entity generation:

    4. Choose the database connection as:



      If not configured, then can be easily done by clicking on "New Database Connection ..." in the list box.
      1. Click on "Add All >>" to generate the mapped JPA entities for all tables and views.
      2. The views do not have primary keys and will need to be appropriately annotated (described later).
      3. Click on "Next >".
    5. Give the package name as:



      and specify the package name as "sakila". Click on "Create Persistence Unit ...".
    6. Change the default PU name from "SakilaPUPU" to "SakilaPU":



      and click on "Finish". Notice that "EclipseLink", the Reference Implementation of JPA 2.0, is used as the persistence library.
    7. Add "@javax.persistence.Id" annotation to the following class/field combination:
      Class Field
      sakila.SalesByFilmCategory category
      sakila.ActorInfo actorId
      sakila.FilmList fid
      sakila.CustomerList id
      sakila.NicerButSlowerFilmList fid
      sakila.StaffList id
      sakila.SalesByStore store

      This is required because none of the "views" are defined with a primary key.
    8. Right-click on the project and select "Clean & Build". This generates "dist/SakilaPU.jar" and the structure looks like:



This JAR file can now be included in any web application. The pre-built JAR file can also be downloaded here.

In order for this PU to be used in an application server (such as GlassFish) that is pre-configured with a JDBC resource, the "persistence.xml" needs to be changed to:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
 <persistence-unit name="SakilaPU" transaction-type="JTA">
 <jta-data-source>jdbc/sakila</jta-data-source>
 <properties/>
 </persistence-unit>
</persistence>

The JDBC resource name is specified using <jta-data-source>.

The key items to note about this pre-built JAR:

  • Persistence Unit Name: "SakilaPU"
  • All classes are in "sakila.\*" package.
  • Each class has a pre-defined "<CLASS-NAME>.findAll" named query that returns all elements from the underlying view/table.

This JAR can be installed to your local Maven repository as:

mvn install:install-file -Dfile=SakilaPU.jar -DgroupId=org.glassfish.samples -DartifactId=sakilapu -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true

and then included in your "pom.xml" as:

 <dependency>
   <groupId>org.glassfish.samples</groupId>
   <artifactId>sakilapu</artifactId>
   <version>1.0</version>
   <scope>compile</scope>
 </dependency>

Even though this blog uses a MySQL sample database, these steps can be easily followed for any other database such as Oracle or JavaDB.

Technorati: totd javaee glassfish v3 jpa eclipselink persistenceunit mysql sakila netbeans

Monday Feb 08, 2010

TOTD #121: JDBC resource for MySQL and Oracle sample database in GlassFish v3

This blog clearly explains how to configure the MySQL sample database (sakila) with GlassFish. Even though the instructions use a specific database but should work for other databases (such as Oracle, JavaDB, PostgreSQL, and others) as well. The second half of the blog provide specific syntax for the Oracle sample database.

  1. Download sakila sample database and unzip the archive.
  2. Install the database as described here - basically load and run "sakila-schema.sql" and "sakila-data.sql" extracted from the archive.
  3. Create a new MySQL user account using MySQL CLI Admin and assign the privileges
    1. Using "root" user (sudo mysql --user root)
      CREATE USER glassfish IDENTIFIED BY 'glassfish';
      GRANT ALL PRIVILEGES ON \*.\* TO 'glassfish'@'localhost' IDENTIFIED BY 'glassfish';
      FLUSH PRIVILEGES;
      
    2. Using "glassfish" user (sudo mysql --user glassfish)
      source sakila-schema.sql;
      source sakila-data.sql;
      
  4. Download Connector/J, unzip and copy "mysql-connector-java-5.x.x-bin.jar" to "glassfish/domains/domain1/lib/ext" directory.
  5. Start GlassFish server as:
    asadmin start-domain
    
    
  6. Create a JDBC resource
    1. Create JDBC connection pool as:
      asadmin create-jdbc-connection-pool --datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource --restype javax.sql.DataSource --property "User=glassfish:Password=glassfish:URL=jdbc\\:mysql\\://localhost/sakila" jdbc/sakilaPool
      
    2. Test the JDBC connection pool as:
      asadmin ping-connection-pool jdbc/sakilaPool
      
    3. Create the JDBC resource as:
      asadmin create-jdbc-resource --connectionpoolid jdbc/sakilaPool jdbc/sakila
      

That's it!

Creating a JDBC resource for any other database requires the following updates to the steps mentioned above. Lets consider modifying these steps for the Oracle sample database.

  1. Use the client interface SQL\*PLus and connect as:
    sqlplus "/ as sysdba"
    

    create user and grant the privileges as:
    CREATE USER glassfish IDENTIFIED BY glassfish DEFAULT tablespace users TEMPORARY tablespace temp;
    GRANT CONNECT TO glassfish IDENTIFIED BY glassfish;
    GRANT UNLIMITED TABLESPACE TO glassfish;
    GRANT CREATE TABLE TO glassfish;
    GRANT CREATE SEQUENCE TO glassfish;
    
  2. Copy the appropriate JDBC driver (ojdbc6.jar).
  3. Create the JDBC resource as:
    asadmin create-jdbc-connection-pool --datasourceclassname oracle.jdbc.pool.OracleDataSource --restype javax.sql.DataSource --property "User=hr:Password=hr:URL=jdbc\\:oracle\\:thin\\:@localhost\\:1521\\:orcl" jdbc/hr
    asadmin ping-connection-pool jdbc/hr
    asadmin create-jdbc-resource --connectionpoolid jdbc/hr jdbc/hr
    

    as explained in TOTD #108.

Here are a few other related entries:

Technorati: totd javaee glassfish v3 jpa mysql sakila oracle

About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today