This article shows how to process Coherence events by using Map Triggers. Basically, Distributed Data Management in Oracle Coherence is suggested to look over basic configuration and implementation of Oracle Coherence API.
Map Triggers are one of the most important features of Oracle Coherence to provide a highly customized cache management system. MapTrigger represents a functional agent that allows to validate, reject or modify mutating operations against an underlying map. Also, they can prevent invalid transactions, enforce security, provide event logging and auditing, and gather statistics on data modifications.
For example, we have code that is working with a NamedCache, and we want to change an entry’s behavior or contents before the entry is inserted into the map. This change can be made without modifying all the existing code by enabling a map trigger.
There are two ways to add Map Triggers feature to application :
1) A MapTriggerListener can be used to register a MapTrigger with a Named Cache
2) The class-factory mechanism can be used in the coherence-cache-config.xml configuration file
In the following sample application, MapTrigger functionality is implemented by following the first way. A new cluster called OTV, is created and User bean is distributed by user-map NamedCache object used among two members of the cluster.
Used Technologies :
JDK 1.6.0_35
Spring 3.1.2
Coherence 3.7.1
Maven 3.0.2
STEP 1 : CREATE MAVEN PROJECT
A maven project is created as below. (It can be created by using Maven or IDE Plug-in).
STEP 2 : COHERENCE PACKAGE
Coherence is downloaded via Coherence Package
STEP 3 : LIBRARIES
Firstly, Spring dependencies are added to Maven’ s pom.xml.
<!-- Spring 3.1.2 dependencies --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency>
Coherence library is installed to Local Maven Repository manually and its description is added to pom.xml as below. Also if Maven is not used to manage the project, coherence.jar file can be added to classpath.
<!-- Coherence library(from local repository) --> <dependency> <groupId>com.tangosol</groupId> <artifactId>coherence</artifactId> <version>3.7.1</version> </dependency>
For creating runnable-jar, the following Maven plugin can be used.
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>1.3.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.otv.exe.Application</mainClass> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.handlers</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.schemas</resource> </transformer> </transformers> </configuration> </execution> </executions> </plugin>
STEP 4 : CREATE otv-coherence-cache-config.xml
First Coherence configuration file is otv-coherence-cache-config.xml. It contains caching-schemes(distributed or replicated) and caching-scheme-mapping configuration. Created cache configuration should be added to coherence-cache-config.xml.
<?xml version="1.0"?> <cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config" xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config coherence-cache-config.xsd"> <caching-scheme-mapping> <cache-mapping> <cache-name>user-map</cache-name> <scheme-name>MapDistCache</scheme-name> </cache-mapping> </caching-scheme-mapping> <caching-schemes> <distributed-scheme> <scheme-name>MapDistCache</scheme-name> <service-name>MapDistCache</service-name> <backing-map-scheme> <local-scheme> <unit-calculator>BINARY</unit-calculator> </local-scheme> </backing-map-scheme> <autostart>true</autostart> </distributed-scheme> </caching-schemes> </cache-config>
STEP 5 : CREATE tangosol-coherence-override.xml
Second Coherence configuration file is tangosol-coherence-override.xml. It contains cluster, member-identity and configurable-cache-factory configuration.
tangosol-coherence-override.xml for first member of the cluster :
<?xml version='1.0'?> <coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config" xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config coherence-operational-config.xsd"> <cluster-config> <member-identity> <cluster-name>OTV</cluster-name> <role-name>OTV1</role-name> </member-identity> <unicast-listener> <well-known-addresses> <socket-address id="1"> <address>x.x.x.x</address> <port>8089</port> </socket-address> <socket-address id="2"> <address>x.x.x.x</address> <port>8090</port> </socket-address> </well-known-addresses> <machine-id>1001</machine-id> <address>x.x.x.x</address> <port>8089</port> <port-auto-adjust>true</port-auto-adjust> </unicast-listener> </cluster-config> <configurable-cache-factory-config> <init-params> <init-param> <param-type>java.lang.String</param-type> <param-value system-property="tangosol.coherence.cacheconfig"> otv-coherence-cache-config.xml</param-value> </init-param> </init-params> </configurable-cache-factory-config> </coherence>
tangosol-coherence-override.xml for second member of the cluster :
<?xml version='1.0'?> <coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config" xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config coherence-operational-config.xsd"> <cluster-config> <member-identity> <cluster-name>OTV</cluster-name> <role-name>OTV2</role-name> </member-identity> <unicast-listener> <well-known-addresses> <socket-address id="1"> <address>x.x.x.x</address> <port>8090</port> </socket-address> <socket-address id="2"> <address>x.x.x.x</address> <port>8089</port> </socket-address> </well-known-addresses> <machine-id>1002</machine-id> <address>x.x.x.x</address> <port>8090</port> <port-auto-adjust>true</port-auto-adjust> </unicast-listener> </cluster-config> <configurable-cache-factory-config> <init-params> <init-param> <param-type>java.lang.String</param-type> <param-value system-property="tangosol.coherence.cacheconfig"> otv-coherence-cache-config.xml</param-value> </init-param> </init-params> </configurable-cache-factory-config> </coherence>
STEP 6 : CREATE applicationContext.xml
Spring Configuration file, applicationContext.xml, is created.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- Beans Declaration --> <bean id="userCacheService" class="com.otv.srv.UserCacheService"></bean> <bean id="userCacheUpdater" class="com.otv.exe.UserCacheUpdater"> <property name="userCacheService" ref="userCacheService" /> </bean> </beans>
STEP 7 : CREATE User CLASS
A new User Spring bean is created. This bean will be distributed between two node in OTV cluster. For serializing,java.io.Serializable interface has been implemented but PortableObject can be implemented for better performance.
package com.otv.user; import java.io.Serializable; /** * User Bean * * @author onlinetechvision.com * @since 29 Oct 2012 * @version 1.0.0 * */ public class User implements Serializable { private static final long serialVersionUID = -1963764656789800896L; private String id; private String name; private String surname; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSurname() { return surname; } public void setSurname(String surname) { this.surname = surname; } @Override public String toString() { StringBuilder strBuff = new StringBuilder(); strBuff.append("id : ").append(id); strBuff.append(", name : ").append(name); strBuff.append(", surname : ").append(surname); return strBuff.toString(); } }
STEP 8 : CREATE IUserCacheService INTERFACE
A new IUserCacheService Interface is created for service layer to expose cache functionality.
package com.otv.srv; import com.tangosol.net.NamedCache; /** * IUserCacheService Interface exposes User Cache operations * * @author onlinetechvision.com * @since 29 Oct 2012 * @version 1.0.0 * */ public interface IUserCacheService { /** * Adds user entries to cache * * @param Object key * @param Object value * */ void addToUserCache(Object key, Object value); /** * Deletes user entries from cache * * @param Object key * */ void deleteFromUserCache(Object key); /** * Gets user cache * * @retun NamedCache Coherence named cache */ NamedCache getUserCache(); }
STEP 9 : CREATE UserCacheService IMPL CLASS
UserCacheService is created by implementing IUserCacheService.
package com.otv.srv; import com.otv.listener.UserMapListener; import com.otv.trigger.UserMapTrigger; import com.tangosol.net.CacheFactory; import com.tangosol.net.NamedCache; import com.tangosol.util.MapTriggerListener; /** * CacheService Class implements the ICacheService * * @author onlinetechvision.com * @since 29 Oct 2012 * @version 1.0.0 * */ public class UserCacheService implements IUserCacheService { private NamedCache userCache = null; private static final String USER_MAP = "user-map"; private static final long LOCK_TIMEOUT = -1; public UserCacheService() { setUserCache(CacheFactory.getCache(USER_MAP)); getUserCache().addMapListener(new UserMapListener()); getUserCache().addMapListener(new MapTriggerListener(new UserMapTrigger())); } /** * Adds user entries to cache * * @param Object key * @param Object value * */ public void addToUserCache(Object key, Object value) { // key is locked getUserCache().lock(key, LOCK_TIMEOUT); try { // application logic getUserCache().put(key, value); } finally { // key is unlocked getUserCache().unlock(key); } } /** * Deletes user entries from cache * * @param Object key * */ public void deleteFromUserCache(Object key) { // key is locked getUserCache().lock(key, LOCK_TIMEOUT); try { // application logic getUserCache().remove(key); } finally { // key is unlocked getUserCache().unlock(key); } } /** * Gets user cache * * @retun NamedCache Coherence named cache */ public NamedCache getUserCache() { return userCache; } public void setUserCache(NamedCache userCache) { this.userCache = userCache; } }
STEP 10 : CREATE UserMapTrigger CLASS
A new UserMapTrigger class is created by implementing com.tangosol.util.MapTrigger Interface. This trigger processes the logic before the entry is inserted into the user-map.
package com.otv.trigger; import org.apache.log4j.Logger; import com.otv.listener.UserMapListener; import com.otv.user.User; import com.tangosol.util.MapTrigger; /** * UserMapTrigger executes required logic before the operation is committed * * @author onlinetechvision.com * @since 29 Oct 2012 * @version 1.0.0 * */ public class UserMapTrigger implements MapTrigger { private static final long serialVersionUID = 5411263646665358790L; private static Logger logger = Logger.getLogger(UserMapListener.class); /** * Processes user cache entries * * @param MapTrigger.Entry entry * */ public void process(MapTrigger.Entry entry) { User user = (User) entry.getValue(); String id = user.getId(); String name = user.getName(); String updatedName = name.toUpperCase(); String surname = user.getSurname(); String updatedSurname = surname.toUpperCase(); if (!updatedName.equals(name)) { user.setName(updatedName); } if (!updatedSurname.equals(surname)) { user.setSurname(updatedSurname); } user.setId(user.getName() + "_" + user.getSurname()); entry.setValue(user); logger.debug("UserMapTrigger processes the entry before committing. " + "oldId : " + id + ", newId : " + ((User)entry.getValue()).getId() + ", oldName : " + name + ", newName : " + ((User)entry.getValue()).getName() + ", oldSurname : " + surname + ", newSurname : " + ((User)entry.getValue()).getSurname() ); } public boolean equals(Object o) { return o != null && o.getClass() == this.getClass(); } public int hashCode() { return getClass().getName().hashCode(); } }
STEP 11 : CREATE USERMAPLISTENER IMPL CLASS
A new UserMapListener class is created. This listener receives distributed user-map events.
package com.otv.listener; import org.apache.log4j.Logger; import com.tangosol.util.MapEvent; import com.tangosol.util.MapListener; /** * UserMapListener Class listens user cache events * * @author onlinetechvision.com * @since 29 Oct 2012 * @version 1.0.0 * */ public class UserMapListener implements MapListener { private static Logger logger = Logger.getLogger(UserMapListener.class); public void entryDeleted(MapEvent me) { logger.debug("Deleted Key = " + me.getKey() + ", Value = " + me.getOldValue()); } public void entryInserted(MapEvent me) { logger.debug("Inserted Key = " + me.getKey() + ", Value = " + me.getNewValue()); } public void entryUpdated(MapEvent me) { // logger.debug("Updated Key = " + me.getKey() + ", New_Value = " + me.getNewValue() + ", Old Value = " + me.getOldValue()); } }
STEP 12 : CREATE CacheUpdater CLASS
CacheUpdater Class is created to add new entry to cache and monitor cache content.
package com.otv.exe; import java.util.Collection; import org.apache.log4j.Logger; import com.otv.srv.IUserCacheService; import com.otv.user.User; /** * CacheUpdater Class updates and prints user cache entries * * @author onlinetechvision.com * @since 29 Oct 2012 * @version 1.0.0 * */ public class UserCacheUpdater implements Runnable { private static Logger logger = Logger.getLogger(UserCacheUpdater.class); private IUserCacheService userCacheService; /** * Runs the UserCacheUpdater Thread * */ public void run() { //New User are created... User user = new User(); //Only Name and Surname properties are set and Id property will be set at trigger level. user.setName("James"); user.setSurname("Joyce"); //Entries are added to cache... getUserCacheService().addToUserCache("user1", user); // The following code block shows the entry which will be inserted via second member of the cluster // so it should be opened and above code block should be commented-out before the project is built. // user.setName("Thomas"); // user.setSurname("Moore"); // getUserCacheService().addToUserCache("user2", user); //Cache Entries are being printed... printCacheEntries(); } /** * Prints User Cache Entries * */ @SuppressWarnings("unchecked") private void printCacheEntries() { Collection<User> userCollection = null; try { while(true) { userCollection = (Collection<User>)getUserCacheService().getUserCache().values(); for(User user : userCollection) { logger.debug("Cache Content : "+user); } Thread.sleep(60000); } } catch (InterruptedException e) { logger.error("CacheUpdater is interrupted!", e); } } public IUserCacheService getUserCacheService() { return userCacheService; } public void setUserCacheService(IUserCacheService userCacheService) { this.userCacheService = userCacheService; } }
STEP 13 : CREATE Application CLASS
Application Class is created to run the application.
package com.otv.exe; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Application class starts the application * * @author onlinetechvision.com * @since 29 Oct 2012 * @version 1.0.0 * */ public class Application { /** * Starts the application * * @param String[] args * */ public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserCacheUpdater cacheUpdater = (UserCacheUpdater) context.getBean("userCacheUpdater"); new Thread(cacheUpdater).start(); } }
STEP 14 : BUILD PROJECT
After OTV_Spring_Coherence_MapTrigger Project is build, OTV_Spring_Coherence_MapTrigger-0.0.1-SNAPSHOT.jar will be created.
Important Note : The Members of the cluster have got different configuration for Coherence so the project should be built separately for each member.
STEP 15 : RUN PROJECT BY STARTING ON MEMBER OF THE CLUSTER
After created OTV_Spring_Coherence-0.0.1-SNAPSHOT.jar file is run at the members of the cluster, below output logs will be shown on first member’ s console:
--A new cluster is created and First Member joins the cluster and adds a new entry to the cache. 29.10.2012 18:26:44 DEBUG (UserMapTrigger.java:49) - UserMapTrigger processes the entry before committing. oldId : null, newId : JAMES_JOYCE , oldName : James, newName : JAMES, oldSurname : Joyce, newSurname : JOYCE 29.10.2012 18:26:44 DEBUG (UserMapListener.java:25) - Inserted Key = user1, Value = id : JAMES_JOYCE, name : JAMES, surname : JOYCE 29.10.2012 18:26:44 DEBUG (UserCacheUpdater.java:63) - Cache Content : id : JAMES_JOYCE, name : JAMES, surname : JOYCE ....... --Second Member joins the cluster and adds a new entry to the cache. 29.10.2012 18:27:33 DEBUG (UserMapTrigger.java:49) - UserMapTrigger processes the entry before committing. oldId : null, newId : THOMAS_MOORE, oldName : Thomas, newName : THOMAS, oldSurname : Moore, newSurname : MOORE 29.10.2012 18:27:34 DEBUG (UserMapListener.java:25) - Inserted Key = user2, Value = id : THOMAS_MOORE, name : THOMAS, surname : MOORE ....... --After second member adds a new entry, cache content is shown as below : 29.10.2012 18:27:44 DEBUG (UserCacheUpdater.java:63) - Cache Content : id : THOMAS_MOORE, name : THOMAS, surname : MOORE 29.10.2012 18:27:45 DEBUG (UserCacheUpdater.java:63) - Cache Content : id : JAMES_JOYCE, name : JAMES, surname : JOYCE 29.10.2012 18:28:45 DEBUG (UserCacheUpdater.java:63) - Cache Content : id : THOMAS_MOORE, name : THOMAS, surname : MOORE 29.10.2012 18:28:45 DEBUG (UserCacheUpdater.java:63) - Cache Content : id : JAMES_JOYCE, name : JAMES, surname : JOYCE
Second member’ s console :
--After Second Member joins the cluster and adds a new entry to the cache, cache content is shown as below and the members has got same entries :. 29.10.2012 18:27:34 DEBUG (UserMapListener.java:25) - Inserted Key = user2, Value = id : THOMAS_MOORE, name : THOMAS, surname : MOORE 29.10.2012 18:27:34 DEBUG (UserCacheUpdater.java:63) - Cache Content : id : JAMES_JOYCE, name : JAMES, surname : JOYCE 29.10.2012 18:27:34 DEBUG (UserCacheUpdater.java:63) - Cache Content : id : THOMAS_MOORE, name : THOMAS, surname : MOORE 29.10.2012 18:28:34 DEBUG (UserCacheUpdater.java:63) - Cache Content : id : JAMES_JOYCE, name : JAMES, surname : JOYCE 29.10.2012 18:28:34 DEBUG (UserCacheUpdater.java:63) - Cache Content : id : THOMAS_MOORE, name : THOMAS, surname : MOORE
STEP 16 : DOWNLOAD
https://github.com/erenavsarogullari/OTV_Spring_Coherence_MapTrigger
REFERENCES :
相关推荐
标题中的"main pipper_robust_cap81h_mt_Coherence_processing_"表明这是一个关于“主处理管道(Main Pipper)”的项目,其中涉及到了“鲁棒性(Robustness)”、“CAP81H”标准以及“多时相(Multi-Temporal, mt)...
《深入理解Coherence.jar与coherence-work.jar》 在分布式计算和大数据处理领域,Oracle Coherence是一款强大的数据网格解决方案,它提供了高效的缓存、数据共享和数据管理功能。本文将详细探讨Coherence.jar和...
### Coherence企业级缓存(二):QuickStart与编程详解 #### 1. Coherence简介及重要性 Coherence是一款高性能、可扩展的企业级内存数据网格解决方案,由Oracle公司提供。它允许开发者构建分布式、容错且具有高度可...
《Coherence企业级缓存深度解析》 Oracle Coherence是一款高效的企业级数据缓存系统,它为分布式应用程序提供了数据管理、缓存以及服务网格的功能。本文将深入探讨Coherence的核心特性,包括其QuickStart和编程模型...
在IT行业中,Coherence是Oracle公司提供的一种分布式数据管理解决方案,它主要被用来构建高性能、高可用性的数据网格。这个技术的核心在于提供了一个强大的缓存层,能够支持大规模并发访问和分布式计算。在这个场景...
"coherence-work.jar, coherence.jar, tangosol.jar"这三个文件是Oracle Coherence数据网格产品的一部分,它们对于Openfire的高性能、高可用性和分布式数据管理至关重要。 首先,让我们逐一了解这些文件的作用: 1...
标题“Coherence_matlab_Coherence_multichannel_”表明我们正在探讨的是使用MATLAB进行多通道相干性分析。在信号处理和通信领域,相干性分析是一种衡量两个或多个信号之间线性关系的方法,特别是在时间域或频域内。...
标题中的"coherence.jar-coherence-work.jar-tangosol.jar-"揭示了这是一组与Oracle Coherence相关的Java库文件。Coherence是Oracle公司提供的一种分布式数据管理解决方案,它主要用于实现高性能的数据缓存、数据...
在这种情况下,关键的三个 jar 包是:`coherence.jar`、`coherence-work.jar` 和 `tangosol.jar`。这些 jar 文件对于 OpenFire 的正常运行至关重要,因为它们提供了必要的库支持和服务功能。 `coherence.jar` 是 ...
1. `coherence.jar`:这是Oracle Coherence的一个组成部分,Coherence是一款分布式数据管理产品,主要用于提供数据缓存、数据复制、事件处理等功能。在Openfire中,它可能被用于优化数据库访问性能,实现高效的缓存...
### Oracle Coherence:起步与关键技术解析 #### 一、Oracle Coherence简介 Oracle Coherence是一款高性能、可扩展的分布式数据网格平台,它主要用于在多个应用服务器之间共享数据,并提供一致性和高可用性保障。...
### Oracle Coherence 系统架构详解 #### 一、引言 随着Web应用对高性能、高可用性的需求不断增加,如何优化应用服务器中的数据处理成为了一个关键问题。传统的做法是在应用服务器内部缓存数据,但这种方法容易导致...
"Wavelet Coherence"是小波分析的一个重要分支,主要研究两个时间序列之间的相干性,即在不同频率和时间点上它们的相关性。 在这个"wavelet-coherence-master.rar"压缩包中,包含了用于执行小波分析和计算相关性的...
而Coherence是Oracle的一个数据网格解决方案,它提供了高度可扩展的数据缓存和处理服务,常用于提高大规模分布式系统的性能和可用性。当WebLogic与Coherence结合时,可以构建出高效率、高可用性的集群环境。接下来,...
Mandel L., Wolf E. Optical Coherence and Quantum Optics (CUP, 1995)(ISBN 0521417112)(400dpi)(KA)(T)(1190s)_PEo_.djvu
### Oracle Coherence中文开发文档知识点解析 #### 一、引言 Oracle Coherence是一款高性能、分布式内存数据网格平台,主要用于解决大数据环境下对于实时数据处理的需求。该文档为Oracle Coherence的中文开发指南,...
### Coherence 入门知识点详解 #### 一、Coherence简介 Coherence是一款由Oracle公司提供的内存数据网格解决方案,主要用于缓存Java对象。它能够帮助应用程序显著提高性能和可伸缩性,尤其适用于那些需要处理大量...
Oracle Coherence 是一款由 Oracle 公司提供的分布式数据网格解决方案,它主要被用于提升应用程序的性能和可伸缩性。Coherence 提供了一个高度可配置的、基于内存的数据存储和缓存平台,允许应用程序在无需修改的...