練習 JBoss 的JMS...Local client呼叫
1. 要記得把 server config 切到 standalone-full.xml
(要用原本的standalone.xml也可以,但是我看就是要加很多東西,有人建議就直接跑full就好,事實上也是,跑 full 幾乎沒啥問題)
在 windows 更換啟動的指令
cd xxxxxx\jboss-eap-6.2\bin\
standalone.bat -c standalone-full.xml
(一般直接啟用,不帶參數,就是跑 standalone.xml)
2. 如果有設定 datasource,或是什麼要定在 standalone**.xml 裡面東西的,要再下一次。
(總之,就比對一下 兩邊的 xml,大概就可以看出點什麼差別)
3. 查一下 standalone-full.xml 裡面有沒有 <mdb 這個 tag內容
理論上長成這樣
<subsystem xmlns="urn:jboss:domain:ejb3:1.4">
....
<mdb>
<resource-adapter-ref resource-adapter-name="${ejb.resource-adapter-name:hornetq-ra}"/>
<bean-instance-pool-ref pool-name="mdb-strict-max-pool"/>
</mdb>
如果search 沒有 <mdb 就要手動新增,我一樣用 cli 語法加
/subsystem=ejb3:write-attribute(name="default-mdb-instance-pool", value="mdb-strict-max-pool")
/subsystem=ejb3:write-attribute(name="default-resource-adapter-name", value="${ejb.resource-adapter-name:hornetq-ra.rar}")
(ps:jboss 內建是 hornetq,如果要換別家的話,就要多灌lib進來才行吧)
4. 查一下 socket bind
理論上長這樣
<socket-binding-group
.....
<socket-binding name="messaging" port="5445"/>
<socket-binding name="messaging-group" port="0" multicast-address="${jboss.messaging.group.address:231.7.7.7}" multicast-port="${jboss.messaging.group.port:9876}"/>
<socket-binding name="messaging-throughput" port="5455"/>
(不過這個應該 default 就有,只是看一下,知道他會把服務起在那個 port 就是)
5. 寫 jms 設定檔,webapp/META-INF/*-hornetq-jms.xml ,ex: my-hornetq-jms.xml
<?xml version="1.0" encoding="UTF-8"?>
<messaging-deployment xmlns="urn:jboss:messaging-deployment:1.0">
<hornetq-server>
<jms-destinations>
<jms-queue name="MyMDBQueue">
<entry name="/queue/MyQueue"/>
</jms-queue>
<jms-topic name="MyQueueMDBTopic">
<entry name="/topic/MyTopic"/>
</jms-topic>
</jms-destinations>
</hornetq-server>
</messaging-deployment>
6. 寫 Server side listener
import java.util.Date;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.TextMessage;
@MessageDriven(activationConfig = {
@ActivationConfigProperty(
propertyName = "destinationType",
propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(
propertyName = "destination",
propertyValue = "queue/MyQueue") })
public class QueueListenerMDB implements MessageListener {
public QueueListenerMDB() {
}
public void onMessage(Message message) {
try {
if (message instanceof TextMessage) {
System.out.println("Queue: Server listener received ="+System.currentTimeMillis());
TextMessage msg = (TextMessage) message;
System.out.println("Message is : " + msg.getText());
} else if (message instanceof ObjectMessage) {
System.out.println("Queue: Server received an ObjectMessage at "+System.currentTimeMillis());
ObjectMessage msg = (ObjectMessage) message;
Object pojo = msg.getObject();
System.out.println("pojo Details: "+pojo);
} else {
System.out.println("Not valid message for this Queue MDB");
}
} catch (JMSException e) {
e.printStackTrace();
}
}
}
7. 寫Client 驗證
(基本的 連接傳送是降子)
QueueConnection conn;
QueueSession session;
Queue que;
QueueSender send;
private void connect() throws Exception {
//
InitialContext iniCtx = new InitialContext();
Object tmp = iniCtx.lookup("ConnectionFactory");
QueueConnectionFactory qcf = (QueueConnectionFactory) tmp;
conn = qcf.createQueueConnection();
que = (Queue) iniCtx.lookup("queue/MyQueue");
session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
conn.start();
}
private void stop() throws JMSException {
conn.stop();
session.close();
conn.close();
}
private void sendText(String text) throws Exception {
send = session.createSender(que);
TextMessage tm = session.createTextMessage(text);
log.info("sendRecvAsync, sent text=" + tm.getText());
send.send(tm);
send.close();
}
private void sendObject(Serializable obj) throws Exception {
MessageProducer producer = session.createProducer( que );
ObjectMessage message = session.createObjectMessage( obj );
producer.send( message );
send.close();
}
(呼叫時使用就是照順序 open connect(session) -> session create send -> sendMessage(text/Object) -> close send -> close session)
client.connect();
client.sendText("Hi!");
client.sendObject( MyObject );
client.stop();
8. 包一包丟到JBoss 上
因為 JMS 有跑的時後看起來在 init 的時後,好像會咬住server的資源,如果不是用 shutdown的機制(直接關cmd),我碰到的是會有「存取被拒」的情況,就算是電腦關機後再開,還是會衝,大概還是就是先 正常的 shutdown 後(記得要等個幾秒),再重起 JBoss就會過去
那個 錯誤 在 log 裡會像降子(假警報,可是就是會被嚇到,明明沒動,想說是那裡又改錯了一.一|||,如果沒去看 server log 大概又會以為程式有問題...然後其實那個 war 是在deploy 成功的狀態(fail會有 xxxx.war.fail 的文字檔寫錯誤)...追log看,前面該跑的也都有跑起來,但是就是在後面會卡住)
[javax.enterprise.resource.webcontainer.jsf.config] (ServerService Thread Pool -- 62) 正在初始化環境「/xxxxxx」的 Mojarra 2.1.19-jbossorg-1 20131024-0833
SEVERE [javax.enterprise.resource.webcontainer.jsf.config] (ServerService Thread Pool -- 62) Critical error during deployment: : com.sun.faces.config.ConfigurationException: java.util.concurrent.ExecutionException: javax.faces.FacesException: java.io.FileNotFoundException: D:\jboss-eap-6.2\standalone\tmp\vfs\temp\tempb1f1831541a362e4\xxxxxx.war-adb47e313f325e6a\xxxxxx.war-8494329521517097592.tmp (存取被拒。)
9. 其它
如果 JMS 有跑起來的話,用 cli 看 jndi-view 是有些東西的喔,local 呼叫的話,就是可以找 ConnectionFactory 裡面,有這東西,如果是遠端,大概要麻就是直接從那個 port 送進來,或者從 remote 那邊找進來了(網路上蠻多是走 jnp,不過 jnp 感覺好像又是另一門作業一.一")
"ConnectionFactory" => {
"class-name" => "org.hornetq.jms.client.HornetQJMSConnectionFactory",
"value" => "HornetQConnectionFactory [serverLocator=ServerLocatorImpl [initialCo
nnectors=[TransportConfiguration(name=in-vm, factory=org-hornetq-core-remoting-impl-invm-InVMConnect
orFactory) ?server-id=0], discoveryGroupConfiguration=null], clientID=null, dupsOKBatchSize=1048576,
transactionBatchSize=1048576, readOnly=true]"
JMS 像 default 起在 5445,也可以用 telnet 127.0.0.1 5445 驗證是否有在聽
"java:jboss/exported" => {"jms" => {
"class-name" => "javax.naming.Context",
"children" => {"RemoteConnectionFactory" => {
"class-name" => "org.hornetq.jms.client.HornetQJMSConnectionFactory",
"value" => "HornetQConnectionFactory [serverLocator=ServerLocatorImpl [initialCo
nnectors=[TransportConfiguration(name=netty, factory=org-hornetq-core-remoting-impl-netty-NettyConne
ctorFactory) ?port=5445&host=127-0-0-1], discoveryGroupConfiguration=null], clientID=null, dupsOKBat
chSize=1048576, transactionBatchSize=1048576, readOnly=false]"
}}
}},
大概這樣,就可以跑一個簡單的 sample了。
話說,JMS 好像還有蠻多種作法(光找練習參考,就...總之每次建環境都覺得很無言啦...)
不過這個應該是最單純的,只靠設定用JBoss 內建的 JMS 來跑。
沒有留言:
張貼留言