JBossMQ
La configurazione del JMS Provider di JBoss avviene
nel file jboss.jcml nella directory di configurazione
(jboss\conf\default) identificata dal commento:
<!--
=======================================================
-->
<!-- JBossMQ -->
<!-- =======================================================
-->
Generalmente posso compiere 3 tipi operazioni per modificare
la configurazione di base:
1) aggiunta di una nuova destinazione
2) gestione utente
3) gestione del connection factories
Aggiunta di una nuova destinazione
Ho
2 modi per aggiungere una nuova destinazione in Jboss:
- Nel
file jboss.jcml: se per esempio voglio creare una
nuova topic chiamata 'testTopic' devo inserire il
seguente codice in formato xml:
<mbean
code="org.jboss.mq.server.TopicManager"
name="JBossMQ:service=Topic,name=testTopic"/>
- Servendomi
dell'interfaccia fornita da JBoss. Eseguire lo startup
(comando run directory
bin), aprire un browser e digitare http://localhost:8082,
comparirà la lista di tutti i servizi
attivi in JBoss.
Figura 1
Selezionado 'service=Server' si accede ad una seconda
pagina che mi permette la
creazione della mia nuova destinazione
Figura 2
Alla fine dopo la conferma dell'avvenuta creazione tornando
alla pagina iniziale vedrò una
nuova riga con la nuova destinazione.
Figura 3
Attenzione: questa operazione a differenza della numero
1) è momentanea nel senso
che facendo un reboot di JBoss verrà persa.
Quando
farò la look up per utilizzare questa nuova risorsa
dovrò specificare il nome con un prefisso ovvero
nel nostro caso avendo creato una topic quando farò
la look up il JNDI name sarà topic/testTopic.
Gestione
Utente
Questa
funzionalità è necessaria se voglio gestire
una persistenza duratura dei miei messaggi. Nel file
jbossmq-state.xml ( jboss\conf\default ) viene inserito
il seguente codice:
<User>
<Name>Davide</Name>
<Password>Yarelys</Password>
<Id>Naike</Id>
</User>
Il
riferimento al file jbossmq-state.xml lo troviamo all'interno
del solito jboss.jcml:
<mbean
code="org.jboss.mq.server.StateManager" name="JBossMQ:service=StateManager">
<attribute name="StateFile">jbossmq-state.xml</attribute>
</mbean>
Gestione Connection Factories
JBoss
definisce un differente numero di connection factories
per topics e queues dipendente dal tipo di protocollo
utilizzato. Tutti i tipi di factories e properties ad
esse associate sono specificate nel file jboss.jcml:
<mbean
code="org.jboss.mq.il.jvm.JVMServerILService"
name="JBossMQ:service=InvocationLayer,type=JVM">
<attribute name="ConnectionFactoryJNDIRef">
java:/ConnectionFactory
</attribute>
<attribute name="XAConnectionFactoryJNDIRef">
java:/XAConnectionFactory
</attribute>
</mbean>
<mbean
code="org.jboss.mq.il.rmi.RMIServerILService"
name="JBossMQ:service=InvocationLayer,type=RMI">
<attribute name="ConnectionFactoryJNDIRef">
RMIConnectionFactory</attribute>
<attribute
name="XAConnectionFactoryJNDIRef">RMIXAConnectionFactory</attribute>
</mbean>
<mbean
code="org.jboss.mq.il.oil.OILServerILService"
name="JBossMQ:service=InvocationLayer,type=OIL">
<attribute name="ConnectionFactoryJNDIRef">
ConnectionFactory
</attribute>
<attribute name="XAConnectionFactoryJNDIRef">
XAConnectionFactory
</attribute>
</mbean>
<mbean
code="org.jboss.mq.il.uil.UILServerILService"
name="JBossMQ:service=InvocationLayer,type=UIL">
<attribute name="ConnectionFactoryJNDIRef">
UILConnectionFactory
</attribute>
<attribute name="XAConnectionFactoryJNDIRef">
UILXAConnectionFactory
</attribute>
</mbean>
Vediamo
brevemente il significato:
OIL: è quella di default risulta molto veloce
basata su socket
UIL: utilizzata per passare dal firewall e quando il
client non conosce correttamente IP del
server
RMI: è il primo tipo scritto molto stabile ma
lenta
Diamo
un elenco di alcune connection factories presenti in
JBoss con il loro tipo:
Es.
di codice riassuntivo
private
void maker(){
Hashtable props = new Hashtable();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingConnectionFactory");
props.put(Context.PROVIDER_URL,"localhost:1099");
props.put("java.naming.rmi.security","yes");
props.put(Context.URL_PKG_PREFIXES,"org.jboss.naming");
Context context = new InitialContext(props);
TopicConnectionFactory topicFactory;
topicFactory
=(TopicConnectionFactory)context.lookup(
"TopicConnectionFactory");
TopicConnection topicConnection;
topicConnection
= TopicFactory.createTopicConnection();
Topic topic = (Topic) context.lookup("topic/testTopic");
...
}
Persistenza
dei Messaggi
Il
Persistence Manager è il responsabile per memorizzare
i messaggi in caso di fault del server, e permettere
quindi il loro recupero in un secondo tempo.
Ci sono quattro tipi di persistenza:
La persistenza di default è di tipo rolliglogged:
<mbean
code="org.jboss.mq.pm.rollinglogged.PersistenceManager"
name="JBossMQ:service=PersistenceManager">
<attribute name="DataDirectory">../../db/jbossmq/</attribute>
</mbean>
Mi
permette di memorizzare diversi messaggi in file di
log nella directory definita da 'DataDirectory'.
Se voglio cambiare il tipo di persistenza per File e
Logged è sufficiente cambiare 'code' dell'mbean;
in particolare per File è 'org.jboss.mq.pm.file.PersistenceManager'
mentre per la Logged e 'org.jboss.mq.pm.logged.PersistenceManager'.
Discorso a parte è per la persistenza JDBC.
Persistenza
JDBC
Per
questo tipo di persistenza ho bisogno di un db di appoggio.
Devo creare :
- le
seguenti tabelle:
CREATE TABLE JMS_MESSAGES(
MESSAGEID CHAR(17) NOT NULL,
DESTINATION VARCHAR(30) NOT NULL,
MESSAGEBLOB BLOB,
PRIMARY KEY (MESSAGEID, DESTINATION));
CREATE INDEX JMS_MESSAGES_DEST ON JMS_MESSAGES(DESTINATION);
CREATE TABLE JMS_TRANSACTIONS(
ID CHAR(17)
);
-
configurare
una connessione JDBC nel file jcml.jboss ( vedi
articolo Configurare una
connessione a db con JBoss 2.4.x) es con il nome
'OracleDS'
- inserire
nel file jboss.jcml il seguente codice (commentando
quello precedente):
<mbean
code="org.jboss.mq.pm.jdbc.PersistenceManager"
name="JBossMQ:service=PersistenceManager">
<attribute name="JmsDBPoolName">java:/OracleDS
</attribute>
</mbean>
Es
di codice per un subscriber:
private
void method(String factoryJNDI, String topicJNDI
String user,String password){
Hashtable props = new Hashtable();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingConnectionFactory");
props.put(Context.PROVIDER_URL,"localhost:1099");
props.put("java.naming.rmi.security","yes");
props.put(Context.URL_PKG_PREFIXES,"org.jboss.naming");
Context context = new InitialContext(props);
TopicConnectionFactory topicFactory =
(TopicConnectionFactory)context.lookup(factoryJNDI);
TopicConnection topicConnection =
topicFactory.createTopicConnection(user,password);
TopicSession topicSession = topicConnection.createTopicSession(
false,Session.AUTO_ACKNOWLEDGE);
Topic topic = (Topic)context.lookup(topicJNDI);
TopicSubscriber topicSubscriber =
topicSession.createDurableSubscriber(topic,user);
}
File jboss.xml
Se
voglio attenermi alle specifiche J2EE devo rimappare
le risorse utilizzando i file messi a disposizione da
JBoss.
Dopo il deploy avrò il riferimento alle mie risorse
all'interno del file ejb-jar.xml es. per un session
bean
<session>
<ejb-name>nomeBean</ejb-name>
...
<resource-env-ref>
<resource-env-ref-name>jms/testTopic
</resource-env-ref-name>
<resource-env-ref-type>javax.jms.Topic
</resource-env-ref-type>
</resource-env-ref>
</session>
la corrispondente porzione di codice nel file jboss.xml:
<session>
<ejb-name>nomeBean</ejb-name>
<resource-env-ref>
<resource-env-ref-name>jms/testTopic
</resource-env-ref-name>
<jndi-name>topic/testTopic</jndi-name>
</resource-env-ref>
</session>
così
facendo nella look up potrò scrivere
InitialContext
iniCtx = new InitialContext();
Topic topic = (Topic)iniCtx.lookup("java:comp/env/jms/testTopic");
Nel
caso utilizzi un MDB utilizzando una scrittura persistente
dei messaggi distinguo 2 casi di persistenza 1) BPM,
2) CMP
1)
Tralasciando il codice i file di configurazione saranno:
file
ejb-jar.xml:
..
<message-driven>
<ejb-name>nome</ejb-name>
<ejb-class>nome classe<ejb-class>
<transaction-type>Bean</transaction-type>
<acknowledge-mode>Auto-acknowledge</acknowledge-mode>
<message-driven-destination>
<destination-type>javax.jms.Topic</destination-type>
</message-driven-destination>
</message-driven>
file jboss.xml:
<message-driven>
<ejb-name>nome</ejb-name>
<resource-env-ref>
<resource-env-ref-name>jms/testTopic
</resource-env-ref-name>
<jndi-name>topic/testTopic</jndi-name>
</resource-env-ref>
</message-driven>
in questo caso tutta la logica di 'gestione' della topic
è fatta da codice.
2)
CMP:
file
ejb-jar.xml:
...
<message-driven>
<ejb-name>nome</ejb-name>
<ejb-class>nome classe<ejb-class>
<transaction-type>Container</transaction-type>
<acknowledge-mode>Auto-acknowledge</acknowledge-mode>
<message-driven-destination>
<destination-type>javax.jms.Topic</destination-type>
<subscription-durability>Durable
</subscription-durability >
</message-driven-destination>
</message-driven>
file
jboss.xml: (Vedi Gestione Utente file jbossmq-state.xml)
<message-driven>
<ejb-name>nome</ejb-name>
<resource-env-ref>
<resource-env-ref-name>jms/testTopic
</resource-env-ref-name>
<jndi-name>topic/testTopic</jndi-name>
</resource-env-ref>
<mdb-user>Davide</mdb-user>
<mdb-passwd>Yarelys</mdb-passwd>
<mdb-subscriber-id>Naike</mdb-subscriber-id>
</message-driven>
Come
ci si può immaginare il codice con la CMP sarà
molto più snello poiché tutte le operazioni
di 'autenticazione', settaggio ID etc. verranno fatte
dal Container.
Conclusioni
Come già citato il comportamento di JBoss è
all'altezza di altri, anche se purtroppo più
si cerca di approfondire e più la documentazione
è centellinata. Il più grosso lavoro a
volte consiste nel leggere lunghissime mailing list
(www.jboss.org) per risolvere problemi di qualche riga
di codice.
E' vero anche, questo è un mio personale pensiero,
che se non si 'soffre' non ci si diverte.
Bibliografia
[1] * "Manual - online HTML version"- www.jboss.org
[2] * SCOTT STARK, MARC FLEURY "JBoss Administration
and Development "- JBoss Group
|