ヘッダーをスキップ
Oracle® Coherence統合ガイド
リリース3.6
B61372-01
  ドキュメント・ライブラリへ
ライブラリ
製品リストへ
製品
目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

3 Oracle Coherence CacheFactoryとSpringの統合

Springは、エンタープライズJava/J2EEアプリケーションの構築および実行を目的としたプラットフォームです。この章では、Springプラットフォーム上で実行されるアプリケーションが使用するOracle Coherenceキャッシュの構成方法について説明します。

Coherenceの静的なファクトリ・メソッドCacheFactoryを使用すると、Coherenceのすべてのキャッシュおよびサービスにアクセスできます。これらのメソッド(getCacheなど)は、ConfigurableCacheFactoryインタフェースに委任しますが、このインタフェースは、CacheFactory.setConfigurableCacheFactoryまたはオペレーション・オーバーライド・ファイル(tangosol-coherence-override.xml)を使用してプラッガブルになります。

Coherenceキャッシュ構成ファイル(coherence-cache-config.xml)では、ユーザーがCacheStoreMapListenerのような独自のCoherenceインタフェースを実装できるように、フックが提供されています。これは、class-scheme要素を使用して構成します。Coherenceでは、これらのクラスを2つの方法でインスタンス化できます。新しい演算子を使用して新しいインスタンスを作成する方法と、ユーザーが指定したファクトリ・メソッドを起動する方法です。

アプリケーションによっては、独自のインスタンスを作成するよりも、class-schemeで構成されているオブジェクトをSpring BeanFactoryから取得するほうが便利な場合があります。これは、CacheStoreオブジェクトのスタンドアロンJVMでの実行が構成されているキャッシュ・サーバーでは特に有効です。これらのCacheStoreオブジェクトには通常、データソース、接続プールなども合せて構成する必要があるからです。Springは、単純なJavaオブジェクトのデータソースを簡単に構成できることで定評があります。

SpringAwareCacheFactoryは、class-scheme Beanのインスタンス化をSpring BeanFactoryに委任する機能を持つカスタムのConfigurableCacheFactoryです。これには、次の2つの操作モードがあります。

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);

SpringAwareCacheFactoryBeanFactoryAwareであるため、アプリケーション・コンテキストでも定義できます。

例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>
    * &lt;class-name&gt;spring-bean:sampleCacheStore&lt;/class-name&gt;
    * </pre>
    *
    * Parameters may be passed to these beans through setter injection as well:
    * <pre>
    *   &lt;init-params&gt;
    *     &lt;init-param&gt;
    *       &lt;param-name&gt;setEntityName&lt;/param-name&gt;
    *       &lt;param-value&gt;{cache-name}&lt;/param-value&gt;
    *     &lt;/init-param&gt;
    *   &lt;/init-params&gt;
    * </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>
    *   &lt;bean id="sampleCacheStore"
    *         class="com.company.SampleCacheStore"
    *         scope="prototype"/&gt;
    * </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:";
    }