`
longgangbai
  • 浏览: 7330566 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

【转】How to distribute Spring Beans by using Coherence

阅读更多

转载自:

         http://www.onlinetechvision.com/?p=425         

          This article shows how to distribute Spring beans by using Coherence. In below sample application, a new cluster named OTV has been created and a spring bean has been distributed by using a cache object named user-map. It has been distributed between two members of the cluster.

Used Technologies :

JDK 1.6.0_21
Spring 3.0.5
Maven 3.0.2
Coherence 3.7.0
SolarisOS 5.10

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 : DOWNLOAD COHERENCE PACKAGE

Coherence package is downloaded via http://www.oracle.com/technetwork/middleware/coherence/downloads/index.html

STEP 3 : LIBRARIES

Firstly, Spring dependencies are added to Maven’ s pom.xml.

1
2
3
4
5
6
7
8
9
10
11
<!-- 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 is installed to Local Maven Repository and its description is added to pom.xml as below. Also if maven is not used, coherence.jar file can be added to classpath.

1
2
3
4
5
6
<!-- Coherence library(from local repository) -->
<dependency>
    <groupId>com.tangosol</groupId>
    <artifactId>coherence</artifactId>
    <version>3.7.0</version>
</dependency>

For creating runnable-jar, below plugin can be used.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<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

otv-coherence-cache-config.xml contains caching-schemes(distributed or replicated) and caching-scheme-mapping configuration. Created cache configuration should be added to coherence-cache-config.xml.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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

tangosol-coherence-override.xml contains cluster, member-identity and configurable-cache-factory configuration. Also below configuration xml file show first member of the cluster.

tangosol-coherence-override.xml for first member of the cluster :

<iframe id="aswift_1" style="margin: 0px; padding: 0px; border-width: 0px; vertical-align: baseline; left: 0px; position: absolute; top: 0px;" name="aswift_1" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="728" height="90"></iframe>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?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">
              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 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?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">
              otv-coherence-cache-config.xml</param-value>
         </init-param>
      </init-params>
   </configurable-cache-factory-config>
</coherence>

STEP 6 : CREATE applicationContext.xml

applicationContext.xml is created.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<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"></bean>
        <bean id="CacheService" class="com.otv.srv.CacheService"></bean>
        <bean id="CacheUpdater" class="com.otv.exe.CacheUpdater">
           <property name="user" ref="User" />
       <property name="cacheService" ref="CacheService" />
        </bean>
</beans>

STEP 7 : CREATE SPRING BEAN

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.otv.user;
 
import java.io.Serializable;
 
/**
 * @author onlinetechvision.com
 * @since 15 Oct 2011
 * @version 1.0.0
 *
 */
public class User implements Serializable {
 
    private static final long serialVersionUID = 1L;
    private String name;
    private String surname;
 
    public User(String name, String surname) {
        this.name = name;
        this.surname = surname;
    }
 
    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() {
        StringBuffer strBuff = new StringBuffer();
        strBuff.append("name : ").append(name);
        strBuff.append(", surname : ").append(surname);
        return strBuff.toString();
    }
}

STEP 8 : CREATE ICacheService INTERFACE

A new ICacheService Interface is created for service layer.

1
2
3
4
5
6
7
8
9
10
11
package com.otv.srv;
 
import com.tangosol.net.NamedCache;
 
public interface ICacheService {
 
    public NamedCache getCache();
    public void addToCache(Object key, Object value);
    public void deleteFromCache(Object key);
 
}

STEP 9 : CREATE CacheService

CacheService is created for service layer by implementing ICacheService.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package com.otv.srv;
 
import org.apache.log4j.Logger;
 
import com.otv.listener.UserMapListener;
import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;
 
/**
 * @author onlinetechvision.com
 * @since 15 Oct 2011
 * @version 1.0.0
 *
 */
public class CacheService implements ICacheService {
 
    private static Logger log = Logger.getLogger(CacheService.class);
    private NamedCache cache = null;
    private static final String USER_MAP = "user-map";
    private static final long LOCK_TIMEOUT = -1;
 
    public CacheService() {
        cache = CacheFactory.getCache(USER_MAP);
        cache.addMapListener(new UserMapListener());
    }  
 
    public NamedCache getCache() {
        return cache;
    }
 
    public void setCache(NamedCache cache) {
        this.cache = cache;
    }
 
    public void addToCache(Object key, Object value) {
        // key is locked
        cache.lock(key, LOCK_TIMEOUT);
        try {
            // application logic
            cache.put(key, value);
        } finally {
            // key is unlocked
            cache.unlock(key);
        }
    }
 
    public void deleteFromCache(Object key) {
        // key is locked
        cache.lock(key, LOCK_TIMEOUT);
        try {
            // application logic
            cache.remove(key);
        } finally {
            // key is unlocked
            cache.unlock(key);
        }
    }
}

STEP 10 : CREATE USERMAPLISTENER IMPL CLASS

A new UserMapListener class is created. This listener receives distributed user-map events.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.otv.listener;
 
import org.apache.log4j.Logger;
 
import com.tangosol.util.MapEvent;
import com.tangosol.util.MapListener;
 
/**
 * @author onlinetechvision.com
 * @since 15 Oct 2011
 * @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 11 : CREATE CacheUpdater

CacheUpdater Class is created to add new entry to cache and monitor cache content.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package com.otv.exe;
 
import java.util.Collection;
 
import org.apache.log4j.Logger;
 
import com.otv.srv.ICacheService;
import com.otv.user.User;
 
/**
 * @author onlinetechvision.com
 * @since 15 Oct 2011
 * @version 1.0.0
 *
 */
public class CacheUpdater implements Runnable {
 
    private static Logger log = Logger.getLogger(CacheUpdater.class);
    ICacheService cacheService;
    User user;
 
    public User getUser() {
        return user;
    }
 
    public void setUser(User user) {
        this.user = user;
    }
 
    public ICacheService getCacheService() {
        return cacheService;
    }
 
    public void setCacheService(ICacheService cacheService) {
        this.cacheService = cacheService;
    }
 
    public void run() {    
 
        //New User are created...
        //Entries which will be inserted via first member of the cluster so before the project is built
        // in order to deploy first member of the cluster, this code block should be opened...
        getUser().setName("Bruce");
        getUser().setSurname("Willis");
 
        //Entries are added to cache...
        getCacheService().addToCache("user1", getUser());
 
//      //New User are created...
//      //Entries which will be inserted via second member of the cluster so before the project is built
//      // in order to deploy second member of the cluster, this code block should be opened...
//      getUser().setName("Clint");
//      getUser().setSurname("Eastwood");
//
//      //Entries are added to cache...
//      getCacheService().addToCache("user2", getUser());
 
        //Cache Entries are printed...
        printCacheEntries();
    }
 
    private void printCacheEntries() {
        Collection<User> userCollection = null;
        try {
            while(true) {
                userCollection = (Collection<User>)getCacheService().getCache().values();
                for(User user : userCollection) {
                    log.debug("Cache Content : "+user);
                }
                Thread.sleep(10000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

STEP 12 : CREATE Application

Application Class is created to run the application.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.otv.exe;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
/**
 * @author onlinetechvision.com
 * @since 15 Oct 2011
 * @version 1.0.0
 *
 */
public class Application {
 
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
 
        CacheUpdater cacheUpdater = (CacheUpdater) context.getBean("CacheUpdater");
        cacheUpdater.run();
    }
}

STEP 13 : BUILD PROJECT

After OTV_Spring_Coherence Project is build, OTV_Spring_Coherence-0.0.1-SNAPSHOT.jar will be created.
Important Note : Members of the cluster have got different configurations for Coherence so the project should be built separately for each member.

STEP 14 : RUN PROJECT ON FIRST 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:

1
2
3
4
5
6
7
8
9
10
--A new cluster is created and First Member joins the cluster and adds a new entry to the cache.
15.10.2011 00:52:48 DEBUG (UserMapListener.java:23) - Inserted Key = user1, Value = name : Bruce, surname : Willis
15.10.2011 00:52:48 DEBUG (CacheUpdater.java:51) - Cache Content : name : Bruce, surname : Willis
.......
--Second Member joins the cluster and adds a new entry to the cache.
15.10.2011 00:53:13 DEBUG (UserMapListener.java:23) - Inserted Key = user2, Value = name : Clint, surname : Eastwood
.......
--After second member adds a new entry, cache content is shown as below :
15.10.2011 00:53:19 DEBUG (CacheUpdater.java:51) - Cache Content : name : Clint, surname : Eastwood
15.10.2011 00:53:19 DEBUG (CacheUpdater.java:51) - Cache Content : name : Bruce, surname : Willis

Second member’ s console :

1
2
3
4
--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 :.
15.10.2011 00:53:13 DEBUG (UserMapListener.java:23) - Inserted Key = user2, Value = name : Clint, surname : Eastwood
15.10.2011 00:53:14 DEBUG (CacheUpdater.java:51) - Cache Content : name : Bruce, surname : Willis
15.10.2011 00:53:15 DEBUG (CacheUpdater.java:51) - Cache Content : name : Clint, surname : Eastwood

STEP 15 : DOWNLOAD

OTV_Spring_Coherence

分享到:
评论

相关推荐

    Xcode Treasures: Master the Tools to Design, Build, and Distribute Great Apps

    Explore the common problems developers face when using Xcode, and find out how to get the most out of your IDE. Dig into Xcode, and you’ll discover it’s richer and more powerful than you might have...

    Android TV Apps Development(Apress,2016)

    This one-of-a-kind short ...How to distribute Android TV apps Audience:Developers with some experience with Android development who are interested in building applications for the Android TV platform.

    distribute

    【标题】:“distribute”是Python的一个包管理工具,它在早期被广泛使用,用于替代setuptools。在Python的生态系统中,包管理是至关重要的,因为它使得开发者能够方便地安装、发布和管理软件包。 【描述】:...

    Packt.Hands-On.GUI.Application.Development.in.Go.1789138418.epub

    In the concluding chapters, you'll discover how to distribute to the main desktop marketplaces and distribution channels. By the end of this book, you'll be a confident GUI developer who can use the...

    Android TV Apps Development

    Series: Protocollen Voor De...How to distribute Android TV apps Audience:Developers with some experience with Android development who are interested in building applications for the Android TV platform.

    Learning TensorFlow: A Guide to Building Deep Learning Systems

    Learning TensorFlow: A Guide to Building Deep Learning Systems ...Learn how to scale TensorFlow, and use clusters to distribute model training Deploy TensorFlow in a production setting

    distribute_setup.zip

    在这个场景下,我们需要先对`distribute_setup.zip`进行解压缩操作,然后将解压出来的`distribute_setup.py`文件移动到Python的Lib目录下。下面我们将详细探讨这个过程以及相关的Python环境配置和库安装知识。 首先...

    Learning TensorFlow A Guide to Building Deep Learning Systems带详细书签

    •Learn how to scale TensorFlow, and use clusters to distribute model training •Deploy TensorFlow in a production setting Table of Contents Chapter 1 Introduction Chapter 2 Go with the Flow: Up and...

    Redis-Essentials.pdf

    Uniqueness support is added to the String and Hash implementations by using the Sorted Set and HyperLogLog data types, respectively. Preface [ viii ] Chapter 4, Commands (Where the Wild Things Are), ...

    FireEye Uncovers CVE-2017-8759: Zero-Day Used in the Wild to Distribute FINSPY

    微软的补丁和安全指导可以在官方链接(fireeye.com/blog/threat-research/2017/09/zero-day-used-to-distribute-finspy.html)中找到。火眼的电子邮件、端点和网络产品能够检测到这些恶意文档。 **针对俄语使用者的...

    Hacker's Guide to Scaling Python

    Python is an excellent programming language ... Adding a few interview of experts on the subject, you will learn how you can distribute your Python application so it can process thousands of requests.

Global site tag (gtag.js) - Google Analytics