Jump to: navigation, search

Difference between revisions of "EclipseLink/Examples/JPA/CacheCoordination"

(Running the example)
(Overview)
(19 intermediate revisions by the same user not shown)
Line 11: Line 11:
 
* use optimistic locking (writes on stale data will fail, and will automatically invalidate the cache)
 
* use optimistic locking (writes on stale data will fail, and will automatically invalidate the cache)
 
* using a distributed cache (such as Oracle TopLink Grid with Oracle Coherence)
 
* using a distributed cache (such as Oracle TopLink Grid with Oracle Coherence)
 +
* using database events to invalidate changed data
 
* using cache coordination (synchronizing the caches, as discussed in this example)
 
* using cache coordination (synchronizing the caches, as discussed in this example)
  
Line 16: Line 17:
  
 
EclipseLink provides a cache coordination feature that enables a set of EclipseLink sessions to synchronize their changes in a distributed network such as an application server cluster.  Cache coordination works by each EclipseLink session (ServerSession/persistence unit) on each server in the cluster being able to broadcast notification of transactional object changes to the other EclipseLink sessions in the cluster.  EclipseLink supports cache coordination over RMI and JMS.  The cache coordination framework is also extensible so other options could be developed.
 
EclipseLink provides a cache coordination feature that enables a set of EclipseLink sessions to synchronize their changes in a distributed network such as an application server cluster.  Cache coordination works by each EclipseLink session (ServerSession/persistence unit) on each server in the cluster being able to broadcast notification of transactional object changes to the other EclipseLink sessions in the cluster.  EclipseLink supports cache coordination over RMI and JMS.  The cache coordination framework is also extensible so other options could be developed.
 +
 +
JGroups is not currently supported, to request JGroups support vote for,
 +
https://bugs.eclipse.org/bugs/show_bug.cgi?id=282074
  
 
This example demonstrates enabling cache coordination using JMS or RMI for a JEE EJB 3.0 SessionBean application using JPA deployed to an Oracle Weblogic cluster.  The example could be ported to other JEE application servers or environments.  EclipseLink supports cache coordination in any Java environment, including Java SE, or Tomcat.
 
This example demonstrates enabling cache coordination using JMS or RMI for a JEE EJB 3.0 SessionBean application using JPA deployed to an Oracle Weblogic cluster.  The example could be ported to other JEE application servers or environments.  EclipseLink supports cache coordination in any Java environment, including Java SE, or Tomcat.
Line 21: Line 25:
 
If you encounter any issues in running this example, or are running in another app server or version please discuss,
 
If you encounter any issues in running this example, or are running in another app server or version please discuss,
 
[[Talk:EclipseLink/Examples/JPA/CacheCoordination|here]]
 
[[Talk:EclipseLink/Examples/JPA/CacheCoordination|here]]
 +
 +
If you wish to port this example to another application server, or provide a different config or fix, please submit your changes to the [https://bugs.eclipse.org/bugs/show_bug.cgi?id=326343 bug#326343].
  
 
==Prerequisites==
 
==Prerequisites==
Line 27: Line 33:
 
* ant (1.7 was used, but other versions should also work) - [http://ant.apache.org/bindownload.cgi download link]
 
* ant (1.7 was used, but other versions should also work) - [http://ant.apache.org/bindownload.cgi download link]
 
* Oracle database (or any other client/server database (embedded database will not work as cannot be accessed from all machines)) - [http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html download link]
 
* Oracle database (or any other client/server database (embedded database will not work as cannot be accessed from all machines)) - [http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html download link]
* EclipseLink (WLS 10.3.4 includes EclipseLink 2.1, a 2.2 build or any >= 1.2 version could be used) - [http://www.eclipse.org/eclipselink/downloads/ download link]
+
* EclipseLink (WLS 10.3.3 includes EclipseLink 2.0, 2.1, a 2.2 build or any >= 1.2 version could be used) - [http://www.eclipse.org/eclipselink/downloads/ download link]
* Cache coordination example - download link
+
* Cache coordination example - [http://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/examples/org.eclipse.persistence.example.jpa.server.cachecoordination/org.eclipse.persistence.example.jpa.server.cachecoordination.zip download link] - [http://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/examples/org.eclipse.persistence.example.jpa.server.cachecoordination/ SVN]
  
 
==Configuring the example==
 
==Configuring the example==
 +
There are several ways to configure cache coordination, and the settings required differ depending on the environment and EclipseLink version.  The example source code provides a complete configuration, this section is only provided as a reference.  The example defaults to using JMS, and RMI persistence.xml file (persistence-wls-rmi.xml) is also provided as well as an non-clustered RMI build file (build-wls-servers.xml).  To run these examples just rename the files.
 +
 +
EclipseLink supports cache coordination using either JMS, RMI or RMI-IIOP.  A custom TransportManager could also be implemented to support another protocol, such as JGroups.
 +
 +
Cache coordination can be configured using persistence unit properties (in your persistence.xml).  It can also be configured in code using a SessionCustomizer, or using System properties (which match the persistence unit properties).  This example will use persistence unit properties.
 +
 +
===RMI===
 +
To enable cache coordination the minimal amount of configuration required is to set the protocol,
 +
 +
<source lang="xml">
 +
<property name="eclipselink.cache.coordination.protocol" value="rmi" />
 +
</source>
 +
 +
In EclipseLink 2.2 in a WebLogic cluster this is all that is required as JNDI is replicated, each server will be able to look-up each others listener.  Previous to EclipseLink 2.2 a URL was still required, in a cluster any URL in the cluster could be given, or localhost.
 +
 +
If running outside of a cluster, or if JNDI is not replicated, then each server must provide its URL.  This could be done through the persistence.xml, but would require a different persistence.xml (thus jar/ear) per server, which is normally not desired.  Another option is to set the URL as a System property to the WebLogic start script (or other application server).  A SessionCustomizer could also be used to set the URL in code.
 +
 +
<source lang="xml">
 +
<property name="eclipselink.cache.coordination.rmi.url" value="t3://myserver:7001/" />
 +
</source>
 +
 +
If a user-name/password are required to access the server, these can be configured (normally not required when running in the same domain).
 +
<source lang="xml">
 +
<property name="eclipselink.cache.coordination.jndi.user" value="weblogic" />
 +
<property name="eclipselink.cache.coordination.jndi.password" value="welcome1" />
 +
</source>
 +
 +
For RMI cache coordination the broadcast can be configured to be either asynchronous or synchronous.  Asynchronous is the default,
 +
synchronous can be used to ensure that all of the servers are updated before the request returns.
 +
 +
<source lang="xml">
 +
<property name="eclipselink.cache.coordination.propagate-asynchronously" value="false" />
 +
</source>
 +
 +
If multiple applications on the same server/network use cache coordination a separate channel can be used for each application.
 +
 +
<source lang="xml">
 +
<property name="eclipselink.cache.coordination.channel" value="EmployeeChannel" />
 +
</source>
 +
 +
RMI cache coordination use a multicast socket to allow the servers to find eachother.  The multicast setting can also be configured,
 +
but are normally not required.
 +
 +
<source lang="xml">
 +
<property name="eclipselink.cache.coordination.rmi.announcement-delay" value="1000" />
 +
<property name="eclipselink.cache.coordination.rmi.multicast-group" value="239.192.0.0" />
 +
<property name="eclipselink.cache.coordination.rmi.multicast-group.port" value="3121" />
 +
<property name="eclipselink.cache.coordination.packet-time-to-live" value="2" />
 +
</source>
 +
 +
===JMS===
 +
For JMS a JMS topic JNDI name and topic connection factory JNDI name must also be provided in addition to the protocol.
 +
The JMS topic should not be JTA enabled and should not have persistent messages.
 +
 +
<source lang="xml">
 +
<property name="eclipselink.cache.coordination.protocol" value="jms" />
 +
<property name="eclipselink.cache.coordination.jms.topic" value="jms/EmployeeTopic" />
 +
<property name="eclipselink.cache.coordination.jms.factory" value="jms/EmployeeTopicConnectionFactory" />
 +
</source>
 +
 +
In EclipseLink 2.2, in a WebLogic cluster this is all that is required.
 +
 +
In previous EclipseLink versions, or if not running in a cluster, then its URL must be provided.
 +
 +
<source lang="xml">
 +
<property name="eclipselink.cache.coordination.jms.host" value="t3://myserver:7001/" />
 +
</source>
 +
 +
If a user-name/password are required to access the server, these can be configured (normally not required when running in the same domain).
 +
<source lang="xml">
 +
<property name="eclipselink.cache.coordination.jndi.user" value="weblogic" />
 +
<property name="eclipselink.cache.coordination.jndi.password" value="welcome1" />
 +
</source>
  
 
==Running the example==
 
==Running the example==
Line 43: Line 122:
 
## or, you could create your own DataSource in your application server using your application server's tools or config,
 
## or, you could create your own DataSource in your application server using your application server's tools or config,
 
## this example uses ant to automatically create a DataSource in the server.
 
## this example uses ant to automatically create a DataSource in the server.
 +
# Configure persistence.xml in <example>src/meta-inf/
 +
## Configure the JMS host if not running a clustered JMS Topic.
 +
## If using another application server, ensure the "eclipselink.target-server" is set to the correct platform for your server.
 +
## The example uses JMS by default, if RMI is desired, change the protocol to rmi, or switch the persistence.xml file with the persistence-wls-rmi.xml file.
 
# Install ant (or uses existing ant install)
 
# Install ant (or uses existing ant install)
 
# Ensure the prompt environment variables have been set to use the JVM provided in the WebLogic install (JRockit was used for this example)
 
# Ensure the prompt environment variables have been set to use the JVM provided in the WebLogic install (JRockit was used for this example)
Line 64: Line 147:
 
# Run the example
 
# Run the example
 
## Run "ant example"
 
## Run "ant example"
## This should give the following output,
+
## This should give the following output.
 +
## If an OptimisticLockException occurs, then this indicates that cache coordination is not working, check your logs and configuration.
 
<pre>
 
<pre>
 
Buildfile: build.xml
 
Buildfile: build.xml
Line 151: Line 235:
 
* [http://download.oracle.com/docs/cd/E13222_01/wls/docs103/ConsoleHelp/core/index.html WLS admin console documentation]
 
* [http://download.oracle.com/docs/cd/E13222_01/wls/docs103/ConsoleHelp/core/index.html WLS admin console documentation]
 
* [http://download.oracle.com/docs/cd/E11035_01/wls100/wlsmbeanref/core/index.html WLS MBean reference]
 
* [http://download.oracle.com/docs/cd/E11035_01/wls100/wlsmbeanref/core/index.html WLS MBean reference]
 +
* [http://www.eclipse.org/forums/index.php?t=msg&th=206035&start=0&S=148a38c34dd52db46b69783799d73e69 Forum Post on using Cache Coordination in Glassfish with JMS]
  
 
[[Category:EclipseLink/Example/JPA|CacheCoordination ]]
 
[[Category:EclipseLink/Example/JPA|CacheCoordination ]]

Revision as of 10:40, 24 April 2012

Overview

EclipseLink supports a shared (L2) object cache that avoids database access for objects and their relationships. This cache is enabled by default which is normally not a problem, unless the database is modified directly by other applications, or by the same application on other servers in a clustered environment.

There are many solutions to caching in a clustered environment, including:

  • disable the shared cache
  • only cache read-only objects
  • set a cache invalidation timeout
  • use refreshing on objects/queries when fresh data is required
  • use optimistic locking (writes on stale data will fail, and will automatically invalidate the cache)
  • using a distributed cache (such as Oracle TopLink Grid with Oracle Coherence)
  • using database events to invalidate changed data
  • using cache coordination (synchronizing the caches, as discussed in this example)

This example gives an overview of the cache coordination option.

EclipseLink provides a cache coordination feature that enables a set of EclipseLink sessions to synchronize their changes in a distributed network such as an application server cluster. Cache coordination works by each EclipseLink session (ServerSession/persistence unit) on each server in the cluster being able to broadcast notification of transactional object changes to the other EclipseLink sessions in the cluster. EclipseLink supports cache coordination over RMI and JMS. The cache coordination framework is also extensible so other options could be developed.

JGroups is not currently supported, to request JGroups support vote for, https://bugs.eclipse.org/bugs/show_bug.cgi?id=282074

This example demonstrates enabling cache coordination using JMS or RMI for a JEE EJB 3.0 SessionBean application using JPA deployed to an Oracle Weblogic cluster. The example could be ported to other JEE application servers or environments. EclipseLink supports cache coordination in any Java environment, including Java SE, or Tomcat.

If you encounter any issues in running this example, or are running in another app server or version please discuss, here

If you wish to port this example to another application server, or provide a different config or fix, please submit your changes to the bug#326343.

Prerequisites

The following software is required to run this example:

  • Oracle Weblogic Server (10.3.3 was used, but any WLS version supporting EJB 3 should work, or any JEE application server with some work) - download link
  • ant (1.7 was used, but other versions should also work) - download link
  • Oracle database (or any other client/server database (embedded database will not work as cannot be accessed from all machines)) - download link
  • EclipseLink (WLS 10.3.3 includes EclipseLink 2.0, 2.1, a 2.2 build or any >= 1.2 version could be used) - download link
  • Cache coordination example - download link - SVN

Configuring the example

There are several ways to configure cache coordination, and the settings required differ depending on the environment and EclipseLink version. The example source code provides a complete configuration, this section is only provided as a reference. The example defaults to using JMS, and RMI persistence.xml file (persistence-wls-rmi.xml) is also provided as well as an non-clustered RMI build file (build-wls-servers.xml). To run these examples just rename the files.

EclipseLink supports cache coordination using either JMS, RMI or RMI-IIOP. A custom TransportManager could also be implemented to support another protocol, such as JGroups.

Cache coordination can be configured using persistence unit properties (in your persistence.xml). It can also be configured in code using a SessionCustomizer, or using System properties (which match the persistence unit properties). This example will use persistence unit properties.

RMI

To enable cache coordination the minimal amount of configuration required is to set the protocol,

<property name="eclipselink.cache.coordination.protocol" value="rmi" />

In EclipseLink 2.2 in a WebLogic cluster this is all that is required as JNDI is replicated, each server will be able to look-up each others listener. Previous to EclipseLink 2.2 a URL was still required, in a cluster any URL in the cluster could be given, or localhost.

If running outside of a cluster, or if JNDI is not replicated, then each server must provide its URL. This could be done through the persistence.xml, but would require a different persistence.xml (thus jar/ear) per server, which is normally not desired. Another option is to set the URL as a System property to the WebLogic start script (or other application server). A SessionCustomizer could also be used to set the URL in code.

<property name="eclipselink.cache.coordination.rmi.url" value="t3://myserver:7001/" />

If a user-name/password are required to access the server, these can be configured (normally not required when running in the same domain).

<property name="eclipselink.cache.coordination.jndi.user" value="weblogic" />
<property name="eclipselink.cache.coordination.jndi.password" value="welcome1" />

For RMI cache coordination the broadcast can be configured to be either asynchronous or synchronous. Asynchronous is the default, synchronous can be used to ensure that all of the servers are updated before the request returns.

<property name="eclipselink.cache.coordination.propagate-asynchronously" value="false" />

If multiple applications on the same server/network use cache coordination a separate channel can be used for each application.

<property name="eclipselink.cache.coordination.channel" value="EmployeeChannel" />

RMI cache coordination use a multicast socket to allow the servers to find eachother. The multicast setting can also be configured, but are normally not required.

<property name="eclipselink.cache.coordination.rmi.announcement-delay" value="1000" />
<property name="eclipselink.cache.coordination.rmi.multicast-group" value="239.192.0.0" />
<property name="eclipselink.cache.coordination.rmi.multicast-group.port" value="3121" />
<property name="eclipselink.cache.coordination.packet-time-to-live" value="2" />

JMS

For JMS a JMS topic JNDI name and topic connection factory JNDI name must also be provided in addition to the protocol. The JMS topic should not be JTA enabled and should not have persistent messages.

<property name="eclipselink.cache.coordination.protocol" value="jms" />
<property name="eclipselink.cache.coordination.jms.topic" value="jms/EmployeeTopic" />
<property name="eclipselink.cache.coordination.jms.factory" value="jms/EmployeeTopicConnectionFactory" />

In EclipseLink 2.2, in a WebLogic cluster this is all that is required.

In previous EclipseLink versions, or if not running in a cluster, then its URL must be provided.

<property name="eclipselink.cache.coordination.jms.host" value="t3://myserver:7001/" />

If a user-name/password are required to access the server, these can be configured (normally not required when running in the same domain).

<property name="eclipselink.cache.coordination.jndi.user" value="weblogic" />
<property name="eclipselink.cache.coordination.jndi.password" value="welcome1" />

Running the example

  1. Install Oracle WebLogic (or your desired JEE application server, or use existing application server)
  2. Configure paths to server in the <example>/build.xml (JEE_HOME, JEE_SERVER, JEE_HOST, JEE_USER, JEE_PASSWORD)
  3. Upgrade the eclipselink.jar in your application server to be the latest release (not required)
    1. In WebLogic the eclipselink.jar is in <weblogic-home>/modules/ directory named org.eclipse.persistence_1.0.0.0_x-x.jar, where x depends on the version of WebLogic.
    2. If using another application server you may need to add the eclipselink.jar to your application server's library path.
    3. You must also update the path in the <example>/build.xml to point to EclipseLink, JPA and EJB (JPA_LIB, EJB_LIB, ECLIPSELINK_LIB)
  4. Install Oracle database (or use existing database, ensure the database is not an embedded database)
  5. Configure database in <example>/build.xml (DB_DRIVER, DB_URL, DB_USER, DB_PASSWORD)
    1. or, you could create your own DataSource in your application server using your application server's tools or config,
    2. this example uses ant to automatically create a DataSource in the server.
  6. Configure persistence.xml in <example>src/meta-inf/
    1. Configure the JMS host if not running a clustered JMS Topic.
    2. If using another application server, ensure the "eclipselink.target-server" is set to the correct platform for your server.
    3. The example uses JMS by default, if RMI is desired, change the protocol to rmi, or switch the persistence.xml file with the persistence-wls-rmi.xml file.
  7. Install ant (or uses existing ant install)
  8. Ensure the prompt environment variables have been set to use the JVM provided in the WebLogic install (JRockit was used for this example)
  9. Create the WebLogic domain and cluster
    1. Run "ant create-cluster",
    2. this will create a new WebLogic domain, a cluster and three servers on the same machine but with different ports.
    3. An existing domain/cluster could also be used, or separate machines for each server in the cluster.
    4. If using an existing domain/cluster, you will need to manually configure and start each server.
  10. Start the cluster
    1. Run "ant start-cluster",
    2. this will start 4 weblogic servers, an admin server, and 3 servers in a cluster.
  11. Configure the cluster
    1. Run "ant setup-cluster"
    2. this will create a DataSource, ConnectionPool, JMSServer and deploy then to the cluster.
  12. Build the application
    1. Run "ant"
    2. this will compile the example code and build the employee.ear
  13. Deploy the application
    1. Run "ant deploy"
    2. this will deploy the ear to the cluster
  14. Run the example
    1. Run "ant example"
    2. This should give the following output.
    3. If an OptimisticLockException occurs, then this indicates that cache coordination is not working, check your logs and configuration.
Buildfile: build.xml

example:
     [java] Populating database.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7031/
     [java] Preloading cache on all servers.
     [java] Looking up next EmployeeServer.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7041/
     [java] Loading all Employees into cache.
     [java] Looking up next EmployeeServer.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7021/
     [java] Loading all Employees into cache.
     [java] Looking up next EmployeeServer.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7031/
     [java] Loading all Employees into cache.
     [java] Preloading done.
     [java] Updating employee on each server.
     [java] Looking up next EmployeeServer.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7041/
     [java] Finding employee: 31535
     [java] Employee name was: Brendan 94
     [java] Updating employee: 31535
     [java] Employee name updated to: 513101 513101
     [java] Looking up next EmployeeServer.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7021/
     [java] Finding employee: 31535
     [java] Employee name was: 513101 513101
     [java] Updating employee: 31535
     [java] Employee name updated to: 465529 465529
     [java] Looking up next EmployeeServer.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7031/
     [java] Finding employee: 31535
     [java] Employee name was: 465529 465529
     [java] Updating employee: 31535
     [java] Employee name updated to: 353681 353681
     [java] Looking up next EmployeeServer.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7041/
     [java] Finding employee: 31535
     [java] Employee name was: 353681 353681
     [java] Updating employee: 31535
     [java] Employee name updated to: 302792 302792
     [java] Looking up next EmployeeServer.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7021/
     [java] Finding employee: 31535
     [java] Employee name was: 302792 302792
     [java] Updating employee: 31535
     [java] Employee name updated to: 76582 76582
     [java] Looking up next EmployeeServer.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7031/
     [java] Finding employee: 31535
     [java] Employee name was: 76582 76582
     [java] Updating employee: 31535
     [java] Employee name updated to: 944086 944086
     [java] Looking up next EmployeeServer.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7041/
     [java] Finding employee: 31535
     [java] Employee name was: 944086 944086
     [java] Updating employee: 31535
     [java] Employee name updated to: 89857 89857
     [java] Looking up next EmployeeServer.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7021/
     [java] Finding employee: 31535
     [java] Employee name was: 89857 89857
     [java] Updating employee: 31535
     [java] Employee name updated to: 51640 51640
     [java] Looking up next EmployeeServer.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7031/
     [java] Finding employee: 31535
     [java] Employee name was: 51640 51640
     [java] Updating employee: 31535
     [java] Employee name updated to: 872883 872883
     [java] Looking up next EmployeeServer.
     [java] Connecting to server:t3://qaott48.ca.oracle.com:7041/
     [java] Finding employee: 31535
     [java] Employee name was: 872883 872883
     [java] Updating employee: 31535
     [java] Employee name updated to: 762396 762396

BUILD SUCCESSFUL

Links