顯示具有 jboss 標籤的文章。 顯示所有文章
顯示具有 jboss 標籤的文章。 顯示所有文章

2012-07-03

[jboss] birt viewer on jboss as 7.1.1

最近需要在 JBoss AS 上面安裝 birt viewer.
安裝步驟
1. 從官方網站上下載 runtime package.
2. 解開以後將 WebExample 那個目錄放到 standalone/deploments/ , 並且改名為 birt.war.
3. 新增一個檔案 birt.war.deployed.
4. 編輯 birt.war.deployed, 檔案內容存放 birt.war
5. start jboss standalone

原本有一個設定 standlone.xml 方法, 但是那樣會造成 jboss 不斷的deploy birt.war

2012-06-22

[jboss] SwitchYard 學習之路 - SwitchYard 0.4 on JBoss 7.1.1.FInal

在 Eclipse 開發環境中, 直接讓 switchyard deployment jar 直接可以放到自己的 開發環境. 所以, 試著將 switchyard 0.4 安裝在  Jboss 7.1.1.Final 上面.

準備檔案
1. JBoss 7.1.1.Final ZIP
2. SwitchYard Installer 0.4

安裝

1. 解開 JBoss 7,1,1,Final to ${JBoss_Path}
2. 解開 SwitchYard Installer 0.4 to ${SwitchYard_Installer_Path}
3. 打開  console command , 移轉到 ${SwitchYard_Installer_Path}
4. 在 ${SwitchYard_Installer_Path} 下, ant
5. 當問到  jboss ap path , 輸入 ${JBoss_Path}
6. 因為沒有使用到 forge , 所以當問道 forge 時選擇 N

2012-06-20

[jboss] SwitchYard 學習之路 - Eclipse BPMN 顯示 SwitchYard Icon

SwitchYard 宣稱作為 Jboss SOA 的下一代 ESB 平台. 現階段 Jboss ESB 為目前 Jboss SOA 中的ESB.

 SwitchYard 整合目前 jboss jbpm 5.0 也就是 最新版. 讓你得ESB 可以整合 jbpm 還做使用.
所以開發jbpm 5.0 可以用bpmn 作為基底, 並且可以整合進去 jboss drools 中.

在SwitchYard 0.4 中, 有Demo 一個透過 jbpm 呼叫SwitchYard Service 得icon . 但在官方文件中, 並沒有想細說明如何讓 jbpm designer 出現 SwitchYard Icon . 在經過反覆, 研究Demo Source Code 後, 發現必須在含有jbpm process 的那個專案中, 需要加入 switchyard-compoment-bpm.jar 等相關, 才可以在 jbpm designer 中出現 SwitchYard Service Icon.

如果使用 Eclipse Jboss Tools 中, 開啟SwitchYard Project. 其中選擇 Component 時, 把BPM 選進去, 這樣在新增 jbpm process時, 就可以出現 SwitchYard Service Icon.

2011-12-08

[Jboss] ESB SQL Provider

公司的異質系統傳輸資料幾乎都是採用 DB 交換. EDI 與 ERP 之間的資料交換, 除了文件內容的Table 外. 另外多建立了一個  Document_Change Table , 裡頭存有 Document Type, Document Name 等等. 每一個系統各自去建立相關的 Schedule , 去檢查該Table 是否有自己需要的 Document. 這樣的整合也沒有說不好, 再沒有整合工具的前提下, 是一個可以接受的方案.

Jboss ESB 有提供 SQL-Provider 的工具.  應該是JBoss ESB 在遇到很多公司都有同樣的需求時, 所發展出來的 Provider.  可以讓 SOA 採用漸進的方式替換掉原有系統整合.

SQL-Provider 有其使用前提, JBoss ESB 並沒有清楚的解釋. 只能從 相關的sample code 去看出一些端倪.  下面就先介紹 前置作業.

1. Table Column 需要的欄位
  • message-id-column :  也就是 Table primary Key , 不能是 combo Key
  • message-column : ESB 只會抓取單一欄位的內容
  • status-column :   ESB 會填入相關的 Status.
    org.jboss.soa.esb.listeners.gateway.SqlTableGatewayListener 針對欄位所做的解釋
    A field that will be used to mark a row as 'P' (pending), 'W' (in process), 'D' (done) or 'E' (error). When adding a pending row, make sure that the status_col value if an upper-cased 'P', as upper-cased characters are used as a convention.

    所以簡單的說, 如果要 ESB 把該資料抓去處理, 一定要放 'P'. ESB 處理中 會被改成'W', 最後的解過就是 'D' or 'E'.

  • insert-timestamp-column : ESB 會填入最後的時間
2. SQL-Provider 設定
  • 下面是 ESB sample code
    <sql-provider name="SQLprovider" url="jdbc:hsqldb:hsql://localhost:1704" driver="org.hsqldb.jdbcDriver" username="sa" password=""> <sql-bus busid="helloSQLChannel" > <sql-message-filter tablename="GATEWAY_TABLE" status-column="STATUS_COL" order-by="DATA_COLUMN" where-condition="DATA_COLUMN like 'data%'" message-column="message" message-id-column="UNIQUE_ID" insert-timestamp-column="TIMESTAMP_COL" /> </sql-bus> </sql-provider>
  • 這是我自己改用Datasource 的方式

2011-09-21

[Jboss] Jboss AS 6 Final upgrade from 6.0.0 to 6.1.0

最近發現 jboss as 6 已經release 6.1.0.
看了一下 release note , 有講到 JMS Queue redeliver 的問題. 這個問題, 我之前升級到 6.0.0 final 後 , 就發現有一些問題.  目前工作環境中, 有些工作事先丟到 Queue 裡面, 在利用 MDB 來作 接收工作的入口. 但有時網路或是DB 並不是很穩定, 所以 Task 需要retry . 就利用  Queue redeliver 的功能來作 task rework.
但是在 6.0.0 M6 這樣的模式是很正常的, 但是在 6.0.0. final 中, queue redeliver 有時會有問題, 會讓message 一直停留在Queue 中, 不會自動redeliver . 自己還特地寫了一個測試的mdb 去作 redeliver testing. 但是, 測試結果就是時靈時不靈, 看不出一個結果.

升級到 6.1.0 final 以後, 這個bug 有解掉, 就不用一直需要去monitor queue 有沒有task 了.
如果要升級到 6.1.0, 不能直接使用已經在 6.0.0 產生的檔案. 因為會在6.1.0 中啟動失敗, 所以要把所有的設定值, 搬到新的環境重新產生.

2011-07-29

[Jboss] Jboss AS 6 Final use Log4j

之前寫過一篇, 怎樣在 Jboss 下面使用 Log4j. 不過到了 Jboss as 6 final 就沒辦法使用了. 其實之前在M4 就有發現已經不太能用了.
今天花了一些時間, 在做一次測試. 結果發現, 每一個 ear 裡面請不要在放 log4j.jar 了.在 ${JBOSS_Home}/common/lib 下面已經有一個 log4j.jar. 如果你在自己的路徑裡頭在放一個 log4j.jar, 就沒辦法共用 jboss-logger.xml 的參數了

2011-07-14

[Java] 設定 JVM 起始的 Timezone

原因
在目前的工作裡頭, 需要協助管理美國分公司的Server. 但是, 要管理又只能偷偷進去美國Server偷偷作. 所以這一次需要換掉 Jboss Server, 我打算將美國的Server 轉回台灣Server. 因為這件事情只能偷偷作, 所以得在台灣模擬美國的環境. 就碰到 時區問題, 因為美國那邊堅持在塞資料進他們家的Database 要用他們的 時區. 所以當 Jboss Server 跑在台灣Server 時間就會是台灣的時間. 所以必須想辦法, 變動 台灣Server 的時區.
解法
只好從JVM 啟動時入手. 查過資料, java -Duser.timezone 就可以設定 啟動時的時區.
所以在 Jboss 中, 啟動時 多加入 -Duser.timezone 就可以. 要特別注, 網路上有說法要用 -Duser.timezoe='xxx'. 這樣會無法使用, 得使用-Duser.timezone=xxx 就可以.
下面的設定會有日光節約時間

-Duser.timezone=America/Los_Angeles

這樣就沒有節約時間

-Duser.timezone=GMT-0800

2011-07-06

[Jboss] Server 執行檔 與 Server Deploy 分開

在一般的Jboss AP Server 安裝路徑下, 會有 bin, client, common, docs, lib, server. server 這個目錄下放的就是可以啟動的 Server Configurations. 所以當你需要升級你的 jboss server 時, 每裝新版就需要把 目錄下的設搬移到新版 jboss/server 下.
為了省去麻煩, 網路上找了一下 jboss 啟動參數設定, 可以指定到其他目錄去啟動. 不一定得掛在 jboss 目錄下. 再起啟動下 -Djboss.server.base.dir=d:/xxxx/server -Djboss.server.base.url=file:/d:/xxxx/server, 就可以將server configuration 不用掛在${JbossHome} 下面.

好處有
  1. 當jboss ap 有新版時, 可以共用同一個設定參數, 不需要每一個版本下面都放完整的設定
  2. 在測試機器上面, 每一個開發人員可以有自己的 server configuration , 但是可以共用相同的 jboss server bin. 不需要每一個人都安裝 jboss server.
  3. 可以將 JBoss installation 放在網路硬碟上面, 讓所有機器共用

Reference
1. Shared JBoss Installation Directory
2. JBossProperties

2011-06-27

[Jboss] 多個Server 共用同一個 IP 設定

目標
在同一台機器下同一個IP , 可以起不同的 Jboss AS Instance.
原因
在開發系統時, 需要超過2個Jboss AS 來作資料的傳送. 模擬當兩台不同的AS 可以護傳資料. 但是開發測試環境只能有個 IP .
作法
1. 啟動時, 改用 run.bat -c default -Djboss.service.binding.set=ports-xx
2. 其中 ports-xx , xx 可使用01 , 02 , 03 , 04
3. 如果想要修改增加或修改 ports 的參數 到 server/default/conf/bindingservice.beans/META-INF/bindings-jboss-beans.xml 即可. (default 跟你要啟動的目錄有關)
參考
1. Configuring Multiple JBoss Instances On One Machine
2. Setting up multiple instances of JBoss on the same machine
3. JBoss: run 2 instances in the same environment avoiding port conflicts

2011-04-08

共用EJB - Remote JNDI 篇

先前寫了 Remote篇, 就開始把 EJB 都作成 EJB3 Module 方式去 deploy 在 Jboss Server上面. 經過一段時間的驗正, 都還蠻順利的. 不過, 還是出問題了.
先前把一堆共用的 java class 放在同一個 jar 中, 讓其他 EJB 共用這一個 jar.  就出現一個怪問題了,  EJB_A 包涵 jar , EJB_B 也包涵 jar. 先將 EJB_A deploy上去成功, 在 將 EJB_B deploy 時就會出現 duplicat class 的Exception. 反過來, EJB_B 先放, 在放 EJB_A 就不會出現問題. 但是系統是會越來越大的, 不會只有兩個 EJB . 所以, 問題是要解決的.
所以想到的方式是, 是不是 可以透過 ear 包裝方式, 解決這一個問題.  但是, 之前用ear deploy 在 JNDI Tree 中, 都會出現 ear project name . 這樣還是沒辦法解決最原始的問題 , 就是要透過 JNDI Name  找出相關的 service 來用壓.
就在看著 source code時,  噹噹靈感來了. 在原來的code 中.
@Stateless(name = "edi/service/Workflow")
就想說試試看 多一定義 會不會有不一樣. 把 code 改成
@Stateless(name = "edi/service/Workflow", mappedName="/edi/service/Workflow"

實驗出爐....
這樣改比原來的還要好, 在 JNDI Tree 中 直接出現 edi/service/Workflow . 不用像之前的版本一樣在多加一個 remote. 所以這樣的方法會比較好, 可以避免多重問題.

2011-02-10

ORA-24777 發生在 Jee Server

最近用 jpa 搭配 Oracle Database Link Query .用 JPA 搭配 RESOURCE_LOCAL可以執行.
但是, 當程式換成 Session Bean 時會出現. 

ORA-24777:  use of non-migratable database link not allowed.



第一次遇到, google一下....找到解答的網頁 . 

ORA-24777 When Using XA Driver

解答篇中 提出三種解決問題的方法
1. 設定 Oracle Database 支援 multi-threaded server. (這個工程浩大, 網頁也是不建議作)
2. 改變 create database link 語法. (文章中他們是這樣解的, 不過我沒辦法因為 DB 不是我能動的)
3. 改用 non-XA Driver. (這各在我的案例中是唯一的解法, 因為修改自己的東西最簡單)


結論
經過測試, 第三種方式可以解決我的問題, 因為我要的只是Query 並不牽涉到 Transaction. 所以, 只好新增 DataSource for non-XA .

2011-01-11

jboss 設定檔 對應 啟動時給對應的 ip

之前測試jboss 的相關設定與啟動, 都是在localhost 下面作業的. 最近要在正式環境裡頭作兩個Server 的 jms bridge 時, 按照之前自己寫得  Jboss JMS Bridge (Jboss to Jboss) 

設定完畢以後就只會出現    [org.hornetq.jms.bridge.impl.JMSBridgeImpl] Failed to set up JMS bridge connections. Most probably the source or target servers are unavailable. Will retry after a pause of 5000 ms . 最後試過可種可能, 終於發現  問題出在 localhost.

在開啟 jboss server 時,  -b xxx.xxx.xxx.xxx . 在jboss  設定時都要用 xxx.xxx.xxx.xxx 取代 locahost. 因為, 看起來  jboss 不會認得 localhost.

2010-12-29

共用EJB - Remote 篇

先前寫了共用EJB - Local 篇. 後來,要把他運用在同一個container Server , 不同的EJB3 或者 web 上時, 發現他根本不能work . 會一直跑出 Wrong target Eroror message. 研究了一下, 發現應該是不同的 EJB package 不能共用 local ,要用 remote 的方式.

另外就是, 如果你是不同的EJB package 採用 resource inject 方式, 那如果被引用的 EJB shutdown. 引用別人的 EJB or web 在 jboss 6 上面會掛掉, 得重新啟動才有辦法繼續運作. 所以. 建議方式是採用 InitialContext 方式去 引用外部的 EJB resource, 不然一天到晚你要記得去 restart .


在 Session Bean 部份的寫法


package test;

import javax.ejb.Stateless;

@Stateless(name="test/TestSessionBean")
public class TestSessionBean implements TestSessionBeanRLocal,TestSessionBeanRemote {

@Override
public void test() {
System.out.println("Hello Test Bean");
}

}


引用 共用 SessionBean 的寫法(Resource Injection)


package test;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import test.TestSessionBeanLocal;


@Stateless
public class TestBean implements TestBeanLocal {

@EJB(mappedName = "test/TestSessionBean/remote")
TestSessionBeanRemote testBean;

@Override
public void testBean() {
testBean.test();
}
}



上面標注紅色字體部份, 就是在jboss 下面可以正常運做的 code.
主要在 引用共用session bean 那邊的設定, 需要多加一個 /remote , 這是跟local 不一樣的地方.



引用 共用 SessionBean 的寫法(jndi lookup)


package test;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import test.TestSessionBeanLocal;
import javax.naming.InitialContext;

@Stateless
public class TestBean implements TestBeanLocal {

TestSessionBeanRemote testBean;

@Override
public void testBean() {
InitialContext ctx = new InitialContext();
testBean = (TestSessionBeanRemote)ctx.lookup("
test/TestSessionBean/remote");
testBean.test();
}
}

2010-11-29

共用EJB - Local 篇

之前寫 jee application 都是將所有用到的 SessionBean 全部放在同一個 application ear檔案. 就會出現在 同一個 jee container 上面出現很多相同的 SessionBean 掛在不同的 ear 下面. 這樣整體吃掉的資源其實是很大的, 而且不能把一些共用的Session Bean 拉出來共用.

個人認為 jee 應該不是這樣用的. 所以, 利用一些空閒時間研究一下. 下面是我在 Jboss 下面試出來的, 寫下來自己參考.

在 Session Bean 部份的寫法


package test;

import javax.ejb.Stateless;

@Stateless(name="test/TestSessionBean")
public class TestSessionBean implements TestSessionBeanLocal {

@Override
public void test() {
System.out.println("Hello Test Bean");
}

}


引用 共用 SessionBean 的寫法


package test;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import test.TestSessionBeanLocal;


@Stateless
public class TestBean implements TestBeanLocal {

@EJB(mappedName = "test/TestSessionBean/local")
TestSessionBean testBean;

@Override
public void testBean() {
testBean.test();
}
}



上面標注紅色字體部份, 就是在jboss 下面可以正常運做的 code.
主要在 引用共用session bean 那邊的設定, 需要多加一個 /local , 這是從 jboss jndi tree view 看得. 或許有其他寫法, 但是我還沒有研究出來.

2010-10-28

Eclipse Link JPA on jboss

之前使用 jpa + jta 的時候, 使用到transaction commit 時, 沒有詳細去注意各個 jpa 時做的問題. 但是, 今天就遇到一個問題, 讓目前開發的時候, 如果針對同一個 table 要作資料更新, 才發現不一樣的 jpa 實做會有不一樣的結果.
同一份 EJB 的程式放在 Jboss 6.0 and weblogic 會有不一樣的結果. Jboss 會出現 rollback , 但是 weblogic 不會. 這下又有趣了.
還好, 從Exception 中我看到 jboss 是 org.hibernate 的Exception. 就讓我想到會不會是 jpa 實做的不同導致的. 果然, weblogic 不是採用 hibernate jpa , 是用 eclipse link jpa.
有了這一條線索, 就上網找資料如何讓 jboss 可以採用 eclipse link jpa. EclipseLink/Examples/JPA/JBoss Web Tutorial 這一篇有講到, 但是有一些不一樣.
整個做完以後, eclipselink 做的 有些地方比 hibernate 好.

作法
  1. 下載 eclipse link jpa
  2. 將 eclipselink.jar 放入 ${jboss_home}/server/${server_name}/lib (這邊個上面的文章放的地方不太一樣, 因為我放過 有問題)
  3. 修改
    persistence.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    <persistence-unit name="DefaultDB" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>java:jdbc/DefaultDB</jta-data-source>
    <class>entity.testBean</class>
    <properties>
    <property name="eclipselink.target-server" value="JBoss"/>
    <property name="eclipselink.target-database" value="Oracle"/>
    </properties>
    </persistence-unit>
    </persistence>


provider 之前沒有設定 jboss 會直接抓 container server 的, 現在在這邊指定就可以讓jpa 使用設定的 jpa implements.

eclipselink.target-server 這一個設定值一定要做, 尤其在 jboss server上面, 前沒有做的時候. 一直跑出 No Transaction is currently. 應該是沒有設定 eclipselink 沒有辦法去抓到 jboss xa manager.
eclipselink.target-database 這一個建議要設定, 開始的時候使用Oracle 沒有設定是沒有問題的. 但是轉成 MSSQL 後, 就會有問題. 設定值參考 Sun GlassFish Enterprise Server v3 Prelude Developer's Guide , Chapter 6 Using the Java Persistence API -Specifying the Database 裡頭有各家 DB 的設定值.



詳細問題
在Oracle 設計Table 的時候, 除了會設定primary key 以外, 還可針對欄位作一些 check rule. 現在遇到問題就是, 當我要作一筆 Transaction, 所做的動作為 :
  1. 找尋就有資料是否有存在的組合.
  2. 有符合的資料, 就將資料欄位 isAtvice 從 true 改為 false.
  3. Insert 新的資料進去
在weblogic 中, 這樣一個transaction 是可以完成的. 但是轉換到 jboss 時, 會出現 check rule Exception.
問題後來發現就是出在 hibernate 在處理 transaction 的方法, 跟 eclipselink 處理不同, 所以相同的DB 會出現不同的結果.

參考文獻
  1. Integrating EclipseLink with an Application Server (ELUG)
  2. EclipseLink/Examples/JPA/JBoss Web Tutorial
  3. Sun GlassFish Enterprise Server v3 Prelude Developer's Guide , Chapter 6 Using the Java Persistence API -Specifying the Database

2010-09-29

log4j on Jboss

最近把 project 到了一個段落, 要回來處理一下 log 的問題.
看了很多篇文章, 都發現jboss 上面 要跑含 log4j 的code 像是會有點問題. 看很多網頁, 沒有真的去試試看還不知道會是怎樣. 是了一兩個在 jboss 5.0 jboss 4.0 的解決方案, 好像不是適用於 jboss 6.0 M3.
就硬著把 ${JBOSS_HOME}/server/default/deply 看一輪, 發現到有一個檔案 jboss-logging.xml 裡面有用到jboss 自己的 log , 還有幾個appended 是用 log4j. 想說那就來試試看吧.
想說不用太複雜可以跑就好, 就找 ${JBOSS_HOME}/server/standard/ 來改好了. 要把log4j.jar 放見 ${JBOSS_HOME}/server/stardand/lib 裡面, 發現哇勒 裡面已經有放 一個log4j.jar. 跟在default裡面的lib 不一樣, default/lib 裡面一個東西都沒有, 這邊居然有. 簡單寫一個 web app, 用到log4j 去放.

修改 ${JBOSS_HOME}/server/stardand/deploy/jboss-logging.xml
1. 我是選用 他原有的 FILE 下去修改 , 新增到 檔案裡頭

<size-rotating-file-handler
file-name="${jboss.server.log.dir}/app.log"
name="FILE-APP"
autoflush="true"
append="true"
rotate-size="500k"
max-backup-index="5">

<error-manager>
<only-once/>
</error-manager>

<formatter>
<pattern-formatter pattern="%d %-5p [%c] (%t) %m%n"/>
</formatter>
</size-rotating-file-handler>

2. 新增相對的 logger

<logger category="test.logger">
<level name="DEBUG"/>
<handlers>
<handler-ref name="CONSOLE"/>
<handler-ref name="FILE-APP"/>
</handlers>
</logger>

3. 撰寫測試 log4j 的code

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;

@WebServlet(name = "Test", urlPatterns = {"/Test"})
public class Test extends HttpServlet {

private static Logger log = Logger.getLogger("test.logger");

/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
log.debug("Log Debug");
log.info("Log Info");
} finally {
out.close();
}
}

// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}



測試一下, 發現很正常, 可以在jboss container 下面, 正常的使用.不用像 jboss docs 裡面寫得, 得用 jboss 包過得 Logger 下去做事情.

ps: 測試的過程中, 我將 standard/lib/log4j.jar copy to default/lib/ 來使用

2010-09-09

JBoss 啟動參數

一開始裝好 jboss 大概都只會用 ${JBOSS_HOME}/bin/run.bat. 這樣的用法大概就是啟動 ${JBOSS_HOME}/server/default 的設定. 不過現在 已經從 Installation and getting started guide 研究出下參數啟動.

run.bat -b 192.168.1.1
這樣的下法, 可以讓server 以外的可以連近來, 最早在做測試的時候都是用localhost , 直到要連接兩台的時候發現怎樣都過不去. 以為是防火牆, 還是那個東西沒有打開. 後來發現, 原來jboss 初始值是讓你在 開發用的. 要等到正式啟用在給他相對應的ip , 這是為了安全性考量.

run.bat -c stardand
這樣的下法, 就可以啟動 ${JBOSS_HOME}/server/stardand 的server .

2010-08-31

Jboss JMS Bridge (Jboss to Jboss)

今天開始測試 Jboss JMS Bridge.
看過不少的document後, 看起來 jboss bridge 是用內建JNDI 幫你連接到 Remote JMS Server. 等於省掉了程式開發者自己連接 JNDI等等的 JMS 事項. 另外一個好處就是, Local and Remote 各有一個Queue , 然後 AP server 幫你作保證送達的工作.
下面用到的範例都是從 HornetQ Example 拿出來改得, 因為有些並非原廠文件寫得那樣.

先來運用原廠的 單機兩個Queue作 JMS bridge.
  • /queue/source 是用來接收client 送出來的 message
  • /queue/target 是用來接收 /queue/source 轉送過來的message
  • jms-bridge-jboss-beans.xml 是在jee server 下面 設定的bridge beans

首先 在 hornetq-jms.xml 新增兩個 queue

<queue name="source">
<entry name="/queue/source"/>
</queue>
<queue name="target">
<entry name="/queue/target"/>
</queue>

新增一個 jms-bridge-jboss-beans.xml 到 ${JBOSS_HOME}/server/default/deploy/hornetq
要注意的地方, 在原廠的設定中 target 的 user and password 是沒有設定的. 沒有設定是沒辦法正常使用的, 所以我把 guest/guest 加進去才可以正常運作.

<?xml version="1.0" encoding="UTF-8"?>

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<bean name="JMSBridge" class="org.hornetq.jms.bridge.impl.JMSBridgeImpl">
<!-- HornetQ must be started before the bridge -->
<depends>HornetQServer</depends>
<constructor>
<!-- Source ConnectionFactory Factory -->
<parameter>
<inject bean="SourceCFF"/>
</parameter>
<!-- Target ConnectionFactory Factory -->
<parameter>
<inject bean="TargetCFF"/>
</parameter>
<!-- Source DestinationFactory -->
<parameter>
<inject bean="SourceDestinationFactory"/>
</parameter>
<!-- Target DestinationFactory -->
<parameter>
<inject bean="TargetDestinationFactory"/>
</parameter>
<!-- Source username (no username here) -->
<parameter><null /></parameter>
<!-- Source password (no password here)-->
<parameter><null /></parameter>
<!-- Target username (no username here)-->
<parameter>guest</parameter>
<!-- Target password (no password here)-->
<parameter>guest</parameter>
<!-- Selector -->
<parameter><null /></parameter>
<!-- Interval to retry in case of failure (in ms) -->
<parameter>5000</parameter>
<!-- Maximum number of retries to connect to the source and target -->
<parameter>10</parameter>
<!-- Quality of service -->
<parameter>ONCE_AND_ONLY_ONCE</parameter>
<!-- Maximum batch size -->
<parameter>1</parameter>
<!-- Maximum batch time (-1 means infinite) -->
<parameter>-1</parameter>
<!-- Subscription name (no subscription name here)-->
<parameter><null /></parameter>
<!-- client ID (no client ID here)-->
<parameter><null /></parameter>
<!-- concatenate JMS messageID to the target's message header -->
<parameter>true</parameter>
<!-- register the JMS Bridge in the AS MBeanServer -->
<parameter>
<inject bean="TheMBeanServer"/>
</parameter>
<parameter>org.hornetq:service=JMSBridge</parameter>
</constructor>
<property name="transactionManager">
<inject bean="RealTransactionManager"/>
</property>
<!--<property name="transactionManagerLocatorClass">org.hornetq.integration.jboss.tm.JBoss5TransactionManagerLocator</property>
<property name="transactionManagerLocatorMethod">getTm</property>-->
</bean>

<!-- SourceCFF describes the ConnectionFactory used to connect to the source destination -->
<bean name="SourceCFF" class="org.hornetq.jms.bridge.impl.JNDIConnectionFactoryFactory">
<constructor>
<parameter>
<inject bean="JNDI" />
</parameter>
<parameter>/ConnectionFactory</parameter>
</constructor>
</bean>

<!-- TargetCFF describes the ConnectionFactory used to connect to the target destination -->
<bean name="TargetCFF" class="org.hornetq.jms.bridge.impl.JNDIConnectionFactoryFactory">
<constructor>
<parameter>
<inject bean="JNDI" />
</parameter>
<parameter>/ConnectionFactory</parameter>
</constructor>
</bean>

<!-- SourceDestinationFactory describes the Destination used as the source -->
<bean name="SourceDestinationFactory" class="org.hornetq.jms.bridge.impl.JNDIDestinationFactory">
<constructor>
<parameter>
<inject bean="JNDI" />
</parameter>
<parameter>/queue/source</parameter>
</constructor>
</bean>

<!-- TargetDestinationFactory describes the Destination used as the target -->
<bean name="TargetDestinationFactory" class="org.hornetq.jms.bridge.impl.JNDIDestinationFactory">
<constructor>
<parameter>
<inject bean="JNDI" />
</parameter>
<parameter>/queue/target</parameter>
</constructor>
</bean>

<!-- JNDI is a Hashtable containing the JNDI properties required -->
<!-- to connect to the sources and targets JMS resrouces -->
<bean name="JNDI" class="java.util.Hashtable">
<constructor class="java.util.Map">
<map class="java.util.Hashtable" keyClass="java.lang.String"
valueClass="java.lang.String">
<entry>
<key>java.naming.factory.initial</key>
<value>org.jnp.interfaces.NamingContextFactory</value>
</entry>
<entry>
<key>java.naming.provider.url</key>
<value>jnp://localhost:1099</value>
</entry>
<entry>
<key>java.naming.factory.url.pkgs</key>
<value>org.jboss.naming:org.jnp.interfaces"</value>
</entry>
</map>
</constructor>
</bean>

</deployment>


接下測試 兩台不同 AP Server 作為 bridge
  • AP1 新增 /queue/source
  • AP2 新增 /queue/target
  • AP1 新增 jms-bridge-jboss-beans.xml
這一部份直接進入 AP1 jms-bridge-jboss-beans.xml 的設定. 其實跟單機的部份很像. 只不過jndi 的部份需要另外新增. 新增了一個 JNDI-Remote 的 設定檔, 就是告知 AP1 如何連接到 AP2 的JNDI 設定. 當然, target 的 ConnectionFactory and Queue 都要改指向新的 jndi 設定.
在測試的過程中, 發現 第一次設定好以後. 發現message 根本沒有送過去, 就這樣反覆的把AP1 shutdown and start 好幾次以後, 突然message 都傳送到 AP2 了. 搞不清楚怎樣發生的就在繼續測試下去. 最後得到一個結論, 那就是Ap Start 以後, 要接過一小段時間以後, 才會開始傳送Message 而不是 馬上就動工.


<?xml version="1.0" encoding="UTF-8"?>

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<bean name="JMSBridge" class="org.hornetq.jms.bridge.impl.JMSBridgeImpl">
<!-- HornetQ must be started before the bridge -->
<depends>HornetQServer</depends>
<constructor>
<!-- Source ConnectionFactory Factory -->
<parameter>
<inject bean="SourceCFF"/>
</parameter>
<!-- Target ConnectionFactory Factory -->
<parameter>
<inject bean="TargetCFF"/>
</parameter>
<!-- Source DestinationFactory -->
<parameter>
<inject bean="SourceDestinationFactory"/>
</parameter>
<!-- Target DestinationFactory -->
<parameter>
<inject bean="TargetDestinationFactory"/>
</parameter>
<!-- Source username (no username here) -->
<parameter><null /></parameter>
<!-- Source password (no password here)-->
<parameter><null /></parameter>
<!-- Target username (no username here)-->
<parameter>guest</parameter>
<!-- Target password (no password here)-->
<parameter>guest</parameter>
<!-- Selector -->
<parameter><null /></parameter>
<!-- Interval to retry in case of failure (in ms) -->
<parameter>5000</parameter>
<!-- Maximum number of retries to connect to the source and target -->
<parameter>10</parameter>
<!-- Quality of service -->
<parameter>ONCE_AND_ONLY_ONCE</parameter>
<!-- Maximum batch size -->
<parameter>1</parameter>
<!-- Maximum batch time (-1 means infinite) -->
<parameter>-1</parameter>
<!-- Subscription name (no subscription name here)-->
<parameter><null /></parameter>
<!-- client ID (no client ID here)-->
<parameter><null /></parameter>
<!-- concatenate JMS messageID to the target's message header -->
<parameter>true</parameter>
<!-- register the JMS Bridge in the AS MBeanServer -->
<parameter>
<inject bean="TheMBeanServer"/>
</parameter>
<parameter>org.hornetq:service=JMSBridge</parameter>
</constructor>
<property name="transactionManager">
<inject bean="RealTransactionManager"/>
</property>
<!--<property name="transactionManagerLocatorClass">org.hornetq.integration.jboss.tm.JBoss5TransactionManagerLocator</property>
<property name="transactionManagerLocatorMethod">getTm</property>-->
</bean>

<!-- SourceCFF describes the ConnectionFactory used to connect to the source destination -->
<bean name="SourceCFF" class="org.hornetq.jms.bridge.impl.JNDIConnectionFactoryFactory">
<constructor>
<parameter>
<inject bean="JNDI" />
</parameter>
<parameter>/ConnectionFactory</parameter>
</constructor>
</bean>

<!-- TargetCFF describes the ConnectionFactory used to connect to the target destination -->
<bean name="TargetCFF" class="org.hornetq.jms.bridge.impl.JNDIConnectionFactoryFactory">
<constructor>
<parameter>
<inject bean="JNDI-Remote" />
</parameter>
<parameter>/ConnectionFactory</parameter>
</constructor>
</bean>

<!-- SourceDestinationFactory describes the Destination used as the source -->
<bean name="SourceDestinationFactory" class="org.hornetq.jms.bridge.impl.JNDIDestinationFactory">
<constructor>
<parameter>
<inject bean="JNDI" />
</parameter>
<parameter>/queue/source</parameter>
</constructor>
</bean>

<!-- TargetDestinationFactory describes the Destination used as the target -->
<bean name="TargetDestinationFactory" class="org.hornetq.jms.bridge.impl.JNDIDestinationFactory">
<constructor>
<parameter>
<inject bean="JNDI-Remote" />
</parameter>
<parameter>/queue/target</parameter>
</constructor>
</bean>

<!-- JNDI is a Hashtable containing the JNDI properties required -->
<!-- to connect to the sources and targets JMS resrouces -->
<bean name="JNDI" class="java.util.Hashtable">
<constructor class="java.util.Map">
<map class="java.util.Hashtable" keyClass="java.lang.String"
valueClass="java.lang.String">
<entry>
<key>java.naming.factory.initial</key>
<value>org.jnp.interfaces.NamingContextFactory</value>
</entry>
<entry>
<key>java.naming.provider.url</key>
<value>jnp://localhost:1099</value>
</entry>
<entry>
<key>java.naming.factory.url.pkgs</key>
<value>org.jboss.naming:org.jnp.interfaces"</value>
</entry>
</map>
</constructor>
</bean>
<bean name="JNDI-Remote" class="java.util.Hashtable">
<constructor class="java.util.Map">
<map class="java.util.Hashtable" keyClass="java.lang.String"
valueClass="java.lang.String">
<entry>
<key>java.naming.factory.initial</key>
<value>org.jnp.interfaces.NamingContextFactory</value>
</entry>
<entry>
<key>java.naming.provider.url</key>
<value>jnp://localhost:2099</value>
</entry>
<entry>
<key>java.naming.factory.url.pkgs</key>
<value>org.jboss.naming:org.jnp.interfaces"</value>
</entry>
</map>
</constructor>
</bean>
</deployment>

2010-08-23

設定 Oracle XA DataSource

直接在 ${Jboss}\server\default\deploy 下面新增 oracel-xa-ds.xml
Jboss 會自動生效 不用重新開機

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<xa-datasource>
<jndi-name>jdbc/TestDataSource</jndi-name>
<!-- uncomment to enable interleaving <interleaving/> -->
<isSameRM-override-value>false</isSameRM-override-value>
<xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
<xa-datasource-property name="URL">jdbc:oracle:thin:@localhost:1521:xe</xa-datasource-property>
<xa-datasource-property name="User">root</xa-datasource-property>
<xa-datasource-property name="Password">root</xa-datasource-property>
<!-- Uses the pingDatabase method to check a connection is still valid before handing it out from the pool -->
<!--valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name-->
<!-- Checks the Oracle error codes and messages for fatal errors -->
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
<!-- Oracles XA datasource cannot reuse a connection outside a transaction once enlisted in a global transaction and vice-versa -->
<no-tx-separate-pools/>

<!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
<metadata>
<type-mapping>Oracle10i</type-mapping>
</metadata>
</xa-datasource>

<mbean code="org.jboss.resource.adapter.jdbc.vendor.OracleXAExceptionFormatter"
name="jboss.jca:service=OracleXAExceptionFormatter">
<depends optional-attribute-name="TransactionManagerService">jboss:service=TransactionManager</depends>
</mbean>

</datasources>

2010-08-18

Jboss 安裝紀錄

windows 下載與安裝
  1. 下載 jboss-6.0.0.20100721-M4, 直接解開找一個路徑放就可以了.
  2. 設定環境變數 JBOSS_HOME 到 ${JOSS_DIR}, 啟動的時候會用到.
  3. 不建議放在 "c:\Program Files" 下面, 因為會跑不動. 大概目錄有空格就會跑不動.
  4. ${JBOSS_DIR}\bin\run.bat , 跑得起來 沒有任何錯誤. 就是已經開起了.
  5. http://localhost:8080 看得到就是成功了, 選用 admin console.
  6. admin/admin 就可以看到 jboss ap server 的管理介面.

Session Bean 測試
測試過後, 基本上可以 在glassfish and weblogic 上面跑得簡易Session, 都是可以正常運作.

Message Driven Bean測試
  1. 1. 設定 ConnectionFactory 和 Queue 都可以透過 admin console. 只是 我不知道設定檔存在哪邊. 從${JBOSS_DIR}\server\default\deploy\hornetq 裡頭看不出來, 透過admin console 的設定存放在哪邊. 所以後來我統統用自己去修改 ${JBOSS_DIR}\server\default\deploy\hornetq 的所有設定檔.
  2. 2. 佈署 MDB(Message Driver Bean). 把glassfish and weblogic 都會過得 MDB 透過 admin console 放去, 就出現錯誤啦 .
  3. 變裝前
    @MessageDriven(mappedName = "jms/TestQueue", activationConfig = {
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
    })

    變裝後

    @MessageDriven( activationConfig = {
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    @ActivationConfigProperty(propertyName = "destination", propertyValue = "/jms/TestQueue"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
    })

    差距就在他不吃 mappedName 的設定, 要改寫在 ActivationConfigProperty 裡頭. 不過我想如果改寫在 deploy jboss.xml 裡頭會比較好一點.

  4. 事情不是這樣簡單的, 繼續下去吧. 拿去deploy 還是會繼續發生問題的. 錯誤訊息一直跟我說user=null,問題點看了很久,還是看不出來問題出在哪邊. 所以, google 大神請了老半天, 有看沒有懂. 怎麼辦, 老大交待要選一個, 還要能夠用的.
    只好下在hornetq 來看摟, ${hornetq}\example 裡面有很多範例可以慢慢欣賞. 就直接切進去 ${hornetq}\example\javaee\ 來找答案了. 看了老半天, 也沒發現不一樣的. 找兩天, 幾乎沒有看到任何文章或者解釋可以說明的.
    就在要放棄的時候, 想說那看一下 ${hornetq}\example\jms. 發現一個怪現象, 幾乎每一個jms example 的設定檔裡面, 都會多出一個 hornetq-users.xml. 好奇殺死貓, 打開來看, 哇老天壓.....

    <configuration xmlns="urn:hornetq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:hornetq /schema/hornetq-users.xsd">
    <!-- the default user. this is used where username is null-->
    <defaultuser name="guest" password="guest">
    <role name="guest"/>
    </defaultuser>
    </configuration>

    有沒有看到 哪行註解.... the default user. this is used where username is null 就直接把檔案放進 ${JBOSS_DIR}\server\default\deploy\hornetq. 再把 server 重開, 安裝測試檔. 哇...過了.... 還我兩天的青春壓...


  5. 很多事情高興一天就好了, 沒想到我高興不到半小時, 就繼續陷入苦戰了. 可以安裝上AP 不代表可以正常的跑. 安裝上去以後, 總是要測試一下 Queue 到底可不可用, 能不能正常作用. 就寫了一個簡單的 Session 做為 Message Provider, 測試一下 到底資料可不可以透過 Queue 送給 MDB. 安裝後, 呼叫Session送資料到 Queue. 沒想到 console 傳回了一個要命的error.

    [STDERR] Caused by: java.lang.ClassNotFoundException: org.hornetq.integration.transports.netty.NettyConnectorFactory from BaseClassLoader@12e
    bf9a{vfs:///C:/jboss-6.0.0.20100721-M4/server/default/deploy/TestQueue.ear}

    看到這樣的錯誤, 第一個反應是不是少了那一個 jar 沒有放進去 server lib 裡面. 不過沒有到底壓, Jboss 6 已經是內建 hornetq , 不應該會少東西壓. 網路上查了一下, 也看到他們說已經把改補的在五月補上去了壓, 我是抓七月的檔壓. 又花了一天在找資料作測試. 還是一樣徒勞無功. 那就休息吧... 不要在做測試了
    噹噹, 兩天過去了. 不行都已經奮戰了五天了, 不能這樣就放棄 Jboss. 把org.hornetq.integration.transports.netty.NettyConnectorFactory放進 google 找看看好了. google 找到的第一文件 The HornetQ Team Blog: Understanding Connectors & Acceptors 看起來跟解問題沒有關係, 但是列在下面的幾篇又都已經看過了, 反正沒希望了, 就看看 Connectors and Acceptores 有何差別也好學一下人家的設計好了.
    好學不倦的人就是有福了, 文章就直接先解釋Acceptores and Connectors 在的作用. 接下來就講到一個東西 "HornetQ defines 2 types of acceptor/connector : invm and netty". 嘿嘿這解釋就讓我瞭解了, 之前再看設定檔老是看到 netty 不知道怎樣使用的, 沒想到 invm 才是另外一個重點.
    我的測試機上面, AP 和 hornetq 是同一台機器, 而且 hornetq 是設定 embedden 模式, 所以ap and hornetq 會長在同一個vm. (hornetq 還有local and remote mode, 就是一個跟 ap 會同生死但是是分別兩個vm , remote就不會跟AP同生死, 當然也不是在同一個vm. ). 所以按照文章的講法, 我猜想是我的設定檔指定錯connectors 了, 回去翻我當時的設定檔 hornetq-jms.xml.

    <connection-factory name="NettyConnectionFactory">
    <connectors>
    <connector-ref connector-name="netty"/>
    </connectors>
    <entries>
    <entry name="/ConnectionFactory"/>
    <entry name="/XAConnectionFactory"/>
    <entry name="jms/ConnectionFactory"/>
    </entries>
    </connection-factory>
    <connection-factory name="InVMConnectionFactory">
    <connectors>
    <connector-ref connector-name="in-vm"/>
    </connectors>
    <entries>
    <entry name="java:/ConnectionFactory"/>
    <entry name="java:/XAConnectionFactory"/>
    </entries>
    </connection-factory>

    作個實驗修改後

    <connection-factory name="NettyConnectionFactory">
    <connectors>
    <connector-ref connector-name="netty"/>
    </connectors>
    <entries>
    <entry name="/ConnectionFactory"/>
    <entry name="/XAConnectionFactory"/>
    </entries>
    </connection-factory>
    <connection-factory name="InVMConnectionFactory">
    <connectors>
    <connector-ref connector-name="in-vm"/>
    </connectors>
    <entries>
    <entry name="java:/ConnectionFactory"/>
    <entry name="java:/XAConnectionFactory"/>
    <entry name="jms/ConnectionFactory"/>
    </entries>
    </connection-factory>

    嘿嘿, 重開server以後, 測試一下. 哇 恭喜老爺高中狀元, 留下十年寒窗的眼淚, 在console 下看到 我要看到的 Info 了.



後記
搞了一個多禮拜(不包涵六日), 終於最基本的 EJB 都可以在 Jboss上面運做了. 心裡真的爽度很高, 但是也是這樣覺得 Jboss 的設定真的很複雜, 跟weblogic and glassfish 比較起來真的差距很大, 而且現階段 jboss.org 上面的 document 也都是停留在 jboss 5的文件. 所以很多文件讀起來跟實際 jboss 6 有點落差, 光是 JMS部份就 從 messaging 轉換到 hornetq. 所以, 文件中都使以 jboss messaging 為主體, 沒辦法直接套用在 jboss 6.
另外, 在讀 hornetq 的說明也都是如何將 hornetq 掛到 jboss5 上面的說明. 只能從example 跟 hornetq user guide 來推測放在 jboss6 上面應該要如何作設定.
這篇文章就是自己 在做完一整個search and retry 的心得跟作法.