Springは、エンタープライズJava/J2EEアプリケーションの構築および実行を目的としたプラットフォームです。この章では、Springプラットフォーム上で実行されるアプリケーションが使用するOracle Coherenceキャッシュの構成方法について説明します。
Coherenceの静的なファクトリ・メソッドCacheFactory
を使用すると、Coherenceのすべてのキャッシュおよびサービスにアクセスできます。これらのメソッド(getCache
など)は、ConfigurableCacheFactory
インタフェースに委任しますが、このインタフェースは、CacheFactory.setConfigurableCacheFactory
またはオペレーション・オーバーライド・ファイル(tangosol-coherence-override.xml
)を使用してプラッガブルになります。
Coherenceキャッシュ構成ファイル(coherence-cache-config.xml
)では、ユーザーがCacheStore
やMapListener
のような独自のCoherenceインタフェースを実装できるように、フックが提供されています。これは、class-scheme
要素を使用して構成します。Coherenceでは、これらのクラスを2つの方法でインスタンス化できます。新しい演算子を使用して新しいインスタンスを作成する方法と、ユーザーが指定したファクトリ・メソッドを起動する方法です。
アプリケーションによっては、独自のインスタンスを作成するよりも、class-schemeで構成されているオブジェクトをSpring BeanFactory
から取得するほうが便利な場合があります。これは、CacheStore
オブジェクトのスタンドアロンJVMでの実行が構成されているキャッシュ・サーバーでは特に有効です。これらのCacheStore
オブジェクトには通常、データソース、接続プールなども合せて構成する必要があるからです。Springは、単純なJavaオブジェクトのデータソースを簡単に構成できることで定評があります。
SpringAwareCacheFactory
は、class-scheme Beanのインスタンス化をSpring BeanFactory
に委任する機能を持つカスタムのConfigurableCacheFactory
です。これには、次の2つの操作モードがあります。
BeanFactory
を実行時に提供できます。これは、BeanFactory
がすでに存在するコンテナで実行されているCoherenceアプリケーションで役立ちます。
SpringAwareCacheFactory
を使用するようにCoherenceを構成するには、例3-1のXMLコードをオペレーション・オーバーライド・ファイル(tangosol-coherence-override.xml
)に配置する必要があります。ここでは、デフォルトでcoherence-cache-config.xml
をキャッシュ構成ファイルとして、application-context.xml
をSpring構成ファイルとして指定します。
例3-1 SpringAwareCacheFactoryを使用するキャッシュの構成
<configurable-cache-factory-config> <class-name system-property="tangosol.coherence.cachefactory"> com.tangosol.coherence.spring.SpringAwareCacheFactory </class-name> <init-params> <init-param> <param-type>java.lang.String</param-type> <param-value system-property="tangosol.coherence.cacheconfig"> coherence-cache-config.xml </param-value> </init-param> <init-param id="1"> <param-type>java.lang.String</param-type> <param-value system-property="tangosol.coherence.springconfig"> application-context.xml </param-value> </init-param> </init-params> </configurable-cache-factory-config>
構成ファイルを使用するかわりに、例3-2に示すように、SpringAwareCacheFactory
をプログラムで構成することもできます。
例3-2 SpringAwareCacheFactoryのプログラムでの構成
BeanFactory bf = ... SpringAwareCacheFactory scf = new SpringAwareCacheFactory(); scf.setBeanFactory(bf); CacheFactory.setConfigurableCacheFactory(scf);
SpringAwareCacheFactory
はBeanFactoryAware
であるため、アプリケーション・コンテキストでも定義できます。
例3-3 SpringAwareCacheFactoryのアプリケーション・コンテキストでの定義
<bean id="cacheFactory" class="com.tangosol.coherence.spring.SpringAwareCacheFactory"> </bean>
さらに改変して、Coherence CacheFactory
をアプリケーション・コンテキスト内で構成できます。
例3-4 CacheFactoryのアプリケーション・コンテキストでの構成
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetClass" value="com.tangosol.net.CacheFactory"/> <property name="targetMethod" value="setConfigurableCacheFactory"/> <property name="arguments" ref="cacheFactory"/> </bean>
アプリケーション・コンテキストでは、例3-5に示すようにCacheStore
を構成できます。EntityCacheStore
は、prototypeとして範囲指定されています。このような範囲が指定されるのは、Coherenceでは、new
を使用してオブジェクトをインスタンス化した場合と同様、Springから取得したBeanのライフサイクルも管理されるためです。
例3-5 CacheStoreのアプリケーション・コンテキストでの構成
<bean id="dataSource" class="..."> ... </bean> <bean id="sessionFactory" class="..."> <property name="dataSource" ref="dataSource"/> ... </bean> <bean id="entityCacheStore" class="com.company.app.EntityCacheStore" scope="prototype"> <property name="sessionFactory" ref="sessionFactory" /> </bean>
Coherenceでは、例3-6で示すようにentityCacheStore
Beanを使用できます。init-param
要素を指定することにより、setterインジェクションを使用して、Springから取得したBeanのプロパティを設定できます。このBeanは、キャッシュ名を指定したsetEntityName
メソッドを起動してからCoherenceで使用されます。
例3-6 Beanのプロパティを設定するsetterインジェクションの構成
<?xml version="1.0"?> <!DOCTYPE cache-config SYSTEM "cache-config.dtd"> <cache-config> <caching-scheme-mapping> <cache-mapping> <cache-name>com.company.app.domain.*</cache-name> <scheme-name>distributed-domain</scheme-name> </cache-mapping> </caching-scheme-mapping> <caching-schemes> <distributed-scheme> <scheme-name>distributed-domain</scheme-name> <backing-map-scheme> <read-write-backing-map-scheme> <internal-cache-scheme> <local-scheme /> </internal-cache-scheme> <cachestore-scheme> <class-scheme> <class-name>spring-bean:entityCacheStore</class-name> <init-params> <init-param> <param-name>setEntityName</param-name> <param-value>{cache-name}</param-value> </init-param> </init-params> </class-scheme> </cachestore-scheme> <write-delay>5s</write-delay> </read-write-backing-map-scheme> </backing-map-scheme> <autostart>true</autostart> </distributed-scheme> </caching-schemes> </cache-config>
例3-7には、SpringAwareCacheFactory
のソースが列挙されています。これには、Coherence 3.4.xとSpring 2.xが必要です。
例3-7 Spring対応キャッシュ・ファクトリの更新サンプル
/* * SpringAwareCacheFactory.java * * Copyright 2001-2007 by Oracle. All rights reserved. * * Oracle is a registered trademarks of Oracle Corporation and/or its affiliates. * * This software is the confidential and proprietary information of * Oracle Corporation. You shall not disclose such confidential and * proprietary information and shall use it only in accordance with the * terms of the license agreement you entered into with Oracle. * * This notice may not be removed or altered. */ package com.tangosol.coherence.spring; import com.tangosol.net.BackingMapManagerContext; import com.tangosol.net.DefaultConfigurableCacheFactory; import com.tangosol.run.xml.SimpleElement; import com.tangosol.run.xml.XmlElement; import com.tangosol.run.xml.XmlHelper; import com.tangosol.util.ClassHelper; import java.util.Iterator; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; /** * SpringAwareCacheFactory provides a facility to access caches declared * in a "cache-config.dtd" compliant configuration file, similar to its super * class {@link DefaultConfigurableCacheFactory}. In addition, this factory * provides the ability to reference beans in a Spring application context * through the use of a class-scheme element. * * <p>This factory can be configured to start its own Spring application * context from which to retrieve these beans. This can be useful for standalone * JVMs such as cache servers. It can also be configured at run time with a * preconfigured Spring bean factory. This can be useful for Coherence * applications running in an environment that is itself responsible for starting * the Spring bean factory, such as a web container. * * @see #instantiateAny(CacheInfo, XmlElement, BackingMapManagerContext, ClassLoader) * */ public class SpringAwareCacheFactory extends DefaultConfigurableCacheFactory implements BeanFactoryAware { // ----- constructors ------------------------------------------------- /** * Construct a default DefaultConfigurableCacheFactory using the * default configuration file name. */ public SpringAwareCacheFactory() { super(); } /** * Construct a SpringAwareCacheFactory using the specified path to * a "cache-config.dtd" compliant configuration file or resource. This * will also create a Spring ApplicationContext based on the supplied * path to a Spring compliant configuration file or resource. * * @param sCacheConfig location of a cache configuration * @param sAppContext location of a Spring application context */ public SpringAwareCacheFactory(String sCacheConfig, String sAppContext) { super(sCacheConfig); azzert(sAppContext != null && sAppContext.length() > 0, "Application context location required"); m_beanFactory = sCacheConfig.startsWith("file:") ? (BeanFactory) new FileSystemXmlApplicationContext(sAppContext) : new ClassPathXmlApplicationContext(sAppContext); // register a shutdown hook so the bean factory cleans up // upon JVM exit ((AbstractApplicationContext) m_beanFactory).registerShutdownHook(); } /** * Construct a SpringAwareCacheFactory using the specified path to * a "cache-config.dtd" compliant configuration file or resource and * the supplied Spring BeanFactory. * * @param sPath the configuration resource name or file path * @param beanFactory Spring BeanFactory used to load Spring beans */ public SpringAwareCacheFactory(String sPath, BeanFactory beanFactory) { super(sPath); m_beanFactory = beanFactory; } // ----- extended methods ----------------------------------------------- /** * Create an Object using the "class-scheme" element. * <p/> * In addition to the functionality provided by the super class, * this will retreive an object from the configured Spring BeanFactory * for class names that use the following format: * <pre> * <class-name>spring-bean:sampleCacheStore</class-name> * </pre> * * Parameters may be passed to these beans through setter injection as well: * <pre> * <init-params> * <init-param> * <param-name>setEntityName</param-name> * <param-value>{cache-name}</param-value> * </init-param> * </init-params> * </pre> * * Note that Coherence will manage the lifecycle of the instantiated Spring * bean, therefore any beans that are retreived using this method should be * scoped as a prototype in the Spring configuration file, for example: * <pre> * <bean id="sampleCacheStore" * class="com.company.SampleCacheStore" * scope="prototype"/> * </pre> * * @param info the cache info * @param xmlClass "class-scheme" element. * @param context BackingMapManagerContext to be used * @param loader the ClassLoader to instantiate necessary classes * * @return a newly instantiated Object * * @see DefaultConfigurableCacheFactory#instantiateAny( * CacheInfo, XmlElement, BackingMapManagerContext, ClassLoader) */ public Object instantiateAny(CacheInfo info, XmlElement xmlClass, BackingMapManagerContext context, ClassLoader loader) { if (translateSchemeType(xmlClass.getName()) != SCHEME_CLASS) { throw new IllegalArgumentException( "Invalid class definition: " + xmlClass); } String sClass = xmlClass.getSafeElement("class-name").getString(); if (sClass.startsWith(SPRING_BEAN_PREFIX)) { String sBeanName = sClass.substring(SPRING_BEAN_PREFIX.length()); azzert(sBeanName != null && sBeanName.length() > 0, "Bean name required"); XmlElement xmlParams = xmlClass.getElement("init-params"); XmlElement xmlConfig = null; if (xmlParams != null) { xmlConfig = new SimpleElement("config"); XmlHelper.transformInitParams(xmlConfig, xmlParams); } Object oBean = getBeanFactory().getBean(sBeanName); if (xmlConfig != null) { for (Iterator iter = xmlConfig.getElementList().iterator(); iter.hasNext();) { XmlElement xmlElement = (XmlElement) iter.next(); String sMethod = xmlElement.getName(); String sParam = xmlElement.getString(); try { ClassHelper.invoke(oBean, sMethod, new Object[]{sParam}); } catch (Exception e) { ensureRuntimeException(e,"Could not invoke " + sMethod + "(" + sParam + ") on bean " + oBean); } } } return oBean; } else { return super.instantiateAny(info, xmlClass, context, loader); } } /** * Get the Spring BeanFactory used by this CacheFactory * @return the Spring {@link BeanFactory} used by this CacheFactory */ public BeanFactory getBeanFactory() { azzert(m_beanFactory != null, "Spring BeanFactory == null"); return m_beanFactory; } /** * Set the Spring BeanFactory used by this CacheFactory * @param beanFactory the Spring {@link BeanFactory} used by this CacheFactory */ public void setBeanFactory(BeanFactory beanFactory) { m_beanFactory = beanFactory; } // ----- data fields ---------------------------------------------------- /** * Spring BeanFactory used by this CacheFactory */ private BeanFactory m_beanFactory; /** * Prefix used in cache configuration "class-name" element to indicate * this bean is in Spring */ private static final String SPRING_BEAN_PREFIX = "spring-bean:"; }