-
Notifications
You must be signed in to change notification settings - Fork 208
/
appserver-integration.xml
762 lines (739 loc) · 41.6 KB
/
appserver-integration.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
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Copyright © 2009 Red Hat, Inc. and others. -->
<!-- -->
<!-- The text of and illustrations in this document are licensed by Red Hat under -->
<!-- a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). -->
<!-- -->
<!-- An explanation of CC-BY-SA is available at -->
<!-- -->
<!-- http://creativecommons.org/licenses/by-sa/3.0/. -->
<!-- -->
<!-- In accordance with CC-BY-SA, if you distribute this document or an adaptation -->
<!-- of it, you must provide the URL for the original version. -->
<!-- -->
<!-- Red Hat, as the licensor of this document, waives the right to enforce, -->
<!-- and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent -->
<!-- permitted by applicable law. -->
<!-- ============================================================================= -->
<chapter id="appserver-integration">
<title>Application Server Integration and Java EE</title>
<para>HornetQ can be easily installed in JBoss Application Server 4 or later. For details on
installing HornetQ in the JBoss Application Server please refer to quick-start guide.</para>
<para>Since HornetQ also provides a JCA adaptor, it should also be possible to integrate HornetQ
as a JMS provider in other JEE compliant app servers. For instructions on how to integrate a
remote JCA adaptor into another application sever, please consult the other application server's
instructions.</para>
<para>A JCA Adapter basically controls the inflow of messages to Message Driven Beans and the
outflow of messages sent from other JEE components, e.g. EJBs and Servlets.</para>
<para>This section explains the basics behind configuring the different JEE components in the
AS.</para>
<section>
<title>Configuring Message Driven Beans</title>
<para>The delivery of messages to an MDB using HornetQ is configured on the JCA Adapter via
a configuration file <literal>ra.xml</literal> which can be found under in the <literal
>jms-ra.rar</literal> archive of directory. By default this is configured to consume
messages using an InVM connector from the instance of HornetQ running within the
application server. A full list of what is configurable is found later in this chapter. </para>
<para>All MDB's however need to have the destination type and the destination configured.
The following example shows how this can be done via annotations.</para>
<programlisting>@MessageDriven(name = "MDBExample",
activationConfig =
{
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue")
})
@ResourceAdapter("hornetq-ra.rar")
public class MDBExample implements MessageListener
{
public void onMessage(Message message)...
}</programlisting>
<para>In this example you can see that the MDB will consume messages from a queue that is
mapped into JNDI with the binding <literal>queue/testQueue</literal>. This queue must be
preconfigured in the usual way using the HornetQ configuration files.</para>
<para>The <literal>ResourceAdapter</literal> annotation is used to specify which adaptor
should be used. To use this you will need to import <literal
>org.jboss.ejb3.annotation.ResourceAdapter</literal> which can be found in the
<literal>jboss-ejb3-ext-api.jar</literal> which can be found in the jboss
repository. Alternatively you can add use a deployment descriptor and add something like
the following to <literal
>jboss.xml</literal><programlisting><message-driven>
<ejb-name>ExampleMDB</ejb-name>
<resource-adapter-name>quartz-ra.rar</resource-adapter-name>
</message-driven>
</programlisting>You
can also rename the hornetq-ra.rar directory to jms-ra.rar and neither the annotation or
the extra descriptor information will be needed. If you do this you will need to edit
the <literal>jms-ds.xml</literal> datasource file and change <literal>rar-name</literal>
element.</para>
<para>All the examples shipped with the HornetQ distribution use the annotation.</para>
<section>
<title>Using Container Managed Transactions</title>
<para>When an MDB is using Container Managed Transactions (CMT), the delivery of the
message is done within the scope of a JTA transaction. The commit or rollback of
this transaction is controlled by the container itself. If the transaction is rolled
back then the message delivery semantics will kick in (by default this is to try and
redeliver the message up to 10 times before sending to a DLQ). Using annotations
this would be configured as follows:</para>
<programlisting>@MessageDriven(name = "MDB_CMP_TxRequiredExample",
activationConfig =
{
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue")
})
@TransactionManagement(value= TransactionManagementType.CONTAINER)
@TransactionAttribute(value= TransactionAttributeType.REQUIRED)
@ResourceAdapter("hornetq-ra.rar")
public class MDB_CMP_TxRequiredExample implements MessageListener
{
public void onMessage(Message message)...
}</programlisting>
<para>The <literal>TransactionManagement</literal> annotation tells the container to
treat this MDB to use Container Managed Persistence. The <literal
>TransactionAttribute</literal> annotation tells the container that a JTA
transaction is required for this MDB. Note that the only other valid value for this
is <literal>TransactionAttributeType.NOT_SUPPORTED</literal> which tells the
container that this MDB does not support JTA transactions and one should not be
created.</para>
<para>It is also possible to inform the container that it must rollback the transaction
by calling <literal>setRollbackOnly</literal> on the <literal
>MessageDrivenContext</literal>. The code for this would look something
like:</para>
<programlisting> @Resource
MessageDrivenContext ctx;
public void onMessage(Message message)
{
try
{
//something here fails
}
catch (Exception e)
{
ctx.setRollbackOnly();
}
}</programlisting>
<para>If you don't want the over head of an xa transaction being created every time but
you would still like the message delivered within a transaction (i.e. you are only
using a JMS resource) then you can configure the MDB to use a local transaction.
This would be configured as such:</para>
<programlisting>@MessageDriven(name = "MDB_CMP_TxLocalExample",
activationConfig =
{
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"),
@ActivationConfigProperty(propertyName = "useLocalTx", propertyValue = "true")
})
@TransactionManagement(value = TransactionManagementType.CONTAINER)
@TransactionAttribute(value = TransactionAttributeType.NOT_SUPPORTED)
@ResourceAdapter("hornetq-ra.rar")
public class MDB_CMP_TxLocalExample implements MessageListener
{
public void onMessage(Message message)...
}</programlisting>
</section>
<section>
<title>Using Bean Managed Transactions</title>
<para>Message driven beans can also be configured to use Bean Managed Transactions
(BMT). In this case a User Transaction is created. This would be configured as
follows:</para>
<programlisting>@MessageDriven(name = "MDB_BMPExample",
activationConfig =
{
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Dups-ok-acknowledge")
})
@TransactionManagement(value= TransactionManagementType.BEAN)
@ResourceAdapter("hornetq-ra.rar")
public class MDB_BMPExample implements MessageListener
{
public void onMessage(Message message)
}</programlisting>
<para>When using Bean Managed Transactions the message delivery to the MDB will occur
outside the scope of the user transaction and use the acknowledge mode specified by
the user with the <literal>acknowledgeMode</literal> property. There are only 2
acceptable values for this <literal>Auto-acknowledge</literal> and <literal
>Dups-ok-acknowledge</literal>. Please note that because the message delivery is outside
the scope of the transaction a failure within the MDB will not cause the message to
be redelivered.</para>
<para>A user would control the lifecycle of the transaction something like the
following:</para>
<programlisting> @Resource
MessageDrivenContext ctx;
public void onMessage(Message message)
{
UserTransaction tx;
try
{
TextMessage textMessage = (TextMessage)message;
String text = textMessage.getText();
UserTransaction tx = ctx.getUserTransaction();
tx.begin();
//do some stuff within the transaction
tx.commit();
}
catch (Exception e)
{
tx.rollback();
}
}</programlisting>
</section>
<section>
<title>Using Message Selectors with MDB's</title>
<para>It is also possible to use MDB's with message selectors. To do this simple define
your message selector as follows:</para>
<programlisting>@MessageDriven(name = "MDBMessageSelectorExample",
activationConfig =
{
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"),
@ActivationConfigProperty(propertyName = "messageSelector", propertyValue = "color = 'RED'")
})
@TransactionManagement(value= TransactionManagementType.CONTAINER)
@TransactionAttribute(value= TransactionAttributeType.REQUIRED)
@ResourceAdapter("hornetq-ra.rar")
public class MDBMessageSelectorExample implements MessageListener
{
public void onMessage(Message message)....
}</programlisting>
</section>
</section>
<section>
<title>Sending Messages from within JEE components</title>
<para>The JCA adapter can also be used for sending messages. The Connection Factory to use
is configured by default in the <literal>jms-ds.xml</literal> file and is mapped to
<literal>java:/JmsXA</literal>. Using this from within a JEE component will mean
that the sending of the message will be done as part of the JTA transaction being used
by the component.</para>
<para>This means that if the sending of the message fails the overall transaction would
rollback and the message redelivered. Heres an example of this from within an
MDB:</para>
<programlisting>@MessageDriven(name = "MDBMessageSendTxExample",
activationConfig =
{
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue")
})
@TransactionManagement(value= TransactionManagementType.CONTAINER)
@TransactionAttribute(value= TransactionAttributeType.REQUIRED)
@ResourceAdapter("hornetq-ra.rar")
public class MDBMessageSendTxExample implements MessageListener
{
@Resource(mappedName = "java:/JmsXA")
ConnectionFactory connectionFactory;
@Resource(mappedName = "queue/replyQueue")
Queue replyQueue;
public void onMessage(Message message)
{
Connection conn = null;
try
{
//Step 9. We know the client is sending a text message so we cast
TextMessage textMessage = (TextMessage)message;
//Step 10. get the text from the message.
String text = textMessage.getText();
System.out.println("message " + text);
conn = connectionFactory.createConnection();
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = sess.createProducer(replyQueue);
producer.send(sess.createTextMessage("this is a reply"));
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if(conn != null)
{
try
{
conn.close();
}
catch (JMSException e)
{
}
}
}
}
}</programlisting>
<para>In JBoss Application Server you can use the JMS JCA adapter for sending messages from
EJBs (including Session, Entity and Message Driven Beans), Servlets (including jsps) and
custom MBeans.</para>
</section>
<section>
<title>Configuring the JCA Adaptor</title>
<para>The Java Connector Architecture (JCA) Adapter is what allows HornetQ to be integrated
with JEE components such as MDB's and EJB's. It configures how components such as MDB's
consume messages from the HornetQ server and also how components such as EJB's or
Servlet's can send messages.</para>
<para>The HornetQ JCA adapter is deployed via the <literal>jms-ra.rar</literal> archive. The
configuration of the adapter is found in this archive under <literal
>META-INF/ra.xml</literal>.</para>
<para>The configuration will look something like the following:</para>
<programlisting><resourceadapter>
<resourceadapter-class>org.hornetq.ra.HornetQResourceAdapter</resourceadapter-class>
<config-property>
<description>The transport type</description>
<config-property-name>ConnectorClassName</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>org.hornetq.core.remoting.impl.invm.InVMConnectorF
actory</config-property-value>
</config-property>
<config-property>
<description>The transport configuration. These values must be in the form of key=val;key=val;</description>
<config-property-name>ConnectionParameters</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>server-id=0</config-property-value>
</config-property>
<outbound-resourceadapter>
<connection-definition>
<managedconnectionfactory-class>org.hornetq.ra.HornetQRAManagedConnection
Factory</managedconnectionfactory-class>
<config-property>
<description>The default session type</description>
<config-property-name>SessionDefaultType</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>javax.jms.Queue</config-property-value>
</config-property>
<config-property>
<description>Try to obtain a lock within specified number of seconds; less
than or equal to 0 disable this functionality</description>
<config-property-name>UseTryLock</config-property-name>
<config-property-type>java.lang.Integer</config-property-type>
<config-property-value>0</config-property-value>
</config-property>
<connectionfactory-interface>org.hornetq.ra.HornetQRAConnectionFactory
</connectionfactory-interface>
<connectionfactororg.hornetq.ra.HornetQConnectionFactoryImplonFactoryImpl
</connectionfactory-impl-class>
<connection-interface>javax.jms.Session</connection-interface>
<connection-impl-class>org.hornetq.ra.HornetQRASession
</connection-impl-class>
</connection-definition>
<transaction-support>XATransaction</transaction-support>
<authentication-mechanism>
<authentication-mechanism-type>BasicPassword
</authentication-mechanism-type>
<credential-interface>javax.resource.spi.security.PasswordCredential
</credential-interface>
</authentication-mechanism>
<reauthentication-support>false</reauthentication-support>
</outbound-resourceadapter>
<inbound-resourceadapter>
<messageadapter>
<messagelistener>
<messagelistener-type>javax.jms.MessageListener</messagelistener-type>
<activationspec>
<activationspec-class>org.hornetq.ra.inflow.HornetQActivationSpec
</activationspec-class>
<required-config-property>
<config-property-name>destination</config-property-name>
</required-config-property>
</activationspec>
</messagelistener>
</messageadapter>
</inbound-resourceadapter>
</resourceadapter></programlisting>
<para>There are 3 main parts to this configuration.</para>
<orderedlist>
<listitem>
<para>A set of global properties for the adapter</para>
</listitem>
<listitem>
<para>The configuration for the outbound part of the adapter. This is used for
creating JMS resources within EE components. </para>
</listitem>
<listitem>
<para>The configuration of the inbound part of the adapter. This is used for
controlling the consumption of messages via MDB's. </para>
</listitem>
</orderedlist>
<section>
<title>Adapter Global properties</title>
<para>The first element you see is <literal>resourceadapter-class</literal> which should
be left unchanged. This is the HornetQ resource adapter class.</para>
<para>After that there is a list of configuration properties. This will be where most of
the configuration is done. The first 2 configure the transport used by the adapter
and the rest configure the connection factory itself.<note><para>All connection
factory properties will use the defaults when not provided. This is accept
for the <literal>reconnectAttempts</literal> which will default to -1 which
signifies that the connection should attempt to reconnect on connection
failure indefinately. This is only used when the adapter is configured to
connect to a remote server as an InVM connector can never
fail.</para></note></para>
<para>The following table explains what each property is for.</para>
<table frame="topbot" border="2">
<title>Global Configuration Properties</title>
<tgroup cols="3">
<colspec colname="c1" colnum="1"/>
<colspec colname="c2" colnum="2"/>
<colspec colname="c3" colnum="3"/>
<thead>
<row>
<entry>Property Name</entry>
<entry>Property Type</entry>
<entry>Property Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>ConnectorClassName</entry>
<entry>String</entry>
<entry>The Connector class name see <xref
linkend="configuring-transports"/> for info on available
connectors</entry>
</row>
<row>
<entry>ConnectionParameters</entry>
<entry>String</entry>
<entry>The transport configuration. These values must be in the form of
key=val;key=val; and will be specific to the connector used</entry>
</row>
<row>
<entry>useLocalTx</entry>
<entry>boolean</entry>
<entry>True will enable local transaction optimisation.</entry>
</row>
<row>
<entry>UseXA</entry>
<entry>boolean</entry>
<entry>Whether XA should be used</entry>
</row>
<row>
<entry>UserName</entry>
<entry>String</entry>
<entry>The user name to use when making a connection </entry>
</row>
<row>
<entry>Password</entry>
<entry>String</entry>
<entry>The password to use when making a connection</entry>
</row>
<row>
<entry>BackUpTransportType</entry>
<entry>String</entry>
<entry>The back up transport to use on failure.</entry>
</row>
<row>
<entry>TransportConfiguration</entry>
<entry>String</entry>
<entry>The back up transport configuration</entry>
</row>
<row>
<entry>DiscoveryGroupAddress</entry>
<entry>String</entry>
<entry>The discovery group address to use to autodetect a server</entry>
</row>
<row>
<entry>DiscoveryGroupPort</entry>
<entry>integer</entry>
<entry>The port to use for discovery</entry>
</row>
<row>
<entry>DiscoveryRefreshTimeout</entry>
<entry>long</entry>
<entry>The timeout, in milli seconds, to refresh.</entry>
</row>
<row>
<entry>DiscoveryInitialWaitTimeout</entry>
<entry>long</entry>
<entry>The initial time to wait for discovery.</entry>
</row>
<row>
<entry>LoadBalancingPolicyClassName</entry>
<entry>String</entry>
<entry>The load balancing policy class to use.</entry>
</row>
<row>
<entry>PingPeriod</entry>
<entry>long</entry>
<entry>The period, in milliseconds, to ping the server for
failure.</entry>
</row>
<row>
<entry>ConnectionTTL</entry>
<entry>long</entry>
<entry>The time to live for the connection.</entry>
</row>
<row>
<entry>CallTimeout</entry>
<entry>long</entry>
<entry>the call timeout, in milli seconds, for each packet sent.</entry>
</row>
<row>
<entry>DupsOKBatchSize</entry>
<entry>integer</entry>
<entry>The batch size of message acks to use if Dups ok is used.</entry>
</row>
</tbody>
</tgroup>
</table>
<para>continued..</para>
<informaltable frame="topbot">
<tgroup cols="3">
<colspec colname="c1" colnum="1"/>
<colspec colname="c2" colnum="2"/>
<colspec colname="c3" colnum="3"/>
<tbody>
<row>
<entry>TransactionBatchSize</entry>
<entry>integer</entry>
<entry>The batch size to use for sending messages within a
transaction</entry>
</row>
<row>
<entry>ConsumerWindowSize</entry>
<entry>integer</entry>
<entry>The window size for the consumers internal buffer.</entry>
</row>
<row>
<entry>ConsumerMaxRate</entry>
<entry>integer</entry>
<entry>The max rate a consumer can receive.</entry>
</row>
<row>
<entry>ConfirmationWindowSize</entry>
<entry>integer</entry>
<entry>The window size for confirmations.</entry>
</row>
<row>
<entry>ProducerMaxRate</entry>
<entry>integer</entry>
<entry>The max rate a producer can send messages.</entry>
</row>
<row>
<entry>MinLargeMessageSize</entry>
<entry>integer</entry>
<entry>The size a message can be, in bytes, before it is sent as a multi
part large message.</entry>
</row>
<row>
<entry>BlockOnAcknowledge</entry>
<entry>boolean</entry>
<entry>If true then block on acknowledge of messages.</entry>
</row>
<row>
<entry>BlockOnNonDurableSend</entry>
<entry>boolean</entry>
<entry>If true then block when sending non-durable messages</entry>
</row>
<row>
<entry>BlockOnDurableSend</entry>
<entry>boolean</entry>
<entry>If true then block when sending durable messages</entry>
</row>
<row>
<entry>AutoGroup</entry>
<entry>boolean</entry>
<entry>If true then auto group messages</entry>
</row>
<row>
<entry>PreAcknowledge</entry>
<entry>boolean</entry>
<entry>Whether to pre acknowledge messages before sending to
consumer</entry>
</row>
<row>
<entry>reconnectAttempts</entry>
<entry>Integer</entry>
<entry>How attemts to try at reconnecting, default is -1</entry>
</row>
<row>
<entry>RetryInterval</entry>
<entry>long</entry>
<entry>How long to wait , in milli seconds, before retrying a failed
connection</entry>
</row>
<row>
<entry>RetryIntervalMultiplier</entry>
<entry>double</entry>
<entry>Used for calculating the retry interval</entry>
</row>
<row>
<entry>FailoverOnServerShutdown</entry>
<entry>boolean</entry>
<entry>If true client will reconnect to another server if
available</entry>
</row>
<row>
<entry>ClientID</entry>
<entry>String</entry>
<entry>The client ID of the connection</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
<section>
<title>Adapter Outbound configuration</title>
<para>The outbound configuration should remain unchanged as they define connection
factories that are used by Java EE components. These Connection Factories can be
defined inside a configuration file that matches the name <literal
>*-ds.xml</literal>. You'll find a default <literal>jms-ds.xml</literal>
configuration under the <literal>hornetq.sar</literal> directory in the Jboss AS
deployment. The connection factories defined in the config file inherit their
properties from the main <literal>ra.xml</literal> configuration but can also be
overridden, the following example show how to define one.</para>
<para>Please note that this configuration only applies to install the HornetQ resource
adapter in the JBoss Application Server. If you are using another JEE application
server please refer to your application servers documentation for how to do
this.</para>
<programlisting><tx-connection-factory>
<jndi-name>RemoteJmsXA</jndi-name>
<xa-transaction/>
<rar-name>jms-ra.rar</rar-name>
<connection-definition>org.hornetq.ra.HornetQRAConnectionFactory
</connection-definition>
<config-property name="SessionDefaultType" type="String">javax.jms.Topic
</config-property>
<config-property name="ConnectorClassName" type="String">
org.hornetq.core.remoting.impl.netty.NettyConnectorFactory
</config-property>
<config-property name="ConnectionParameters" type="String">
port=5445</config-property>
<max-pool-size>20</max-pool-size>
</tx-connection-factory></programlisting>
<para>In this example the connection factory will be bound to JNDI with the name
<literal>RemoteJmsXA</literal> and can be looked up in the usual way using JNDI
or defined within the EJB or MDB as such:</para>
<programlisting>@Resource(mappedName="java:RemoteJmsXA")
private ConnectionFactory connectionFactory;</programlisting>
<para>The <literal>config-property</literal> elements are what over rides those in the
<literal>ra.xml</literal> config. Any of the elements pertaining to the
connection factory can be over ridden here.</para>
</section>
<section>
<title>Adapter Inbound configuration</title>
<para>The inbound configuration should again remain unchanged. This controls what
forwards messages onto MDB's. It is possible to override properties on the MDB by
adding an activation configuration to the MDB itself. This could be used to
configure the MDB to consume from a different server. The next section demonstrates
over riding the configuration.</para>
</section>
</section>
<section>
<title>High Availability JNDI (HA-JNDI)</title>
<para>If you are using JNDI to look-up JMS queues, topics and connection factories from a
cluster of servers, it is likely you will want to use HA-JNDI so that your JNDI look-ups
will continue to work if one or more of the servers in the cluster fail.</para>
<para>HA-JNDI is a JBoss Application Server service which allows you to use JNDI from
clients without them having to know the exact JNDI connection details of every server in
the cluster. This service is only available if using a cluster of JBoss Application
Server instances.</para>
<para>To use it use the following properties when connecting to JNDI.</para>
<programlisting>Hashtable<String, String> jndiParameters = new Hashtable<String, String>();
jndiParameters.put("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
jndiParameters.put("java.naming.factory.url.pkgs=",
"org.jboss.naming:org.jnp.interfaces");
initialContext = new InitialContext(jndiParameters);</programlisting>
<para>For more information on using HA-JNDI see the <ulink
url="http://www.jboss.org/file-access/default/members/jbossas/freezone/docs/Clustering_Guide/5/html/clustering-jndi.html"
>JBoss Application Server clustering documentation</ulink></para>
</section>
<section id="xa-recovery">
<title>XA Recovery</title>
<para><emphasis>XA recovery</emphasis> deals with system or application failures to ensure
that of a transaction are applied consistently to all resources affected by the
transaction, even if any of the application processes or the machine hosting them crash
or lose network connectivity. For more information on XA Recovery,please refer to <ulink
url="http://www.jboss.org/community/wiki/JBossTransactions">JBoss
Transactions</ulink>.</para>
<para>When HornetQ is integrated with JBoss AS, it can take advantage of JBoss Transactions
to provide recovery of messaging resources. If messages are involved in a XA
transaction, in the event of a server crash, the recovery manager will ensure that the
transactions are recovered and the messages will either be committed or rolled back
(depending on the transaction outcome) when the server is restarted.</para>
<section>
<title>XA Recovery Configuration</title>
<para>To enable HornetQs XA Recovery, the Recovery Manager must be configured to connect
to HornetQ to recover its resources. The following property must be added to the
<literal>jta</literal> section of <literal>conf/jbossts-properties.xml</literal>
of JBoss AS profiles:</para>
<programlisting>
<properties depends="arjuna" name="jta">
...
<property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.HornetQ1"
value="org.hornetq.jms.server.recovery.HornetQXAResourceRecovery;[connection configuration]"/>
</properties>
</programlisting>
<para>The <literal>[connection configuration]</literal> contains all the information
required to connect to HornetQ node under the form <literal>[connector factory class
name],[user name], [password], [connector parameters]</literal>. </para>
<itemizedlist>
<listitem>
<para><literal>[connector factory class name]</literal> corresponds to the name
of the <literal>ConnectorFactory</literal> used to connect to HornetQ.
Values can be <literal
>org.hornetq.core.remoting.impl.invm.InVMConnectorFactory</literal> or
<literal
>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</literal></para>
</listitem>
<listitem>
<para><literal>[user name]</literal> is the user name to create a client
session. It is optional</para>
</listitem>
<listitem>
<para><literal>[password]</literal> is the password to create a client session.
It is mandatory only if the user name is specified</para>
</listitem>
<listitem>
<para><literal>[connector parameters]</literal> is a list of comma-separated
key=value pair which are passed to the connector factory (see <xref
linkend="configuring-transports"/> for a list of the transport
parameters).</para>
</listitem>
</itemizedlist>
<note>
<para>HornetQ must have a valid acceptor which corresponds to the connector
specified in <literal>conf/jbossts-properties.xml</literal>.</para>
</note>
<section>
<title>Configuration Settings</title>
<para>If HornetQ is configured with a default in-vm acceptor:</para>
<programlisting>
<acceptor name="in-vm">
<factory-class>org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory</factory-class>
</acceptor>
</programlisting>
<para>the corresponding configuration in <literal
>conf/jbossts-properties.xml</literal> is:</para>
<programlisting>
<property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.HORNETQ1"
value="org.hornetq.jms.server.recovery.HornetQXAResourceRecovery;org.hornetq.core.remoting.impl.invm.InVMConnectorFactory"/>
</programlisting>
<para>If it is now configured with a netty acceptor on a non-default port:</para>
<programlisting>
<acceptor name="netty">
<factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
<param key="port" value="8888"/>
</acceptor>
</programlisting>
<para>the corresponding configuration in <literal
>conf/jbossts-properties.xml</literal> is:</para>
<programlisting>
<property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.HORNETQ1"
value="org.hornetq.jms.server.recovery.HornetQXAResourceRecovery;org.hornetq.core.remoting.impl.netty.NettyConnectorFactory, , , port=8888"/>
</programlisting>
<note>
<para>Note the additional commas to skip the user and password before connector
parameters</para>
</note>
<para>If the recovery must use <literal>admin, adminpass</literal>, the
configuration would have been:</para>
<programlisting>
<property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.HORNETQ1"
value="org.hornetq.jms.server.recovery.HornetQXAResourceRecovery;org.hornetq.core.remoting.impl.netty.NettyConnectorFactory, admin, adminpass, port=8888"/>
</programlisting>
<para>Configuring HornetQ with an invm acceptor and configuring the Recovery Manager
with an invm connector is the recommended way to enable XA Recovery.</para>
</section>
</section>
<section>
<title>Example</title>
<para>See <xref linkend="xa-recovery-example"/> which shows how to configure XA Recovery
and recover messages after a server crash.</para>
</section>
</section>
</chapter>