Toplink分布式 Session Cache同步的方法oracle官方默认提供了JMS和RMI两种实现方式,当然用户也可以自定方法,自定义一个Transport Manager Class, 具体可参见:
 
 
http://download-west.oracle.com/docs/cd/B25221_04/web.1013/b13593/cachun003.htm
Oracle Coherence是用来实现Data Grid的framework。到目前为止,它还不能和Toplink的native版本整合,但是已经可以和Toplink Essential版本整合。Toplink升级版EclipseLink也承诺将会提供一个公共的接口让用户添加第三方的Cache Cluster到EclipseLink中来作为L2 Cache,但目前尚未实现。把coherence作为toplink session cache的transport manager是因为认为coherence的TCMP集群协议要比普通的jms和rmi的通信协议快。具体还有待进一步测试比较、分析。在目前我们无法使用coherence data grid作为toplink的L2 Cache情况下,又无法忍受使用JMS和RMI带来的性能上的问题,使用一个自定义的Transport Manager是一个很好的尝试。
Coherence介绍:
http://wiki.tangosol.com/display/COH/Oracle+Coherence+Knowledge+Base+Home
我们用Coherence实现Toplink Coordinated Cache,以下是这个demo的具体实现过程,它也仅仅是个demo。对于如何自定义toplink的cache coordinator还是很有帮助的。
1     Demo是用maven2+archifactory构建的,也使用了ant来作为部署时替换文本内容的工具。
2     Coherence配置
Coherence需要两个配置文件: tangosol-coherence.xml和coherence-cache-config,并且用户可以自己提供tangosol-coherence-override-dev.xml来重写tangosol-coherence.xml的部分内容,根据不同的环境定义不同的tangosol-coherence.xml文件。可以参见tangosol的网站来进行配置。
coherence-cache-config,的配置:
 
 <?xml version="1.0"?>
<?xml version="1.0"?>

 <!DOCTYPE cache-config SYSTEM "cache-config.dtd">
<!DOCTYPE cache-config SYSTEM "cache-config.dtd">

 <cache-config>
<cache-config>

 <caching-scheme-mapping>
    <caching-scheme-mapping>

 <cache-mapping>
       <cache-mapping>

 <cache-name>toplinkSyn</cache-name>
           <cache-name>toplinkSyn</cache-name>

 <scheme-name>DistributedCacheScheme</scheme-name>
           <scheme-name>DistributedCacheScheme</scheme-name>

 </cache-mapping>
       </cache-mapping>

 </caching-scheme-mapping>
    </caching-scheme-mapping>

 <caching-schemes>
    <caching-schemes>

 <distributed-scheme>
       <distributed-scheme>

 <scheme-name>DistributedCacheScheme</scheme-name>
           <scheme-name>DistributedCacheScheme</scheme-name>

 <service-name>DistributedCache</service-name>
           <service-name>DistributedCache</service-name>

 <backing-map-scheme>
           <backing-map-scheme>

 <local-scheme>
              <local-scheme>

 <scheme-ref>DistributedMap</scheme-ref>
                  <scheme-ref>DistributedMap</scheme-ref>

 </local-scheme>
              </local-scheme>

 </backing-map-scheme>
           </backing-map-scheme>

 <backup-count>0</backup-count>
           <backup-count>0</backup-count>

 <autostart>true</autostart>
           <autostart>true</autostart>

 </distributed-scheme>
       </distributed-scheme>

 <local-scheme>
       <local-scheme>

 <scheme-name>DistributedMap</scheme-name>
           <scheme-name>DistributedMap</scheme-name>

 <eviction-policy>LRU</eviction-policy>
           <eviction-policy>LRU</eviction-policy>

 <high-units>10000</high-units>
           <high-units>10000</high-units>

 <expiry-delay>1D</expiry-delay>
           <expiry-delay>1D</expiry-delay>

 <flush-delay>1D</flush-delay>
           <flush-delay>1D</flush-delay>

 <cachestore-scheme></cachestore-scheme>
           <cachestore-scheme></cachestore-scheme>

 </local-scheme>
       </local-scheme>

 </caching-schemes>
    </caching-schemes>

 </cache-config>
</cache-config>

 
tangosol-coherence-override-dev.xml的配置
 <?xml version='1.0'?>
<?xml version='1.0'?>

 <!--
<!--

 This operational configuration override file is set up for use with Coherence in
    This operational configuration override file is set up for use with Coherence in

 a development mode.
    a development mode.

 -->
-->

 <coherence xml-override="/tangosol-coherence-override.xml">
<coherence xml-override="/tangosol-coherence-override.xml">

 <cluster-config>
    <cluster-config>

 <member-identity>
       <member-identity>

 <cluster-name
           <cluster-name

 system-property="tangosol.coherence.cluster">
              system-property="tangosol.coherence.cluster">

 Toplink Cache Synchronization
              Toplink Cache Synchronization

 </cluster-name>
           </cluster-name>

 <member-name system-property="tangosol.coherence.member">
           <member-name system-property="tangosol.coherence.member">

 @{coherence.member.name}
              @{coherence.member.name}

 </member-name>
           </member-name>

 <role-name>cache servers</role-name>
           <role-name>cache servers</role-name>

 </member-identity>
       </member-identity>

 <unicast-listener>
       <unicast-listener>

 <well-known-addresses>
           <well-known-addresses>

 <socket-address id="1">
              <socket-address id="1">

 <address system-property="tangosol.coherence.wka">
                  <address system-property="tangosol.coherence.wka">

 146.222.51.20
                     146.222.51.20

 </address>
                  </address>

 <port
                  <port

 system-property="tangosol.coherence.wka.port">
                     system-property="tangosol.coherence.wka.port">

 8088
                     8088

 </port>
                  </port>

 </socket-address>
              </socket-address>

 <socket-address id="2">
              <socket-address id="2">

 <address system-property="tangosol.coherence.wka">
                  <address system-property="tangosol.coherence.wka">

 146.222.51.20
                     146.222.51.20

 </address>
                  </address>

 <port
                  <port

 system-property="tangosol.coherence.wka.port">
                     system-property="tangosol.coherence.wka.port">

 8089
                     8089

 </port>
                  </port>

 </socket-address>
              </socket-address>

 </well-known-addresses>
           </well-known-addresses>

 <address system-property="tangosol.coherence.localhost">
           <address system-property="tangosol.coherence.localhost">

 @{coherence.local.address}
              @{coherence.local.address}

 </address>
           </address>

 <port system-property="tangosol.coherence.localport">
           <port system-property="tangosol.coherence.localport">

 @{coherence.local.port}
              @{coherence.local.port}

 </port>
           </port>

 </unicast-listener>
       </unicast-listener>

 <authorized-hosts>
       <authorized-hosts>

 <host-address></host-address>
           <host-address></host-address>

 <host-range>
           <host-range>

 <from-address>146.222.51.0</from-address>
              <from-address>146.222.51.0</from-address>

 <to-address>146.222.51.255</to-address>
              <to-address>146.222.51.255</to-address>

 </host-range>
           </host-range>

 </authorized-hosts>
       </authorized-hosts>

 <packet-publisher>
       <packet-publisher>

 <packet-delivery>
           <packet-delivery>

 <timeout-milliseconds>30000</timeout-milliseconds>
              <timeout-milliseconds>30000</timeout-milliseconds>

 </packet-delivery>
           </packet-delivery>

 </packet-publisher>
       </packet-publisher>

 </cluster-config>
    </cluster-config>

 <logging-config>
    <logging-config>

 <destination>stderr</destination>
       <destination>stderr</destination>

 <severity-level
       <severity-level

 system-property="tangosol.coherence.log.level">
           system-property="tangosol.coherence.log.level">

 5
           5

 </severity-level>
       </severity-level>

 <character-limit
       <character-limit

 system-property="tangosol.coherence.log.limit">
           system-property="tangosol.coherence.log.limit">

 0
           0

 </character-limit>
       </character-limit>

 </logging-config>
    </logging-config>

 </coherence>
</coherence>


本demo会使用ant替换@{}中的内容。替换的key value值对需要在build.properties文件中给出。如:
coherence.member.name = tts-server2
coherence.local.address = 146.222.51.20
coherence.local.port = 8089
3           toplink配置
Demo使用了toplink tutorial的范例作为一个example来演示结果的正确性。下载地址:
http://www.oracle.com/technology/products/ias/toplink/doc/1013/main/_html/prt_tut.htm
4           demo的配置文件tts.properties:
#one of jms, rmi, coherence or set it blank
toplink.cache.type = coherence
#the name of toplink command channel
toplin.command.channel = OOCLToplinkCoherence
第一个参数用来根据不同的情况使用不同toplink session的配置文件。第二个参数是toplink Command Channel的名字,唯一标识一个toplink cluster。
 
3          主要代码
1)      CoherenceTransportManager继承TransportManager实现自定义的Transport Manager Class
 package com.oocl.isdc.sha.frm.tts.remotecommand;
package com.oocl.isdc.sha.frm.tts.remotecommand;

 import oracle.toplink.internal.remotecommand.RemoteConnection;
import oracle.toplink.internal.remotecommand.RemoteConnection;
 import oracle.toplink.remotecommand.DiscoveryManager;
import oracle.toplink.remotecommand.DiscoveryManager;
 import oracle.toplink.remotecommand.RemoteCommandManager;
import oracle.toplink.remotecommand.RemoteCommandManager;
 import oracle.toplink.remotecommand.ServiceId;
import oracle.toplink.remotecommand.ServiceId;
 import oracle.toplink.remotecommand.TransportManager;
import oracle.toplink.remotecommand.TransportManager;

 import com.oocl.isdc.sha.frm.tts.cohererence.cache.CoherenceCache;
import com.oocl.isdc.sha.frm.tts.cohererence.cache.CoherenceCache;


 public class CoherenceTransportManager extends TransportManager
public class CoherenceTransportManager extends TransportManager  {
{
 protected CoherenceCache cache;
    protected CoherenceCache cache;
 
    

 public CoherenceTransportManager(RemoteCommandManager rcm)
    public CoherenceTransportManager(RemoteCommandManager rcm)  {
{
 this.rcm = rcm;
        this.rcm = rcm;
 this.initialize();
        this.initialize();
 }
    }
 
    

 public void initialize()
    public void initialize()  {
{
 super.initialize();
        super.initialize();
 this.cache = new CoherenceCache();
        this.cache = new CoherenceCache();
 }
    }
 
    

 /** *//**
    /** *//**
 * When get a session, toplink will call this method to listen to
     * When get a session, toplink will call this method to listen to
 * remote connection, and when some object is changed, it will get
     * remote connection, and when some object is changed, it will get
 * the chages.
     * the chages.
 */
     */

 public void connectBackToRemote(RemoteConnection connection)
    public void connectBackToRemote(RemoteConnection connection)  {
{
 CoherenceRemoteConnection coherenceConnection = (CoherenceRemoteConnection)connection;
        CoherenceRemoteConnection coherenceConnection = (CoherenceRemoteConnection)connection;
 coherenceConnection.becomeMapListener();
        coherenceConnection.becomeMapListener();
 }
    }


 public void createLocalConnection()
    public void createLocalConnection()  {
{
 CoherenceRemoteConnection connection = new CoherenceRemoteConnection(rcm, cache);
        CoherenceRemoteConnection connection = new CoherenceRemoteConnection(rcm, cache);
 addConnectionToExternalService(connection);
        addConnectionToExternalService(connection);
 }
    }


 public RemoteConnection createConnection(ServiceId serviceId)
    public RemoteConnection createConnection(ServiceId serviceId)  {
{
 return null;
        return null;
 }
    }

 
  

 public void removeLocalConnection()
    public void removeLocalConnection()  {
{
 this.localConnection = null;
        this.localConnection = null;
 }
    }
 
    
 
    

 public DiscoveryManager createDiscoveryManager()
    public DiscoveryManager createDiscoveryManager()  {
{
 return new CoherenceDiscoveryManager(rcm);
        return new CoherenceDiscoveryManager(rcm);
 }
    }


 public CoherenceCache getCache()
    public CoherenceCache getCache()  {
{
 return cache;
        return cache;
 }
    }
 
   

 public String getServiceUrl()
    public String getServiceUrl()  {
{
 return cache.getUrl();
        return cache.getUrl();
 }
    }
 }
}

2)        CoherenceRemoteConnection继承RemoteConnection从一个和Transport Mnager相关的连接。
 1 package com.oocl.isdc.sha.frm.tts.remotecommand;
package com.oocl.isdc.sha.frm.tts.remotecommand;
 2
 3 import oracle.toplink.exceptions.CommunicationException;
import oracle.toplink.exceptions.CommunicationException;
 4 import oracle.toplink.internal.remotecommand.RemoteConnection;
import oracle.toplink.internal.remotecommand.RemoteConnection;
 5 import oracle.toplink.remotecommand.Command;
import oracle.toplink.remotecommand.Command;
 6 import oracle.toplink.remotecommand.RemoteCommandManager;
import oracle.toplink.remotecommand.RemoteCommandManager;
 7
 8 import com.oocl.isdc.sha.frm.tts.cohererence.cache.CoherenceCache;
import com.oocl.isdc.sha.frm.tts.cohererence.cache.CoherenceCache;
 9 import com.tangosol.util.MapEvent;
import com.tangosol.util.MapEvent;
10 import com.tangosol.util.MapListener;
import com.tangosol.util.MapListener;
11
12
 public class CoherenceRemoteConnection extends RemoteConnection implements MapListener
public class CoherenceRemoteConnection extends RemoteConnection implements MapListener  {
{
13
14
 /** *//** Comment for <code>serialVersionUID</code> */
    /** *//** Comment for <code>serialVersionUID</code> */
15 private static final long serialVersionUID = 8527315103990557963L;
    private static final long serialVersionUID = 8527315103990557963L;
16
17 private CoherenceCache cache;
    private CoherenceCache cache;
18
19 private RemoteCommandManager rcm;
    private RemoteCommandManager rcm;
20
21
 public CoherenceRemoteConnection(RemoteCommandManager rcm, CoherenceCache cache)
    public CoherenceRemoteConnection(RemoteCommandManager rcm, CoherenceCache cache)  {
{
22 this.serviceId = rcm.getServiceId();
        this.serviceId = rcm.getServiceId();
23 this.rcm = rcm;
        this.rcm = rcm;
24 this.cache = cache;
        this.cache = cache;
25 }
    }
26
27
 /** *//**
    /** *//**
28 * When some object in toplink session cache is chaged, it will callback this
     * When some object in toplink session cache is chaged, it will callback this
29 * method to put the changed object infomation to coherence cache
     * method to put the changed object infomation to coherence cache
30 */
     */
31
 public Object executeCommand(Command command) throws CommunicationException
    public Object executeCommand(Command command) throws CommunicationException  {
{
32 cache.putCache(command.getServiceId(), command);
        cache.putCache(command.getServiceId(), command);
33 return null;
        return null;
34 }
    }
35
36 @SuppressWarnings("unchecked")
    @SuppressWarnings("unchecked")
37
 protected void processObject(Object object)
    protected void processObject(Object object)  {
{
38 Command command = null;
        Command command = null;
39
 if (object instanceof Command)
        if (object instanceof Command)  {
{
40 command = (Command) object;
            command = (Command) object;
41
 if (command.getServiceId().getChannel().equals(serviceId.getChannel()))
            if (command.getServiceId().getChannel().equals(serviceId.getChannel()))  {
{
42 rcm.processCommandFromRemoteConnection(command);
                rcm.processCommandFromRemoteConnection(command);
43 }
            }
44
 } else if (null == object)
        } else if (null == object)  {
{
45
46
 } else
        } else  {
{
47
48 }
        }
49
50 }
    }
51
52
 public void close()
    public void close()  {
{
53 this.cache.removeMapListener(this);
        this.cache.removeMapListener(this);
54 }
    }
55 
    
56
 public void becomeMapListener()
    public void becomeMapListener()  {
{
57 this.cache.addMapListener(this);
        this.cache.addMapListener(this);
58 }
    }
59
60
 public void entryDeleted(MapEvent arg0)
    public void entryDeleted(MapEvent arg0)  {
{
61 }
    }
62
63
 /** *//**
    /** *//**
64 * When an object is inserted into coherence, this method of
     * When an object is inserted into coherence, this method of
65 * listener will be called
     * listener will be called
66 */
     */
67
 public void entryInserted(MapEvent event)
    public void entryInserted(MapEvent event)  {
{
68 processObject(event.getNewValue());
        processObject(event.getNewValue());
69 }
    }
70
71
 /** *//**
    /** *//**
72 * When an object in coherence cache is updated, this method
     * When an object in coherence cache is updated, this method
73 * of listener will be called
     * of listener will be called
74 */
     */
75
 public void entryUpdated(MapEvent event)
    public void entryUpdated(MapEvent event)  {
{
76 processObject(event.getNewValue());
        processObject(event.getNewValue());
77 }
    }
78
79 }
}
80
 
 
3)        CoherenceSessionHelper将transport manager添加到当前session中支持server和database两种session
 1 package com.oocl.isdc.sha.frm.tts.remotecommand;
package com.oocl.isdc.sha.frm.tts.remotecommand;
 2
 3 import oracle.toplink.remotecommand.CommandProcessor;
import oracle.toplink.remotecommand.CommandProcessor;
 4 import oracle.toplink.remotecommand.RemoteCommandManager;
import oracle.toplink.remotecommand.RemoteCommandManager;
 5 import oracle.toplink.sessions.DatabaseSession;
import oracle.toplink.sessions.DatabaseSession;
 6 import oracle.toplink.sessions.Session;
import oracle.toplink.sessions.Session;
 7 import oracle.toplink.threetier.Server;
import oracle.toplink.threetier.Server;
 8
 9 import com.oocl.isdc.sha.frm.tts.config.TTSConfigConstants;
import com.oocl.isdc.sha.frm.tts.config.TTSConfigConstants;
10 import com.oocl.isdc.sha.frm.tts.config.TTSConfigParser;
import com.oocl.isdc.sha.frm.tts.config.TTSConfigParser;
11
12
 public class CoherenceSessionHelper
public class CoherenceSessionHelper  {
{
13
 public static Session addCoherenceTransportManagerToSession(Session session)
    public static Session addCoherenceTransportManagerToSession(Session session)  {
{
14 RemoteCommandManager commandMgr = new RemoteCommandManager((CommandProcessor) session);
        RemoteCommandManager commandMgr = new RemoteCommandManager((CommandProcessor) session);
15 commandMgr.setChannel((String) TTSConfigParser.getInstance().get(
        commandMgr.setChannel((String) TTSConfigParser.getInstance().get(
16 TTSConfigConstants.TOPLINK_COMMAND_CHANNEL_KEY));
                TTSConfigConstants.TOPLINK_COMMAND_CHANNEL_KEY));
17 CoherenceTransportManager tm = new CoherenceTransportManager(commandMgr);
        CoherenceTransportManager tm = new CoherenceTransportManager(commandMgr);
18 tm.setInitialContextFactoryName(TTSConfigConstants.TTS_CONTEXT_FACTOYR_NAME);
        tm.setInitialContextFactoryName(TTSConfigConstants.TTS_CONTEXT_FACTOYR_NAME);
19 commandMgr.setUrl(tm.getServiceUrl());
        commandMgr.setUrl(tm.getServiceUrl());
20 commandMgr.setTransportManager(tm);
        commandMgr.setTransportManager(tm);
21 tm.setShouldRemoveConnectionOnError(true);
        tm.setShouldRemoveConnectionOnError(true);
22
 if (session instanceof Server)
        if (session instanceof Server)  {
{
23 ((Server) session).setCommandManager(commandMgr);
            ((Server) session).setCommandManager(commandMgr);
24 ((Server) session).setShouldPropagateChanges(true);
            ((Server) session).setShouldPropagateChanges(true);
25 ((Server) session).getCommandManager().initialize();
            ((Server) session).getCommandManager().initialize();
26
 } else if (session instanceof DatabaseSession)
        } else if (session instanceof DatabaseSession)  {
{
27 ((DatabaseSession) session).setCommandManager(commandMgr);
            ((DatabaseSession) session).setCommandManager(commandMgr);
28 ((DatabaseSession) session).setShouldPropagateChanges(true);
            ((DatabaseSession) session).setShouldPropagateChanges(true);
29 ((DatabaseSession) session).getCommandManager().initialize();
            ((DatabaseSession) session).getCommandManager().initialize();
30
 } else
        } else  {
{
31 throw new IllegalArgumentException("Session must be a server or database session");
            throw new IllegalArgumentException("Session must be a server or database session");
32 }
        }
33 return session;
        return session;
34 }
    }
35 }
}
36
 
 
4)        CoherenceCache:自定义一个Coherence NamedCache
 package com.oocl.isdc.sha.frm.tts.cohererence.cache;
package com.oocl.isdc.sha.frm.tts.cohererence.cache;

 import java.net.InetAddress;
import java.net.InetAddress;
 import java.util.Collection;
import java.util.Collection;

 import com.oocl.isdc.sha.frm.tts.config.TTSConfigConstants;
import com.oocl.isdc.sha.frm.tts.config.TTSConfigConstants;
 import com.tangosol.net.CacheFactory;
import com.tangosol.net.CacheFactory;
 import com.tangosol.net.Cluster;
import com.tangosol.net.Cluster;
 import com.tangosol.net.Member;
import com.tangosol.net.Member;
 import com.tangosol.net.NamedCache;
import com.tangosol.net.NamedCache;
 import com.tangosol.net.Service;
import com.tangosol.net.Service;
 import com.tangosol.util.MapListener;
import com.tangosol.util.MapListener;


 public class CoherenceCache
public class CoherenceCache  {
{
 private NamedCache namedCache;
    private NamedCache namedCache;


 public CoherenceCache()
    public CoherenceCache()  {
{
 this.namedCache = CacheFactory.getCache("toplinkSyn");
        this.namedCache = CacheFactory.getCache("toplinkSyn");
 }
    }


 public void putCache(Object key, Object value)
    public void putCache(Object key, Object value)  {
{
 namedCache.put(key, value);
        namedCache.put(key, value);
 }
    }


 public Object retrieveCache(Object key)
    public Object retrieveCache(Object key)  {
{
 return namedCache.get(key);
        return namedCache.get(key);
 }
    }


 public NamedCache getNamedCache()
    public NamedCache getNamedCache()  {
{
 return namedCache;
        return namedCache;
 }
    }
 
    

 public void addMapListener(MapListener listener)
    public void addMapListener(MapListener listener)  {
{
 this.namedCache.addMapListener(listener);
        this.namedCache.addMapListener(listener);
 }
    }
 
    

 public void removeMapListener(MapListener listener)
    public void removeMapListener(MapListener listener)  {
{
 this.namedCache.removeMapListener(listener);
        this.namedCache.removeMapListener(listener);
 }
    }
 
    
 @SuppressWarnings("unchecked")
    @SuppressWarnings("unchecked")

 public Collection retrieveCacheAll()
    public Collection retrieveCacheAll()  {
{
 return  this.namedCache.values();
       return  this.namedCache.values();
 }
    }
 
    

 public String getUrl()
    public String getUrl()  {
{
 Member member = getLocalMember();
        Member member = getLocalMember();
 InetAddress address = member.getAddress();
        InetAddress address = member.getAddress();
 String ipAddress = address.getHostAddress();
        String ipAddress = address.getHostAddress();
 int port = member.getPort();
        int port = member.getPort();
 StringBuffer sb = new StringBuffer(TTSConfigConstants.TOPLINK_SERVICEID_PREFIX)
        StringBuffer sb = new StringBuffer(TTSConfigConstants.TOPLINK_SERVICEID_PREFIX)
 .append(ipAddress).append(":").append(port);
            .append(ipAddress).append(":").append(port);
 return sb.toString();
        return sb.toString();
 }
    }
 
    

 public Member getLocalMember()
    public Member getLocalMember()  {
{
 Service service = namedCache.getCacheService();
        Service service = namedCache.getCacheService();
 Cluster cluster = service.getCluster();
        Cluster cluster = service.getCluster();    
 Member member = cluster.getLocalMember();
        Member member = cluster.getLocalMember();
 return member;
        return member;
 }
    }
 }
}

5)        CoherenceDiscoveryManager继承DiscoveryManager,主要重写了startDiscovery和stopDiscovery方法
 1 package com.oocl.isdc.sha.frm.tts.remotecommand;
package com.oocl.isdc.sha.frm.tts.remotecommand;
 2
 3 import oracle.toplink.exceptions.ValidationException;
import oracle.toplink.exceptions.ValidationException;
 4 import oracle.toplink.remotecommand.DiscoveryManager;
import oracle.toplink.remotecommand.DiscoveryManager;
 5 import oracle.toplink.remotecommand.RemoteCommandManager;
import oracle.toplink.remotecommand.RemoteCommandManager;
 6
 7
 public class CoherenceDiscoveryManager extends DiscoveryManager
public class CoherenceDiscoveryManager extends DiscoveryManager  {
{
 8 
    
 9
 public CoherenceDiscoveryManager(RemoteCommandManager rcm)
    public CoherenceDiscoveryManager(RemoteCommandManager rcm)  {
{
10 super(rcm);
        super(rcm);
11 }
    }
12
13
 public RemoteCommandManager getRemoteCommandManager()
    public RemoteCommandManager getRemoteCommandManager()  {
{
14 return this.rcm;
        return this.rcm;
15 }
    }
16 
    
17
 public boolean isDiscoveryStopped()
    public boolean isDiscoveryStopped()  {
{
18 throw ValidationException.operationNotSupported("isDiscoveryStopped");
        throw ValidationException.operationNotSupported("isDiscoveryStopped");
19 }
    }
20
21
 public void startDiscovery()
    public void startDiscovery()  {
{
22 ((CoherenceTransportManager)rcm.getTransportManager()).createLocalConnection();
        ((CoherenceTransportManager)rcm.getTransportManager()).createLocalConnection();
23 }
    }
24 
    
25
 /** *//**
    /** *//**
26 * We must implement this method, and we keep it blank
     * We must implement this method, and we keep it blank
27 */
     */
28
 public void stopDiscovery()
    public void stopDiscovery()  {
{
29 
      
30 }
    }
31
32
 public void setAnnouncementDelay(int millisecondsToDelay)
    public void setAnnouncementDelay(int millisecondsToDelay)  {
{
33 throw ValidationException.operationNotSupported("setAnnouncementDelay");
        throw ValidationException.operationNotSupported("setAnnouncementDelay");
34 }
    }
35
36
 public int getAnnouncementDelay()
    public int getAnnouncementDelay()  {
{
37 throw ValidationException.operationNotSupported("getAnnouncementDelay");
        throw ValidationException.operationNotSupported("getAnnouncementDelay");
38 }
    }
39
40
 public String getMulticastGroupAddress()
    public String getMulticastGroupAddress()  {
{
41 throw ValidationException.operationNotSupported("getMulticastGroupAddress");
        throw ValidationException.operationNotSupported("getMulticastGroupAddress");
42 }
    }
43
44
 public void setMulticastGroupAddress(String address)
    public void setMulticastGroupAddress(String address)  {
{
45 throw ValidationException.operationNotSupported("setMulticastGroupAddress");
        throw ValidationException.operationNotSupported("setMulticastGroupAddress");
46 }
    }
47
48 
 
49
 public void setMulticastPort(int port)
    public void setMulticastPort(int port)  {
{
50 throw ValidationException.operationNotSupported("setMulticastPort");
        throw ValidationException.operationNotSupported("setMulticastPort");
51 }
    }
52
53
 public int getMulticastPort()
    public int getMulticastPort()  {
{
54 throw ValidationException.operationNotSupported("getMulticastPort");
        throw ValidationException.operationNotSupported("getMulticastPort");
55 }
    }
56 }
}
57
 
 
3           命令行下mvn clean install部署Demo,部署的oc4j instance信息需要在ear下的pom.xml中给出。
    <properties>
       <home.j2ee>D:/oc4j_extended_101310/j2ee/home</home.j2ee>
       <oc4j.host>localhost</oc4j.host>
       <rmi.port>23791</rmi.port>
       <deploy.username>oc4jadmin</deploy.username>
       <deploy.password>welcome</deploy.password>
    </properties>
因为我们需要检测cache同步还需要部署到另外一个oc4j instance上,需要修改build.properties为:
coherence.member.name = tts-server1
coherence.local.address = 146.222.51.20
coherence.local.port = 8088
ear下的pom.xml为:
<properties>
       <home.j2ee>C:/oc4j_extended_101310/j2ee/home</home.j2ee>
       <oc4j.host>localhost</oc4j.host>
       <rmi.port>23792</rmi.port>
       <deploy.username>oc4jadmin</deploy.username>
       <deploy.password>welcome</deploy.password>
    </properties>
4           通过浏览器访问demo,并检测cache实现,我们在一个oc4j instance上修改employee的数据在另外一个oc4j的instance中就会立即呈现这个改变。并可以看到merge employee的相关toplink的log。如果没有cache同步(demo的cache和cache 同步策略都基本采用了toplink的默认配置),因为employee上有乐观锁,当在另外一个oc4j instance或者说服务器上修改employee的数据,就会出现乐观锁异常,会rollback此次修改,如果有cache同步就会拿到最新的数据而不需要直接访问db,最新的数据和db一致,大大减少了乐观锁出现的频率。当然为了辅助更好的使用cache同步我们还需要定义cache invalidation机制。当然还有很多其他的cache策略避免出现脏数据。
Toplink Log:
[TopLink 非常详细]: 2008.05.23 07:50:16.355--ServerSession(7674162)--Thread(Thread[DistributedCache:EventDispatcher,5,Cluster])--Received remote command oracle.toplink.remotecommand.MergeChangeSetCommand from Service[OOCL Toplink Coherence, 26464827, tcmp://146.222.51.20:8089]
[TopLink 非常详细]: 2008.05.23 07:50:16.355--ServerSession(7674162)--Thread(Thread[DistributedCache:EventDispatcher,5,Cluster])--Executing command oracle.toplink.remotecommand.MergeChangeSetCommand from Service[OOCL Toplink Coherence, 26464827, tcmp://146.222.51.20:8089]
[TopLink 较详细]: 2008.05.23 07:50:16.355--ServerSession(7674162)--Thread(Thread[DistributedCache:EventDispatcher,5,Cluster])--Received updates from Remote Server
[TopLink 非常详细]: 2008.05.23 07:50:16.355--ServerSession(7674162)--Thread(Thread[DistributedCache:EventDispatcher,5,Cluster])--Merging com.oocl.isdc.sha.frm.tts.model.Employee: [558] from remote server
页面演示:
 
 
 
上面两个网页截图上的url表明是两个不同的oc4j server。并且他们用了同一个db也是同一个application。在在server1上修改数据:
 
