В этой статье показано, как распространять компоненты Spring с помощью функций EntryProcessor и Portable Object Format (POF) в Oracle Coherence.
Coherence поддерживает модель программирования без блокировки через API EntryProcessor. Эта функция повышает производительность системы за счет сокращения доступа к сети и выполнения неявной низкоуровневой блокировки записей. Эта неявная функциональность низкоуровневой блокировки отличается от явной блокировки (ключа), предоставляемой API ConcurrentMap.
Явная блокировка, Transaction Framework API и Coherence Resource Adapter — это другие параметры транзакции Coherence в качестве процессоров ввода. Для получения подробной информации о параметрах Coherence Transaction, пожалуйста, просмотрите раздел ссылок. Кроме того, для реализации Coherence Explicit Lock можно предложить распределенное управление данными в статье Oracle Coherence .
Portable Object Format (POF) — это независимый от платформы формат сериализации. Это позволяет кодировать эквивалентные объекты Java, .NET и C ++ в одинаковую последовательность байтов. POF рекомендуется для производительности системы, так как характеристики POF для сериализации и десериализации лучше, чем стандартная сериализация Java (согласно справочному документу Coherence, в простом тестовом классе со строкой String, long и Three Ints, (de) сериализации было семь в разы быстрее, чем стандартная сериализация Java).
Coherence предлагает много видов типов кэша, таких как распределенный (или разделенный), реплицированный, оптимистический, ближний, локальный и удаленный кэш. Распределенный кеш определяется как набор данных, который распределен (или разделен) по любому количеству узлов кластера, так что ровно один узел в кластере отвечает за каждый фрагмент данных в кеше, а ответственность распределяется (или, балансировка нагрузки) среди узлов кластера. Обратите внимание, что в этой статье использовался тип распределенного кэша. Поскольку другие типы кэша не входят в сферу применения этой статьи, ознакомьтесь с разделом «Ссылки» или документом Coherence Reference. Их конфигурации очень похожи на конфигурацию распределенного кэша.
Как распространять Spring Beans с помощью статьи Coherence, в которой рассматривается явная блокировка — стандартная сериализация Java , предлагается сравнить две разные реализации ( EntryProcessor — переносимый объектный формат (POF) и явная блокировка — стандартная сериализация Java ).
В этой статье был создан новый кластер с именем OTV и распределенный bean-компонент с использованием объекта кэша с именем user-cache . Он был распределен между двумя членами кластера.
Давайте посмотрим на реализации AbsctractProcessor реализующего EntryProcessor интерфейс и PortableObject интерфейс для распределения Весны — бобов между виртуальными машинами в кластере.
Используемые технологии:
JDK 1.6.0_31
Spring 3.1.1
Coherence 3.7.0
SolarisOS 5.10
Maven 3.0.2
ШАГ 1: СОЗДАТЬ MAVEN ПРОЕКТ
Maven проект создается как показано ниже. (Его можно создать с помощью Maven или IDE Plug-in).
ШАГ 2: КОГЕРЕНТНЫЙ ПАКЕТ
Coherence загружается через пакет Coherence
ШАГ 3: БИБЛИОТЕКИ
Во-первых, Spring-зависимости добавляются в pom.xml Maven. Обратите внимание, что библиотека Coherence установлена в локальный репозиторий Maven, а ее описание добавляется в pom.xml следующим образом. Также, если maven не используется, файл coherence.jar можно добавить в classpath.
<properties> <spring.version>3.1.1.RELEASE</spring.version> </properties> <dependencies> <!-- Spring 3 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(from local repository) --> <dependency> <groupId>com.tangosol</groupId> <artifactId>coherence</artifactId> <version>3.7.0</version> </dependency> <!-- Log4j library --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> </dependencies>
Следующий maven-плагин можно использовать для создания runnable-jar.
<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>
ШАГ 4: СОЗДАНИЕ otv-pof-config.xml
otv-pof-config.xml охватывает классы, использующиефункцию Portable Object Format (POF) для сериализации. В этом примере; Классы user , UpdateUserProcessor и DeleteUserProcessor реализуютинтерфейс com.tangosol.io.pof.PortableObject .
Аргумент -Dtangosol.pof.config может использоваться для определения пути otv-pof -config.xml в сценарии запуска.
<?xml version="1.0"?> <!DOCTYPE pof-config SYSTEM "pof-config.dtd"> <pof-config> <user-type-list> <!-- coherence POF user types --> <include>coherence-pof-config.xml</include> <!-- The definition of classes which use Portable Object Format --> <user-type> <type-id>1001</type-id> <class-name>com.otv.user.User</class-name> </user-type> <user-type> <type-id>1002</type-id> <class-name>com.otv.user.processor.UpdateUserProcessor</class-name> </user-type> <user-type> <type-id>1003</type-id> <class-name>com.otv.user.processor.DeleteUserProcessor</class-name> </user-type> </user-type-list> <allow-interfaces>true</allow-interfaces> <allow-subclasses>true</allow-subclasses> </pof-config>
ШАГ 5: СОЗДАТЬ otv-coherence-cache-config.xml
otv-coherence-cache-config.xml содержит конфигурацию кэширования (распределенную или реплицированную) и конфигурацию отображения схемы кэширования. Созданная конфигурация кэша должна быть добавлена в 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-cache</cache-name> <scheme-name>UserDistributedCacheWithPof</scheme-name> </cache-mapping> </caching-scheme-mapping> <caching-schemes> <distributed-scheme> <scheme-name>UserDistributedCacheWithPof</scheme-name> <service-name>UserDistributedCacheWithPof</service-name> <serializer> <instance> <class-name>com.tangosol.io.pof.SafeConfigurablePofContext </class-name> <init-params> <init-param> <param-type>String</param-type> <param-value> <!-- pof-config.xml path should be set--> otv-pof-config.xml </param-value> </init-param> </init-params> </instance> </serializer> <backing-map-scheme> <local-scheme /> </backing-map-scheme> <autostart>true</autostart> </distributed-scheme> </caching-schemes> </cache-config>
ШАГ 6: СОЗДАЙТЕ tangosol-coherence-override.xml
tangosol-coherence-override.xml охватывает конфигурацию кластера, идентификатора участника и настраиваемую фабрику кэша. Также в следующем XML-файле конфигурации показан первый член кластера. Аргумент -Dtangosol.coherence.override может использоваться для определения пути tangosol-coherence-override.xml в сценарии запуска.
tangosol-coherence-override.xml для первого члена кластера:
<?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> <!-- Name of the first member of the cluster --> <role-name>OTV1</role-name> </member-identity> <unicast-listener> <well-known-addresses> <socket-address id="1"> <!-- IP Address of the first member of the cluster --> <address>x.x.x.x</address> <port>8089</port> </socket-address> <socket-address id="2"> <!-- IP Address of the second member of the cluster --> <address>y.y.y.y</address> <port>8089</port> </socket-address> </well-known-addresses> <!-- Name of the first member of the cluster --> <machine-id>OTV1</machine-id> <!-- IP Address of the first member of the cluster --> <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"> <!-- coherence-cache-config.xml path should be set--> otv-coherence-cache-config.xml </param-value> </init-param> </init-params> </configurable-cache-factory-config> </coherence>
tangosol-coherence-override.xml для второго члена кластера:
<?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> <!-- Name of the second member of the cluster --> <role-name>OTV2</role-name> </member-identity> <unicast-listener> <well-known-addresses> <socket-address id="1"> <!-- IP Address of the first member of the cluster --> <address>x.x.x.x</address> <port>8089</port> </socket-address> <socket-address id="2"> <!-- IP Address of the second member of the cluster --> <address>y.y.y.y</address> <port>8089</port> </socket-address> </well-known-addresses> <!-- Name of the second member of the cluster --> <machine-id>OTV2</machine-id> <!-- IP Address of the second member of the cluster --> <address>y.y.y.y</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"> <!-- coherence-cache-config.xml path should be set--> otv-coherence-cache-config.xml</param-value> </init-param> </init-params> </configurable-cache-factory-config> </coherence>
ШАГ 7: СОЗДАТЬ applicationContext.xml
applicationContext.xml создан.
<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="User" class="com.otv.user.User" scope="prototype" /> <bean id="UserCacheService" class="com.otv.user.cache.srv.UserCacheService" /> <bean id="CacheUpdaterTask" class="com.otv.cache.updater.task.CacheUpdaterTask"> <property name="userCacheService" ref="UserCacheService" /> </bean> </beans>
ШАГ 8: СОЗДАЙТЕ SystemConstants CLASS
Класс SystemConstants создан. Этот класс охватывает все системные константы.
package com.otv.common; /** * System Constants * * @author onlinetechvision.com * @since 2 Jun 2012 * @version 1.0.0 * */ public class SystemConstants { public static final String APPLICATION_CONTEXT_FILE_NAME = "applicationContext.xml"; //Named Cache Definition... public static final String USER_CACHE = "user-cache"; //Bean Names... public static final String BEAN_NAME_CACHE_UPDATER_TASK = "CacheUpdaterTask"; public static final String BEAN_NAME_USER = "User"; }
ШАГ 9: СОЗДАНИЕ БИНА ПОЛЬЗОВАТЕЛЯ
Новый бин User Spring создан. Этот компонент будет распределен между двумя узлами в кластере OTV . PortableObject может быть реализован для сериализации. Интерфейс PortableObject имеет два не реализованных метода, как readExternal и writeExternal . Свойства, которые только сериализуются, должны быть определены. В этом примере все свойства (идентификатор, имя и фамилия пользователя) сериализуются.
package com.otv.user; import java.io.IOException; import com.tangosol.io.pof.PofReader; import com.tangosol.io.pof.PofWriter; import com.tangosol.io.pof.PortableObject; /** * User Bean * * @author onlinetechvision.com * @since 2 Jun 2012 * @version 1.0.0 * */ public class User implements PortableObject { private String id; private String name; private String surname; /** * Gets User Id * * @return String id */ public String getId() { return id; } /** * Sets User Id * * @param String id */ public void setId(String id) { this.id = id; } /** * Gets User Name * * @return String name */ public String getName() { return name; } /** * Sets User Name * * @param String name */ public void setName(String name) { this.name = name; } /** * Gets User Surname * * @return String surname */ public String getSurname() { return surname; } /** * Sets User Surname * * @param String surname */ public void setSurname(String surname) { this.surname = surname; } @Override public String toString() { StringBuilder strBuilder = new StringBuilder(); strBuilder.append("Id : ").append(id); strBuilder.append(", Name : ").append(name); strBuilder.append(", Surname : ").append(surname); return strBuilder.toString(); } /** * Restore the contents of a user type instance by reading its state * using the specified PofReader object. * * @param PofReader in */ public void readExternal(PofReader in) throws IOException { this.id = in.readString(0); this.name = in.readString(1); this.surname = in.readString(2); } /** * Save the contents of a POF user type instance by writing its state * using the specified PofWriter object. * * @param PofWriter out */ public void writeExternal(PofWriter out) throws IOException { out.writeString(0, id); out.writeString(1, name); out.writeString(2, surname); } }
ШАГ 10: СОЗДАЙТЕ IUserCacheService ИНТЕРФЕЙС
Новый интерфейс IUserCacheService создан для выполнения операций кэширования.
package com.otv.user.cache.srv; import com.otv.user.User; import com.otv.user.processor.DeleteUserProcessor; import com.otv.user.processor.UpdateUserProcessor; import com.tangosol.net.NamedCache; /** * User Cache Service Interface * * @author onlinetechvision.com * @since 2 Jun 2012 * @version 1.0.0 * */ public interface IUserCacheService { /** * Gets Distributed User Cache * * @return NamedCache User Cache */ NamedCache getUserCache(); /** * Adds user to cache * * @param User user */ void addUser(User user); /** * Updates user on the cache * * @param String userId * @param UpdateUserProcessor processor * */ void updateUser(String userId, UpdateUserProcessor processor); /** * Deletes user from the cache * * @param String userId * @param DeleteUserProcessor processor * */ void deleteUser(String userId, DeleteUserProcessor processor); }
ШАГ 11: СОЗДАНИЕ КЛАССА UserCacheService
Класс UserCacheService создается путем реализации интерфейса IUserCacheService .
package com.otv.user.cache.srv; import com.otv.cache.listener.UserMapListener; import com.otv.common.SystemConstants; import com.otv.user.User; import com.otv.user.processor.DeleteUserProcessor; import com.otv.user.processor.UpdateUserProcessor; import com.tangosol.net.CacheFactory; import com.tangosol.net.NamedCache; /** * User Cache Service * * @author onlinetechvision.com * @since 2 Jun 2012 * @version 1.0.0 * */ public class UserCacheService implements IUserCacheService { private NamedCache userCache = null; public UserCacheService() { setUserCache(CacheFactory.getCache(SystemConstants.USER_CACHE)); //UserMap Listener is registered to listen user-cache operations getUserCache().addMapListener(new UserMapListener()); } /** * Adds user to cache * * @param User user */ public void addUser(User user) { getUserCache().put(user.getId(), user); } /** * Deletes user from the cache * * @param String userId * @param DeleteUserProcessor processor * */ public void deleteUser(String userId, DeleteUserProcessor processor) { getUserCache().invoke(userId, processor); } /** * Updates user on the cache * * @param String userId * @param UpdateUserProcessor processor * */ public void updateUser(String userId, UpdateUserProcessor processor) { getUserCache().invoke(userId, processor); } /** * Gets Distributed User Cache * * @return NamedCache User Cache */ public NamedCache getUserCache() { return userCache; } /** * Sets User Cache * * @param NamedCache userCache */ public void setUserCache(NamedCache userCache) { this.userCache = userCache; } }
ШАГ 12: СОЗДАТЬ КЛАСС USERMAPLISTENER
Новый класс UserMapListener создан. Этот слушатель получает распределенные события пользовательского кэша .
package com.otv.cache.listener; import org.apache.log4j.Logger; import com.tangosol.util.MapEvent; import com.tangosol.util.MapListener; /** * User Map Listener * * @author onlinetechvision.com * @since 2 Jun 2012 * @version 1.0.0 * */ public class UserMapListener implements MapListener { private static Logger logger = Logger.getLogger(UserMapListener.class); /** * This method is invoked when an entry is deleted from the cache... * * @param MapEvent me */ public void entryDeleted(MapEvent me) { logger.debug("Deleted Key = " + me.getKey() + ", Value = " + me.getOldValue()); } /** * This method is invoked when an entry is inserted to the cache... * * @param MapEvent me */ public void entryInserted(MapEvent me) { logger.debug("Inserted Key = " + me.getKey() + ", Value = " + me.getNewValue()); } /** * This method is invoked when an entry is updated on the cache... * * @param MapEvent me */ public void entryUpdated(MapEvent me) { logger.debug("Updated Key = " + me.getKey() + ", New_Value = " + me.getNewValue() + ", Old Value = " + me.getOldValue()); } }
ШАГ 13: СОЗДАТЬ UpdateUserProcessor CLASS
AbstractProcessor — это абстрактный класс в пакете com.tangosol.util.processor . Он реализует интерфейс EntryProcessor .
Класс UpdateUserProcessor создан для обработки операции обновления пользователя в кеше. Когда UpdateUserProcessor вызывается для ключа, сначала в кластере обнаруживается элемент, содержащий ключ. После этого UpdateUserProcessor вызывается из члена, который содержит связанный ключ, и его значение (объект пользователя) обновляется. Поэтому сетевой трафик уменьшается.
package com.otv.user.processor; import java.io.IOException; import org.apache.log4j.Logger; import com.otv.user.User; import com.tangosol.io.pof.PofReader; import com.tangosol.io.pof.PofWriter; import com.tangosol.io.pof.PortableObject; import com.tangosol.util.InvocableMap.Entry; import com.tangosol.util.processor.AbstractProcessor; /** * Update User Processor * * @author onlinetechvision.com * @since 2 Jun 2012 * @version 1.0.0 * */ public class UpdateUserProcessor extends AbstractProcessor implements PortableObject { private static Logger logger = Logger.getLogger(UpdateUserProcessor.class); private User newUser; /** * This empty constructor is added for Portable Object Format(POF). * */ public UpdateUserProcessor() { } public UpdateUserProcessor(User newUser) { this.newUser = newUser; } /** * Processes a Map.Entry object. * * @param Entry entry * @return Object newUser */ public Object process(Entry entry) { Object newValue = null; try { newValue = getNewUser(); entry.setValue(newValue); } catch (Exception e) { logger.error("Error occured when entry was being processed!", e); } return newValue; } /** * Gets new user * * @return User newUser */ public User getNewUser() { return newUser; } /** * Sets new user * * @param User newUser */ public void setNewUser(User newUser) { this.newUser = newUser; } /** * Restore the contents of a user type instance by reading its state * using the specified PofReader object. * * @param PofReader in */ public void readExternal(PofReader in) throws IOException { setNewUser((User) in.readObject(0)); } /** * Save the contents of a POF user type instance by writing its state * using the specified PofWriter object. * * @param PofWriter out */ public void writeExternal(PofWriter out) throws IOException { out.writeObject(0, getNewUser()); } }
ШАГ 14: СОЗДАЙТЕ DeleteUserProcessor CLASS
Класс DeleteUserProcessor создан для обработки операции удаления пользователя в кеше. Когда DeleteUserProcessor вызывается для ключа, сначала в кластере обнаруживается элемент, содержащий ключ. После этого DeleteUserProcessor вызывается из члена, который содержит связанный ключ. Поэтому сетевой трафик уменьшается.
package com.otv.user.processor; import java.io.IOException; import org.apache.log4j.Logger; import com.otv.user.User; import com.tangosol.io.pof.PofReader; import com.tangosol.io.pof.PofWriter; import com.tangosol.io.pof.PortableObject; import com.tangosol.util.InvocableMap.Entry; import com.tangosol.util.processor.AbstractProcessor; /** * Delete User Processor * * @author onlinetechvision.com * @since 2 Jun 2012 * @version 1.0.0 * */ public class DeleteUserProcessor extends AbstractProcessor implements PortableObject { private static Logger logger = Logger.getLogger(DeleteUserProcessor.class); /** * Processes a Map.Entry object. * * @param Entry entry * @return Object user */ public Object process(Entry entry) { User user = null; try { user = (User) entry.getValue(); entry.remove(true); } catch (Exception e) { logger.error("Error occured when entry was being processed!", e); } return user; } /** * Restore the contents of a user type instance by reading its state * using the specified PofReader object. * * @param PofReader in */ public void readExternal(PofReader in) throws IOException { } /** * Save the contents of a POF user type instance by writing its state * using the specified PofWriter object. * * @param PofWriter out */ public void writeExternal(PofWriter out) throws IOException { } }
ШАГ 15: СОЗДАЙТЕ CacheUpdaterTask CLASS
CacheUpdaterTask Class создан для выполнения операций кэширования (добавления, обновления и удаления) и мониторинга содержимого кэша.
package com.otv.cache.updater.task; import java.util.Collection; import org.apache.log4j.Logger; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import com.otv.common.SystemConstants; import com.otv.user.User; import com.otv.user.cache.srv.IUserCacheService; import com.otv.user.processor.DeleteUserProcessor; import com.otv.user.processor.UpdateUserProcessor; /** * Cache Updater Task * * @author onlinetechvision.com * @since 2 Jun 2012 * @version 1.0.0 * */ public class CacheUpdaterTask implements BeanFactoryAware, Runnable { private static Logger log = Logger.getLogger(CacheUpdaterTask.class); private IUserCacheService userCacheService; private BeanFactory beanFactory; public void run() { try { while(true) { /** * Before the project is built for the first member, * this code block should be used instead of * method processRequestsOnSecondMemberOfCluster. */ processRequestsOnFirstMemberOfCluster(); /** * Before the project is built for the second member, * this code block should be used instead of * method processRequestsOnFirstMemberOfCluster. */ // processRequestsOnSecondMemberOfCluster(); } } catch (InterruptedException e) { e.printStackTrace(); } } /** * Processes the cache requests on the first member of cluster... * * @throws InterruptedException */ private void processRequestsOnFirstMemberOfCluster() throws InterruptedException { //Entry is added to cache... getUserCacheService().addUser(getUser("1", "Bruce", "Willis")); //Cache Entries are being printed... printCacheEntries(); Thread.sleep(10000); User newUser = getUser("1", "Client", "Eastwood"); //Existent Entry is updated on the cache... getUserCacheService().updateUser(newUser.getId(), new UpdateUserProcessor(newUser)); //Cache Entries are being printed... printCacheEntries(); Thread.sleep(10000); //Entry is deleted from cache... getUserCacheService().deleteUser(newUser.getId(), new DeleteUserProcessor()); //Cache Entries are being printed... printCacheEntries(); Thread.sleep(10000); } /** * Processes the cache requests on the second member of cluster... * * @throws InterruptedException */ private void processRequestsOnSecondMemberOfCluster() throws InterruptedException { //Entry is added to cache... getUserCacheService().addUser(getUser("2", "Nathalie", "Portman")); Thread.sleep(15000); User newUser = getUser("2", "Sharon", "Stone"); //Existent Entry is updated on the cache... getUserCacheService().updateUser(newUser.getId(), new UpdateUserProcessor(newUser)); User newUser2 = getUser("1", "Maria", "Sharapova"); //Existent Entry is updated on the cache... getUserCacheService().updateUser(newUser2.getId(), new UpdateUserProcessor(newUser2)); Thread.sleep(15000); //Entry is deleted from cache... getUserCacheService().deleteUser(newUser.getId(), new DeleteUserProcessor()); Thread.sleep(15000); } /** * Prints cache entries * */ private void printCacheEntries() { Collection<User> userCollection = (Collection<User>)getUserCacheService().getUserCache().values(); for(User user : userCollection) { log.debug("Cache Content : "+user); } } /** * Gets new user instance * * @param String user id * @param String user name * @param String user surname * @return User user */ private User getUser(String id, String name, String surname) { User user = getNewUserInstance(); user.setId(id); user.setName(name); user.setSurname(surname); return user; } /** * Gets user cache service... * * @return IUserCacheService userCacheService */ public IUserCacheService getUserCacheService() { return userCacheService; } /** * Sets user cache service... * * @param IUserCacheService userCacheService */ public void setUserCacheService(IUserCacheService userCacheService) { this.userCacheService = userCacheService; } /** * Gets a new instance of User Bean * * @return User */ public User getNewUserInstance() { return (User) getBeanFactory().getBean(SystemConstants.BEAN_NAME_USER); } /** * Gets bean factory * * @return BeanFactory */ public BeanFactory getBeanFactory() { return beanFactory; } /** * Sets bean factory * * @param BeanFactory beanFactory * @throws BeansException */ public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } }
ШАГ 16: СОЗДАЙТЕ КЛАСС ПРИЛОЖЕНИЙ
Класс приложения создан для запуска приложения.
package com.otv.exe; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.otv.cache.updater.task.CacheUpdaterTask; import com.otv.common.SystemConstants; /** * Application Class * * @author onlinetechvision.com * @since 2 Jun 2012 * @version 1.0.0 * */ public class Application { /** * Starts the application * * @param String[] args * */ public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext(SystemConstants.APPLICATION_CONTEXT_FILE_NAME); CacheUpdaterTask cacheUpdaterTask = (CacheUpdaterTask) context.getBean(SystemConstants.BEAN_NAME_CACHE_UPDATER_TASK); Thread cacheUpdater = new Thread(cacheUpdaterTask); cacheUpdater.start(); } }
ШАГ 17: СТРОИМ ПРОЕКТ
После сборки проекта OTV_Spring_Coherence_With_Processor_and_POF будет создан файл OTV_Spring_Coherence-0.0.1-SNAPSHOT.jar .
Обратите внимание, что члены кластера имеют различную конфигурацию для Coherence, поэтому проект должен быть построен отдельно для каждого участника.
ШАГ 18: ЗАПУСК ПРОЕКТА ПЕРВОГО ЧЛЕНА КЛАСТЕРА
После запуска созданного файла OTV_Spring_Coherence-0.0.1-SNAPSHOT.jar на элементах кластера на консоли первого участника будут показаны следующие выходные журналы:
--After A new cluster is created and First Member joins the cluster, a new entry is added to the cache. 02.06.2012 14:21:45 DEBUG (UserMapListener.java:33) - Inserted Key = 1, Value = Id : 1, Name : Bruce, Surname : Willis 02.06.2012 14:21:45 DEBUG (CacheUpdaterTask.java:116) - Cache Content : Id : 1, Name : Bruce, Surname : Willis ....... --After Second Member joins the cluster, a new entry is added to the cache. 02.06.2012 14:21:45 DEBUG (UserMapListener.java:33) - Inserted Key = 2, Value = Id : 2, Name : Nathalie, Surname : Portman ....... --Cache operations go on both first and second members of the cluster: 02.06.2012 14:21:55 DEBUG (UserMapListener.java:42) - Updated Key = 1, New_Value = Id : 1, Name : Client, Surname : Eastwood, Old Value = Id : 1, Name : Bruce, Surname : Willis 02.06.2012 14:21:55 DEBUG (CacheUpdaterTask.java:116) - Cache Content : Id : 2, Name : Nathalie, Surname : Portman 02.06.2012 14:21:55 DEBUG (CacheUpdaterTask.java:116) - Cache Content : Id : 1, Name : Client, Surname : Eastwood 02.06.2012 14:22:00 DEBUG (UserMapListener.java:42) - Updated Key = 2, New_Value = Id : 2, Name : Sharon, Surname : Stone, Old Value = Id : 2, Name : Nathalie, Surname : Portman 02.06.2012 14:22:00 DEBUG (UserMapListener.java:42) - Updated Key = 1, New_Value = Id : 1, Name : Maria, Surname : Sharapova, Old Value = Id : 1, Name : Client, Surname : Eastwood 02.06.2012 14:22:05 DEBUG (UserMapListener.java:24) - Deleted Key = 1, Value = Id : 1, Name : Maria, Surname : Sharapova 02.06.2012 14:22:05 DEBUG (CacheUpdaterTask.java:116) - Cache Content : Id : 2, Name : Sharon, Surname : Stone 02.06.2012 14:22:15 DEBUG (UserMapListener.java:24) - Deleted Key = 2, Value = Id : 2, Name : Sharon, Surname : Stone 02.06.2012 14:22:15 DEBUG (UserMapListener.java:33) - Inserted Key = 1, Value = Id : 1, Name : Bruce, Surname : Willis 02.06.2012 14:22:15 DEBUG (CacheUpdaterTask.java:116) - Cache Content : Id : 1, Name : Bruce, Surname : Willis
ШАГ 19: СКАЧАТЬ
OTV_Spring_Coherence_With_Processor_and_POF
РЕКОМЕНДАЦИИ :
Выполнение транзакций в когерентности с
использованием формата переносимых объектов в Coherence
Spring Framework Reference 3.x