Skip to main content

JBoss DataGrid - Client 連接到 Hot Rod Server 存取 Data Grid Cache(快取)

明明說要花點時間寫寫最新的BPM 還有 Switchyard的,可是天不從人願,
老實說,對於Data Grid 小姐本來是是興趣缺缺... 因為我還是喜歡玩系統邏輯跟整合,不過花了時間進去看了一下後,程式魂燃燒,發現其實還滿好玩的. (囧TZ.. 怎麼這麼容易滿足啊...)

(對了,這個demo是需要安裝Maven,請先自己裝好囉~)

好吧,切入正題,為了不讓事情複雜化,JBoss Data Grid 是啥,等我有空再寫一篇,這篇主要做的事情,是要單獨啓動一個Data Grid Server,

1. 啓動JBoss Data Grid Server 兩台,裡面建立一個叫做Book 的 Cache, 把兩台的設定成Cluster。
2. 寫一個Client 去這兩台Server, 透過Hot Rod 存取物件。

如下圖:




要啓動Data Grid 的Server 有兩種方式,

A. 下載Data Grid Server
B. 另外一種就是自己Data Grid需要的JAR檔放到project裡面透過infinispan.xml 的設定啓動。


這次介紹就是Data Grid Server 的設定方式。
==================================================

1, 到Red Hat 網站下載JBoss Data Grid Server (沒有帳號的請自己註冊一個,可以免費試用下載90天喔~)



2. 解壓縮 jboss-datagrid-xx-server.zip 到電腦中的某個目錄下,取名叫datagrid1, 這時你會看到以下的目錄結構。



3. 回到前一層目錄中,進入Standalone 下的configuration 目錄,/xx/datagrid1/standalone/configuration,打開cluster.xml
到裡面,找到 infinispan:server 的subsystem. (這裡就是設定這台Server node 要哪些Cache 的地方。)

<subsystem xmlns="urn:infinispan:server:core:5.3" default-cache-container="clustered">
  .....
</subsystem>

這次先用內建已經有的cache-container,因此,請在

<cache-container name="clustered" default-cache="default">
  .....
</cache-container>

之中,加上:

<distributed-cache name="Book" owners="2" start="EAGER" mode="SYNC">
     <!-- Disable transactions for this cache -->
     <transaction mode="NONE" />
</distributed-cache>

以上我們叫做Book 的Cache 已經設定好了。

4. 然後,我們還要再設定另外一台Data Grid, 也就是datagrid2, 請把剛剛的datagrid1 目錄,複製成 datagrid2,因為我們要把兩個server 啓動在同一個IP 之下,為了避免port 衝突,請到 /xx/datagrid2/standalone/configuration ,打開cluster.xml 修改,把所有的port 都增加100.

<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:100}">
</socket-binding-group>

5. 然後就可以啓動了。 分別到 datagrid1 與 datagrid2 下透過 bin/下的cluster.sh (windows 就是 cluster.bat)

datagrid1
ChristinatekiMacBook-Air:bin christina$ ./clustered.sh -Djboss.node.name=node1



datagrid2
ChristinatekiMacBook-Air:bin christina$ ./clustered.sh -Djboss.node.name=node2



可以看到datagrid1 裡面,出現新的cluster view, 就表示完成了.

6. 好拉~Server 設定完成了! 現在來看一下Client, 因為這次的Client 端程式,是透過Hot Rod 的通訊協定呼叫的,所以我們要建立的是RemoteCacheManager 而不是一般的CacheManager.

在寫Client 程式之前,先去到Red Hat 網站下載把maven 的程式庫下載下來,
 
下載之後,請將檔案解壓縮到你的電腦的某處,

7. 一樣到JBoss 的開發工具,JBoss Developer Studio 下,新增一個Maven 的專案。

8. 點選 Create a simple project 

    請輸入你的Group,Artifact ID,Version 還有Name... 

     Group ID: org.christina.blogdemo
   Artifact ID: remoteJDG
   Packaging: JAR 
   Name: RemoteJDG


   這時左邊就會出現,如下的Project


9. 開始設定POM, 我們要先把檔案指到我們剛剛安裝好的Maven程式庫,並且把需要用到的程式庫設定上去。以下是我的pom.xml


  4.0.0
  org.christina.blogdemo
  remoteJDG
  0.0.1-SNAPSHOT
  RemoteJDG

  
   
    org.infinispan
    infinispan-core
    6.0.0.CR1-redhat-4
   
   
    org.infinispan
    infinispan-client-hotrod
    6.0.0.CR1-redhat-4
   
  
  
  
        
            JBoss-Data-Grid
            file:///Applications/jbossrepo/jboss-datagrid-6.2.0-maven-repository
        
  


裡面只有一個要注意的地方,就是程式庫的位置,請修改到你剛剛解壓縮下載回來Data Grid 程式庫的位置。

<repositories>
  <repository>
    <id>JBoss-Data-Grid</id>
    <url>file:///Applications/jbossrepo/jboss-datagrid-6.2.0-maven-repository</url>
  </repository>
</repositories>

10. 請更新你的Maven Project.
                              

11. 然後就開始寫程式拉,以下放在兩個Package 之下,請將3個不同的Java 檔案放進去。
org.christina.blogdem.model.Author
package org.christina.blogdem.model;

import java.io.Serializable;

public class Author implements Serializable {

 private static final long serialVersionUID = 8505465476089630568L;
 
 String name;
 Integer age;
 String gender;
 
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public Integer getAge() {
  return age;
 }
 public void setAge(Integer age) {
  this.age = age;
 }
 public String getGender() {
  return gender;
 }
 public void setGender(String gender) {
  this.gender = gender;
 }
 
 @Override
 public String toString(){
  return "\n "+name+"=> age:["+age+"] gender:["+gender+"]";
 }

}

org.christina.blogdem.model.Book
package org.christina.blogdem.model;

import java.io.Serializable;
import java.util.HashMap;

public class Book implements Serializable {

 private static final long serialVersionUID = 8035994059258919284L;
 
 String name;
 String isbn;
 Integer year;
 String category;
 HashMap author;
 
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getIsbn() {
  return isbn;
 }
 public void setIsbn(String isbn) {
  this.isbn = isbn;
 }
 public Integer getYear() {
  return year;
 }
 public void setYear(Integer year) {
  this.year = year;
 }
 public String getCategory() {
  return category;
 }
 public void setCategory(String category) {
  this.category = category;
 }
 public HashMap getAuthor() {
  return author;
 }
 public void setAuthor(HashMap author) {
  this.author = author;
 }
 
 @Override
 public String toString(){
  String tempString = "Book Name:["+name+"] ISBN:["+isbn+"] Year:["+year+"] Category:["+category+"] \n Authors:[";
  for(String key : this.getAuthor().keySet()){
   tempString +=this.getAuthor().get(key);
  }
  tempString +="]";
  return tempString;
 }

}


org.christina.blogdemo.client.Librarian
package org.christina.blogdemo.client;

import java.io.Console;
import java.util.HashMap;

import org.christina.blogdem.model.Author;
import org.christina.blogdem.model.Book;
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;


public class Librarian {
 
 private static final String initPrompt = "Choose action:\n" + "============= \n" +"addBook  -  Add Book\n"+"rmBook  -  Remove Book\n"+ "findBook   -  Find Book\n"+ "q   -  quit\n";
 private static final String msgEnterBookName = "Enter name for book(to stop adding, type \"q\"): ";
 private static final String msgEnterBookISBN = "Enter ISBN for book(to stop adding, type \"q\"): ";
 private static final String msgEnterBookYear = "Enter publisg year for book (to stop adding, type \"q\" -- Integer Only): ";
 private static final String msgEnterBookCategory = "Enter category for book(to stop adding, type \"q\"): ";
 
 private static final String msgAlreadyHasBook = "You already have this book, type \"q\" to quit, type \"aa\" to add author, or just remove the book: ";
 
 
 private static final String msgEnterAuthorName = "Enter name for Author(to stop adding, type \"q\"): ";
 private static final String msgEnterAuthorAge = "Enter age for Author(to stop adding, type \"q\" -- Integer Only): ";
 private static final String msgEnterAuthorGender = "Enter gender for Author(to stop adding, type \"q\"): ";
 
 private static final String msgAlreadyHasAuthor = "You already have this author, type \"q\" to quit : ";
 
 private static final String msgEnterFindBook = "Enter Name of Book(to stop adding, type \"q\"): ";
 
 private static final String msgEnterRMBook = "WARNING, removing book!! Enter Name of Book(to stop adding, type \"q\"): ";
 private Console con;
    private RemoteCacheManager cacheManager;
    private RemoteCache library;
    
    public Librarian(Console con){
     this.con = con;
     ConfigurationBuilder builder = new ConfigurationBuilder();
     builder.addServer().host("localhost").port(11222).addServer().host("localhost").port(11322);
     
     this.cacheManager = new RemoteCacheManager(builder.build());
     library = cacheManager.getCache("Book");
    }
    
    
    public void addBook(){

     Book book;
     
     String bookName = con.readLine(msgEnterBookName);
     book = library.get(bookName);
     if(book != null){
      String action = con.readLine(msgAlreadyHasBook);
      
      if ("q".equals(action)) {
             return;
            } else if ("aa".equals(action)) {
             //DO Nothing
            }else{
             return;
            }
      
     }else{
      book = new Book();
         book.setName(bookName);
      
         String bookISBN = con.readLine(msgEnterBookISBN);
         book.setIsbn(bookISBN);
         String bookYear = con.readLine(msgEnterBookYear);
         book.setYear(Integer.valueOf(bookYear));
         String bookCategory = con.readLine(msgEnterBookCategory);
         book.setCategory(bookCategory);
     }
     
     HashMap authors =book.getAuthor();
     
     if(authors == null){
      authors = new HashMap();
     }

     authors = (HashMap) this.addAuthor(authors);
     book.setAuthor(authors);
     System.out.println("Book Added ===>"+book);
     library.put(book.getName(),book);
    }
    
    private HashMap addAuthor(HashMap authors){
     
     Author author;

     String authorName = con.readLine(msgEnterAuthorName);
     
     if(authors.get(authorName)!= null){
      String action = con.readLine(msgAlreadyHasAuthor);
      if ("q".equals(action)) {
             return authors;
            } 
     }else{
      author = new Author();
      author.setName(authorName);
      
      String authorAge = con.readLine(msgEnterAuthorAge);
      author.setAge(Integer.valueOf(authorAge));
      String authorGender = con.readLine(msgEnterAuthorGender);
      author.setGender(authorGender);
      authors.put(author.getName(), author);
     }
     
     
     return authors;
    }
    
    public void findBook(){
     System.out.println(library.get(con.readLine(msgEnterFindBook)));
    }
    
    public void removeBook(){
     library.remove(library.remove(con.readLine(msgEnterRMBook)));
    }

    
    public void close(){
     cacheManager.stop();
    }
    public static void main(String[] args) {
     try{
         Console con = System.console();
         con.printf(initPrompt);
         Librarian librarian = new Librarian(con);
 
         while (true) {
             String action = con.readLine(">");
             if ("addBook".equals(action)) {
              librarian.addBook();
             } else if ("rmBook".equals(action)) {
              librarian.removeBook();
             } else if ("findBook".equals(action)) {
              librarian.findBook();
             } else if ("q".equals(action)) {
              librarian.close();
                 break;
             }
         }
     }catch(Exception e){
      e.printStackTrace();
     }
    }
}

這個程式非常簡單,有兩個物件,一個叫做Book(書), 一個叫做 Author (作者)。這兩個物件就是會被放到Cache 裡面的東西拉。

還有一個主檔物件叫做 Librarian (圖書館管理員),它就是我們Hot Rod 的 Client.
他身上就負責,掛了一個叫做 RemoteCacheManager,透過這個 RemoteCacheManager,去跟Server 溝通,連接到我們在Server 上叫做Book 的 Cache,並將之命名為library.

然後就可以透過Librarian (圖書館管理員)身上的方法,開始新增,查詢或刪除書籍啦。



 
12. 可以開始執行程式了,請先確認兩個Data Grid 的Server 還在執行。然後到pom.xml 相同的路徑下執行 :

 mvn exec:java -Dexec.mainClass="org.christina.blogdemo.client.Librarian"

13. 就可以開始加把書放到Cache 裡面,並且取出來修改囉!

ChristinatekiMacBook-Air:remoteJDG christina$ mvn exec:java -Dexec.mainClass="org.christina.blogdemo.client.Librarian"
[INFO] Scanning for projects...
objc[6284]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/bin/java and /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building RemoteJDG 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] >>> exec-maven-plugin:1.2.1:java (default-cli) @ remoteJDG >>>
[INFO] 
[INFO] <<< exec-maven-plugin:1.2.1:java (default-cli) @ remoteJDG <<<
[INFO] 
[INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ remoteJDG ---
Choose action:
============= 
addBook  -  Add Book
rmBook  -  Remove Book
findBook   -  Find Book
q   -  quit
log4j:WARN No appenders could be found for logger (org.jboss.logging).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
>addBook
Enter name for book(to stop adding, type "q"): JDG
Enter ISBN for book(to stop adding, type "q"): A123456789
Enter publisg year for book (to stop adding, type "q" -- Integer Only): 2013
Enter category for book(to stop adding, type "q"): JBoss
Enter name for Author(to stop adding, type "q"): Christina Lin
Enter age for Author(to stop adding, type "q" -- Integer Only): 25
Enter gender for Author(to stop adding, type "q"): F
Book Added ===>Book Name:[JDG] ISBN:[A123456789] Year:[2013] Category:[JBoss] 
 Authors:[
 Christina Lin=> age:[25] gender:[F]]
>findBook
Enter Name of Book(to stop adding, type "q"): JDG
Book Name:[JDG] ISBN:[A123456789] Year:[2013] Category:[JBoss] 
 Authors:[
 Christina Lin=> age:[25] gender:[F]]
>rmBook
WARNING, removing book!! Enter Name of Book(to stop adding, type "q"): JDG
>findBook
Enter Name of Book(to stop adding, type "q"): JDG
null


以上。




Comments

Popular posts from this blog

Fuse Integration Service - Setup JBDS and create first quickstart application

Before we go and start creating our first application, I want to show you how to setup your JBoss Developer Studio, create a small application from the quickstart example and then running it on Fuse Integration Service.

I am using JBoss Developer Studio version 9, you can find it here.
After download the

jboss-devstudio-9.0.0.GA-installer-eap.jar
double-click it, and start installing with default values.

After successful installation, we will need install the plugins for Fuse, on JBoss Central view, select software update, select enable early access.


And select JBoss Fuse Development for the plugin,


Click on install, and we are all set to go!

First thing first, we want to create a Fuse project to deploy on the base of Fuse Integration Service, which is OpenShift. If you have not installed it, please go back to my previous post for instructions. So on your JBDS, right click and start creating the project. Select new, maven project, if you have installed the plugin correctly, you should …

Red Hat JBoss Fuse/A-MQ - Fuse and A-MQ Version 6.3 GA is released!

Fuse and A-MQ 6.3 GA has just went out. Maybe, you would think this is just only a minor version release why should I care? Hold your thoughts on that! Because they have done a lot of improvements and also added many new features into this release.

Besides various bug fixes and making sure Fuse Fabric is much more stable. There are two major change in this version update:

New Tooling in JBoss Developer Studio (JBDS) 9.1 GA. Newer Apache Camel version – Camel v2.17. I was really impressed by the work put in to make developing Camel application much simpler. First is the installation of tooling itself. Now it has a all-in-one installer so you don't need to worry about which plugins you need to check. See the videos below to see the new "Getting Started" of Fuse 6.3.



And If you notice from the above video, the presentation of camel route in JBDS has also updated. It fixed some of the miss representation of logic and making it easier to read.

Old Camel Route
New Camel Route
On …

RHTE - Supercharge your integration services

Red Hat Tech Exchange has taken place in Vietnam, Ho Chi Minh city two weeks ago, it is a great event held by Red Hat in Asia Pacific Region. It is open to all Red Hat partners who are interested in learning what Red Hat is doing recently, see what the trend of the open source world, basically it is a great event to share your knowledge and experience, to meet other enthusiastic people.

I am very fortunate to talk in this great event, to talk about the things I have been working on and even discuss it with many. Also got lots of great ideas too. So here are the slide.

My first talk was with Thomas Qvarnström about how to handle large size data in JBoss Fuse and how JBoss Data Grid can help in the situation.

Here is the agenda of the talk, we will be talk about this in the up coming webinar on 24th Sept.

Integration often involves storing, retrieving, and transforming data. Using a traditional database in your integration is likely to becomes a bottleneck that is expensive and hard to …