Skip Headers
Oracle® Fusion Middleware Integration Guide for Oracle TopLink with Coherence Gird
11g Release 1 (11.1.1)

Part Number E16596-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

Labs and Examples

This lab introduces how to use Oracle TopLink Grid feature to grid enable a Java Persistence API (JPA) application with Oracle Coherence. TopLink Grid and Coherence can be combined using two distinct application architectures:

This lab will focuses on using TopLink Grid to build JPA on the Grid applications that provide a way to scale JPA applications through the use of Coherence.

This document includes the following sections:

Configuring the Lab Environment

This lab requires the following (minimum requirements):

Setup

Before running the labs, you must install the necessary software and configure your environment.

You can download the lab samples from:

http://www.oracle.com/technology/products/ias/toplink/doc/11110/grid/labs/toplinkgridlab.zip

Software Installation

Use this procedure to install the necessary software for the labs.

  1. If not already installed on your machine, download and install a Java 1.5 or higher JDK or JRE.

  2. Download and unzip the lab .ZIP file into a folder, referred to as LAB_ROOT. After unzipped unzipping the file, the folder will contain several sub-folders, including toplink and coherence.

  3. Download Oracle TopLink 11g Release 1 (11.1.1) and unzip into LAB_ROOT/toplink.

  4. Download Coherence 3.5 and unzip into LAB_ROOT. It will extract into the LAB_ROOT/coherence folder.

    Note:

    Confirm that the folder structure is correct; that you have LAB_ROOT/coherence and not LAB_ROOT/coherence/coherence.
  5. Download OEPE 11g Release 1 (11.1.1), based on Eclipse Galileo (3.5), and unzip into any folder, referred to as OEPE install.

  6. Download and install Oracle XE. Follow the installation instructions included with the download. You can install XE in any folder, referred to as ORACLE_XE_ROOT.

  7. Create or enable the Oracle database user scott with password tiger. Grant the connect and resource permissions to the user scott.

    The labs are configured for username scott with password tiger. To use a different user, you must change the database login values used in the labs.

Environment Configuration

Use this procedure to configure your lab environment.

  1. Open OEPE by running eclipse.exe from the OEPE install directory.

    You'll be prompted for a workspace. Select the LAB_ROOT folder, which contains your Eclipse workspace.

    Figure 10 Select Workspace Directory dialog

    The Select Workspace Directory dialog.
  2. If you've unzipped TopLink and Coherence into the correct folders, the workspace will open with no errors in the Problems view.

    If you do have errors, select Project > Clean from the menu and select Clean all projects to recompile and revalidate the labs. If errors remain, confirm that you have unzipped both TopLink and Coherence into the correct folders.

  3. From the menu, select Window > Perspectives to open the JPA perspective.

    Figure 11 Open Perspective dialog

    Selecting JPA in the Open Perspective dialog.
  4. In the JPA Perspective use the Data Source Explorer view to change the Oracle XE connection, if needed. By default, the Oracle XE connection uses scott/tiger @ localhost.

    Figure 12 Data Source Explorer

    Right-click the connection and select Properties.

    To use a different schema, right-click the Oracle XE connection in the Data Source Explorer and select Properties, as shown in Figure 12. Select the Driver Properties section and edit the values to reflect your connection as shown in Figure 13.

    Note:

    If you change the defaults, you must also edit the connection values in the persistence.xml configuration files used in the labs.

    Figure 13 Driver Properties

    Driver Properties dialog.

    Figure 14 Common connection properties

    Common connection properties for the OracleXE connection.

Running the Labs

Each of the three labs works with the same simple domain model shown in Figure 15. It consists of an Employee entity with an Address and a collection of PhoneNumbers.

Figure 15 Lab Domain Model

Domain model for the labs.
Description of "Figure 15 Lab Domain Model"

The entities are all pre-mapped, allowing you to focus on the TopLink Grid configuration – not JPA mapping.

This document contains the following Labs:

Lab 1: Grid Cache Configuration

The most basic configuration is using Coherence with EclipseLink as a shared (L2) cache. EclipseLink has a local, built-in shared-object cache that allows concurrent and successive transactions to benefit from reads and updates performed by other transactions. When entities are updated, after a successful database commit, the updates are then applied to the shared cache, allowing transactions can see the changes.

Replacing the local, built-in shared-object cache with Coherence maintains the same cache semantics. Applications do not need to be changed – they are unaware that the cache implementation has become a distributed cache rather than a local one.

Configuring Coherence as a shared cache involves:

  • Configuring entities to use Coherence

  • Defining a Coherence cache configuration for those entities

Lab 1 (see Figure 16) is provided as a ready-to-run JPA project in Eclipse.

Figure 16 Lab 1 Project

The Project Explorer view of the Lab 1 Project.

Getting Started

Open the Employee, Address, and PhoneNumber entities and examine how they are mapped.

Use the following procedure once, before configuring Coherence as the shared cache, to confirm your environment is correct.

  1. If your database connection differs from the defaults, you must update the following EclipseLink JDBC properties in the META-INF/persistence.xml file:

    • eclipselink.jdbc.driver

    • eclipselink.jdbc.url

    • eclipselink.jdbc.user

    • eclipselink.jdbc.password

  2. From the Project Explorer view, right-click the Lab 1-TopLink Grid Cache project and select JPA > Generate Tables from Entities… from the menu to drop and create the database tables used in the lab. You can safely ignore any errors due to failures to DROP non-existent tables. Generating tables will log you into the database.

    Note:

    f you encounter a Schema "null" cannot be resolved for table "<TABLE_NAME>" error, you've hit a known Eclipse bug. To resolve the issue, right-click the project and choose select Validate from menu. Eclipse will clear the errors.
  3. Run gridcache.example.InsertExample to populate the database with an Employee, Address, and a PhoneNumber. The createEmployee() method, shown here, defines the entities:

    public static Employee createEmployee() {
      Employee employee = new Employee();
      employee.setFirstName("Bob");
      employee.setLastName("Smith");
     
      Address address = new Address();
      address.setCity("Toronto");
      address.setPostalCode("L5J2B5");
      address.setProvince("ON");
      address.setStreet("1450 Acme Cr., Suite 4");
      address.setCountry("Canada");
      employee.setAddress(address);
      
      employee.addPhoneNumber("Work", "613", "5558812");
    
      return employee;
      }
    

    The console output displays the following:

    [EL Fine]: Connection(876215)--UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
    [EL Fine]: Connection(876215)--
         bind => [50, SEQ_GEN]
    [EL Fine]: Connection(876215)--SELECT SEQ_COUNT FROM SEQUENCE WHERE SEQ_NAME = ?
        bind => [SEQ_GEN]
    [EL Fine]: Connection(876215)--INSERT INTO GRIDCACHE_ADDRESS (ID, POSTALCODE, STREET, PROVINCE, VERSION, COUNTRY, CITY) VALUES (?, ?, ?, ?, ?, ?, ?)
    [EL Fine]: Connection(876215)--
         bind => [2, L5J2B5, 1450 Acme Cr., Suite 4, ON, 1, Canada, Toronto]
    [EL Fine]: Connection(876215)--INSERT INTO GRIDCACHE_EMPLOYEE (ID, LASTNAME, FIRSTNAME, VERSION, ADDRESS_ID) VALUES (?, ?, ?, ?, ?)
    [EL Fine]: Connection(876215)--
         bind => [1, Smith, Bob, 1, 2]
    [EL Fine]: Connection(876215)--INSERT INTO GRIDCACHE_PHONE (ID, AREACODE, NUM, TYPE, VERSION, OWNER_ID) VALUES (?, ?, ?, ?, ?, ?)
    [EL Fine]: Connection(876215)--
         bind => [3, 613, 5558812, Work, 1, 1]
    [EL Config]: Connection(14361585)--disconnect
    

    EclipseLink updates an ID, generates the SEQUENCE table, and inserting the ID into three tables. All tables in this lab are prefixed with GRIDCACHE_.

  4. Run gridcache.example.QueryExample1. This queries all Employees with JPQL and a single Employee with an EntityManager.find call, then prints the results.

    ...
    List<Employee> employees = em.createQuery("select e from Employee e").getResultList();
    ...
      Employee employee = em.find(Employee.class, employeeId);
    ...
    

    The console output displays the following:

    ------------------JPQL Query
    [EL Fine]: Connection(876215)--SELECT ID, LASTNAME, FIRSTNAME, VERSION, ADDRESS_ID FROM GRIDCACHE_EMPLOYEE
    l2.model.Employee@e33e18(1: Smith, Bob)
    [EL Fine]: Connection(876215)--SELECT ID, POSTALCODE, STREET, PROVINCE, VERSION, COUNTRY, CITY FROM GRIDCACHE_ADDRESS WHERE (ID = ?)
         bind => [2]
         City: Toronto
    [EL Fine]: Connection(876215)--SELECT ID, AREACODE, NUM, TYPE, VERSION, OWNER_ID FROM GRIDCACHE_PHONE WHERE (OWNER_ID = ?)
         bind => [1]
         l2.model.PhoneNumber@21d23b(3: Work: 613-5558812)
    ------------------em.find Query
         l2.model.Employee@e33e18(1: Smith, Bob)
         City: Toronto
         l2.model.PhoneNumber@21d23b(3: Work: 613-5558812)
    

    EclipseLink issues three SELECT statements:

    • To read all the Employees

    • To read the one Employee's Address

    • To read its PhoneNumbers

The EntityManager.find() does not result in a SQL statement because the Employee is found in the local cache without needing a database query.

Configuring Coherence Grid Caching

To instruct EclipseLink to cache in Coherence you need to configure a CoherenceInterceptor as the cache interceptor for an Entity. A Coherence interceptor will reroute all cache get and put operations to Coherence instead of the built-in EclipseLink shared cache. This configuration, shown in Figure 17, is referred to as "cache aside."

Figure 17 Coherence as Shared (L2) Cache

Description of Figure 17 follows
Description of "Figure 17 Coherence as Shared (L2) Cache"

Add the @CacheInterceptor annotation to all lab entities with the CoherenceInterceptor.class as its sole parameter, as shown in this example:

import oracle.eclipselink.coherence.integrated.cache.CoherenceInterceptor;
import org.eclipse.persistence.annotations.CacheInterceptor;
 
@CacheInterceptor(CoherenceInterceptor.class)
public class Employee implements Serializable {
...

Coherence Cache Configuration

The labs include a coherence-cache-config.xml file. In the lab configuration file, all entities are configured identically. Although there is no need to edit the file, you should note and review the following elements:

<caching-scheme-mapping>
  <cache-mapping>
    <cache-name>*</cache-name>
    <scheme-name>eclipselink-distributed</scheme-name>
  </cache-mapping>
</caching-scheme-mapping>

The asterisk, *, in the cache-name element will match any entity name. By default, TopLink Grid uses the entity name as the name of the associated cache. You can override this behavior by using the EclipseLink @Property annotation on an entity, as shown in this example:

@Property(name="coherence.cache.name", value="Employee")
@CacheInterceptor(CoherenceInterceptor.class)
public class Employee implements Serializable {
...

In these labs, the cache names are default to the entity name.

In the Grid Cache lab, all entities use a cache scheme named eclipselink-distributed which is a distributed (partitioned) cache. The distributed backing map scheme eclipselink-distributed has a serializer configured to support serialization of entity relationships into Coherence, as shown in this example:

<caching-schemes>
  <distributed-scheme>
    <scheme-name>eclipselink-distributed</scheme-name>
    <service-name>EclipseLinkJPA</service-name>
  <!--
   Configure a wrapper serializer to support serialization of
   relationships.
  -->
  <serializer>
    <class-name>
      oracle.eclipselink.coherence.integrated.cache.WrapperSerializer
    </class-name>
  </serializer>
...

Running Lab 1 with Coherence

Now that the entities are configured to be cached in Coherence and a coherence-cache-config.xml file is defined, you can re-run the lab with Coherence.

  1. Reset the database by right-clicking the Lab 1-TopLinkGrid Grid Cache project in the Project Explorer view and selecting JPA > Generate Tables from Entities… from the pop-up menu to drop and create the lab tables.

  2. Run gridcache.example.StartCacheServer to start the Coherence cache server. After being configured to use Coherence, of the examples require a cache server to be running.

    Tip:

    When running multiple programs in Eclipse, use the drop-down list to switch between each program's console, as shown in Figure 18. When reviewing the console output, be aware of which console you are viewing: the cache server console or the example console.

    Figure 18 Eclipse Console

    Use the drop-down list to swtich output consoles.
  3. Run gridcache.example.InsertExample to create example entities in the database and populate the Coherence cache. In addition to Coherence boot messages and INSERT statements in the console you will also see messages showing entities being put into Coherence under their primary key, as shown in this example:

    [EL Fine]: Coherence(PhoneNumber)::Put: 3 value: l2.model.PhoneNumber@59cbda(3: Work: 613-5558812)
    [EL Fine]: Coherence(Employee)::Put: 1 value: l2.model.Employee@11c55bb(1: Smith, Bob)
    [EL Fine]: Coherence(Address)::Put: 2 value: l2.model.Address@135133(Toronto)
    
  4. Run gridcache.example.QueryExample1. In the console you will see a single SELECT statement for all Employees resulting from the JQPL query select e from Employee e -- that's all. You will also see the messages logging Coherence interaction. Compare this output with the output generated when you ran QueryExample1 before enabling the Coherence cache.

  5. Run gridcache.example.QueryExample2 to illustrate which database queries are produced when you have a series of EntityManagers, such as for an application deployed to an application server. This example is useful when compared to the output generated in subsequent labs.

Lab 2: "Grid Read" Configuration

In "Lab 1: Grid Cache Configuration" you learned how to configure Coherence as a shared entity cache. In this lab you will increase the use of Coherence by directing all read queries (i.e., select and find) to Coherence. In this "Grid Read" configuration, all read operations are directed to Coherence but write operations are handled by EclipseLink and directed to the database. This configuration is described as "read through," as shown in Figure 19. Use this configuration when you need highly available data and a database that is always up-to-date. This configuration supports JTA so you can participate in a distributed transaction, Coherence is only updated once the entire JTA transaction commits.

Figure 19 Grid Read Configuration

Description of Figure 19 follows
Description of "Figure 19 Grid Read Configuration"

Configuring Grid Read

The Grid Read configuration extends the Grid Cache configuration. In addition to a cache interceptor, various read query types are also directed to Coherence. To simplify configuration, TopLink Grid provides an EclipseLink customizer class that performs the necessary configuration changes, including setting the cache interceptor you configured in Lab 1.

The CoherenceReadCustomizer is configured using the EclipseLink @Customizer annotation, as shown here:

import oracle.eclipselink.coherence.integrated.config.CoherenceReadCustomizer;
import org.eclipse.persistence.annotations.Customizer;
 
@Customizer(CoherenceReadCustomizer.class)
public class Employee implements Serializable {

Alternatively, you can also a Customizer in the persistence.xml and eclipselink-orm.xml.

From the Project Explorer view, right click the Lab 2-TopLinkGrid Grid Read project and select Open Project from the popup menu. Eclipse may report errors due to missing tables that correspond to the JPA entities in the project-we'll resolve the errors by generating the tables.

Add @Customizer(CoherenceReadCustomizer.class), as shown in the previous code example, to all the lab entities.

Coherence Cache Configuration

With all read queries directed to Coherence, the coherence-cache-config.xml is different than in the Grid Cache configuration. In particular, it makes sense to configure a CacheLoader so that Coherence can query the database for an individual object if it doesn't contain it.

This example shows an excerpt of the coherence-cache-config.xml from Lab 2:

<distributed-scheme>
  <scheme-name>eclipselink-distributed-readonly</scheme-name>
  <service-name>EclipseLinkJPAReadOnly</service-name>
  ...
  <backing-map-scheme>
    <read-write-backing-map-scheme>
      ...
      <!-- Define the cache scheme -->
      <cachestore-scheme>
        <class-scheme>
          <class-name>
            oracle.eclipselink.coherence.integrated.EclipseLinkJPACacheLoader
          </class-name>
          <init-params>
            <init-param>
              <param-type>java.lang.String</param-type>
              <param-value>{cache-name}</param-value>
            </init-param>
            <init-param>
              <param-type>java.lang.String</param-type>
              <param-value>employee</param-value>
            </init-param>
          </init-params>
        </class-scheme>
      </cachestore-scheme>
      <read-only>true</read-only>
    </read-write-backing-map-scheme>
  </backing-map-scheme>
  <autostart>true</autostart></distributed-scheme>

We configure an EclipseLinkJPACacheLoader on the backing map from the oracle.eclipselink.coherence.integrated package. Note the integrated package name -- use this CacheLoader when using TopLink Grid with a JPA front end, as in this lab.

When using a TopLink Grid CacheLoader in a traditional Coherence API based application, use the EclipseLinkJPACacheLoader in the oracle.eclipselink.coherence.standalone package.

Running Lab 2 with Coherence

After configuring the entities with the CoherenceReadCustomizer and configuring the caches in the coherence-cache-config.xml with a CacheLoader you can run the lab.

  1. Stop any CacheServers that may still be running from the previous Lab.

  2. If your database connection differs from the defaults, you must update the following EclipseLink JDBC properties in the META-INF/persistence.xml file:

    • eclipselink.jdbc.driver

    • eclipselink.jdbc.url

    • eclipselink.jdbc.user

    • eclipselink.jdbc.password

  3. From the Project Explorer view, right-click the Lab 2 project and select JPA > Generate Tables from Entities… from the pop-up menu to reset the database

  4. Run gridread.example.StartCacheServer to start the a Coherence cache server.

  5. Run gridread.example.InsertExample to create example entities in the database and populate the Coherence cache. In addition to Coherence boot messages and INSERT statements in the console you will also see messages showing entities being put into Coherence under their primary key, as shown in this example.

    [EL Fine]: Connection(4889213)--INSERT INTO GRIDREAD_ADDRESS (ID, POSTALCODE, STREET, PROVINCE, VERSION, COUNTRY, CITY) VALUES (?, ?, ?, ?, ?, ?, ?)
    [EL Fine]: Connection(4889213)--
         bind => [2, L5J2B5, 1450 Acme Cr., Suite 4, ONT, 1, Canada, Toronto]
    [EL Fine]: Connection(4889213)--INSERT INTO GRIDREAD_EMPLOYEE (ID, LASTNAME, FIRSTNAME, VERSION, ADDRESS_ID) VALUES (?, ?, ?, ?, ?)
    [EL Fine]: Connection(4889213)--
         bind => [1, Smith, Bob, 1, 2]
    [EL Fine]: Connection(4889213)--INSERT INTO GRIDREAD_PHONE (ID, AREACODE, NUM, TYPE, VERSION, OWNER_ID) VALUES (?, ?, ?, ?, ?, ?)
    [EL Fine]: Connection(4889213)--
         bind => [3, 613, 5558812, Work, 1, 1]
    [EL Fine]: Coherence(Employee)::Put: 1 value: read.model.Employee@948069(1: Smith, Bob)
    [EL Fine]: Coherence(Address)::Put: 2 value: read.model.Address@1b59919(Toronto)
    [EL Fine]: Coherence(PhoneNumber)::Put: 3 value: read.model.PhoneNumber@1588325(3: Work: 613-5558812)
    

    The console is similar to the console output from Lab 1 with the Grid Cache configuration

  6. Run gridread.example.QueryExample1. In the QueryExample1 console EclipseLink does not issue a SELECT statement from the JQPL query select e from Employee e because the query was translated to a Coherence Filter and passed to Coherence for evaluation.

Compare this output with the output from gridcache.example.QueryExample1 in "Lab 3: "Grid Entity" Configuration":

  • In Lab 1, JPQL queries were always translated to SQL and executed on the database.

  • In Lab 2, the EntityManager.find(), is evaluated against Coherence and produces no SQL.

Lab 3: "Grid Entity" Configuration

The Grid Entity configuration extends the Grid Read configuration, redirecting all write queries (INSERT, UPDATE, and DELETE) to Coherence instead of the database. This configuration is useful when you need quick response time and can use a write-behind strategy to periodically flush updates to the database. This is achieved through configuration of a CacheStore on the Coherence cache. This configuration may be described to as both "read through" and "write through" (Figure 20).

Potential downsides to this configuration are the loss of JTA transaction participation, EclipseLink write optimizations like batch writing, and the need to relax referential integrity rules due to the unpredictable order in which Coherence caches may write updates to the database.

Figure 20 Grid Entity Configuration

Description of Figure 20 follows
Description of "Figure 20 Grid Entity Configuration"

Configuring Grid Entity

Like the "Lab 2: "Grid Read" Configuration", Grid Entity is enabled by an EclipseLink Customizer, CoherenceReadWriteCustomizer, set on an individual entity as shown in the following example:

import oracle.eclipselink.coherence.integrated.config.CoherenceReadWriteCustomizer;
import org.eclipse.persistence.annotations.Customizer;
 
@Customizer(CoherenceReadWriteCustomizer.class)
public class Employee implements Serializable {
 

From the Project Explorer view, right-click the Lab 3-TopLinkGrid Grid Entity project and select Open Project from the popup menu. As in the other labs, you may see errors due to missing tables that correspond to the JPA entities in the project. These will be resolved after generating the tables.

Add @Customizer(CoherenceReadWriteCustomizer.class), as shown in the previous code example, to all the lab entities.

Coherence Cache Configuration

To propagate updates to the database, a Coherence entity cache needs to be configured with a CacheStore. A CacheStore is configured like a CacheLoader. The difference is in the implementation which supports write operations in addition to read operations.

<distributed-scheme>
    <scheme-name>eclipselink-distributed-readwrite</scheme-name>
      ...
      <cachestore-scheme>
        <class-scheme>
          <class-name>
            oracle.eclipselink.coherence.integrated.EclipseLinkJPACacheStore
          </class-name>
...

As in "Lab 2: "Grid Read" Configuration", the EclipseLinkJPACacheStore is in the integrated package because we are using JPA as our programming API.

Running Lab 3 with Coherence

After configuring the your entities with the CoherenceReadWriteCustomizer and configuring the caches in the coherence-cache-config.xml with a CacheStore, you can run the lab.

  1. Stop any CacheServers that may still be running from the previous Lab.

  2. If your database connection differs from the defaults, you must update the following EclipseLink JDBC properties in the META-INF/persistence.xml file:

    • eclipselink.jdbc.driver

    • eclipselink.jdbc.url

    • eclipselink.jdbc.user

    • eclipselink.jdbc.password

  3. From the Project Explorer view, right-click the Lab 3 project and select JPA>Generate Tables from Entities… from the pop-up menu to reset the database.

  4. Run gridentity.example.StartCacheServer to start the Coherence cache server.

  5. Run gridentity.example.InsertExample to create example entities in the database and populate the Coherence cache. In the InsertExample console you will see messages showing entities being put into Coherence under their primary key, but no INSERT statements.

    [EL Fine]: Coherence(Employee)::ConditionalPut: 1 value: readwrite.model.Employee@b9b618(1: Smith, Bob)
    [EL Fine]: Coherence(PhoneNumber)::ConditionalPut: 3 value: readwrite.model.PhoneNumber@800aa1(3: Work: 613-5558812)
    [EL Fine]: Coherence(Address)::ConditionalPut: 2 value: readwrite.model.Address@169dd64(Toronto)
    

    You will see database queries in the CacheServer console because with CoherenceReadWrite configured, all queries in the QueryExample client program are being directed to Coherence. When an entity is put into Coherence, the CacheStore determines if the put entity is new, which will produce an INSERT statement, or has been updated, which will produce an UPDATE statement.

  6. Since the Grid Entity configuration has the same read behavior as the "Lab 2: "Grid Read" Configuration" configuration, running gridentity.example.QueryExample1 will produce the same results as gridread.example.QueryExample1. In the console, there are no SELECT statements resulting from the JQPL query select e from Employee e.

Summary

TopLink Grid provides integration between EclipseLink JPA and Oracle Coherence. This lab demonstrated configurations ranging from using Coherence as a shared L2 cache to using Coherence as data source with JPQL queries translated to Filters executed in the grid.

As these labs illustrated, configuring Coherence with TopLink Grid is simple, straight forward, and introduces limited changes to JPA applications.