<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3893978476954864710</id><updated>2012-01-28T22:02:58.629+01:00</updated><category term='CXF'/><category term='login.config'/><category term='network of brokers'/><category term='transaction'/><category term='FuseSource'/><category term='authentication'/><category term='ErrorHandler'/><category term='producer flow control'/><category term='TimeStampPlugin'/><category term='security'/><category term='Ruby SOAP'/><category term='TimeStampingBrokerPlugin'/><category term='ServiceMix'/><category term='JMSExpiration'/><category term='ActiveMQ'/><category term='camel-jms'/><category term='CachingConnectionFactory'/><category term='professional support'/><category term='cache level'/><category term='memory limit'/><category term='SingleConnectionFactory'/><category term='master slave'/><category term='LDAP'/><category term='JDBC'/><category term='queue'/><category term='missing messages'/><category term='temp storage'/><category term='subscription'/><category term='Jetty'/><category term='sendFailIfNoSpace'/><category term='Topic'/><category term='broker'/><category term='JMS'/><category term='Camel'/><category term='Apache'/><category term='Spring'/><category term='OSGI CXF bus failover'/><category term='systemUsage'/><category term='hung'/><category term='DMLC'/><category term='authorization'/><category term='PooledConnectionFactory'/><category term='CACHE_CONSUMER'/><title type='text'>Ramblings on pretty much anything technical.</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>27</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-5203823643156962681</id><published>2011-12-22T09:08:00.000+01:00</published><updated>2011-12-22T10:05:42.745+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='login.config'/><category scheme='http://www.blogger.com/atom/ns#' term='LDAP'/><category scheme='http://www.blogger.com/atom/ns#' term='Jetty'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveMQ'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='authentication'/><title type='text'>Securing the ActiveMQ web console using LDAP based authentication</title><content type='html'>In my &lt;a href="http://tmielke.blogspot.com/2011/12/activemq-ldap-based-authentication-and.html"&gt;previous blog post&lt;/a&gt; I described how to configure LDAP based authentication and authorization in ActiveMQ while also allowing anonymous access to certain destinations in the broker. That previous post as well as this post is based on the &lt;a href="http://fusesource.com/docs/broker/5.5/security/LDAP.html" target="_blank"&gt;LDAP tutorial&lt;/a&gt; in the ActiveMQ &lt;a href="http://fusesource.com/docs/broker/5.5/security/front.html" target="_blank"&gt;Security Guide&lt;/a&gt; provided by &lt;a href="http://fusesource.com/"&gt;Fusesource.com&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;In this article I want to expand on the previous post and show how to secure the ActiveMQ web console so that web users will be authenticated against user information stored in LDAP. All the configuration from the previous post can extended in order to secure the web console but I will provide full configuration here as well so that there is no need to copy and paste config snippets from the previous article. &lt;br /&gt;I recommend the &lt;a href="http://fusesource.com/docs/broker/5.5/security/LDAP.html" target="_blank"&gt;LDAP tutorial&lt;/a&gt; as a prerequisite to this article as it populates the LDAP server with the right security information (users, passwords, groups and roles), which is needed if you want to follow the steps of this blog post. &lt;br /&gt;&lt;br /&gt;The ActiveMQ web console internally uses Jetty as the web container. So securing the web console basically means configuring the Jetty HTTP server to authenticate any web clients. The way how Jetty gets secured is completely independent from the way how ActiveMQ gets secured. However both support JAAS so the actual configuration principles are the same. Jetty also supports LDAP based authentication through its own JAAS LoginModule class &lt;a href="http://org.eclipse.jetty.plus.jaas.spi.ldaploginmodule/"&gt;org.eclipse.jetty.plus.jaas.spi.LdapLoginModule&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Prerequisites before taking off&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://fusesource.com/docs/broker/5.5/security/LDAP.html" target="_blank"&gt;LDAP tutorial&lt;/a&gt; in the ActiveMQ Security Guide (version 5.5) makes some configuration that will not work quite well with the JAAS LDAP login module used by the ActiveMQ web console (i.e. Jetty). Two configuration changes are required in your LDAP user and group data to successfully authenticate any web users via Jetty's LdapLoginModule. Here are the required changes to your LDAP data: &lt;br /&gt;&lt;br /&gt;&lt;b&gt;1) Store passwords in plain text in LDAP:&lt;/b&gt;&lt;br /&gt;The LDAP tutorial instructs you to store any user passwords as SHA hashes. See steps 18 and 19 of the &lt;a href="http://fusesource.com/docs/broker/5.5/security/LDAP-AddUserEntries.html" target="_blank"&gt;Add User Entries&lt;/a&gt; part of the tutorial (and Figure 6.7). The LdapLoginModule from Jetty reads that password from LDAP as it is (i.e. SHA hash) and tries to match it against the password supplied by the web user, which is in plain text. So the SHA hashed password stored in LDAP is string compared against the plain text password, which will obviously fail.&lt;br /&gt;Rather than storing the password as SHA hash in LDAP, store it in plain text.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-1Lii2h7XV5s/TvIMiRIUEJI/AAAAAAAAAB0/JcdxF-62qW0/s1600/newpassword.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-1Lii2h7XV5s/TvIMiRIUEJI/AAAAAAAAAB0/JcdxF-62qW0/s1600/newpassword.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;This needs to be done for all users.&lt;br /&gt;Storing the password in plain text will not change the ability of the ActiveMQ LDAPLoginModule class to authenticate users. This LoginModule takes a different approach. Rather than retrieving the password and comparing it against the password given by the user, it tries to bind the user (an operation on the LDAP server) whereby the password gets verified by the LDAP server and not by the LoginModule class. &lt;br /&gt;Perhaps there is a way to configure the Jetty LdapLoginModule to also work with SHA hashed password, however I did not find it (also tried DIGEST based authentication but that did not help). &lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;2) User to group mapping in LDAP must use users full dn + basedn name:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Steps 30-31 and figure 6.8 of the &lt;a href="http://fusesource.com/docs/broker/5.5/security/LDAP-AddUserEntries.html" target="_blank"&gt;Add User Entries&lt;/a&gt; part of the LDAP tutorial explain how to make users member of a particular group. It uses the member attribute of the groupOfNames LDAP class and the mapping to a user is done via the users uid attribute, like in this example mapping that is taken from the LDAP tutorial:&lt;br /&gt;&amp;nbsp; &lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;member=uid=jdoe&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This won't work with the Jetty LdapLoginModule implementation, as it queries for a users group using the user's full name (i.e. uid + base dn), e.g.&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;member=uid=jdoe,ou=User,ou=ActiveMQ,ou=system&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;and as a result won't find any user groups if the group members are only specified using the uid (i.e. jdoe).&lt;br /&gt;To overcome this difference in the LDAP login module implementations, it is necessary to always provide the dn + basedn of the user that you want to add to a group.&lt;br /&gt;E.g. rather than setting the members of a group like this ((see Figure 6.8 of the LDAP tutorial)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-zEVlaCCTl2g/TvIRzjC19II/AAAAAAAAACA/xqNjTWDW770/s1600/groupsOld.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-zEVlaCCTl2g/TvIRzjC19II/AAAAAAAAACA/xqNjTWDW770/s1600/groupsOld.png" /&gt;&lt;/a&gt;&lt;/div&gt;use this&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Zh2zkOzXrTc/TvIRzE7iQ_I/AAAAAAAAAB8/qEff61319LA/s1600/groupsNew.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-Zh2zkOzXrTc/TvIRzE7iQ_I/AAAAAAAAAB8/qEff61319LA/s1600/groupsNew.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;This change of users to groups wiring however requires an update on the ActiveMQ login module configuration in login.config from&lt;br /&gt;&amp;nbsp; &lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;roleSearchMatching="(member=uid={1})"&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;to&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &lt;b&gt;roleSearchMatching="(member=uid={1},ou=User,ou=ActiveMQ,ou=system)"&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;That way both, the LDAP LoginModule of ActiveMQ and Jetty will be able to retrieve the groups (roles) a user is in. &amp;nbsp; &lt;br /&gt;With these two changes to the LDAP data we are ready to go and configure the web console for LDAP based authentication.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Steps to securing the web console&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;All of the Jetty configuration in ActiveMQ is stored in $ACTIVEMQ_HOME/conf/jetty.xml. Its Spring config already instantiates a security handler but authentication is turned off by default via the authenticate=false property.&amp;nbsp; It needs to be enable in this bean:&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:595.0pt 842.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:595.0pt 842.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background: silver; color: #3f7f7f; font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco; mso-highlight: silver;"&gt;bean&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt; &lt;span style="color: #7f007f;"&gt;id&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"securityConstraint"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: #7f007f;"&gt;class&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"org.eclipse.jetty.http.security.Constraint"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt;property&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt; &lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"name"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: #7f007f;"&gt;value&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"BASIC"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt;property&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt; &lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"roles"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: #7f007f;"&gt;value&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"admins"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: teal;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt;property&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt; &lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"authenticate"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: #7f007f;"&gt;value&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"true"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: teal;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt;&lt;!--&lt;/span--&gt;&lt;span style="background: silver; color: #3f7f7f; font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco; mso-highlight: silver;"&gt;bean&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 10.0pt; mso-bidi-font-family: Monaco;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;br /&gt;Changing the "authenticate" property to "true" is required but isn't enough. Any authenticated user needs to have the role specified by the "roles" attribute in order to get authorized. The administrator role name in LDAP is called "admins" but the Jetty securityConstraint bean uses "admin" out of the box. It is necessary to change the value of the "roles" property to "admins" as in the above example. A fully configured jetty.xml is provided at the end of this article.&lt;br /&gt;&lt;br /&gt;Out of the box Jetty is configured to use a HashLoginService class, which simply reads the user credentials from a text file ${activemq.base}/conf/jetty-realm.properties. In order to authenticate against an LDAP server we need to configure a JAAS LoginService class:&lt;br /&gt;&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:595.0pt 842.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:595.0pt 842.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 10pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background: none repeat scroll 0% 0% silver; color: #3f7f7f; font-family: Monaco; font-size: 10pt;"&gt;bean&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt; &lt;span style="color: #7f007f;"&gt;id&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"securityLoginService"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: #7f007f;"&gt;class&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"org.eclipse.jetty.plus.jaas.JAASLoginService"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 10pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 10pt;"&gt;property&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt; &lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"name"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: #7f007f;"&gt;value&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"ActiveMQLDAPRealm"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 10pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 10pt;"&gt;property&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt; &lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"LoginModuleName"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: #7f007f;"&gt;value&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"jetty-ldap"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 10pt;"&gt;property&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt; &lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"CallbackHandlerClass"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: #7f007f;"&gt;value&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"org.eclipse.jetty.plus.jaas.callback.DefaultCallbackHandler"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 10pt;"&gt;property&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt; &lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"roleClassNames"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: #7f007f;"&gt;value&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"org.eclipse.jetty.plus.jaas.JAASRole"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 10pt;"&gt;&lt;span style="background: none repeat scroll 0% 0% silver; color: #3f7f7f; font-family: Monaco; font-size: 10pt;"&gt;bean&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 10pt;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="font-size: 10pt;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This JAASLoginService is configured for a LoginModuleName called "jetty-ldap". This name refers to the JAAS login module configuration in login.config. In the previous article I already provided a login.config to be used by ActiveMQ. You can simply add the following configuration to that same login.config:&lt;br /&gt;&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:595.0pt 842.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco; font-size: 10pt;"&gt;/** &lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;This LoginModule configuration is only used by Jetty when &lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;authentication of the web console is enabled.&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco; font-size: 10pt;"&gt;*/&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;jetty-ldap {&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;org.eclipse.jetty.plus.jaas.spi.LdapLoginModule required&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;debug=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"true"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;contextFactory=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"com.sun.jndi.ldap.LdapCtxFactory"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;hostname=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"localhost"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;port=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"10389"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;bindDn=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"uid=admin,ou=system"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;bindPassword=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"secret"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;authenticationMethod=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"simple"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;forceBindingLogin=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"false"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;userBaseDn=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"ou=User,ou=ActiveMQ,ou=system"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;userRdnAttribute=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"uid"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;userIdAttribute=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"uid"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;userPasswordAttribute=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"userPassword"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;userObjectClass=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"inetOrgPerson"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;roleBaseDn=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"ou=Group,ou=ActiveMQ,ou=system"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;roleNameAttribute=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"cn"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;roleMemberAttribute=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"member"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;roleObjectClass=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"groupOfNames"&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;authenticated=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 10pt;"&gt;"true"&lt;/span&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 10pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;};&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;Finally Jetty needs to be told where to find this login.config file via a Java property to the JVM.&lt;br /&gt;The easiest way is to add this propery to the bin/activemq script, e.g.&amp;nbsp; &lt;br /&gt;&lt;div class="MsoNormal"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&lt;span style="font-family: inherit; font-size: small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black; font-family: Monaco; font-size: 10pt;"&gt;&lt;br /&gt;ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS_MEMORY -Dorg.apache.activemq.UseDedicatedTaskRunner=true&amp;nbsp;&amp;nbsp; -Djava.util.logging.config.file=logging.properties &lt;b&gt;-Djava.security.auth.login.config=login.config"&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;That's about it. Assuming the data in LDAP is setup according to the prerequisites listed above, the ActiveMQ web console should now be secured. Trying to access http://localhost:8161 should now request a username and password from you which is then authenticated against the LDAP server.&lt;br /&gt;&lt;br /&gt;Note we did not need to change the broker configuration (with the exception of pre-requisite #2) as the authentication done in the web console (based on Jetty) is completely independent of the authentication done by ActiveMQ. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 10pt;"&gt;&lt;/span&gt;&lt;br /&gt;Links to all files used in this post:&lt;br /&gt;&lt;a href="http://abloggerscode.googlecode.com/svn/trunk/Articles/Blog/AMQJettyLDAP/jetty.xml"&gt;jetty.xml&lt;/a&gt;&lt;br /&gt;&lt;a href="http://abloggerscode.googlecode.com/svn/trunk/Articles/Blog/AMQJettyLDAP/login.config"&gt;login.config&lt;/a&gt;&lt;br /&gt;&lt;a href="http://abloggerscode.googlecode.com/svn/trunk/Articles/Blog/AMQJettyLDAP/activemq-ldap-with-anon-access.xml"&gt;activemq-ldap-with-anon-access.xml&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The relevant documentation that helped me on this subject:&lt;br /&gt;&lt;a href="http://wiki.eclipse.org/Jetty/Tutorial/JAAS#Configuring_a_JAASLoginService"&gt;Jetty JAAS Tutorial&lt;/a&gt; &lt;br /&gt;&lt;a href="http://wiki.eclipse.org/Jetty/Tutorial/Realms"&gt;Jetty Realms Tutorial&lt;/a&gt;&lt;br /&gt;&lt;a href="http://download.eclipse.org/jetty/stable-7/apidocs/"&gt;Jetty 7 JavaDoc&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Let me know if this post was helpful. &lt;br /&gt;&lt;span style="font-size: 10pt;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-5203823643156962681?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/5203823643156962681/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=5203823643156962681' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/5203823643156962681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/5203823643156962681'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2011/12/securing-activemq-web-console-using.html' title='Securing the ActiveMQ web console using LDAP based authentication'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-1Lii2h7XV5s/TvIMiRIUEJI/AAAAAAAAAB0/JcdxF-62qW0/s72-c/newpassword.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-8635008054801270165</id><published>2011-12-05T17:24:00.001+01:00</published><updated>2011-12-22T10:12:05.570+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='LDAP'/><category scheme='http://www.blogger.com/atom/ns#' term='authorization'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveMQ'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='authentication'/><title type='text'>ActiveMQ: LDAP based authentication and authorization</title><content type='html'>The FuseSource ActiveMQ &lt;a href="http://fusesource.com/docs/broker/5.5/security/front.html"&gt;Security Guide&lt;/a&gt; has two great chapters on how to configure ActiveMQ for authentication and authorization against an LDAP server. &lt;a href="http://fusesource.com/docs/broker/5.5/security/LDAP.html" target="_blank"&gt;Chapter 5&lt;/a&gt; even has a tutorial that contains step-by-step instructions on how to configure your LDAP server and ActiveMQ based on ApacheDS, an open-source LDAP server. If you need to secure your ActiveMQ broker, then I highly recommend this documentation.&lt;br /&gt;&lt;br /&gt;The tutorial in the Security Guide shows the relevant configuration needed so that &lt;u&gt;every&lt;/u&gt; JMS connection into the broker is authenticated and checked for authorization against the security information stored in an LDAP server.&lt;br /&gt;&lt;br /&gt;Sometimes you may want to allow anonymous access to certain destinations on your broker that are not critical while securing access to your critical destinations.&amp;nbsp; In this post I like to outline a possible solution for such use-case. I will assume the reader is generally familiar with LDAP based authentication and authorization in ActiveMQ. If not, I suggest to first consult the ActiveMQ &lt;a href="http://fusesource.com/docs/broker/5.5/security/front.html" target="_blank"&gt;Security Guide&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;When configuring ActiveMQ for JAAS based authentication against an LDAP server, the file login.config could read as follows (pretty much a copy-and-paste from the FuseSource Security Guide):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:595.0pt 842.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:Times; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}p {mso-style-noshow:yes; mso-style-priority:99; mso-margin-top-alt:auto; margin-right:0cm; mso-margin-bottom-alt:auto; margin-left:0cm; mso-pagination:widow-orphan; font-size:10.0pt; font-family:Times; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-bidi-font-family:"Times New Roman";}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:Times; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}p {mso-style-noshow:yes; mso-style-priority:99; mso-margin-top-alt:auto; margin-right:0cm; mso-margin-bottom-alt:auto; margin-left:0cm; mso-pagination:widow-orphan; font-size:10.0pt; font-family:Times; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-bidi-font-family:"Times New Roman";}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco;"&gt;/** JAAS LoginModule that uses LDAP basedauthentication. &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco;"&gt;Every connection into broker must supplyusername and password&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco;"&gt;for authentication to succeed. Anonymousaccess not allowed.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco;"&gt;*/&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;LDAPLogin {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; org.apache.activemq.jaas.LDAPLoginModulerequired&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; debug=&lt;/span&gt;&lt;b&gt;&lt;span style="color: #7f0055; font-family: Monaco;"&gt;true&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; connectionURL=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"ldap://localhost:10389"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; connectionUsername=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"uid=admin,ou=system"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; connectionPassword=secret&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; connectionProtocol=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;""&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; authentication=simple&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; userBase=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"ou=User,ou=ActiveMQ,ou=system"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; userSearchMatching=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"(uid={0})"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; userSearchSubtree=&lt;/span&gt;&lt;b&gt;&lt;span style="color: #7f0055; font-family: Monaco;"&gt;false&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; roleBase=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"ou=Group,ou=ActiveMQ,ou=system"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; roleName=cn&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; roleSearchMatching=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"(member=uid={1})"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; roleSearchSubtree=&lt;/span&gt;&lt;b&gt;&lt;span style="color: #7f0055; font-family: Monaco;"&gt;false&lt;/span&gt;&lt;/b&gt;&lt;span style="color: black; font-family: Monaco;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;The broker then needs to use the JAAS authentication plug-in referencing the LDAPLogin authentication realm:&lt;br /&gt;&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:Times; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:Times; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}p {mso-style-noshow:yes; mso-style-priority:99; mso-margin-top-alt:auto; margin-right:0cm; mso-margin-bottom-alt:auto; margin-left:0cm; mso-pagination:widow-orphan; font-size:10.0pt; font-family:Times; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-bidi-font-family:"Times New Roman";}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: teal; font-family: Monaco;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco;"&gt;plugins&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: teal; font-family: Monaco;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco;"&gt;jaasAuthenticationPlugin&lt;/span&gt;&lt;span style="font-family: Monaco;"&gt; &lt;span style="color: #7f007f;"&gt;configuration&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"LDAPLogin"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: teal; font-family: Monaco;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco;"&gt;plugins&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: teal; font-family: Monaco;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: teal; font-family: Monaco;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: x-small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Using such configuration, &lt;u&gt;every&lt;/u&gt; JMS connection will be authenticated using the LDAPLoginModule, no matter if it provides a username and password. Needless to say the authentication will fail if no username/password is supplied. Anonymous access won't be allowed in this configuration.&lt;br /&gt;&lt;br /&gt;So in order to also allow anonymous access to the broker we can leverage the ActiveMQ &lt;a href="http://fusesource.com/docs/broker/5.5/security/Auth-JAAS-GuestLoginModule.html" target="_blank"&gt;GuestLoginModule&lt;/a&gt;.&lt;br /&gt;The GuestLoginModule allows JMS connections that are not configured for username/password to still access a secured broker. It is typically used in conjunction with other JAAS login modules and basically successfully authenticates a JMS connection using a configurable username and group name. Here is a sample configuration of this login module:&lt;br /&gt;&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:Times; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}p {mso-style-noshow:yes; mso-style-priority:99; mso-margin-top-alt:auto; margin-right:0cm; mso-margin-bottom-alt:auto; margin-left:0cm; mso-pagination:widow-orphan; font-size:10.0pt; font-family:Times; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-bidi-font-family:"Times New Roman";}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;org.apache.activemq.jaas.GuestLoginModulesufficient&lt;/span&gt; &lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; debug=&lt;/span&gt;&lt;b&gt;&lt;span style="color: #7f0055; font-family: Monaco;"&gt;true&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;org.apache.activemq.jaas.guest.user=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"guest"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;org.apache.activemq.jaas.guest.group=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"guests"&lt;/span&gt;&lt;span style="color: black; font-family: Monaco;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;Authentication will succeed even if no username/password was supplied by the JMS client. Clients will be authenticated as user "guest" and belong to the group "guests". As you see, these names are configurable.&lt;br /&gt;&lt;br /&gt;In JAAS configuration, multiple login modules can be combined in one JAAS authentication realm. They will then be tried in order. &lt;br /&gt;&lt;br /&gt;The basic idea is to configure authentication so that the broker first invokes the GuestLoginModule, before trying the LDAPLoginModule. Here is the configuration:&lt;br /&gt;&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:595.0pt 842.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:Times; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}p {mso-style-noshow:yes; mso-style-priority:99; mso-margin-top-alt:auto; margin-right:0cm; mso-margin-bottom-alt:auto; margin-left:0cm; mso-pagination:widow-orphan; font-size:10.0pt; font-family:Times; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-bidi-font-family:"Times New Roman";}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco;"&gt;/** JAAS LoginModule configuration thatcombines LDAPLoginModule with&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco;"&gt;&amp;nbsp; GuestLoginModule.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco;"&gt;&amp;nbsp; LoginModules can be combined in JAAS.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco;"&gt;&amp;nbsp; Seehttp://fusesource.com/docs/broker/5.5/security/Auth&lt;/span&gt;&lt;span style="color: #7f7f9f; font-family: Monaco;"&gt;-&lt;/span&gt;&lt;span style="color: #3f5fbf; font-family: Monaco;"&gt;JAAS&lt;/span&gt;&lt;span style="color: #7f7f9f; font-family: Monaco;"&gt;-&lt;/span&gt;&lt;span style="color: #3f5fbf; font-family: Monaco;"&gt;GuestLoginModule.html&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco;"&gt;&amp;nbsp; for more information.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco;"&gt;*/&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;LDAPLogin-with-Anon-Access {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;org.apache.activemq.jaas.GuestLoginModule sufficient&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; debug=&lt;/span&gt;&lt;b&gt;&lt;span style="color: #7f0055; font-family: Monaco;"&gt;true&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; credentialsInvalidate=&lt;/span&gt;&lt;b&gt;&lt;span style="color: #7f0055; font-family: Monaco;"&gt;true&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;org.apache.activemq.jaas.guest.user=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"guest"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;org.apache.activemq.jaas.guest.group=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"guests"&lt;/span&gt;&lt;span style="color: black; font-family: Monaco;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp; org.apache.activemq.jaas.LDAPLoginModulerequisite&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; debug=&lt;/span&gt;&lt;b&gt;&lt;span style="color: #7f0055; font-family: Monaco;"&gt;true&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; connectionURL=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"ldap://localhost:10389"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; connectionUsername=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"uid=admin,ou=system"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; connectionPassword=secret&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; connectionProtocol=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;""&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; authentication=simple&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; userBase=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"ou=User,ou=ActiveMQ,ou=system"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; userSearchMatching=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"(uid={0})"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; userSearchSubtree=&lt;/span&gt;&lt;b&gt;&lt;span style="color: #7f0055; font-family: Monaco;"&gt;false&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; roleBase=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"ou=Group,ou=ActiveMQ,ou=system"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; roleName=cn&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; roleSearchMatching=&lt;/span&gt;&lt;span style="color: #2a00ff; font-family: Monaco;"&gt;"(member=uid={1})"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; roleSearchSubtree=&lt;/span&gt;&lt;b&gt;&lt;span style="color: #7f0055; font-family: Monaco;"&gt;false&lt;/span&gt;&lt;/b&gt;&lt;span style="color: black; font-family: Monaco;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: teal; font-family: Monaco;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco;"&gt;plugins&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: teal; font-family: Monaco;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco;"&gt;jaasAuthenticationPlugin&lt;/span&gt;&lt;span style="font-family: Monaco;"&gt; &lt;span style="color: #7f007f;"&gt;configuration&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"LDAPLogin-with-Anon-Access"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin: 0cm 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: teal; font-family: Monaco;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco;"&gt;plugins&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: teal; font-family: Monaco;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-size: x-small;"&gt;&lt;/span&gt;&lt;br /&gt;The GuestLoginModule config above uses an additional property credentialsInvalidate that when set to "true" will only authenticate requests that do not have a username/password supplied.  Each&amp;nbsp; connection without username gets authenticated as user "guest" and belongs&lt;br /&gt;to the group "guest".&lt;br /&gt;Any other JMS connections that contain username and password will be authenticated using the next login module; the LDAP LoginModule. So its important to set credentialsInvalidate=true as otherwise the GuestLoginModule authenticates all requests no matter whether or what username/password is supplied.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Authenticating anonymous connections is only half the story. Without further authorization anonymous users would be allowed all operations on the broker, which is definitely not what we want.&lt;br /&gt;With additional authorization anonymous access to the broker can be restricted to only specific destinations with restricted rights on each destination.&lt;br /&gt;The FuseSource Security Guide also explains how to configure the &lt;a href="http://fusesource.com/docs/broker/5.5/security/Auth-LDAPAuthzPlugin.html" target="_blank"&gt;LDAP Authorization plug-in&lt;/a&gt; and how to create groups and destinations in the LDAP server. A &lt;a href="http://fusesource.com/docs/broker/5.5/security/LDAP-AddAuthzEntries.html" target="_blank"&gt;step-by-step guide&lt;/a&gt; for adding all required entries is given in chapter 5.&lt;br /&gt;Based on the configuration proposed in that documentation it is additionally also necessary to&amp;nbsp; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;define all those destinations in LDAP that anonymous access will be allowed on and &lt;/li&gt;&lt;li&gt;grant the required permissions to the group "guests" to these destinations.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;If for example anonymous access should be allowed to queue "example.A", then the destination "example.A"&amp;nbsp; needs to be defined in LDAP. Further "read", "write" and potentially "admin" privileges need to be given to the group "guests" on this destination. &lt;br /&gt;This procedure needs to be applied to &lt;u&gt;all&lt;/u&gt; destinations that should allow anonymous access.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-12HOvLbyneo/Tt3ViP5F1kI/AAAAAAAAABc/CRnHS52oKnk/s1600/LDAP1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-12HOvLbyneo/Tt3ViP5F1kI/AAAAAAAAABc/CRnHS52oKnk/s1600/LDAP1.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Finally, every new connection into the broker triggers some advisory messages. Without giving "guests" access to these advisory topics, the connection will fail, typically with an error similar to this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:Times; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:"ＭＳ 明朝"; mso-font-charset:78; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 134676480 16 0 131072 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Cambria; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073743103 0 0 415 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}p {mso-style-noshow:yes; mso-style-priority:99; mso-margin-top-alt:auto; margin-right:0cm; mso-margin-bottom-alt:auto; margin-left:0cm; mso-pagination:widow-orphan; font-size:10.0pt; font-family:Times; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-bidi-font-family:"Times New Roman";}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Cambria; mso-ascii-font-family:Cambria; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"ＭＳ 明朝"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Cambria; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}@page WordSection1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;div style="margin: 1pt 0cm 0.0001pt;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: black; font-family: Monaco;"&gt;java.lang.SecurityException:User null is not authorized to create: topic://ActiveMQ.Advisory.Connection&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It is necessary to also grant "admin", "write" and potentially "read" rights for the group "guests" to ActiveMQ.Advisory topics.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-nPae3r6Jtd4/Tt3at9vXerI/AAAAAAAAABs/N17dzK6FDXU/s1600/ldap2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-nPae3r6Jtd4/Tt3at9vXerI/AAAAAAAAABs/N17dzK6FDXU/s1600/ldap2.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-63p2-QhZfvI/Tt3aFLulvaI/AAAAAAAAABk/1pz_yy-olGc/s1600/ldap2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/div&gt;This will allow for anonymous access on certain destinations while enforcing username/password based authentication on all other destinations in the broker.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Links to all files used in this post:&lt;br /&gt;&lt;a href="http://login.config/"&gt;login.config&lt;/a&gt;&lt;br /&gt;&lt;a href="http://activemq-ldap-with-anon-access.xml/"&gt;activemq-ldap-with-anon-access.xml&lt;/a&gt;&lt;br /&gt;&lt;a href="http://abloggerscode.googlecode.com/svn/trunk/Articles/Blog/AMQLDAP/activemq-ldap.xml"&gt;activemq-ldap.xml&lt;/a&gt; - no anonymous access&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-8635008054801270165?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/8635008054801270165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=8635008054801270165' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/8635008054801270165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/8635008054801270165'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2011/12/activemq-ldap-based-authentication-and.html' title='ActiveMQ: LDAP based authentication and authorization'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-12HOvLbyneo/Tt3ViP5F1kI/AAAAAAAAABc/CRnHS52oKnk/s72-c/LDAP1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-2382555173601017519</id><published>2011-11-14T16:25:00.001+01:00</published><updated>2011-11-14T16:35:54.594+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cache level'/><category scheme='http://www.blogger.com/atom/ns#' term='JMS'/><category scheme='http://www.blogger.com/atom/ns#' term='SingleConnectionFactory'/><category scheme='http://www.blogger.com/atom/ns#' term='DMLC'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveMQ'/><category scheme='http://www.blogger.com/atom/ns#' term='PooledConnectionFactory'/><category scheme='http://www.blogger.com/atom/ns#' term='broker'/><category scheme='http://www.blogger.com/atom/ns#' term='missing messages'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='CachingConnectionFactory'/><category scheme='http://www.blogger.com/atom/ns#' term='Topic'/><category scheme='http://www.blogger.com/atom/ns#' term='CACHE_CONSUMER'/><title type='text'>Consuming Topic messages in Spring and Camel</title><content type='html'>&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;}@font-face {font-family:Tahoma; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;}@font-face {font-family:Monaco; panose-1:2 0 5 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; mso-hyphenate:none; font-size:10.0pt; mso-bidi-font-size:12.0pt; font-family:Tahoma; mso-fareast-font-family:"Times New Roman"; mso-bidi-font-family:"Times New Roman"; mso-fareast-language:AR-SA;}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-size:10.0pt; mso-ansi-font-size:10.0pt; mso-bidi-font-size:10.0pt;}@page WordSection1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;&lt;br /&gt;&lt;div class="MsoNormal"&gt;When using a Spring to consume topic messages, make sure tocache the JMS consumer somewhere. Otherwise your consumer may not receive all messages.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;Consider the following Camel route definition that consumesmessages from a JMS topic.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: #3f5fbf; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;!--Can be any JMS broker really, e.g ActiveMQ --&amp;gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;bean&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: #7f007f;"&gt;id&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"JmsConnectionFactory"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: #7f007f;"&gt;class&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"org.apache.activemq.ActiveMQConnectionFactory" &lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;property&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt; &lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"serverUrl"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: #7f007f;"&gt;value&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"tcp://localhost:61616” &lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;/&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;bean&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background: none repeat scroll 0% 0% silver; color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;bean&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt; &lt;span style="color: #7f007f;"&gt;id&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"SingleConnectionFactory"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: #7f007f;"&gt;class&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"org.springframework.jms.connection.SingleConnectionFactory” &lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;property&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt; &lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"targetConnectionFactory"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: #7f007f;"&gt;ref&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"JmsConnectionFactory"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt; /&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;property&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt; &lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"reconnectOnException"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: #7f007f;"&gt;value&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"true"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt; /&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;/&lt;/span&gt;&lt;span style="background: none repeat scroll 0% 0% silver; color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;bean&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;bean&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: #7f007f;"&gt;id&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"jms"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: #7f007f;"&gt;class&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"org.apache.camel.component.jms.JmsComponent" &lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 8pt;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;property&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt; &lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"connectionFactory"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: #7f007f;"&gt;ref&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"SingleConnectionFactory"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt; /&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;property&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt; &lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"cacheLevelName"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: #7f007f;"&gt;value&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"CACHE_SESSION"&lt;/span&gt;&lt;/i&gt; &lt;span style="color: teal;"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 8pt;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;property&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt; &lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"acknowledgementMode"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: #7f007f;"&gt;value&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"1"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt; /&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;/&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;bean&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background: none repeat scroll 0% 0% silver; color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;camelContext&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt; &lt;span style="color: #7f007f;"&gt;xmlns&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"http://camel.apache.org/schema/spring"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: #7f007f;"&gt;trace&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"true" &lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;route&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt; &lt;span style="color: #7f007f;"&gt;id&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"Consume-From-JMS"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: #7f007f; font-family: Monaco; font-size: 8pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;from&lt;/span&gt;&lt;span style="color: #7f007f; font-family: Monaco; font-size: 8pt;"&gt; uri&lt;/span&gt;&lt;span style="color: black; font-family: Monaco; font-size: 8pt;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff; font-family: Monaco; font-size: 8pt;"&gt;"jms:topic:Test.Topic?deliveryPersistent=true"&lt;/span&gt;&lt;/i&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt; &lt;span style="color: teal;"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: black; font-family: Monaco; font-size: 8pt;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;t&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;o&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt; &lt;span style="color: #7f007f;"&gt;uri&lt;/span&gt;&lt;span style="color: black;"&gt;=&lt;/span&gt;&lt;i&gt;&lt;span style="color: #2a00ff;"&gt;"whatever"&lt;/span&gt;&lt;/i&gt;&lt;span style="color: teal;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="mso-hyphenate: auto; mso-layout-grid-align: none; mso-pagination: none; text-autospace: none;"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;/&lt;/span&gt;&lt;span style="color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;route&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal; font-family: Monaco; font-size: 8pt;"&gt;/&lt;/span&gt;&lt;span style="background: none repeat scroll 0% 0% silver; color: #3f7f7f; font-family: Monaco; font-size: 8pt;"&gt;camelContext&lt;/span&gt;&lt;span style="font-family: Monaco; font-size: 8pt;"&gt;&lt;span style="color: teal;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;The camel-jms component is configured to use a SpringsSingleConnectionFactory and a cache level of CACHE_SESSION. This combinationwill cause problems!&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;When using Springs &lt;a href="http://static.springsource.org/spring/docs/3.0.5.RELEASE/api/org/springframework/jca/cci/connection/SingleConnectionFactory.html" target="_blank"&gt;SingleConnectionFactory&lt;/a&gt;, it will not cachethe consumer. This ConnectionFactory only reuses the same connection but doesnot cache any other JMS resources on top of the connection (i.e. session andconsumer).&lt;/div&gt;&lt;div class="MsoNormal"&gt;At the same time Springs &lt;a href="http://static.springsource.org/spring/docs/3.0.5.RELEASE/api/org/springframework/jms/listener/DefaultMessageListenerContainer.html" target="_blank"&gt;DefaultMessageListenerContainer&lt;/a&gt;(which is used by Camel to consume messages from a JMS broker) does not cachethe consumer either as its cache level is set to &lt;a href="http://static.springsource.org/spring/docs/3.0.5.RELEASE/api/constant-values.html#org.springframework.jms.listener.DefaultMessageListenerContainer.CACHE_SESSION" target="_blank"&gt;CACHE_SESSION&lt;/a&gt;. The result ofthis configuration is that a new JMS consumer instance get created by SpringsDMLC prior to requesting the next message from the JMS broker. After themessage has been dispatched and processed, the consumer is destroyed (andunregistered from the broker). &lt;br /&gt;In addition a JMS topic works differently from a JMS queue in the way that ifthere is no subscriber registered, the broker will discard the topic message.As with the above configuration the JMS consumer gets recreated for everymessage by Spring (and registered in the JMS broker), there are certain time windowswhen the broker does not have a topic subscriber registered and so it discardsthe messages it receives. The result will be that your Spring JMS topicconsumer will not receive all of the messages from the broker. &lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;When consuming topic messages in Spring, it is necessary to cachethe JMS consumer. Either by using a connection factory that supports consumercaching like the Spring &lt;a href="http://static.springsource.org/spring/docs/3.0.5.RELEASE/api/org/springframework/jms/connection/CachingConnectionFactory.html" target="_blank"&gt;CachingConnectionFactory&lt;/a&gt; or by configuring the cachelevel of the DMLC to use &lt;a href="http://static.springsource.org/spring/docs/3.0.5.RELEASE/api/constant-values.html#org.springframework.jms.listener.DefaultMessageListenerContainer.CACHE_CONSUMER" target="_blank"&gt;CACHE_CONSUMER&lt;/a&gt;. &lt;/div&gt;&lt;div class="MsoNormal"&gt;Please note that the ActiveMQ &lt;a href="http://activemq.apache.org/maven/activemq-core/apidocs/org/apache/activemq/pool/PooledConnectionFactory.html" target="_blank"&gt;PooledConnectionFactory&lt;/a&gt; doesnot cache consumers! &lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;This only applies to topic consumers in Spring. Topicproducers will not use these cache level settings and hence don't have thisproblem.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-2382555173601017519?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/2382555173601017519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=2382555173601017519' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/2382555173601017519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/2382555173601017519'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2011/11/consuming-topic-messages-in-spring-and.html' title='Consuming Topic messages in Spring and Camel'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-8113703949383535341</id><published>2011-11-07T19:24:00.000+01:00</published><updated>2011-11-14T16:37:16.822+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sendFailIfNoSpace'/><category scheme='http://www.blogger.com/atom/ns#' term='systemUsage'/><category scheme='http://www.blogger.com/atom/ns#' term='JMS'/><category scheme='http://www.blogger.com/atom/ns#' term='transaction'/><category scheme='http://www.blogger.com/atom/ns#' term='Camel'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveMQ'/><category scheme='http://www.blogger.com/atom/ns#' term='broker'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='memory limit'/><category scheme='http://www.blogger.com/atom/ns#' term='producer flow control'/><title type='text'>Loosing messages despite of sending within a transaction</title><content type='html'>&lt;div style="color: black;"&gt;&lt;style&gt;&lt;!-- /* Font Definitions */@font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;}@font-face {font-family:"Courier New"; panose-1:2 7 3 9 2 2 5 2 4 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;}@font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;}@font-face {font-family:Tahoma; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} /* Style Definitions */p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; mso-hyphenate:none; font-size:10.0pt; mso-bidi-font-size:12.0pt; font-family:Tahoma; mso-fareast-font-family:"Times New Roman"; mso-bidi-font-family:"Times New Roman"; mso-fareast-language:AR-SA;}h3 {mso-style-unhide:no; mso-style-qformat:yes; mso-style-link:"Heading 3 Char"; mso-style-next:Normal; margin-top:12.0pt; margin-right:0cm; margin-bottom:3.0pt; margin-left:36.0pt; text-indent:-36.0pt; mso-pagination:widow-orphan; page-break-after:avoid; mso-outline-level:3; mso-list:l0 level3 lfo1; mso-hyphenate:none; tab-stops:list 36.0pt; font-size:13.0pt; font-family:Arial; mso-fareast-language:AR-SA;}span.MsoIntenseEmphasis {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; color:#4F81BD; font-weight:bold; font-style:italic;}span.Heading3Char {mso-style-name:"Heading 3 Char"; mso-style-unhide:no; mso-style-locked:yes; mso-style-link:"Heading 3"; mso-ansi-font-size:13.0pt; mso-bidi-font-size:13.0pt; font-family:Arial; mso-ascii-font-family:Arial; mso-hansi-font-family:Arial; mso-bidi-font-family:Arial; mso-fareast-language:AR-SA; font-weight:bold;}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-size:10.0pt; mso-ansi-font-size:10.0pt; mso-bidi-font-size:10.0pt;}@page WordSection1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;}div.WordSection1 {page:WordSection1;} /* List Definitions */@list l0 {mso-list-id:1; mso-list-template-ids:1;}@list l0:level1 {mso-level-number-format:none; mso-level-suffix:none; mso-level-text:""; mso-level-tab-stop:21.6pt; mso-level-number-position:left; margin-left:21.6pt; text-indent:-21.6pt;}@list l0:level2 {mso-level-number-format:none; mso-level-suffix:none; mso-level-text:""; mso-level-tab-stop:28.8pt; mso-level-number-position:left; margin-left:28.8pt; text-indent:-28.8pt;}@list l0:level3 {mso-level-number-format:none; mso-level-suffix:none; mso-level-text:""; mso-level-tab-stop:36.0pt; mso-level-number-position:left; margin-left:36.0pt; text-indent:-36.0pt;}@list l0:level4 {mso-level-number-format:none; mso-level-suffix:none; mso-level-text:""; mso-level-tab-stop:43.2pt; mso-level-number-position:left; margin-left:43.2pt; text-indent:-43.2pt;}@list l0:level5 {mso-level-number-format:none; mso-level-suffix:none; mso-level-text:""; mso-level-tab-stop:50.4pt; mso-level-number-position:left; margin-left:50.4pt; text-indent:-50.4pt;}@list l0:level6 {mso-level-number-format:none; mso-level-suffix:none; mso-level-text:""; mso-level-tab-stop:57.6pt; mso-level-number-position:left; margin-left:57.6pt; text-indent:-57.6pt;}@list l0:level7 {mso-level-number-format:none; mso-level-suffix:none; mso-level-text:""; mso-level-tab-stop:64.8pt; mso-level-number-position:left; margin-left:64.8pt; text-indent:-64.8pt;}@list l0:level8 {mso-level-number-format:none; mso-level-suffix:none; mso-level-text:""; mso-level-tab-stop:72.0pt; mso-level-number-position:left; margin-left:72.0pt; text-indent:-72.0pt;}@list l0:level9 {mso-level-number-format:none; mso-level-suffix:none; mso-level-text:""; mso-level-tab-stop:79.2pt; mso-level-number-position:left; margin-left:79.2pt; text-indent:-79.2pt;}@list l1 {mso-list-id:984119647; mso-list-type:hybrid; mso-list-template-ids:-1746395958 1300121040 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}@list l1:level1 {mso-level-start-at:0; mso-level-number-format:bullet; mso-level-text:-; mso-level-tab-stop:none; mso-level-number-position:left; text-indent:-18.0pt; font-family:Tahoma; mso-fareast-font-family:"Times New Roman"; mso-bidi-font-family:"Times New Roman";}@list l1:level2 {mso-level-number-format:bullet; mso-level-text:o; mso-level-tab-stop:none; mso-level-number-position:left; text-indent:-18.0pt; font-family:"Courier New";}@list l1:level3 {mso-level-number-format:bullet; mso-level-text:; mso-level-tab-stop:none; mso-level-number-position:left; text-indent:-18.0pt; font-family:Wingdings;}@list l1:level4 {mso-level-number-format:bullet; mso-level-text:; mso-level-tab-stop:none; mso-level-number-position:left; text-indent:-18.0pt; font-family:Symbol;}@list l1:level5 {mso-level-number-format:bullet; mso-level-text:o; mso-level-tab-stop:none; mso-level-number-position:left; text-indent:-18.0pt; font-family:"Courier New";}@list l1:level6 {mso-level-number-format:bullet; mso-level-text:; mso-level-tab-stop:none; mso-level-number-position:left; text-indent:-18.0pt; font-family:Wingdings;}@list l1:level7 {mso-level-number-format:bullet; mso-level-text:; mso-level-tab-stop:none; mso-level-number-position:left; text-indent:-18.0pt; font-family:Symbol;}@list l1:level8 {mso-level-number-format:bullet; mso-level-text:o; mso-level-tab-stop:none; mso-level-number-position:left; text-indent:-18.0pt; font-family:"Courier New";}@list l1:level9 {mso-level-number-format:bullet; mso-level-text:; mso-level-tab-stop:none; mso-level-number-position:left; text-indent:-18.0pt; font-family:Wingdings;}ol {margin-bottom:0cm;}ul {margin-bottom:0cm;}--&gt;&lt;/style&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;Last week I made an interesting observation. I was able toloose persistent queue messages that were sent in a transaction to an ActiveMQbroker. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;I believe its best to share the findings.&lt;/div&gt;&lt;h3 style="color: black;"&gt;SETTING THE SCENE&lt;/h3&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;Suppose you have a MessageProducer that sends messages to anActiveMQ broker inside a transaction. This producer could be anything, a plainJava JMS Producer client, a Spring JMS producer or as in my case a Camel route.It also does not matter if the producer sends one or more messages within thesame transaction. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;Next the ActiveMQ broker instance is configured for aspecific &lt;storeusage&gt; limit. In my test that limit was fairly low inorder to reproduce the problem quickly. In addition I did set the propertysendFailIfNoSpace so that the broker raises an exception back to the produceronce any of its global limits have been reached. So the configuration I usedreads&lt;/storeusage&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: inherit;"&gt;&amp;lt;systemUsage&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: inherit;"&gt;&amp;nbsp; &amp;lt;systemUsage sendFailIfNoSpace="true"&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: inherit;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;memoryUsage&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: inherit;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;memoryUsage limit="10 mb"/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: inherit;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/memoryUsage&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: inherit;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;storeUsage&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: inherit;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;storeUsage limit="64 mb"/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: inherit;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/storeUsage&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: inherit;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;tempUsage&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: inherit;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;tempUsage limit="10 mb"/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: inherit;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/tempUsage&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: inherit;"&gt;&amp;nbsp; &amp;lt;/systemUsage&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: inherit;"&gt;&amp;lt;/systemUsage&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;Without sendFailIfNoSpace="true" ActiveMQ wouldblock the producer until additional space is available on the broker. Thiswould most likely not reproduce the problem I am talking about. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;I ran the ActiveMQ broker with these settings, kicked off myCamel route and let it do what it can do best: route messages (which arefinally sent to a queue on my ActiveMQ broker). Btw, I did not have anyconsumers attached to the broker; only the Camel route producer was connected. Stillthe same problem can occur with slow consumers. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;And finally my producer did not register an exceptionlistener. In my tests the producer was a Camel route and Camel currently doesnot register an exception listener. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style="color: black;"&gt;THE PROBLEM&lt;/h3&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;Now, the problem starts when the broker reaches its configuredlimits. Because of the property sendFailIfNoSpace="true", it will notblock the producer indefinitely but throw an exception back to the producer. Inmy test I was hitting the storeUsage limit of 64 MB. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;On the other hand when sending messages in a transaction,then the actual send is done asynchronously. That means the thread that issending the message does not wait for the ack from the broker. It’s thetransport thread that receives the broker’s ack and deals with it. Using anasync send in the case of running inside a transaction is done for performancereasons. By not waiting for the broker ack, you can send messages more quicklyto the broker. Until the transaction finally commits the messages received bythe broker will not be placed onto the brokers queue.&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;Putting this together the following happened in my test:&lt;/div&gt;&lt;div class="MsoNormal" style="color: black; margin-left: 36pt; text-indent: -18pt;"&gt;-&lt;span style="font: 7pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;The producer started a new transaction. This informationwas sent to the broker, the broker accepted the new transaction. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black; margin-left: 36pt; text-indent: -18pt;"&gt;-&lt;span style="font: 7pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;The producer then sent a message to the broker.As this send was within an existing transaction it was done async. The call tosend the message returned immediately after sending the message. It did notwait for the broker’s ack.&lt;/div&gt;&lt;div class="MsoNormal" style="color: black; margin-left: 36pt; text-indent: -18pt;"&gt;-&lt;span style="font: 7pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;The broker did no accept this message but raiseda "javax.jms.ResourceAllocationException: Persistent store is Full, 100%of 67108864" back to the producer.&lt;/div&gt;&lt;div class="MsoNormal" style="color: black; margin-left: 36pt; text-indent: -18pt;"&gt;-&lt;span style="font: 7pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;The producers transport thread received theexception but didn’t know how to handle it. Instead it printed the followingdebug log message:&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;DEBUG - ActiveMQConnection&amp;nbsp; - Async exception with no exception listener:javax.jms.ResourceAllocationException: Persistent store is Full, 100% of67108864. Stopping producer (ID:Mac.local-51375-1320685288867-2:1:1:1) toprevent flooding queue://TEST.IN. &lt;/span&gt;&lt;br /&gt;It flagged the fact thatthere was an error but it did not mark the current transaction to be rolledback. This would have been the job of an exception listener, but none wasregistered. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black; margin-left: 36pt; text-indent: -18pt;"&gt;-&lt;span style="font: 7pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Theproducer then committed the transaction. From the producers point of view noerrors did happen (it never became aware of the JMSException) so it asked thebroker to commit the transaction. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black; margin-left: 36pt; text-indent: -18pt;"&gt;-&lt;span style="font: 7pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Thebroker committed the transaction just fine although the message did not getstored on the broker’s queue. From the brokers point of view all went fine. Theproducer did start a new transaction, it then sent some msgs, which the brokerrejected and then the broker got asked to commit the transaction. All fine fromthe brokers point of view. It’s the producer’s task to deal with theJMSException and to decide whether to rollback or not. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black; margin-left: 36pt; text-indent: -18pt;"&gt;-&lt;span style="font: 7pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Themessage(s) that got sent inside the transaction is (are) lost!&lt;/div&gt;&lt;div class="MsoNormal" style="color: black; margin-left: 18pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;It does not necessarily require anActiveMQ broker that has reached its configured limits to run into thisproblem. If the transport for any reason fails to send the msg to the brokerbut works again on the transaction commit, then the same problem could arise. Thisis less likely to occur though. Transport related problems (e.g. connectionloss) will most of the time affect the ability to commit the transaction aswell (and not only the individual message send). When there is an exceptionduring commit, it will correctly roll back the entire transaction. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;You wouldthink that using JMS Transactions would guard you against message loss. Ingeneral that is correct. However you need to make sure that any errors that canoccur within the transaction are being dealt with. In this scenario, there wasno exception listener registered in the producer that would deal with theJMSException. So I lost messages because I did not deal with the exceptionreturned from the async send. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;When using Camel as a messageproducer, you currently cannot easily register an exception listener, whichthen ensures the transaction gets rolled back in case of any problems.&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;Luckily there are some simple solutions to this problem:&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style="color: black;"&gt;THE SOLUTION&lt;/h3&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;.. is to either&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;1) Question if you really need to send your messages insidea transaction. When sending only one persistent message at a time inside atransaction, there is not much benefit over sending the message without atransaction. Persistent messages are sent synchronously by default so the producerwaits for the brokers ack before proceeding and it can deal directly with anyerror returned from the broker. Transactions are very useful though whensending multiple messages that need to all succeed or fail as one atomicoperation. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;2) If you need to use transactions for sending your messagesto the broker, then configure the ConnectionFactory to always send messagessynchronously rather than using the default async mode. Changing to sync sendwill have a small performance impact, particularly when sending a batch of messageswithin one transaction. This performance impact however is probably negligiblein most scenarios.&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;You can switch to using a sync send by using thealwaysSyncSend=true property on the ActiveMQConnectionFactor, e.g. for a Springconfiguration:&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;bean id="AMQJMSConnectionFactory3" class="org.apache.activemq.ActiveMQConnectionFactory"&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &amp;lt;property name="brokerURL" value="failover:(tcp://localhost:61620)" /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &amp;lt;property name="alwaysSyncSend" value="true"/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;Alternatively, set jms.useAsyncSend=false on the broker URL,e.g.&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&amp;nbsp;tcp://localhost:61616?jms.useAsyncSend=false&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;3) Register a JMS exception listener programmatically sothat it reacts on any exceptions thrown by the broker in case of sending the messageasync. For a plain Java JMS client you can use&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;span class="MsoIntenseEmphasis"&gt;&lt;span style="font-weight: normal;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ActiveMQConnectionFactory connectionFactory =&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; new ActiveMQConnectionFactory(brokerUrl); connectionFactory.setExceptionListener(new ExceptionListener() { &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; public void onException(JMSException ex) { &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // handle the exception &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; } &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;You can also set this exception listener on an existing JMSConnection object.&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;The somewhat tricky part may be to figure out whichtransaction needs to be rolled back, in case of having multiple threads sendingmessages concurrently to the broker. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;I already mentioned this option is not easily done in casewhere the producer is a Camel route. We hope to improve Camel to have an out ofthe box exception listener registered in future. Till then &lt;a href="https://issues.apache.org/jira/browse/CAMEL-4616" target="_blank"&gt;CAMEL-4616&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;captures this request. &lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black;"&gt;If you want to be on the safe side, the go with option #2and ensure a sync send of your messages.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-8113703949383535341?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/8113703949383535341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=8113703949383535341' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/8113703949383535341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/8113703949383535341'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2011/11/loosing-messages-despite-of-sending.html' title='Loosing messages despite of sending within a transaction'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-4271013605401396993</id><published>2011-09-09T11:01:00.000+02:00</published><updated>2012-01-19T11:06:28.811+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='master slave'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveMQ'/><category scheme='http://www.blogger.com/atom/ns#' term='broker'/><category scheme='http://www.blogger.com/atom/ns#' term='network of brokers'/><title type='text'>ActiveMQ Network Bridge to Master/Slave broker pair</title><content type='html'>&lt;span style="font-family: verdana;"&gt;This article got updated on 10/20/11 in order to include the latest changes to the failover protocol for version 5.6.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;There are scenarios where in a network of brokers each broker instance needs to be highly available. For example in hub and spoke architectures it might not be tolerable to be disconnected from the hub broker for a certain amount of time. This would prevent processing messages from spokes in real-time by consumers attached to the hub broker.&lt;br /&gt;&lt;br /&gt;Consider an ActiveMQ network of brokers configuration of two nodes where each node also needs to be highly available. To achieve High Availability, each node needs to have a slave broker attached like in the following picture:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://abloggerscode.googlecode.com/svn/trunk/Articles/Blog/NetworkBridge/BrokerConfig.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://abloggerscode.googlecode.com/svn/trunk/Articles/Blog/NetworkBridge/BrokerConfig.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="font-family: verdana;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;As shown in the above figure, Master Broker 1 needs to be able to create a network bridge to either Master Broker 2 or in case it is unavailable, Slave Broker 2.&lt;br /&gt;Likewise if Master Broker 1 dies, Slave Broker 1 will take over and it also needs to be able to connect to either Master or Slave of Broker 2. &lt;br /&gt;That way you can achieve high availability of all broker instances in a network of brokers. You already guess that such configuration can become really complex for a larger number of brokers in the network (also depending on the cluster topology).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The configuration of Master/Slave is decently well explained in the ActiveMQ &lt;a href="http://activemq.apache.org/masterslave.html"&gt;documentation&lt;/a&gt;. But how do we configure the brokers network connector so that the network bridge is able to failover to a slave if the master crashes?&lt;br /&gt;&lt;br /&gt;When trying to setup a bridge from Master Broker 1 to the master/slave pair of Broker 2, a configuration like&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: #3d85c6; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;networkConnector name="NC_1" &lt;/span&gt;&lt;br style="color: #3d85c6; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="color: #3d85c6; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; uri="static://(tcp://broker2Master:61616,tcp://broker2Slave:61616)"/&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;won’t be ideal. Because of the static: url list, the network connector will try to connect to both Master Broker 2 and Slave Broker 2. It will connect to Master Broker 2 just fine but will also retry connecting to Slave Broker 2 forever. Any failed attempt will be logged inside Broker 1 with a warning &lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;span style="color: #3d85c6; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;WARN | Could not start network bridge between vm://localhost and tcp://broker2Slave:61616 due to: java.net.ConnectExcption: Connection refused.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This does not only pollute the log file and makes it harder to spot any other issues in the log but it also takes some amount of CPU every couple of seconds for trying a reconnect. &lt;br /&gt;&lt;br /&gt;Side note: When using static:// in the network connector uri, lost connections will be re-established automatically. On this regards it works like the failover protocol but it tries to connect to all urls in the list.&lt;br /&gt;&lt;br /&gt;Instead of trying to connect to all brokers specified in the above network connector uri list (i.e. Master Broker 2 and Slave Broker 2), we only want the bridge to connect to one broker of the list. Therefore a better idea is to use the &lt;a href="http://activemq.apache.org/failover-transport-reference.html"&gt;failover://&lt;/a&gt; protocol inside the network connector configuration. We only want the Master Broker 1 to connect to either Master Broker 2 or Slave Broker 2 but not both. So the configuration now becomes&lt;br /&gt;&lt;b&gt;&lt;br style="color: #3d85c6; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="color: #3d85c6; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;networkConnector name="NC_1" &lt;/span&gt;&lt;br style="color: #3d85c6; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="color: #3d85c6; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; uri="static:failover:(tcp://broker2Master:61616,tcp://broker2Slave:61616)?randomize=false"/&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;By also setting randomize=false we will always try connecting to Master Broker 2 first, before attempting to connect to the Slave Broker 2. This configuration will keep trying to connect to one of the two brokers until a connection gets established. It will not try to connect to both brokers in the list!&lt;br /&gt;&lt;br /&gt;This configuration however still has a problem. &lt;br /&gt;In case of a connection loss the failover transport will keep trying to reconnect to the specified urls transparently and will not propagate any exceptions up to the higher layer. So if after a crash of the Master 2 broker the Slave 2 broker has finally started up, the tcp transport connection will get re-established transparently by the failover transport in Master Broker 1 without flagging the loss of connection to any higher layers. That implies the broker’s discovery agent that is responsible for creating the network bridge will never be notified and hence will never try to re-create the network bridge (which involves exchanging a couple of messages between brokers).&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;You can confirm this in jconsole, looking at the bridge MBean. The name of the MBean will refer to the previous master broker whereas the RemoteAddress property got updated with the new master broker. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Prior to version 5.6 the bridge would most likely not work anymore. Things have improved in 5.6 thanks to the fix of &lt;a href="https://issues.apache.org/jira/browse/AMQ-3542"&gt;AMQ-3542&lt;/a&gt; and the bridge may continue to work but the original problem remains. The bridge need to get re-established after failing over. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;So what is needed to re-establish the network bridge after a failover? The solution is to use the failover transport for trying to connect to the urls in the connection list without any reconnects.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;When the tcp connection of the bridge is lost, the failover protocol will not try to reconnect but raise an exception to the DiscoveryAgent. The agent will clean up its bridge and ask the underlying failover transport to re-establish a connection to either master or slave of Broker 2. Now the failover transport will try all urls in its list only once, it won't attempt any reconnects on its own. If it still can't connect, it raises an exception back to the agent again, which after a timeout will ask the failover transport again to reconnect. This continues until the failover transport succeeds in connecting to one of the specified urls. Once the tcp connection is established, the DiscoveryAgent can recreate the &lt;/span&gt;&lt;span style="font-family: verdana;"&gt;bridge based on the new connection&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;By not letting the failover transport reconnect on its own, the DiscoveryAgent is now aware that the connection of the network bridge got lost (as the error was propagated) and will re-establish the network bridge once the connection got restored.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The failover transport needs to be explicitly configured to not reconnect on its own but raise an exception instead. By default it will reconnect forever.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;From version 5.6 onwards, you should use the failover property maxReconnectAttempts=0 for that reason.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;So the network bridge configuration finally becomes (for versions 5.6 onwards):&lt;br /&gt;&lt;b&gt;&lt;br style="color: #3d85c6; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="color: #3d85c6; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;networkConnector name="NC_1" uri="static:failover:(tcp://broker2Master:61616,tcp://broker2Slave:61616)?randomize=false&amp;amp;maxReconnectAttempts=0"/&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;Prior to version 5.6 you cannot really configure for no reconnects. A&lt;/span&gt;&lt;span style="font-family: verdana;"&gt; value of 0 means "reconnect forever". From version 5.6 the value 0 means "do not reconnect". See the updated &lt;a href="http://activemq.apache.org/failover-transport-reference.html"&gt;failover transport reference&lt;/a&gt;. &lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;So for versions &amp;lt; 5.6 instead use maxReconnectAttempts=1 and allow one reconnect, which by default happen within 10 milliseconds (unless configured otherwise using initialReconnectDelay property of the failover transport). This is generally to short for the slave broker to take over.&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The network bridge configuration for Slave Broker 1 would be the same as it also needs to connect to either Master Broker 2 or Slave Broker 2.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Summary: When trying to setup a network bridge to a master/slave broker pair, use the failover transport with maxReconnectAttempts=0.&lt;br /&gt;&lt;br /&gt;Side note: When the remote broker is shutdown gracefully, the network bridge will get unregistered and closed down so that the discovery agent will always be aware of it. In that case the network bridge will be re-established correctly when the remote broker gets restarted even when not setting maxReconnectAttempts. But it won’t help in case the remote broker crashes.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-4271013605401396993?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/4271013605401396993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=4271013605401396993' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/4271013605401396993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/4271013605401396993'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2011/09/activemq-network-bridge-to-masterslave.html' title='ActiveMQ Network Bridge to Master/Slave broker pair'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-8105285555793292648</id><published>2011-07-26T09:37:00.007+02:00</published><updated>2011-12-22T11:13:44.124+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMS'/><category scheme='http://www.blogger.com/atom/ns#' term='ErrorHandler'/><category scheme='http://www.blogger.com/atom/ns#' term='Camel'/><title type='text'>Error handling in Camel for JMS consumer endpoint</title><content type='html'>&lt;span style="font-family: verdana;"&gt; &lt;br /&gt;As of version 2.0 Camel now uses the &lt;a href="http://camel.apache.org/defaulterrorhandler.html"&gt;DefaultErrorHandler&lt;/a&gt; out of the box. It offers a more Java-like error handling in the way that any exceptions that occur while routing the message will be propagated back to the caller while also ending the Exchange immediately. See the Camel &lt;a href="http://camel.apache.org/error-handler.html"&gt;error handling documentation&lt;/a&gt; for more details.&lt;br /&gt;&lt;br /&gt;This is great for most use cases but not the best choice for every scenario. For illustration purposes lets consider the example of using Camel as a JMS bridge (although the following applies to any Camel route starting with a jms consumer endpoint).&lt;br /&gt;&lt;br /&gt;Here’s a simple Camel route definition that routes messages from &lt;a href="http://www.blogger.com/activemq.apache.org"&gt;Apache ActiveMQ&lt;/a&gt; to IBM WebSphere MQ:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family: verdana;"&gt;&lt;span style="color: #365f91; font-family: Courier New; font-size: 100%;"&gt;&lt;b&gt;&lt;br /&gt;&amp;lt;camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"&amp;gt;&lt;br /&gt;  &amp;lt;route&amp;gt;&lt;br /&gt;    &amp;lt;from uri="activemq:queue:GatewayToWebSphereMQ"/&amp;gt;&lt;br /&gt;    &amp;lt;to uri="webspheremq:queue:FromActiveMQ"/&amp;gt;&lt;br /&gt;  &amp;lt;/route&amp;gt;&lt;br /&gt;&amp;lt;/camelContext&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I leave out the Spring bean definition of the activemq and webspheremq JMS components for simplicity.&lt;br /&gt;This route will forward any messages sent to the ActiveMQ queue "GatewayToWebSphereMQ" to a queue called "FromActiveMQ" in WebSphere MQ. &lt;br /&gt;&lt;br /&gt;Now lets see what happens if WebSphere MQ is down for whatever reasons.&lt;br /&gt;If a new message is put on the GatewayToWebSphereMQ, it will be picked up by the camel-activemq component. This component uses AUTO_ACKNOWLEDGE mode by default. That means Camel will receive the message from the broker and ack it straight away, before routing the message any further. From the point of view of the broker, the message has been consumed and in fact the message is now entirely in the hands of Camel.&lt;br /&gt;&lt;br /&gt;So after acking the message, Camel will now try to route the message, i.e. sending it to WebSphere MQ. But the other end is down, so we won’t get a tcp connection established. Instead some sort of a socket exception will be thrown. &lt;br /&gt;This is where the error handling in Camel comes into play now.&lt;br /&gt;&lt;br /&gt;From Camel 2.0 onwards the &lt;a href="http://camel.apache.org/defaulterrorhandler.html"&gt;DefaultErrorHandler&lt;/a&gt; will be called. The default behavior of this error handler is to propagate the error back to the caller. In this example this isn't possible as the camel-jms component has already consumed and acked the message. So it cannot raise the exception to the broker nor can we put the message back on top of the queue. Instead what happens is the message gets discarded (without being stored anywhere) after logging the error. So the message is basically lost. This is certainly not ideal if you cannot afford to loose messages.&lt;br /&gt;&lt;br /&gt;There are a few solutions:&lt;br /&gt;&lt;br /&gt;1) The DefaultErrorHandler will by default not try to redeliver the message. You can configure the error handler for a different redelivery policy so that it attempts to redeliver the message a couple of times before giving up in the hope that WebSphere will have restarted within that time frame. However when finally giving up on the retries, the message would still be discarded and lost.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2) If you can't afford to loose messages the better solution is to use a different Camel error handler, i.e. the &lt;a href="http://camel.apache.org/dead-letter-channel.html"&gt;Dead Letter Channel&lt;/a&gt;. This handler will move the message to a configurable dead letter queue if it cannot be routed.&lt;br /&gt;Here is a sample configuration for a dead letter channel:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #365f91; font-family: Courier New; font-size: 100%;"&gt;&lt;b&gt;&lt;br /&gt;&amp;lt;bean id="myDeadLetterErrorHandler" class="org.apache.camel.builder.DeadLetterChannelBuilder"&amp;gt;&lt;br /&gt;  &amp;lt;property name="deadLetterUri" value="activemq:queue:ActiveMQ.DLQ"/&amp;gt;&lt;br /&gt;  &amp;lt;property name="redeliveryPolicy" ref="myRedeliveryPolicyConfig"/&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;bean id="myRedeliveryPolicyConfig" class="org.apache.camel.processor.RedeliveryPolicy"&amp;gt;&lt;br /&gt;  &amp;lt;property name="maximumRedeliveries" value="3"/&amp;gt;&lt;br /&gt;  &amp;lt;property name="redeliveryDelay" value="5000"/&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now lets tell Camel to use this error handler instead of the default handler:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #365f91; font-family: Courier New; font-size: 100%;"&gt;&lt;b&gt;&lt;br /&gt;&amp;lt;camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"&amp;gt;&lt;br /&gt;  &amp;lt;route errorHandlerRef="myDeadLetterErrorHandler"&amp;gt;&lt;br /&gt;    &amp;lt;from uri="activemq:queue:GatewayToWebSphereMQ"/&amp;gt;&lt;br /&gt;    &amp;lt;to uri="webspheremq:queue:inbound/inbox"/&amp;gt;&lt;br /&gt;  &amp;lt;/route&amp;gt;&lt;br /&gt;&amp;lt;/camelContext&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This example configures the dead letter channel with a custom redelivery policy. Camel will now retry every message three times with a 5 seconds delay. If delivery is still unsuccessful thereafter, the msg gets moved to the queue "ActiveMQ.DLQ" in ActiveMQ. If the connectivity problem to WebSphere MQ is only short term, a properly configured redelivery policy may prevent moving any messages to a dead letter queue.&lt;br /&gt;You can configure for any other dead letter queue and in fact it does not necessarily have to be a JMS queue, as "seda:errorqueue" will also work.&lt;br /&gt;&lt;br /&gt;This configuration of a Camel error handler will never loose any persistent messages! However you will need to think of a strategy what to do with messages ending up on a dead letter queue (e.g. manually re-route them back to the original queue after the connection to WebSphere MQ got restored).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;3) A third possible solution would be to use a transacted Camel route. For transacted routes the&lt;a href="http://camel.apache.org/transactionerrorhandler.html"&gt;TransactionErrorHandler&lt;/a&gt; is used. The camel-jms endpoint is a transaction capable endpoint, and so do ActiveMQ and WebSphere MQ support transactions. The entire Camel route above could therefore spawn a single transaction. If there are any errors encountered within the transaction (e.g. while trying to send the message to WebSphere MQ), the transaction will be rolled back and the message is moved back to the original queue again (in fact, it never leaves the queue). &lt;br /&gt;Now you require an appropriate redelivery policy configuration inside ActiveMQ (e.g. try to redeliver the message up to 5 times before moving the message to a dead letter queue "ActiveMQ.DLQ"). &lt;br /&gt;Further as the Camel route involves two different JMS endpoints, you would need to configure Camel for XA transactions, involving an XA transaction monitor. XA transactions also have an impact on performance and might not always be needed. The &lt;a href="http://fusesource.com/require_registration_for?url=http://fusesource.com/docs/router/2.7/transactions/index.html"&gt;Camel Transaction Guide&lt;/a&gt; on &lt;a href="http://fusesource.com/"&gt;FuseSource.com&lt;/a&gt; has some really good chapters on configuring Camel for XA transactions.&lt;br /&gt;&lt;br /&gt;The second solution outlined above might be the easiest solution that guarantees messages won’t get lost. &lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-8105285555793292648?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/8105285555793292648/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=8105285555793292648' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/8105285555793292648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/8105285555793292648'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2011/07/error-handling-in-camel-for-jms.html' title='Error handling in Camel for JMS consumer endpoint'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-7558113636623601625</id><published>2011-06-01T10:12:00.005+02:00</published><updated>2011-06-01T10:23:57.585+02:00</updated><title type='text'>java.io.InvalidClassException: NoSuchCustomerException;   local class incompatible: stream classdesc serialVersionUID = 20110530114741</title><content type='html'>&lt;span style=";font-family:verdana;font-size:10;"&gt; &lt;br /&gt;While working on a camel demo that routes a soap message in POJO mode from a cxf-consumer endpoint via jms to a camel processor, I ran into the above exception when the camel processor returned a soap fault. The full error reads [1]. &lt;br /&gt;&lt;br /&gt;The Camel route definition is as simple as&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;&lt;b&gt;&lt;br /&gt;&amp;lt;route id="CXF-to-Queue"&amp;gt;&lt;br /&gt;  &amp;lt;from uri="cxf:bean:customer-ws?dataFormat=POJO"/&amp;gt;&lt;br /&gt;  &amp;lt;inOut uri="activemq:queue:lookupCustomer?jmsMessageType=Object&amp;amp;transferException=true"/&amp;gt;&lt;br /&gt;&amp;lt;/route&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;route id="Queue-to-Processor"&amp;gt;&lt;br /&gt;  &amp;lt;from uri="activemq:queue:lookupCustomer?jmsMessageType=Object&amp;amp;transferException=true" /&amp;gt;&lt;br /&gt;  &amp;lt;process ref="lookupCustomer"/&amp;gt;&lt;br /&gt;&amp;lt;/route&amp;gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I ran each Camel route on a different machine with both routes connecting to the same broker. Further all msgs were passed as ObjectMessages in JMS (but you would get the same issue with JMS ByteMessages or any binary serialization of the exception). &lt;br /&gt;The SOAP fault (raised by the lookupCustomer processor) was marshaled into the JMS ObjectMessage correctly and sent back on the reply-to queue, but the receiving camel-jms endpoint (my first route) had problems unmarshaling the data and raised the InvalidClassException as shown above.&lt;br /&gt;&lt;br /&gt;After some digging I got to learn that since I re-compiled my demo on the other machine, a new and different serialVersionUID was generated for NoSuchCustomerException.java:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;&lt;b&gt;&lt;br /&gt;@WebFault(name = "NoSuchCustomer", &lt;br /&gt;  targetNamespace = "http://demo.fusesource.com/wsdl/CustomerService/")&lt;br /&gt;public class NoSuchCustomerException extends Exception {&lt;br /&gt;    public static final long serialVersionUID = 20110530174707L;&lt;br /&gt;    ... &lt;br /&gt;}&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This serial version uid is generated based on a time stamp by default! So each time wsdl2java is re-run, a different uid will be generated. This is often the case with mvn based projects. As I compiled my demo on both machines (at different times), the uid differed.&lt;br /&gt;&lt;br /&gt;There was an easy fix to it however, which is to tell the wsdl2java compiler to generate the serial version uid based on the fully qualified classname (-useFQCNForFaultSerialVersionUID). This will always generate the same uid for the same fault definition no matter how often I run wsdl2java. See &lt;a href="http://cxf.apache.org/docs/wsdl-to-java.html"&gt;http://cxf.apache.org/docs/wsdl-to-java.html&lt;/a&gt; for more information.&lt;br /&gt;&lt;br /&gt;IMHO, -useFQCNForFaultSerialVersionUID should be the default in order to avoid such problems. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You won't have this problem when using SOAP/HTTP as the transport. The JAXB marshaling won't marshal the uid.&lt;br /&gt;This problem only arises when using binary transports such as JMS. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:80%;"&gt;&lt;br /&gt;[1] full error &lt;br /&gt;org.apache.camel.RuntimeCamelException: Failed to extract body due to: javax.jms.JMSException: Failed to build body from bytes. Reason: java.io.InvalidClassException: com.fusesource.demo.wsdl.customerservice.NoSuchCustomerException; local class incompatible: stream classdesc serialVersionUID = 20110530114741, local class serialVersionUID = 20110530112224. Message: ActiveMQObjectMessage {commandId = 61, responseRequired = false, messageId = ID:nbwfhtmielke-1657-1306750363546-3:1:1:1:4, originalDestination = null, originalTransactionId = null, producerId = ID:nbwfhtmielke-1657-1306750363546-14:1:1:1, destination = queue://reply.test1, transactionId = null, expiration = 0, timestamp = 1306755695062, arrival = 0, brokerInTime = 1306755696022, brokerOutTime = 1306755696678, correlationId = ID-XPS-53828-1306755653494-0-6, replyTo = queue://reply.test1, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@ed92dbb, marshalledProperties = org.apache.activemq.util.ByteSequence@5449579a, dataStructure = null, redeliveryCounter = 0, size = 0, properties = {Content_HYPHEN_Type=text/xml;charset=UTF-8, operationNamespace=http://demo.fusesource.com/wsdl/CustomerService/, operationName=lookupCustomer, Host=localhost:10443, SOAPAction="http://www.example.org/CustomerService/lookupCustomer", User_HYPHEN_Agent=Jakarta Commons-HttpClient/3.1, CamelJmsDeliveryMode=2, accept_HYPHEN_encoding=gzip,deflate}, readOnlyProperties = true, readOnlyBody = true, droppable = false}&lt;br /&gt; at org.apache.camel.component.jms.JmsBinding.extractBodyFromJms(JmsBinding.java:158)[camel-jms-2.5.0-fuse-00-00.jar:2.5.0-fuse-00-00]&lt;br /&gt; at org.apache.camel.component.jms.JmsMessage.createBody(JmsMessage.java:183)[camel-jms-2.5.0-fuse-00-00.jar:2.5.0-fuse-00-00]&lt;br /&gt; at org.apache.camel.impl.MessageSupport.getBody(MessageSupport.java:41)[camel-core-2.5.0-fuse-00-00.jar:2.5.0-fuse-00-00]&lt;br /&gt; at org.apache.camel.component.jms.reply.ReplyManagerSupport.processReply(ReplyManagerSupport.java:112)[camel-jms-2.5.0-fuse-00-00.jar:2.5.0-fuse-00-00]&lt;br /&gt; at org.apache.camel.component.jms.reply.TemporaryQueueReplyHandler.onReply(TemporaryQueueReplyHandler.java:52)[camel-jms-2.5.0-fuse-00-00.jar:2.5.0-fuse-00-00]&lt;br /&gt; at org.apache.camel.component.jms.reply.PersistentQueueReplyHandler.onReply(PersistentQueueReplyHandler.java:45)[camel-jms-2.5.0-fuse-00-00.jar:2.5.0-fuse-00-00]&lt;br /&gt; at org.apache.camel.component.jms.reply.PersistentQueueReplyManager.handleReplyMessage(PersistentQueueReplyManager.java:84)[camel-jms-2.5.0-fuse-00-00.jar:2.5.0-fuse-00-00]&lt;br /&gt; at org.apache.camel.component.jms.reply.ReplyManagerSupport.onMessage(ReplyManagerSupport.java:98)[camel-jms-2.5.0-fuse-00-00.jar:2.5.0-fuse-00-00]&lt;br /&gt; at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:560)[spring-jms-3.0.5.RELEASE.jar:3.0.5.RELEASE]&lt;br /&gt; at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:498)[spring-jms-3.0.5.RELEASE.jar:3.0.5.RELEASE]&lt;br /&gt; at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:467)[spring-jms-3.0.5.RELEASE.jar:3.0.5.RELEASE]&lt;br /&gt; at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325)[spring-jms-3.0.5.RELEASE.jar:3.0.5.RELEASE]&lt;br /&gt; at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263)[spring-jms-3.0.5.RELEASE.jar:3.0.5.RELEASE]&lt;br /&gt; at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1058)[spring-jms-3.0.5.RELEASE.jar:3.0.5.RELEASE]&lt;br /&gt; at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1050)[spring-jms-3.0.5.RELEASE.jar:3.0.5.RELEASE]&lt;br /&gt; at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:947)[spring-jms-3.0.5.RELEASE.jar:3.0.5.RELEASE]&lt;br /&gt; at java.lang.Thread.run(Thread.java:636)[:1.6.0_20]&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-7558113636623601625?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/7558113636623601625/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=7558113636623601625' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/7558113636623601625'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/7558113636623601625'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2011/06/javaioinvalidclassexception.html' title='java.io.InvalidClassException: NoSuchCustomerException;   local class incompatible: stream classdesc serialVersionUID = 20110530114741'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-2845059585437422612</id><published>2011-03-23T13:46:00.002+01:00</published><updated>2011-03-23T13:49:46.654+01:00</updated><title type='text'>ServiceMix with LDAP based authentication</title><content type='html'>&lt;span style=";font-family:verdana;font-size:10;"&gt; &lt;br /&gt;It’s possible to configure LDAP based authentication in ServiceMix. We recently added a complete tutorial in the FUSE ESB &lt;a href="http://fusesource.com/docs/esb/4.3.1/esb_security/index.html"&gt;Security Guide&lt;/a&gt;. It provides step-by-step instructions and screenshots based on the Open Source LDAP server &lt;a href="http://directory.apache.org/"&gt;ApacheDS&lt;/a&gt;. &lt;br /&gt;Anyone having to configure LDAP in SMX, check out chapter 4 &lt;a href="http://fusesource.com/docs/esb/4.3.1/esb_security/LDAP.html"&gt;"LDAP Authentication Tutorial"&lt;/a&gt;. &lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-2845059585437422612?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/2845059585437422612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=2845059585437422612' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/2845059585437422612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/2845059585437422612'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2011/03/servicemix-with-ldap-based.html' title='ServiceMix with LDAP based authentication'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-6601639684507752153</id><published>2011-03-10T10:35:00.006+01:00</published><updated>2011-03-10T11:57:16.402+01:00</updated><title type='text'>How to SSL enable the ServiceMix web console?</title><content type='html'>&lt;span style=";font-family:verdana;font-size:10;"&gt;&lt;br /&gt;ServiceMix 4 comes with a useful web console. It needs to be installed manually; it is not deployed out of the box:&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;karaf@root&gt; features:install webconsole&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;... and thereafter the console can be accessed using URL: &lt;br /&gt;&lt;a href="http://localhost:8181/system/console/bundles"&gt;http://localhost:8181/system/console/bundles&lt;/a&gt;&lt;br /&gt;(applies to 4.3.1, URL might differ on other versions of SMX).&lt;br /&gt;&lt;br /&gt;In order to secure the console to use HTTPS, it is necessary to create a file  &lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;$KARAF_HOME/etc/org.ops4j.pax.web.cfg &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and configure it using any of the property keywords defined in this &lt;a href="https://github.com/ops4j/org.ops4j.pax.web/blob/master/pax-web-api/src/main/java/org/ops4j/pax/web/service/WebContainerConstants.java"&gt;WebContainerConstants&lt;/a&gt; class. &lt;br /&gt;&lt;br /&gt;Here is a possible example:&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;&lt;br /&gt;# configures the SMX Web Console to use SSL&lt;br /&gt;#&lt;br /&gt;# @SeeAlso: https://github.com/ops4j/org.ops4j.pax.web/blob/master/pax-web-api/src/main/java/org/ops4j/pax/web/service/WebContainerConstants.java&lt;br /&gt;# for possible configuration properties&lt;br /&gt;&lt;br /&gt;org.osgi.service.http.enabled=false&lt;br /&gt;org.osgi.service.http.port=8181&lt;br /&gt;&lt;br /&gt;org.osgi.service.http.secure.enabled=true&lt;br /&gt;org.osgi.service.http.port.secure=8183&lt;br /&gt;&lt;br /&gt;org.ops4j.pax.web.ssl.keystore=/path/to/keystore.ks&lt;br /&gt;org.ops4j.pax.web.ssl.keystore.type=JKS&lt;br /&gt;org.ops4j.pax.web.ssl.password=blah&lt;br /&gt;org.ops4j.pax.web.ssl.keypassword=bluh&lt;br /&gt;org.ops4j.pax.web.ssl.clientauthwanted=false&lt;br /&gt;org.ops4j.pax.web.ssl.clientauthneeded=false&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Make sure to access the web console using https:// after applying this configuration. &lt;br /&gt;;-)&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-6601639684507752153?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/6601639684507752153/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=6601639684507752153' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/6601639684507752153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/6601639684507752153'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2011/03/how-to-ssl-enable-servicemix-web.html' title='How to SSL enable the ServiceMix web console?'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-4616849342936260367</id><published>2011-02-24T17:45:00.003+01:00</published><updated>2011-02-24T18:01:38.668+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='temp storage'/><category scheme='http://www.blogger.com/atom/ns#' term='subscription'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveMQ'/><title type='text'>Observations on ActiveMQs temp storage.</title><content type='html'>&lt;span style=";font-family:verdana;font-size:10;"&gt; &lt;br /&gt;In ActiveMQ there are &lt;a href="http://activemq.apache.org/producer-flow-control.html"&gt;3 areas&lt;/a&gt; where messages are stored by the broker: in broker's memory, in persistence store and in temp storage.&lt;br /&gt;All messages get first put into the broker's memory until it fills up. Persistent messages always get additionally saved to the persistence store (KahaDB by default). Non persistent messages are held in memory until broker memory is exhausted. Then, if the default &lt;a href="http://activemq.apache.org/message-cursors.html"&gt;FileCursor&lt;/a&gt; is used, they get swapped out to disk (swapping does not happen with VMCursor).  The temp storage typically resides in directory data/localhost/tmp_storage.&lt;br /&gt;&lt;br /&gt;All three areas are configured in activemq.xml using &lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;&lt;br /&gt;&amp;lt;systemUsage&amp;gt;&lt;br /&gt;  &amp;lt;systemUsage&amp;gt;&lt;br /&gt;    &amp;lt;memoryUsage&amp;gt;&lt;br /&gt;      &amp;lt;memoryUsage limit="20 mb"/&amp;gt;&lt;br /&gt;    &amp;lt;/memoryUsage&amp;gt;&lt;br /&gt;    &amp;lt;storeUsage&amp;gt;&lt;br /&gt;      &amp;lt;storeUsage limit="1 gb"/&amp;gt;&lt;br /&gt;    &amp;lt;/storeUsage&amp;gt;&lt;br /&gt;    &amp;lt;tempUsage&amp;gt;&lt;br /&gt;      &amp;lt;tempUsage limit="100 mb"/&amp;gt;&lt;br /&gt;    &amp;lt;/tempUsage&amp;gt;&lt;br /&gt;  &amp;lt;/systemUsage&amp;gt;&lt;br /&gt;&amp;lt;/systemUsage&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;An important advice is to &lt;b&gt;never set the tempUsage limit below the journalFileSize for the temporary storage&lt;/b&gt; (32 MB by default but configurable)! So if you don't explicitly configure the journaleFileSize for temp messages in KahaDB, never set the tempUsage limit below 32 MB!&lt;br /&gt;&lt;br /&gt;This configuration will most likely cause problems&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;&lt;br /&gt;&amp;lt;tempUsage&amp;gt;&lt;br /&gt;  &amp;lt;tempUsage limit="30 mb"/&amp;gt;&lt;br /&gt;&amp;lt;/tempUsage&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Here is the reason why:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The temp storage is only used with non-persistent messages, so typically with topic messages.&lt;br /&gt;In the case of running fast subscribers that keep up with the producers, you will most likely never need to swap messages as all outstanding messages can all be held in memory. &lt;br /&gt;There may be peak times however where the producer rate is higher than the rate for consuming messages. So swapping of messages might occur. &lt;br /&gt;&lt;br /&gt;When a subscription realizes that there is no further heap memory to take on new messages (due to whatever configured memory limit), it will start to swap out all messages it holds to temp storage. All messages of a particular subscription get swapped in one go! That process is rather slow and for a larger amount of messages to be swapped might easily take a few mins.&lt;br /&gt;&lt;br /&gt;Side Note 1: The dispatching of topic messages to each topic subscription inside the broker is serialized. If a topic has 5 subscribers then a new message gets dispatched to each subscription in a serialized manner. The first subscription that tries to handle a new message might realize that memory is full and starts to swap all of its yet undelivered messages. The swapping is actually done by the &lt;a href="http://svn.apache.org/viewvc/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/broker/region/cursors/FilePendingMessageCursor.java?view=markup"&gt;FilePendingMessageCursor&lt;/a&gt;. After swapping messages to temp storage, the subscription can handle the new message and send it to the external client. There is one FilePendingMessageCursor instance for each subscription. The next subscription is only called once the previous subscription has sent the message and will then normally find enough space in heap memory again to handle the new message in memory. If not, it will start to swap out its  messages too to free more heap.&lt;br /&gt;&lt;br /&gt;Side Note 2: Because of all messages being swapped in one go by a subscription, it may happen that after the swap has finished the temp storage is above 100% usage. This might occur either when &lt;br /&gt;1) using a memoryUsage &gt; tempUsage and the subscription holds a large amount of messages, but also &lt;br /&gt;2) when configuring a tempUsage limit &lt; 32 MB (see above).&lt;br /&gt;&lt;br /&gt;In the case 1) it is possible that the amount of messages held in a subscription is larger than the tempUsage limit. So after swapping all messages of a subscription into temp storage, the tempUsage is &gt; 100%. &lt;br /&gt;In case 2) once swapping starts, the persistence adapter (which is also responsible for writing messages to temp storage) will create a db-1.log file in temp storage and its default file size is 32 MB. Again tempUsage is &gt; 100% after writing this file irrespective of how many messages got swapped to temp storage.&lt;br /&gt;You might see the following log statement in the broker log file when temp storage has filled up after messages got swapped to disk.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;&lt;br /&gt;INFO  TopicSubscription - TopicSubscription: consumer=ID:nbwfhtmielke-1380-1298467525966-2:1:1:1, destinations=1, dispatched=99, delivered=9622, matched=231, discarded=0: &lt;b&gt;Pending message cursor &lt;/b&gt;[org.apache.activemq.broker.region.cursors.FilePendingMessageCursor@3c0737] &lt;b&gt;is full, temp usage (129%) or memory usage (0%) limit reached&lt;/b&gt;, blocking message add() pending the release of resources.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;With producer flow control enabled, any producers will be put on hold until the swapping of messages has finished (and additional heap memory is available) and also until the tempUsage &lt; 100%. Subscribers still get messages dispatched while tempUsage &gt; 100%, only producers are stopped. Any consumed messages free additional space from temp storage. Once the temp usage is &lt; 100% producers get resumed. &lt;br /&gt;&lt;br /&gt;As messages get consumed the data files get deleted from temp storage. All except for the first file which will be reused in case any of new messages that need to be swapped. &lt;br /&gt;&lt;br /&gt;And there is the problem: The first data file never gets deleted. Its default size is 32 MB and hence still above the configured tempUsage limit (30 MB in our example). As the file never gets deleted, tempUsage never goes &lt; 100% and therefore the producer is flow controlled forever and never gets resumed. &lt;br /&gt;From an external viewpoint it seems as if either the broker or the producer is hung. The subscribers have consumed all message but producers don't send any further messages. &lt;br /&gt;&lt;br /&gt;Some more useful notes on broker memory configuration can be found &lt;a href="http://activemq.apache.org/javalangoutofmemory.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Lesson learned:&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Don't configure a tempUsage limit &lt; default size of the journal file (32 MB).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Swapping out messages to temp storage can be rather slow. If you already using producer flow control with topic messages, the VM cursor might be an alternative. It won't swap messages to disk. &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-4616849342936260367?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/4616849342936260367/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=4616849342936260367' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/4616849342936260367'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/4616849342936260367'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2011/02/observations-on-activemqs-temp-storage.html' title='Observations on ActiveMQs temp storage.'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-1074963400503365649</id><published>2011-02-23T19:50:00.003+01:00</published><updated>2011-02-23T19:54:13.247+01:00</updated><title type='text'>Load tests with ActiveMQ</title><content type='html'>&lt;span style=";font-family:verdana;font-size:10;"&gt;&lt;br /&gt;Not sure everyone knows it but ActiveMQ has a maven plug-in that can be easily used to run load tests. Its name is &lt;b&gt;maven-activemq-perf-plugin&lt;/b&gt;. Full documentation is available &lt;a href="http://activemq.apache.org/activemq-performance-module-users-manual.html"&gt;here&lt;/a&gt;.&lt;br /&gt;As I often need to run test using a specific broker configuration or having to test a specific broker feature, this plug-in has helped me a few times already. It is also highly useful for trouble shooting as the many configuration options allow you to simulate certain broker usage patterns.&lt;br /&gt;&lt;br /&gt;You have many options for setting up the load test like the number of producers and consumers, the message size, acknowledge mode, using Queues or Topics, whether to use JMS transactions and many more. &lt;br /&gt;It also includes samplers that measure your performance; you get a nice summary written at the end of the test run. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In order to use the test suite, simply add it the plug-in to your pom. An example is given &lt;a href="http://svn.apache.org/repos/asf/activemq/sandbox/activemq-perftest/pom.xml"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I highly recommend it to anyone who wants to quickly run some load tests and measure broker throughput. &lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-1074963400503365649?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/1074963400503365649/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=1074963400503365649' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/1074963400503365649'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/1074963400503365649'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2011/02/load-tests-with-activemq.html' title='Load tests with ActiveMQ'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-3986864672298264775</id><published>2011-01-21T16:12:00.002+01:00</published><updated>2011-01-21T16:18:23.996+01:00</updated><title type='text'>How to change the ActiveMQ broker configuration when running inside ServiceMix?</title><content type='html'>&lt;span style=";font-family:verdana;font-size:10;"&gt;&lt;br /&gt;I mistakenly assumed that I can simply update the embedded ActiveMQ broker configuration at $KARAF_HOME/etc/activemq-broker.xml and restart SMX for these changes to take effect.&lt;br /&gt;&lt;br /&gt;That is not the case. &lt;br /&gt;&lt;br /&gt;ServiceMix monitors the etc/ folder via an OSGI &lt;a href="http://felix.apache.org/site/apache-felix-file-install.html"&gt;management agent&lt;/a&gt;. It scans the etc/ folder, installs and starts a bundle when it is first placed there. The etc/config.properties file configures this agent:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;&lt;br /&gt;felix.fileinstall.dir    = ${karaf.base}/etc&lt;br /&gt;felix.fileinstall.filter = .*\\.cfg&lt;br /&gt;felix.fileinstall.poll   = 1000&lt;br /&gt;felix.fileinstall.noInitialDelay = true&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;So when ServiceMix starts up the first time the agent will read the activemq-broker.xml file from etc/, wrap it as an OSGI bundle and deploy it into the bundle cache. Changes to etc/activemq-broker.xml thereafter will not cause the bundle to be redeployed automatically, not even after a restart of ServiceMix. This is the actually the same behavior as deploying a bundle using, e.g. osgi:install mvn:… from your local Maven repository. Updating the bundle in your Maven repo does not cause ServiceMix to redeploy it automatically for you (which is certainly good).&lt;br /&gt;&lt;br /&gt;So after changing the configuration of etc/activemq-broker.xml, make sure to update the ActiveMQ broker bundle:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;&lt;br /&gt;karaf@root&gt; list -l | grep activemq-broker.xml&lt;br /&gt;[  57] [Active ] [Created ] [   ] [60] blueprint:file:etc/activemq-broker.xml&lt;br /&gt;karaf@root&gt;update 57&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;It will stop the embedded broker, reload the configuration as an OSGI bundle and restart the broker with the new configuration in effect.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-3986864672298264775?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/3986864672298264775/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=3986864672298264775' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/3986864672298264775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/3986864672298264775'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2011/01/how-to-change-activemq-broker.html' title='How to change the ActiveMQ broker configuration when running inside ServiceMix?'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-4480904285380722824</id><published>2011-01-11T15:22:00.010+01:00</published><updated>2011-01-11T16:41:15.424+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMSExpiration'/><category scheme='http://www.blogger.com/atom/ns#' term='JMS'/><category scheme='http://www.blogger.com/atom/ns#' term='Camel'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveMQ'/><category scheme='http://www.blogger.com/atom/ns#' term='TimeStampingBrokerPlugin'/><category scheme='http://www.blogger.com/atom/ns#' term='camel-jms'/><category scheme='http://www.blogger.com/atom/ns#' term='broker'/><category scheme='http://www.blogger.com/atom/ns#' term='TimeStampPlugin'/><title type='text'>Sync your machine clocks!</title><content type='html'>&lt;span style=";font-family:verdana;font-size:10;"&gt;&lt;br /&gt;When running ActiveMQ with producer and consumers spread across multiple machines, make sure to have the clocks synced on these machines!&lt;br /&gt;Otherwise there might be interesting side effects when using JMS expiration times.&lt;br /&gt;&lt;br /&gt;1) Consider the following simple scenario:&lt;br /&gt;A broker running on host A with the local time 1.35 pm. &lt;br /&gt;Secondly a producer/consumer pair running on host B with the local time of 1.30 pm. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;In summary:&lt;/b&gt;&lt;br /&gt;Broker time: 1.35 pm&lt;br /&gt;JMS client time: 1.30 pm&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The producer sends a message with a JMSExpiration time of 2 mins at 1.30 pm sharp. So the message expires at 1.32 pm. The broker receives the message, checks the expiration time and realizes the message is already expired. So it gets moved to DLQ immediately. The consumer will not get the message! This might be particularly surprising if the consumer is on the same machine as the producer and you start to wonder where your message is. &lt;br /&gt;Note: The JMSExpiration time that is set on the message does not contain the value 2mins, but the actual time in future when the message expires (represented as a long). This value is computed using the local time of the message producer and compared against the local time of the broker before being put on the queue. &lt;br /&gt;&lt;br /&gt;2) Now let's consider the opposite example:&lt;br /&gt;&lt;b&gt;In summary&lt;/b&gt;&lt;br /&gt;Broker time: 1.30 pm&lt;br /&gt;JMS client time: 1.35 pm&lt;br /&gt;&lt;br /&gt;The broker's local time is 1.30 pm and the producers/consumers local time is 1.35 pm.&lt;br /&gt;The Producer again sends a message with a JMSExpiration of 2 mins. It is received by the broker at 1.30 with an expiration time at 1.37pm. The message gets put onto the queue, from where the consumer can grab it. So all is fine in this scenario.&lt;br /&gt;&lt;br /&gt;It is therefore highly suggested that the local times between all parties that participate in messaging are more or less synchronized. One simple option is to configure for NTP synchronization on each machine. There are many NTP tools available for all major operating systems. &lt;br /&gt;&lt;br /&gt;If for whatever reason you cannot synchronize the times between machines (e.g. broker running externally), then I suggest to use a JMSExpiration time that include the delta of the time difference between machines. E.g. if the delta is known to be 5 mins, then perhaps set the JMSExpiration time to 5+ mins (adding enough time for message processing and delivery). &lt;br /&gt;On the other hand if message expiration is an important requirement in your application, you should really try to synchronize times between all involved machines.&lt;br /&gt;&lt;br /&gt;&lt;a name="Part2"&gt;&lt;/a&gt;&lt;h3&gt;Part 2&lt;/h3&gt;&lt;br /&gt;This brings me to the second part of this post, the ActiveMQ &lt;a href="http://activemq.apache.org/timestampplugin.html"&gt;TimeStampingBrokerPlugin&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;From its documentation:&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;"This can be useful when the clocks on client machines are known to not be correct and you can only trust the time set on the broker machines."&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;1) Let's revisit the first scenario again:&lt;br /&gt;Broker time: 1.35 pm&lt;br /&gt;JMS client time: 1.30 pm&lt;br /&gt;&lt;br /&gt;The plug-in can help you in this case. Because the plug-in will not only set the JMS message timestamp to the current time at the broker but also recalculate the resulting JMS expiration time again based on the broker's local time. Thus the message will not be marked as expired when it is handled by the broker. It is therefore put onto the queue from where the consumer can grab it. So the use of the TimeStampingBrokerPlugin can help to resolve the problem of scenario 1). &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2) Now let's consider the second scenario again:&lt;br /&gt;Broker time: 1.30 pm&lt;br /&gt;JMS client time: 1.35 pm&lt;br /&gt;&lt;br /&gt;The JMS producer sends the message at 1.35 pm local time with an expiration time set to 1.37 pm.&lt;br /&gt;The TimeStampingBrokerPlugin resets the expiration time to 1.32 pm (2 mins based on the brokers local time). The message is put onto the queue. &lt;br /&gt;The consumer that is connected has a local time of 1.35 pm. It will not grab the message!! &lt;br /&gt;Why? Because from this consumer's point of view the message has already expired. &lt;br /&gt;&lt;br /&gt;Such situation will generally be difficult to understand when looking at the system using either the ActiveMQ web console or JMX console. There is a message on the queue and there is a consumer connected but the message is not consumed! &lt;br /&gt;You might not immediately think about JMS expiration times and different machine times. You will more likely start to think the attached consumer is hung or there is a bug in ActiveMQ. &lt;br /&gt;If you configure for ActiveMQ debug logging in the consumer, you will notice that the consumer actually gets the message from the queue but it will discard it due to its expiration time. Under debug logging the following is printed:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;&lt;br /&gt;ActiveMQMessageConsumer  DEBUG ID:nbwfhtmielke-4668-1294676704879-2:0:1:1 &lt;b&gt;received expired message:&lt;/b&gt; MessageDispatch {commandId = 0, … expiration = 1294675812454, &lt;br /&gt;timestamp = 1294674812454, …}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;There is a possible solution though, that is to use the plug-in configuration property futureOnly="true". If set to true the plug-in will not set the new expiration time on the message if it is lower than the original expiration time. It will therefore never reset the expiration time to a lower value. Instead the original expiration time gets preserved. That way the remote consumer will grab the message.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Note:&lt;/b&gt; You could also run into this problem with a &lt;a href="http://camel.apache.org/jms"&gt;camel-jms&lt;/a&gt; route using INOUT message exchange pattern and connecting to an external broker that has this plug-in configured.&lt;br /&gt;camel-jms uses requestTimeout=20 secs by default. That generates a JMSExpiration message header with an expiration time of 20 secs. If the broker's local time is only 30 seconds (or even less) behind the local time of the JMS consumer, the same issue of the message not getting consumed might occur. &lt;br /&gt;&lt;br /&gt;Conclusion: If somehow possible, sync the machine clocks on all machines that are involved in the message exchange. If that is not possible, check the time differences and recalculate your JMS expiration times.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-4480904285380722824?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/4480904285380722824/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=4480904285380722824' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/4480904285380722824'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/4480904285380722824'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2011/01/sync-your-machine-clocks.html' title='Sync your machine clocks!'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-7093336352648579140</id><published>2010-12-27T16:40:00.005+01:00</published><updated>2010-12-28T11:07:42.544+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OSGI CXF bus failover'/><title type='text'>Configure client side CXF bus in OSGi bundle</title><content type='html'>&lt;span style=";font-family:verdana;font-size:10;"&gt;&lt;br /&gt;Perhaps it was only me who did not get this right in the first place, but here is what I learned last week. &lt;br /&gt;&lt;br /&gt;Inside the same Spring configuration file I configured a CXF bus instance for client side failover and a plain Java bean that was going to use this CXF bus instance for making an external Web Services invocation.  This configuration was to be deployed into Apache ServiceMix 4.3 as an OSGI bundle. &lt;br /&gt;Here is the straight-forward Spring configuration:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans" &amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- Via these imports a CXF bus instance will be made available --&amp;gt;&lt;br /&gt;&amp;lt;import resource="classpath:META-INF/cxf/cxf.xml" /&amp;gt;&lt;br /&gt;&amp;lt;import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /&amp;gt;&lt;br /&gt;&amp;lt;import resource="classpath:META-INF/cxf/cxf-extension-http.xml" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- Instantiates my Java bean --&amp;gt;&lt;br /&gt;&lt;b&gt;&amp;lt;bean id="testBean" class="org.tmielke.cxf.failovertest.TestBean"/&amp;gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- CXF bus failover configuration: --&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- List of alternative addresses --&amp;gt;&lt;br /&gt;&amp;lt;util:list id="addressList"&amp;gt;&lt;br /&gt;  &amp;lt;value&amp;gt;http://localhost:9000/MyService &amp;lt;/value&amp;gt;&lt;br /&gt;  &amp;lt;value&amp;gt;http://localhost:9001/MyService &amp;lt;/value&amp;gt;&lt;br /&gt;&amp;lt;/util:list&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- CXF failover strategy to use above address list --&amp;gt;&lt;br /&gt;&amp;lt;bean id="RandomAddresses" &lt;br /&gt;  class="org.apache.cxf.clustering.RandomStrategy"&amp;gt;&lt;br /&gt;  &amp;lt;property name="alternateAddresses"&amp;gt;&lt;br /&gt;    &amp;lt;ref bean="addressList"/&amp;gt;&lt;br /&gt;  &amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt; &lt;br /&gt;&amp;lt;!-- CXF bus to use failover strategy --&amp;gt;&lt;br /&gt;&lt;b&gt;&amp;lt;jaxws:client &lt;/b&gt;name="{http://com.fusesource/MyService}MyServiceSoap" &lt;br /&gt;  createdFromAPI="false"&amp;gt;&lt;br /&gt;  &amp;lt;jaxws:features&amp;gt;&lt;br /&gt;    &amp;lt;clustering:failover&amp;gt;&lt;br /&gt;      &amp;lt;clustering:strategy&amp;gt;&lt;br /&gt;        &amp;lt;ref bean="RandomAddresses"/&amp;gt;&lt;br /&gt;      &amp;lt;/clustering:strategy&amp;gt;&lt;br /&gt;    &amp;lt;/clustering:failover&amp;gt;&lt;br /&gt;  &amp;lt;/jaxws:features&amp;gt;&lt;br /&gt;&lt;b&gt;&amp;lt;/jaxws:client&amp;gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;This example configures a JAX-WS client configuration for failover using a random strategy for selecting a failover server. It uses the bus instance that was made available by the cxf imports. &lt;br /&gt;It also instantiates a plain Java bean called testBean.&lt;br /&gt;In this Java bean I simply want to use JAX-WS APIs to make an invocation to an external Web Service and I want this failover configuration to be in effect. &lt;br /&gt;&lt;br /&gt;The JAX-WS client code reads similar to this:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;&lt;pre&gt;&lt;br /&gt;package org.tmielke.cxf.failovertest;&lt;br /&gt;import com.fusesource.test.MyService;&lt;br /&gt;import com.fusesource.test.MyServiceSoap;&lt;br /&gt;&lt;br /&gt;public class TestBean {&lt;br /&gt;&lt;br /&gt;  public void goForIt() {&lt;br /&gt;    MyService service = new MyService();&lt;br /&gt;    MyServiceSoap proxy = service.getMyServiceSoap();&lt;br /&gt;    proxy.callWhateverBusinessMethod();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;My assumption was that because I configured both the Java bean and the CXF bus instance inside the same Spring configuration file, that my Java bean use this pre-configured bus instance when making an outgoing JAX-WS invocation. &lt;br /&gt;&lt;br /&gt;However, that is not the case!&lt;br /&gt;The problem is that when deploying into OSGi, there is a particular thread used at deployment time that parses the Spring configuration files. Then at runtime another thread is used for executing the Java bean and the JAX-WS code.&lt;br /&gt;The SpringDeployer thread at deployment time creates a CXF bus instance and configures it for failover according to my Spring configuration. However this CXF bus instance is only bound to the thread context of this SpringDeployer thread. &lt;br /&gt;&lt;br /&gt;At runtime when the above JAX-WS code gets executed, a different thread will run this code and that thread will have a different CXF thread context assigned. This CXF thread context is not connected to the CXF bus instance created at deployment time, but to a default CXF bus instance that has not got any additional configuration.  Hence no failover will happen in this case!&lt;br /&gt;&lt;br /&gt;So wondering about the solution?&lt;br /&gt;&lt;br /&gt;You may guess it already; a simple solution is to inject the TestBean with the CXF bus instance created at deployment time. &lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;bean id="testBean" class="org.tmielke.cxf.failovertest.TestBean"&amp;gt;&lt;br /&gt;  &lt;b&gt;&amp;lt;property name="bus" ref="cxf"/&amp;gt;&lt;/b&gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;This requires the Java bean to expose a setter method for the CXF bus instance:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#365f91;font-size:100%;"&gt;&lt;pre&gt;&lt;br /&gt;package org.tmielke.cxf.failovertest;&lt;br /&gt;&lt;br /&gt;import com.fusesource.test.MyService;&lt;br /&gt;import com.fusesource.test.MyServiceSoap;&lt;br /&gt;&lt;br /&gt;import org.apache.cxf.Bus;&lt;br /&gt;import org.apache.cxf.BusFactory;&lt;br /&gt;&lt;br /&gt;public class TestBean {&lt;br /&gt;&lt;br /&gt;  //store the configured CXF bus internally&lt;br /&gt;  &lt;b&gt;private Bus bus = null;&lt;/b&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;b&gt;public void setBus(Bus bus) {&lt;br /&gt;    this.bus = bus;&lt;br /&gt;  }&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  public Bus getBus() {&lt;br /&gt;    return bus;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void goForIt() {&lt;br /&gt;    &lt;b&gt;BusFactory.setThreadDefaultBus(bus);&lt;/b&gt;&lt;br /&gt;    MyService service = new MyService();&lt;br /&gt;    MyServiceSoap proxy = service.getMyServiceSoap();&lt;br /&gt;    proxy.callWhateverBusinessMethod();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Before using any JAX-WS APIs in my Java bean I need to call BusFactory.setThreadDefaultBus() to assign my preconfigured bus instance to the current thread context. &lt;br /&gt;&lt;br /&gt;Now I am ready to make the external Web Service invocation with the failover configuration being in effect.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Note, without explicitly setting the CXF bus instance to be used, I would use the instance that gets returned from BusFactory.getDefaultBus().  BusFactory.getDefaultBus() is called by the CXF JAX-WS implementation to set the bus on the CXF server or client.&lt;br /&gt;BusFactory.getDefaultBus() basically returns a default bus instance without any failover configuration, unless I explicitly assign a different bus instance using BusFactory.setThreadDefaultBus(). &lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-7093336352648579140?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/7093336352648579140/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=7093336352648579140' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/7093336352648579140'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/7093336352648579140'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2010/12/configure-client-side-cxf-bus-in-osgi.html' title='Configure client side CXF bus in OSGi bundle'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-947850602324956091</id><published>2010-12-07T11:15:00.003+01:00</published><updated>2010-12-07T11:24:40.945+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FuseSource'/><category scheme='http://www.blogger.com/atom/ns#' term='professional support'/><category scheme='http://www.blogger.com/atom/ns#' term='CXF'/><category scheme='http://www.blogger.com/atom/ns#' term='Camel'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveMQ'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache'/><category scheme='http://www.blogger.com/atom/ns#' term='ServiceMix'/><title type='text'>Rebooting ...</title><content type='html'>This blog is finally going to be revitalized!&lt;br /&gt;&lt;br /&gt;After an entire year I am finally back to work on Open Source again. In November this year I have joined a company called &lt;a href="http://www.fusesource.com/"&gt;FuseSource &lt;/a&gt;as a Senior Engineer and am really excited about the new role!&lt;br /&gt;FuseSource is owned by &lt;a href="http://www.progress.com/"&gt;Progress Software&lt;/a&gt; and offers enterprise subscriptions for the Apache Open Source products ActiveMQ, ServiceMix, Camel and CXF. Wanna know what an enterprise subscription consists of? Check it out &lt;a href="http://fusesource.com/enterprise-support/support-offerings/"&gt;here&lt;/a&gt;. At FuseSource we certify, package and distribute the above Apache projects, backed by enterprise-class professional services to support all phases of development and deployment of these products. A large &lt;a href="http://fusesource.com/community/"&gt;community &lt;/a&gt;has grown fairly quickly around our &lt;a href="http://fusesource.com/enterprise-support/"&gt;offerings&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If you're using any of the above products and their uptime and availability becomes an important factor in your business, you then might want to consider getting &lt;a href="http://fusesource.com/enterprise-support/"&gt;professional support&lt;/a&gt;.&lt;br /&gt;Besides, come along and join our fast growing &lt;a href="http://fusesource.com/community/"&gt;community&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;So watch out for more technical postings on this blog coming up soon…&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-947850602324956091?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/947850602324956091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=947850602324956091' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/947850602324956091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/947850602324956091'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2010/12/rebooting.html' title='Rebooting ...'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-2157587947004473935</id><published>2009-12-17T17:33:00.005+01:00</published><updated>2009-12-18T14:20:21.565+01:00</updated><title type='text'>Using Spring JMS Template for sending messages to ActiveMQ</title><content type='html'>&lt;span style=";font-family:verdana;font-size:10;"/&gt;&lt;br /&gt;&lt;br /&gt;Something that took me a long way to really understand. And I only got there by debugging through the low level Spring and ActiveMQ code.&lt;br /&gt;There are various articles out there that warn you about using JmsTemplate for producing messages outside any container. A runtime container will usually pool your JMS resources (connection, session and producer), but when using JmsTemplate in a standalone application, no pooling is there per se. The JmsTemplate is certainly not responsible for pooling resources.&lt;br /&gt;&lt;br /&gt;I have seen a number of applications that use JmsTemplate outside of any applicaton server container for producing messages. It seems to be more popular than using the plain JMS APIs. No wonder as Spring JMS provides such a nice layer of abstraction that shields all the low level JMS code, just like this snippet:&lt;br /&gt;&lt;span style="color: rgb(54, 95, 145);"&gt;&lt;b&gt;&lt;code&gt;&lt;/code&gt;&lt;pre&gt;&lt;br /&gt;ConnectionFactory cf2 = new ConnectionFactory("tcp://localhost:61616");&lt;br /&gt;JmsTemplate template = new JmsTemplate(cf2);&lt;br /&gt;template.send("MyQueue", new MessageCreator() {&lt;br /&gt;  public Message createMessage(Session session)&lt;br /&gt;  throws JMSException {&lt;br /&gt;    TextMessage tm = session.createTextMessage();&lt;br /&gt;    tm.setText("A new message");&lt;br /&gt;    return tm;&lt;br /&gt;  }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;However something that is easily forgotten is that this code will create a new JMS connection, consumer and producer for each call to JmsTemplate.send(). Creating these JMS objects are expensive operations and according to the JMS spec these resources are meant to be re-used and not re-created for every message. Performance is going to suffer dramatically when they are not re-used.&lt;br /&gt;That’s pretty clear to most developers but very easily forgotten.&lt;br /&gt;&lt;br /&gt;So what is really needed in order to pool all these JMS resources when sending messages with JmsTemplate? I personally was confused whether I need to configure some Jencks container in order to have the JMS resources pooled or could I use plain ActiveMQ connection factories and how does the configuration need to look like? The various documentations I found only added to that confusion.&lt;br /&gt;&lt;br /&gt;The answer is pretty simple: All that is needed is to use the org.apache.activemq.pool.PooledConnectionFactory. It will serve JMS connections from its internal pool and wrap them in a PooledConnection instance. The purpose of the PooledConnection is to also pool any JMS sessions and producers that get created. The pool can be configured of course.&lt;br /&gt;For using the JmsTemplate there is no need to configure any containers like Jencks and others. Also see &lt;a href="http://activemq.apache.org/jmstemplate-gotchas.html"&gt;http://activemq.apache.org/jmstemplate-gotchas.html&lt;/a&gt; for some additional information on this topic.&lt;br /&gt;The following simple and complete Spring configuration is enough:&lt;br /&gt;&lt;span style="color: rgb(54, 95, 145);"&gt;&lt;b&gt;&lt;code&gt;&lt;/code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans"&lt;br /&gt;  xmlns:tx="http://www.springframework.org/schema/tx"&lt;br /&gt;  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;  xsi:schemaLocation="http://www.springframework.org/schema/beans &lt;br /&gt;  http://www.springframework.org/schema/beans/spring-beans-2.0.xsd&lt;br /&gt;  http://www.springframework.org/schema/tx &lt;br /&gt;  http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"&amp;gt;&lt;br /&gt;	&lt;br /&gt;  &amp;lt;bean id="connectionFactory" &lt;br /&gt;    class="org.apache.activemq.pool.PooledConnectionFactory"&amp;gt;&lt;br /&gt;    &amp;lt;constructor-arg value="failover:(tcp://localhost:61616)"/&amp;gt;&lt;br /&gt;  &amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;bean id="jmsTemplate" &lt;br /&gt;    class="org.springframework.jms.core.JmsTemplate"&amp;gt;&lt;br /&gt;    &amp;lt;constructor-arg ref="connectionFactory"/&amp;gt;&lt;br /&gt;    &amp;lt;property name="sessionTransacted" value="false"/&amp;gt;&lt;br /&gt;    &amp;lt;property name="receiveTimeout" value="5000"/&amp;gt;   &lt;br /&gt;  &amp;lt;/bean&amp;gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;It pre-configures the JmsTemplate to use the ActiveMQ PooledConnectionFactory so it can be used straight away in a Java program:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;package org.apache.activemq.test.jmstemplate;&lt;br /&gt;&lt;br /&gt;import javax.jms.JMSException;&lt;br /&gt;import javax.jms.Message;&lt;br /&gt;import javax.jms.Session;&lt;br /&gt;import javax.jms.TextMessage;&lt;br /&gt;&lt;br /&gt;import org.springframework.context.ApplicationContext;&lt;br /&gt;import org.springframework.context.support.ClassPathXmlApplicationContext;&lt;br /&gt;import org.springframework.jms.core.JmsTemplate;&lt;br /&gt;import org.springframework.jms.core.MessageCreator;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class JmsTemplateTest {&lt;br /&gt;&lt;br /&gt;  public static void main(String[] args) throws Exception {&lt;br /&gt;&lt;br /&gt;    ApplicationContext ctx = new ClassPathXmlApplicationContext(&lt;br /&gt;      "JmsTemplateTest-context.xml");&lt;br /&gt;    JmsTemplate template = (JmsTemplate) ctx.getBean("jmsTemplate");&lt;br /&gt;        &lt;br /&gt;    for(int i=0; i&lt;10; i++) {&lt;br /&gt;      template.send("MyQueue", new MessageCreator() {&lt;br /&gt;        public Message createMessage(Session session)&lt;br /&gt;          throws JMSException {&lt;br /&gt;          TextMessage tm = session.createTextMessage();&lt;br /&gt;          tm.setText("This is a test message");&lt;br /&gt;          return tm;&lt;br /&gt;        }&lt;br /&gt;      });&lt;br /&gt;    }&lt;br /&gt;    System.exit(1);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;A Maven based &lt;a href="http://abloggerscode.googlecode.com/svn/trunk/JmsTemplateDemo/"&gt;test case&lt;/a&gt; is provided. It can be checked out using &lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;svn checkout http://abloggerscode.googlecode.com/svn/trunk/JmsTemplateDemo&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;Once checked out, follow the instructions in README.txt.&lt;br /&gt;&lt;br /&gt;Be careful when using Springs SingleConnectionFactory. It does re-use the underlying JMS connection but it does not re-use the JMS session and producer when configured to internally work with the ActiveMQConnectionFactory!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-2157587947004473935?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/2157587947004473935/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=2157587947004473935' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/2157587947004473935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/2157587947004473935'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2009/12/using-spring-jms-template-for-sending.html' title='Using Spring JMS Template for sending messages to ActiveMQ'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-1113130986103924880</id><published>2009-11-04T10:22:00.006+01:00</published><updated>2009-11-04T10:32:16.587+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='queue'/><category scheme='http://www.blogger.com/atom/ns#' term='JDBC'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveMQ'/><category scheme='http://www.blogger.com/atom/ns#' term='hung'/><title type='text'>Does ActiveMQ 5.3 broker get hung if there are millions of messages on a queue and direct JDBC is used?</title><content type='html'>&lt;span style=";font-family:verdana;font-size:10;"&gt;&lt;br /&gt;That was an interesting ActiveMQ issue I had to work on last week.&lt;br /&gt;We used ActiveMQ 5.3.0.3-fuse with direct JDBC persistence to a MySQL database.&lt;br /&gt;&lt;br /&gt;And noticed that when we had 2 million persistent messages on queue A, we could not even process any messages on an empty queue B. It seemed the broker got hung but then it did react to any commands from the web or JMX console.&lt;br /&gt;&lt;br /&gt;When looking into the cause of this more deeply we found this:&lt;br /&gt;&lt;br /&gt;In ActiveMQ there is a cleanup task thread that periodically checks for expired or acknowledged messages. In case of using a direct JDBC persistence, this task runs the following SQL command against the JDBC database table where the JMS messages are stored:&lt;br /&gt;&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;DELETE FROM ACTIVEMQ_MSGS WHERE ( EXPIRATION&lt;&gt;0 AND EXPIRATIONOR ID &lt;= &lt;br /&gt;( SELECT min(ACTIVEMQ_ACKS.LAST_ACKED_ID) FROM ACTIVEMQ_ACKS WHERE &lt;br /&gt;ACTIVEMQ_ACKS.CONTAINER=ACTIVEMQ_MSGS.CONTAINER)&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;Depending on the JDBC database used, that SQL statement might lock the entire database table during the run of that statement. This is certainly the case when using MySQL but not when using Apache Derby. Other JDBC databases might lock the entire table as well.&lt;br /&gt;&lt;br /&gt;During that time no other persistent message (no matter for what queue) can be processed, as all JMS messages for all queues are stored in the same database table called &lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;activemq_msgs&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;. For a database table with millions of messages, this might take several mins or more (I had to wait around 15 mins for that statement to complete).&lt;br /&gt;Also, the cleanup task is scheduled to run at a fixed rate (every 2 mins or so), so once it completed it is already late on schedule and therefore gets kicked off again straight away, not leaving much time for other threads to insert new messages into the db. So the threads managing the other queues starve and might perhaps never get the processing time to process their messages.&lt;br /&gt;&lt;br /&gt;This behavior can be confirmed by adding the following logging configuration&lt;br /&gt;&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;log4j.logger.org.apache.activemq.store.jdbc=DEBUG&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;It will log the above SQL statement being executed for a long time and being called repeatedly as soon as it has finished.&lt;br /&gt;Also when attaching jconsole to the broker and capturing a stack trace of the thread that is to process new messages, it should be waiting for a long time on the JDBC database driver to complete the SQL insert statement.&lt;br /&gt;&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;Name: QueueThread:queue://JMSLoadTest.queue.0&lt;br /&gt; State: RUNNABLE&lt;br /&gt; Total blocked: 1  Total waited: 0&lt;br /&gt;&lt;br /&gt; Stack trace:&lt;br /&gt; java.net.SocketInputStream.socketRead0(Native Method)&lt;br /&gt; java.net.SocketInputStream.read(SocketInputStream.java:129)&lt;br /&gt; com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:113)&lt;br /&gt; com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:160)&lt;br /&gt; com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:188)&lt;br /&gt; com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2428)&lt;br /&gt; com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2882)&lt;br /&gt; com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2871)&lt;br /&gt; com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3414)&lt;br /&gt; com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1936)&lt;br /&gt; com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2060)&lt;br /&gt; com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2542)&lt;br /&gt; com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1734)&lt;br /&gt; com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1876)&lt;br /&gt; org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:91)&lt;br /&gt; org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:91)&lt;br /&gt; org.apache.activemq.store.jdbc.adapter.DefaultJDBCAdapter.doRecoverNextMessages(DefaultJDBCAdapter.java:709)&lt;br /&gt; org.apache.activemq.store.jdbc.JDBCMessageStore.recoverNextMessages(JDBCMessageStore.java:230)&lt;br /&gt; org.apache.activemq.store.ProxyMessageStore.recoverNextMessages(ProxyMessageStore.java:83)&lt;br /&gt; org.apache.activemq.broker.region.cursors.QueueStorePrefetch.doFillBatch(QueueStorePrefetch.java:75)&lt;br /&gt; org.apache.activemq.broker.region.cursors.AbstractStoreCursor.fillBatch(AbstractStoreCursor.java:210)&lt;br /&gt; org.apache.activemq.broker.region.cursors.AbstractStoreCursor.hasNext(AbstractStoreCursor.java:119)&lt;br /&gt; org.apache.activemq.broker.region.cursors.StoreQueueCursor.hasNext(StoreQueueCursor.java:131)&lt;br /&gt; org.apache.activemq.broker.region.Queue.doPageIn(Queue.java:1243)&lt;br /&gt; org.apache.activemq.broker.region.Queue.pageInMessages(Queue.java:1378)&lt;br /&gt; org.apache.activemq.broker.region.Queue.iterate(Queue.java:1086)&lt;br /&gt; org.apache.activemq.thread.DeterministicTaskRunner.runTask(DeterministicTaskRunner.java:84)&lt;br /&gt; org.apache.activemq.thread.DeterministicTaskRunner$1.run(DeterministicTaskRunner.java:41)&lt;br /&gt; java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)&lt;br /&gt; java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)&lt;br /&gt; java.lang.Thread.run(Thread.java:595)&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;The broker itself is not hung but the cleanup task locks the entire JDBC database. If the broker is left running for a longer time, it will process new messages, but only a few within a longer time frame.&lt;br /&gt;I raised &lt;a href="http://fusesource.com/issues/browse/MB-558"&gt;MB-558&lt;/a&gt; (mirrored in &lt;a href="https://issues.apache.org/activemq/browse/AMQ-2470"&gt;AMQ-2470&lt;/a&gt;) for this problem and Gary Tully fixed it by changing the clean up task from a running at a fixed rate to running at a fixed delay.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-1113130986103924880?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/1113130986103924880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=1113130986103924880' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/1113130986103924880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/1113130986103924880'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2009/11/does-activemq-53-broker-get-hung-if.html' title='Does ActiveMQ 5.3 broker get hung if there are millions of messages on a queue and direct JDBC is used?'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-8711167760816194770</id><published>2009-05-13T15:31:00.010+02:00</published><updated>2009-05-13T16:09:50.935+02:00</updated><title type='text'>Understanding Authentication and Authorization in ServiceMix</title><content type='html'>&lt;span style=";font-family:verdana;font-size:10;"&gt;&lt;br /&gt;I spent a good few hours lately trying to understand how authentication and authorization work inside ServiceMix 3. It is this gathered knowledge that I want to share in this post. For those in a hurry, there's an executive summary at the end. For this article I assume you know the basic concepts of JAAS. Some reference material on JAAS can be found &lt;a href="http://java.sun.com/j2se/1.5.0/docs/guide/security/jaas/JAASRefGuide.html"&gt;here&lt;/a&gt; and &lt;a href="http://java.sun.com/j2se/1.5.0/docs/guide/security/jaas/tutorials/GeneralAcnOnly.html#ConfigFile"&gt;here&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Such complex topic is easier to understand if it is based on a valid use-case that others can reproduce easily. A pretty good candidate is the cxf-ws-security demo in ServiceMix 3.2. Anyone not familiar with that demo might want to build and run it prior to reading on. &lt;br /&gt;In addition I encourage you to &lt;a href="http://servicemix.apache.org/SMX4KNL/51-troubleshooting-debugging-and-profiling.html"&gt;debug&lt;/a&gt; through the ServiceMix source code while you read through this article. Simply set the SERVICEMIX_DEBUG=1 environment variable and attach a Java debugger to ServiceMix. You can then place breakpoints into the relevant source code that I discuss below and walk through the call stack and source code as you read along.&lt;br /&gt;&lt;br /&gt;I will not try to discuss all of the security aspects in ServiceMix 3 here as such scope is far too broad. Rather this article is based on running the cxf-ws-security demo and aims to explain how an incoming SOAP/HTTP request gets authenticated and authorized in ServiceMix 3.&lt;br /&gt;&lt;br /&gt;Alright, the stage is set, let's start. &lt;br /&gt;The demo's use-case is &lt;br /&gt;  External CXF Java client -&gt; CXF-BC consumer -&gt; CXF-SE component&lt;br /&gt;&lt;br /&gt;as shown in the demo's README.txt. With regards to security we want to make sure that the client gets authenticated based on a username/password combination before verifying if the client has permissions to call the service (authorization). Sounds simple enough but it involves a good number of components as well we see next. &lt;br /&gt;&lt;br /&gt;As documented in the cxf-ws-security demo, an external SOAP client sends a SOAP/HTTP request to the CXF-BC consumer component deployed in ServiceMix. The SOAP request includes a large WSSE Security header carrying a WS-Security UsernameToken profile among an XML-Signature and some XML-Encrypted content.  I will not focus on XML-Signature and XML-Encryption here (some information on this regards was posted &lt;a href="http://tmielke.blogspot.com/2008/07/ws-security-woes-in-servicemix-32.html"&gt;previously&lt;/a&gt;). For this discussion the UsernameToken profile is of most interest and is included in the SOAP request as follows (omitting some details for clarity):&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;soap:Envelope xmlns:soap="..." &amp;gt;&lt;br /&gt;  &amp;lt;soap:Header&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;    &amp;lt;wsse:Security&amp;gt;&lt;br /&gt;      &amp;lt;wsse:UsernameToken&amp;gt;&lt;br /&gt;        &amp;lt;wsse:Username&amp;gt;alice&amp;lt;/wsse:Username&amp;gt;&lt;br /&gt;        &amp;lt;wsse:Password&amp;gt;password&amp;lt;/wsse:Password&amp;gt;&lt;br /&gt;      &amp;lt;/wsse:UsernameToken&amp;gt;&lt;br /&gt;      ...&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;It is this username/password combination in the SOAP security header that will be used for authentication inside ServiceMix. &lt;br /&gt;So the request first hits the jetty server in the servicemix-cxf-bc component from where it gets passed into the CXF interceptor stack. There are a good couple of CXF &lt;a href="http://cwiki.apache.org/CXF20DOC/interceptors.html"&gt;interceptors&lt;/a&gt; configured by default. In our demo the list of CXF interceptors to be executed is as follows:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;DEBUG - PhaseInterceptorChain:          &lt;br /&gt;  receive [AttachmentInInterceptor, LoggingInInterceptor]&lt;br /&gt;  post-stream [StaxInInterceptor]&lt;br /&gt;  read [ReadHeadersInterceptor]&lt;br /&gt;  pre-protocol [MustUnderstandInterceptor, SAAJInInterceptor, &lt;i&gt;WSS4JInInterceptor&lt;/i&gt;, &lt;br /&gt;                &lt;i&gt;JbiJAASInterceptor&lt;/i&gt;]&lt;br /&gt;  unmarshal [JbiOperationInterceptor]&lt;br /&gt;  pre-invoke [JbiInWsdl1Interceptor, JbiInInterceptor]&lt;br /&gt;  invoke [&lt;i&gt;JbiInvokerInterceptor&lt;/i&gt;, UltimateReceiverMustUnderstandInterceptor]&lt;br /&gt;  post-invoke [JbiPostInvokerInterceptor, OutgoingChainInterceptor]&lt;br /&gt;&lt;/pre&gt;&lt;/b&gt;&lt;/code&gt;&lt;/font&gt;&lt;br /&gt;Those interceptors in italics are of primary interest for this discussion.&lt;br /&gt;In the configuration of the demo's ws-security-cxfbc-su component (in ws-security-cxfbc-su /src/main/resources/xbean.xml) we explicitly added and configured the org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor that will perform the WS-Security functions. It is the first security relevant interceptor that we want to look at closer. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://svn.apache.org/repos/asf/cxf/tags/cxf-2.1.3/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java"&gt;org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage()&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This interceptor handles the entire SOAP WS-Security header. In our example it needs to decrypt all the encrypted parts of the SOAP request, perform the XML-Signature check and extract the username/password information from the WS-Security header. What functions to perform is specified in xbean.xml, where this interceptor is configured (see the "action" list):&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor"&lt;br /&gt;    id="WSS4J"&amp;gt;&lt;br /&gt;    &amp;lt;constructor-arg&amp;gt;&lt;br /&gt;        &amp;lt;map&amp;gt;&lt;br /&gt;          &amp;lt;entry key="action" value="Timestamp Signature Encrypt UsernameToken"/&amp;gt;&lt;br /&gt;            &amp;lt;entry key="..." .../&amp;gt;&lt;br /&gt;            ...&lt;br /&gt;        &amp;lt;/map&amp;gt;&lt;br /&gt;      &amp;lt;/constructor-arg&amp;gt;&lt;br /&gt;    &amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;The name tells it already, this interceptor uses Apache WSS4J to perform these WS-Security functions. This line of code inside CXF WSS4JInInterceptor.handleMessage() method calls into WSS4J:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;Vector wsResult = getSecurityEngine().processSecurityHeader(&lt;br /&gt;  doc.getSOAPPart(), &lt;br /&gt;  actor, &lt;br /&gt;  cbHandler, &lt;br /&gt;  reqData.getSigCrypto(), &lt;br /&gt;  reqData.getDecCrypto()&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;I will not cover the Apache WSS4J specifics here but want to mention that the WSS4JInInterceptor configuration includes a password callback implementation that is used to obtain password for decryption and UsernameToken verification. This is also specified in the xbean.xml of the servicemix-cxf-bc-su component:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;entry key="passwordCallbackClass" &lt;br /&gt;   value="org.apache.servicemix.samples.cxf_ws_security.KeystorePasswordCallback"/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;See the Apache WSS4J &lt;a href="http://ws.apache.org/wss4j/api.html"&gt;documentation&lt;/a&gt; for more detailed information on WSS4J.&lt;br /&gt;&lt;br /&gt;The outcome of each of the WS-Security function performed by WSS4J is stored in a java.util.Vector of org.apache.ws.security.WSSecurityEngineResult objects called wsResult that is then added as a property to the SoapMessage using the key WSHandlerConstants.RECV_RESULTS. This vector carries all the results from processing the WS-Security header, such as the principal, SAML token, X.509 certificates, etc.&lt;br /&gt;&lt;br /&gt;Other interceptors that get invoked later will require these results for their own processing.&lt;br /&gt;&lt;br /&gt;One of the vector elements will contain the result of parsing the WS-Security UsernameToken profile in form of a org.apache.ws.security.WSUsernameTokenPrincipal object instance. This hosts the username and password information that was received with the SOAP request.&lt;br /&gt;&lt;br /&gt;That is roughly what the WSS4JInInterceptor does with our SOAP request.&lt;br /&gt;The next CXF interceptor to be invoked is:&lt;br /&gt;&lt;br /&gt;&lt;a href="https://projects.open.iona.com/projects/svn/iona/servicemix/components/tags/components-pom-2008.01.0.2-fuse/bindings/servicemix-cxf-bc/src/main/java/org/apache/servicemix/cxfbc/interceptors/JbiJAASInterceptor.java"&gt;org.apache.servicemix.cxfbc.interceptors.JbiJAASInterceptor.handleMessage()&lt;/a&gt;&lt;br /&gt;This one is invoked right after the WSSJ4InInterceptor and is rather complex. I will try my best to explain it in most simple terms.&lt;br /&gt;It first of all extracts the WSHandlerConstants.RECV_RESULTS vector that was set by the previous WSS4JInInterceptor &lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;// in JbiJAASInterceptor.handleMessage()&lt;br /&gt;List&amp;lt;Object&amp;gt; results = (Vector&amp;lt;Object&amp;gt;)message.get(WSHandlerConstants.RECV_RESULTS);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;and next checks if this Vector contains any org.apache.ws.security.WSUsernameTokenPrincipal object:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;for (Iterator it = hr.getResults().iterator(); it.hasNext();) {&lt;br /&gt;  WSSecurityEngineResult er = (WSSecurityEngineResult) it.next();&lt;br /&gt;  if (er != null &amp;&amp; er.getPrincipal() instanceof     &lt;br /&gt;      WSUsernameTokenPrincipal){&lt;br /&gt;    WSUsernameTokenPrincipal p = &lt;br /&gt;      (WSUsernameTokenPrincipal)er.getPrincipal();&lt;br /&gt;    subject.getPrincipals().add(p);&lt;br /&gt;                           &lt;br /&gt;    this.authenticationService.authenticate(subject, domain, p.getName(), p.getPassword());&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;If yes, then the principal gets added to the javax.security.auth.Subject instance and the authentication service gets invoked. It is this security Subject instance that will carry all credentials information after a successful authentication!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://svn.apache.org/repos/asf/servicemix/smx3/tags/servicemix-3.3/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/security/auth/impl/JAASAuthenticationService.java"&gt;org.apache.servicemix.jbi.security.auth.impl.JAASAuthenticationService.authenticate()&lt;/a&gt;&lt;br /&gt;JAAS will be used now to perform the authentication.&lt;br /&gt;At first a new JAAS javax.security.auth.login.LoginContext gets created while also registering a JAAS callback handler:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;//in method authenticate()&lt;br /&gt;LoginContext loginContext = new LoginContext(domain, subject, new CallbackHandler() {&lt;br /&gt;  public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {&lt;br /&gt;    for (int i = 0; i &amp;lt; callbacks.length; i++) {&lt;br /&gt;      if (callbacks[i] instanceof NameCallback) {&lt;br /&gt;        ((NameCallback) callbacks[i]).setName(user);&lt;br /&gt;      } else if (callbacks[i] instanceof PasswordCallback &amp;&amp; credentials instanceof String) {&lt;br /&gt;       ((PasswordCallback) callbacks[i]).setPassword(((String) credentials).toCharArray());&lt;br /&gt;      } else if (callbacks[i] instanceof CertificateCallback &amp;&amp; credentials instanceof X509Certificate) {&lt;br /&gt;        ((CertificateCallback) callbacks[i]).setCertificate((X509Certificate) credentials);&lt;br /&gt;      } else {&lt;br /&gt;        throw new UnsupportedCallbackException(callbacks[i]);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;This callback handler that we pass into the LoginContext constructor is able to deal with different types of callbacks (see the handle() method) and will be invoked later in order to take the username and password of the incoming request and place it into the callback object.&lt;br /&gt;Once the LoginContext got instantiated, we can perform the authentication by calling&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;loginContext.login();&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;This API call internally invokes the configured JAAS login modules to perform their respective types of authentication (username/password based or certificate based, etc). If the call to login() returns without throwing an exception, the overall authentication succeeded. It is therefore the login module implementation that really decides whether a client is authenticated or not.&lt;br /&gt;&lt;br /&gt;How are the login modules configured resolved and configured at runtime? Well, the domain argument of the LoginContext constructor specifies the index into a configuration that determines which LoginModules to use for the authentication. In our case the domain value will be "servicemix-domain", which matches the domain defined in conf/login.properties:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;/* conf/login.properties */&lt;br /&gt;servicemix-domain {&lt;br /&gt;    org.apache.servicemix.jbi.security.login.PropertiesLoginModule &lt;br /&gt;        sufficient&lt;br /&gt;        org.apache.servicemix.security.properties.user="users-passwords.properties"&lt;br /&gt;        org.apache.servicemix.security.properties.group="groups.properties";    &lt;br /&gt;&lt;br /&gt;    org.apache.servicemix.jbi.security.login.CertificatesLoginModule &lt;br /&gt;        sufficient&lt;br /&gt;        org.apache.servicemix.security.certificates.user="users-credentials.properties"&lt;br /&gt;        org.apache.servicemix.security.certificates.group="groups.properties";   &lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;By default this registers two login modules which will be invoked in order until the call to login() succeeds. Actually the JAAS javax.security.auth.login.LoginModule will invoke initialize(), login() and commit() on the configured login modules in this order. Each login module class gets configured for a bunch of config files (we'll explore that later).&lt;br /&gt;&lt;br /&gt;So the call to loginContext.login() internally invokes &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;PropertiesLoginModule.initialize()&lt;/li&gt;&lt;br /&gt;&lt;li&gt;PropertiesLoginModule.login()&lt;/li&gt;&lt;br /&gt;&lt;li&gt;PropertiesLoginModule.commit()&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;in this order. If the call to any of these methods raises an exception, the CertificatesLoginModule will be tried. If the CertificatesLoginModule also raises an exception, then the authentication fails. &lt;br /&gt;The various classes used in JAASAuthenticationService.authenticate() method (LoginContext, LoginModule, CallbackHandler, etc) are pure JAAS terminology and not ServiceMix specific. If you are not familiar with these, check the JAAS documentation.&lt;br /&gt;&lt;br /&gt;Time to examine the org.apache.servicemix.jbi.security.login.PropertiesLoginModule next and see how it performs the authentication.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="https://projects.open.iona.com/projects/svn/iona/servicemix/tags/servicemix-3.4.0.0-fuse/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/security/login/PropertiesLoginModule.java"&gt;org.apache.servicemix.jbi.security.login.PropertiesLoginModule&lt;/a&gt;&lt;br /&gt;This JAAS login module is used for username/password based login and is configured for two property files in conf/login.properties. The file users-passwords.properties (to be found in your ServiceMix conf/ directory) stores usernames and their passwords. The other properties file groups.properties maps users to their roles. If authentication succeeds, each authenticated user gets one or more roles assigned, according to this properties file. The authorization decision that is performed later will be done on the user's role, not the user's name (role based access control)!&lt;br /&gt;&lt;b&gt;PropertiesLoginModule.initialize()&lt;/b&gt; does not do too much, it only resolves the two property file names from the login module configuration in login.properties.&lt;br /&gt;In &lt;b&gt;PropertiesLoginModule.login()&lt;/b&gt; these files get loaded into memory. Notice that any changes to either users-passwords.properties or groups.properties will be reloaded when dealing with the next invocation! So you can adjust the user and role mapping at runtime.&lt;br /&gt;The next step is to instantiate a javax.security.auth.callback.Callback array containing a NameCallback and a PasswordCallback. &lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;// in method PropertiesLoginModule.login()&lt;br /&gt;Callback[] callbacks = new Callback[2];&lt;br /&gt;callbacks[0] = new NameCallback("Username: ");&lt;br /&gt;callbacks[1] = new PasswordCallback("Password: ", false);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;These callbacks are then passed into the callback handler that was created with the LoginContext earlier in JAASAuthenticationService.authenticate() (see previous sample code above):&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;//in method PropertiesLoginModule.login()&lt;br /&gt;callbackHandler.handle(callbacks);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;The callback handler now iterates through all the callbacks (in our case two, namely the NameCallback and PasswordCallback) and checks of what type they are. Check the code that I quoted above already:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;//in method JAASAuthenticationService.authenticate()&lt;br /&gt;LoginContext loginContext = new LoginContext(domain, subject, new CallbackHandler() {&lt;br /&gt;  public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {&lt;br /&gt;    for (int i = 0; i &amp;lt; callbacks.length; i++) {&lt;br /&gt;      if (callbacks[i] instanceof NameCallback) {&lt;br /&gt;        ((NameCallback) callbacks[i]).setName(user);&lt;br /&gt;      } else if (callbacks[i] instanceof PasswordCallback &amp;&amp; credentials instanceof String) {&lt;br /&gt;       ((PasswordCallback) callbacks[i]).setPassword(((String) credentials).toCharArray());&lt;br /&gt;      } else if (callbacks[i] instanceof CertificateCallback &amp;&amp; credentials instanceof X509Certificate) {&lt;br /&gt;        ((CertificateCallback) callbacks[i]).setCertificate((X509Certificate) credentials);&lt;br /&gt;      } else {&lt;br /&gt;        throw new UnsupportedCallbackException(callbacks[i]);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;For the NameCallback it sets the username that was extracted from the WS UsernameToken profile of the incoming SOAP request. And for the PasswordCallback it sets the corresponding password. If the callback was of type CertificateCallback, it would set the X.509 certificate of the incoming WSSE security header (this is not the case in our example).&lt;br /&gt;Next we jump back into our PropertiesLoginModule.login() method. The two callback objects now contain the client's username and password (as sent with the SOAP request), so we can authenticate them. &lt;br /&gt;The rest is very simple. The username and password extracted from the callback are compared to the user/password combinations loaded from users-passwords.properties and if they don't math an FailedLoginException is raised.&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;// method PropertiesLoginModule.login() continued&lt;br /&gt;user = ((NameCallback) callbacks[0]).getName();&lt;br /&gt;char[] tmpPassword = ((PasswordCallback) callbacks[1]).getPassword();&lt;br /&gt;if (tmpPassword == null) {&lt;br /&gt;  tmpPassword = new char[0];&lt;br /&gt;}&lt;br /&gt;String password = users.getProperty(user);&lt;br /&gt;if (password == null) {&lt;br /&gt;  throw new FailedLoginException("User does not exist");&lt;br /&gt;}&lt;br /&gt;if (!password.equals(new String(tmpPassword))) {&lt;br /&gt;  throw new FailedLoginException("Password does not match");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;It is this code where the authentication either succeeds or fails. If authentication fails, a FailedLoginException is raised, causing the call to PropertiesLoginModule.abort(), otherwise &lt;b&gt;PropertiesLoginModule.commit()&lt;/b&gt; is invoked. Inside commit() we only add the relevant security roles from groups.properties to the authenticated user and add the entire authenticated principal to the java security Subject:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;public boolean commit() throws LoginException {&lt;br /&gt;        principals.add(new UserPrincipal(user));&lt;br /&gt;&lt;br /&gt;  for (Enumeration enumeration = groups.keys(); enumeration.hasMoreElements();) {&lt;br /&gt;    String name = (String) enumeration.nextElement();&lt;br /&gt;    String[] userList = ((String) groups.getProperty(name) + "").split(",");&lt;br /&gt;    for (int i = 0; i &amp;lt; userList.length; i++) {&lt;br /&gt;      if (user.equals(userList[i])) {&lt;br /&gt;        principals.add(new GroupPrincipal(name));&lt;br /&gt;        break;&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  subject.getPrincipals().addAll(principals);&lt;br /&gt;  ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;The Java security Subject now carries all credential information including its user roles. &lt;br /&gt;The list of roles will be required at last to perform authorization. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Note:&lt;/b&gt; All these operations are performed from within JbiJAASInterceptor.handleMessage(). This interceptor handles &lt;b&gt;all&lt;/b&gt; the complex JAAS authentication part. Thus when this interceptor finishes, the client request is either authenticated or rejected. The remaining CXF interceptors can now be invoked but they won't perform any security related functions. &lt;br /&gt;&lt;br /&gt;Finally the &lt;br /&gt;&lt;a href="http://svn.apache.org/repos/asf/servicemix/components/bindings/servicemix-cxf-bc/tags/servicemix-cxf-bc-2008.01/src/main/java/org/apache/servicemix/cxfbc/CxfBcConsumer.java"&gt;org.apache.servicemix.cxfbc.JbiInvokerInterceptor.handleMessage()&lt;/a&gt;&lt;br /&gt;will use the org.apache.servicemix.jbi.security.SecuredBroker to place the constructed JBI message onto the ServiceMix Normalized Message Router (NMR). But before doing so, the SecuredBroker will check if the caller is authorized. So this is the final authorization.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://projects.open.iona.com/projects/svn/iona/servicemix/tags/servicemix-3.4.0.0-fuse/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/security/SecuredBroker.java"&gt;org.apache.servicemix.jbi.security.SecuredBroker.sendExchangePacket()&lt;/a&gt;&lt;br /&gt;Before the message is sent to the NMR, the SecuredBroker checks if the caller is authorized. Once the JBI message containing the payload of the SOAP message is put onto the NMR it will be delivered to the target service (in our case the demo's ws-security-cxfse-su component) without performing any security checks. So this authorization is the final security operation in our scenario.&lt;br /&gt;&lt;br /&gt;The information about what roles are allowed to invoke on what services are specified in conf/security.xml in your ServiceMix installation. Out of the box there is an &amp;lt;authorizationMap&amp;gt; entry as follows:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;sm:authorizationMap id="authorizationMap"&amp;gt;&lt;br /&gt;    &amp;lt;sm:authorizationEntries&amp;gt;&lt;br /&gt;      &amp;lt;sm:authorizationEntry service="*:*" roles="*" /&amp;gt;&lt;br /&gt;    &amp;lt;/sm:authorizationEntries&amp;gt;&lt;br /&gt;  &amp;lt;/sm:authorizationMap&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;So out of the box anyone can invoke on any service. This basically turns off authorization. The source code actually checks if roles="*" and bypasses authorization completely:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;// inside SecuredBroker.sendExchangePacket()&lt;br /&gt;if (!acls.contains(GroupPrincipal.ANY)) {&lt;br /&gt;   //perform authorization, details omitted.&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;... whereby GroupPrincipal.ANY resolves to "*".&lt;br /&gt;If you want to enable authorization you need to specify one or more authorization entries in security.xml where the role are not just "*", meaning everyone. You would generally list some of the role names from your conf/groups.properties file.&lt;br /&gt;Of course you can fine grain access control to a particular service by specifying the service attribute in the &amp;lt;authorizationEntry&amp;gt; element. The syntax is&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt; &lt;br /&gt; &amp;lt;sm:authorizationEntry service="{namespace}:servicename" roles="admin"/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;as typically defined in your xbean.xml service configuration. So in our example, in order to limit access to only the administrator role for the cxf-se service, you would specify:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;sm:authorizationEntry service="{http://apache.org/hello_world_soap_http}:SOAPServiceWSSecurity" &lt;br /&gt;  roles="admin" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;So this list of authorization entry configuration from security.xml is available to the SecuredBroker. On the other hand it also has access to the javax.security.auth.Subject instance that contains all the clients security credentials including the authenticated user roles and it can extract the service name of the target service to invoke on from the JBI MessageExchange. Hence it is just a question of checking that the user role in the security Subject is allowed to invoke the service named in the MessageExchange. This check will be performed using the authorization configuration from security.xml. &lt;br /&gt;If the caller is not authorized a security exception will be thrown, otherwise the exchanges gets put onto the NMR from where it will be routed to the right service.&lt;br /&gt;That's it. In case the authorization succeeds the JBI message is put onto the NMR from where it will be routed and dispatched to the target service.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Executive Summary:&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;The WSS4JInInterceptor runs the WS-Security related functions, extract WS username and password from the SOAP security header and puts it into a WSUsernameTokenPrincipal object.&lt;br /&gt;&lt;li&gt;The JbiJAASInterceptor is the next CXF interceptor to invoke on and checks for the presence of a WSUsernameTokenPrincipal, extracts the credential information and invokes on the JAAS authentication service.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The JAAS authentication service uses the configured login module class (PropertiesLoginModule as set in conf/login.properties) to delegate the authentication decision.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The PropertiesLoginModules calls back on the registered JAAS callback handler to retrieve the username/password and authenticates these credentials against the definitions in user-passwords.properties. If authentication succeeds, it assigns the list of roles to this authenticated Subject. The call stack returns all the way back to the JbiJAASInterceptor. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;The JbiInvokerInterceptor dispatches the request and uses the SecuredBroker to send the message exchange to the NMR.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The SecuredBroker performs authorization based on the user role names stored in the Java security Subject and based on the authorization configuration made in conf/security.xml.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;I hope I could spot some light onto the mysteries of authentication/authorization in ServiceMix 3. &lt;br /&gt;The ServiceMix documentation does unfortunately not document these concepts in much detail. &lt;br /&gt;&lt;br /&gt;Looking forward to any feedback from you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-8711167760816194770?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/8711167760816194770/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=8711167760816194770' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/8711167760816194770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/8711167760816194770'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2009/05/understanding-authentication-and.html' title='Understanding Authentication and Authorization in ServiceMix'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-2468908012995036670</id><published>2009-04-16T14:48:00.011+02:00</published><updated>2009-04-16T15:05:03.663+02:00</updated><title type='text'>Slower performance with the new servicemix-jms endpoints?</title><content type='html'>&lt;span style=";font-family:verdana;font-size:10;"&gt;&lt;br /&gt;There are two servicemix-jms components available in the later versions of ServiceMix 3. The &lt;a href="http://servicemix.apache.org/servicemix-jms.html"&gt;traditional jms endpoint&lt;/a&gt; that is configured using &lt;font color="#365F91"&gt;&lt;b&gt;&amp;lt;jms:endpoint&amp;gt;&lt;/b&gt;&lt;/font&gt; and the &lt;a href="http://servicemix.apache.org/servicemix-jms-new-endpoints.html"&gt;new jms endpoint&lt;/a&gt; that uses &lt;font color="#365F91"&gt;&lt;b&gt;&amp;lt;jms:consumer&amp;gt&lt;/b&gt;&lt;/font&gt;; and &lt;font color="#365F91"&gt;&lt;b&gt;&amp;lt;jms:provider&amp;gt;&lt;/b&gt;&lt;/font&gt;. The new JMS endpoints reuse much of &lt;a href="http://static.springframework.org/spring/docs/2.0.x/reference/jms.html"&gt;Spring JMS&lt;/a&gt;. Very recently I noticed a pretty large performance difference between these two JMS consumers, in the way that the new servicemix-jms consumer was much slower than the traditional consumer while using a pretty default configuration for both.&lt;br /&gt;The reason for that is that out of the box the new JMS endpoint is configured to use the Spring JMS &lt;a href="http://static.springframework.org/spring/docs/2.0.x/api/index.html?org/springframework/jms/listener/DefaultMessageListenerContainer.html"&gt;DefaultMessageListenerContainer&lt;/a&gt; without any caching, so all JMS resources get re-created and closed for every message being sent or received. This of course degrades performance a lot.&lt;br /&gt;&lt;br /&gt;There are two simple solutions:&lt;br /&gt;&lt;br /&gt;1) &lt;b&gt;Configure caching for this DMLC&lt;/b&gt;&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;  &amp;lt;jms:consumer service="test: NewJMSConsumer" &lt;br /&gt;    endpoint="endpoint" &lt;br /&gt;    targetservice="test:bean" &lt;br /&gt;    targetendpoint="endpoint" &lt;br /&gt;    destinationname="queue/TEST.FOO" &lt;br /&gt;    connectionfactory="#AMQConnectionFactory" &lt;br /&gt;    cachelevel="3"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;Using cacheLevel="3" (CACHE_CONSUMER) is the highest cache option and caches the pretty much all JMS resources for each listener thread (JMS connection, session and message consumer). Other levels are 2 (CACHE_SESSION ), 1 (CACHE_CONNECTION) and 0 (CACHE_NONE). If no cacheLevel is specified, CACHE_NONE is used!&lt;br /&gt;&lt;br /&gt;2) &lt;b&gt;Or configure for a different Spring JMS listener&lt;/b&gt;&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;  &amp;lt;jms:consumer service="test:NewJMSConsumer" &lt;br /&gt;    endpoint="endpoint" &lt;br /&gt;    targetservice="test:bean" &lt;br /&gt;    targetendpoint="endpoint" &lt;br /&gt;    destinationname="queue/TEST.FOO" &lt;br /&gt;    connectionfactory="#AMQConnectionFactory" &lt;br /&gt;    listenertype="server"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://static.springframework.org/spring/docs/2.0.x/api/org/springframework/jms/listener/serversession/ServerSessionMessageListenerContainer.html"&gt;ServerSessionMessageListenerContainer&lt;/a&gt; type internally uses a ServerSessionPool (which as the name suggests pools the server sessions) and also results in reasonable performance. However this listener type might not be suitable for all deployments.&lt;br /&gt;&lt;br /&gt;Both options should boost performance and perform equally fast as the old JMS endpoint. These jms consumer attributes are both &lt;a href=""&gt;documented&lt;/a&gt; but it is easy to overlook them and just use the default configuration.&lt;br /&gt;I recommend solution 1, using the DefaultMessageListenerContainer and enable caching.&lt;br /&gt;&lt;br /&gt;Finally there seems no reason why caching could not be turned on by default. So I raised JIRA &lt;a href=""&gt;SM-1841&lt;/a&gt; at Apache.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-2468908012995036670?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/2468908012995036670/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=2468908012995036670' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/2468908012995036670'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/2468908012995036670'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2009/04/slower-performance-with-new-servicemix.html' title='Slower performance with the new servicemix-jms endpoints?'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-1424429286139646993</id><published>2009-01-23T15:07:00.012+01:00</published><updated>2009-02-10T14:35:52.728+01:00</updated><title type='text'>Using the Camel Aggregator correctly</title><content type='html'>&lt;span style=";font-family:verdana;font-size:10;"  &gt;I was recently working on a project that required the use of a Camel aggregator. Since I had not used the aggregator much before I started by reading through the Camel &lt;a href="http://activemq.apache.org/camel/aggregator.html"&gt;Aggregator documentation&lt;/a&gt;. Some questions remained though.&lt;br /&gt;In my use case I needed to aggregate every five incoming messages of the same format together into a new exchange. Sounds very simple but I did not find it that straight forward. And that's the motivation for this post.&lt;br /&gt;To have an example at hand; let's say I want to aggregate messages of the following general XML format (with different values of course):&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;artist genre='Alternative'&amp;gt;&lt;br /&gt; &amp;lt;name&amp;gt;The White Stripes&amp;lt;/name&amp;gt;&lt;br /&gt; &amp;lt;album&amp;gt;Elephant&amp;lt;/album&amp;gt;&lt;br /&gt; &amp;lt;album&amp;gt;Get Behind Me Satan&amp;lt;/album&amp;gt;&lt;br /&gt; &amp;lt;album&amp;gt;White Blood Cells&amp;lt;/album&amp;gt;&lt;br /&gt;&amp;lt;/artist&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;Suppose that's the message format of the incoming messages. I will build the aggregator according to this format.&lt;br /&gt;As mentioned in the Camel documentation, each aggregator is configured by a &lt;b&gt;correlation expression&lt;/b&gt; and an &lt;b&gt;aggregation strategy&lt;/b&gt;.&lt;br /&gt;The correlation expression is used to define which messages should be aggregated together. When the correlation expression is being evaluated at runtime on a particular message, it returns a value that is used as the correlation id under which messages are being aggregated. All messages that evaluate to the same correlation id are aggregated together. A mistake I made initially was assuming that all messages that do not match my correlation expression will not be aggregated. But &lt;b&gt;every&lt;/b&gt; correlation expression will &lt;b&gt;always&lt;/b&gt; evaluate to a particular correlation id for &lt;b&gt;every&lt;/b&gt; message. Suppose I want to aggregate all those &lt;artist&gt; messages that have an alternative genre (genre='Alternative') and I define my aggregation strategy accordingly (we will explore that later). All messages that have a different genre set will still be aggregated somehow, depending on what id the correlation expression evaluates to for these messages at runtime. We will see more detailed examples of that later, but this is important to keep in mind.&lt;br /&gt;The aggregation strategy on the other hand contains the logic for combining all message exchanges into a single aggregated message. The default aggregation strategy is &lt;a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/processor/aggregate/UseLatestAggregationStrategy.html"&gt;org.apache.camel.processor.aggregate.UseLatestAggregationStrategy&lt;/a&gt;, which only aggregates the latest incoming message, discarding older messages. This is great for throttling purposes but did not serve my use case.&lt;br /&gt;&lt;br /&gt;Generally a Camel aggregator is set up in Java DSL as follows (I will only use Java examples, XML based configuration will be quite similar):&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;from("somewhere").aggregate("somehow").to("some destination");&lt;br /&gt;&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;Let's not care too much about the from(…) and to(…) part of this route, they will be defined by your business use case. It is the aggregate(…) part that we are interested in here.&lt;br /&gt;As mentioned above the aggregator is configured via the correlation expression (which messages to aggregate together) and the aggregation strategy (how to aggregate messages). So it comes as no surprise that the aggregate() method can take the following parameters:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public AggregatorType aggregate(Expression correlationExpression, AggregationStrategy strategy);&lt;br /&gt;&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;When defining a correlation expression, one can either correlate on a particular message header or on the message content. Pretty much all examples I have seen so far did correlate messages on the existence of a particular message header element. In Camel headers are named and can take values - they are basically (name, value) pairs.&lt;br /&gt;Suppose some of my &lt;artist&gt; messages also have a header called "MusicCollection" with a value "Yes" set. I can then aggregate my messages based on this header and define my correlation expression as follows:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;.aggregate(header("MusicCollection"), …).&lt;br /&gt;&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;This correlation expression will evaluate to the value of the header "MusicCollection" at runtime (the String "Yes" in the above example). If no such header is set, the correlation expression will evaluate to null at runtime, which can still be used as a key for aggregating messages.&lt;br /&gt;But what If I don't want to or cannot use message headers? Perhaps the message was received from an external system without any headers. I can then also correlate messages based on their message payload as well. Using an XPath expression I can test if a specific element or structure is present in the message payload. In my example the messages start with &lt;artist&gt; as the root element, so it seems natural to define a correlation expression like this:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;.aggregate(xpath("/artist", …).&lt;br /&gt;&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;This however won't work as expected. Internally the aggregator will use the Camel XPathBuilder to evaluate the XPath expression and the above expression will return a new instance of org.w3c.dom.NodeList for &lt;b&gt;every&lt;/b&gt; new message. The aggregation however can only occur on a correlation expression that evaluates to the same object or primitive value at runtime for all messages to be aggregated (as that object or primitive value is used internally as a HashMap key for storing the aggregated messages into exchanges).  So we need to define an XPath expression that evaluates to the same object (or key) at runtime.  The trick is to select a proper XPath expression and to cast the evaluation result into a type like java.lang.String, such as in the following example:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;br /&gt;&lt;code&gt;&lt;b&gt;&lt;br /&gt;.aggregate(…).xpath("name(/artist)='artist'", String.class).&lt;br /&gt;&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;I had to move the XPath expression after the aggregate() method call because of the additional String.class argument. The above example will take the name of the root &lt;artist&gt; element of my message (which will be "artist") and test if it equals the string "artist". For the sample message shown in the beginning, this expression will evaluate to the String "true". For any other XML messages that don't start with &lt;artist&gt;, this XPath expression will evaluate to the String value "false" and these messages will still be aggregated according to my aggregation strategy.&lt;br /&gt;Aggregating on only the root XML element does not seem very useful. I might want to aggregate on the genre attribute of the &lt;artist&gt; element instead. Here is the corresponding correlation expression:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;.aggregate(…).xpath("/artist/@genre", String.class).&lt;br /&gt;&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;This does serve my use case. If I want to aggregate all messages with an "Alternative" genre I could use:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;.aggregate(…).xpath("name(/artist[@genre='Alternative'])", String.class).&lt;br /&gt;&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;Notice this will aggregate all messages starting with &lt;artist genre="'Alternative'"&gt; together into a new exchange. All other messages that have a different genre will also be aggregated together into a different exchange, no matter what their genre value is. If you wondered why I use the XPath function name() here, then that is because using name() will return the String "artist" as the correlation key for the example message above (the name of the XML element that matches my XPath expression). If I omitted the name() function, it would return a string representation of the node set itself. In the case of my example message the correlation key would be the string "White Stripes  Elephant  Get Behind Me Satan  White Blood Cells". Using "artist" as the key seems better somehow.&lt;br /&gt;If you are unsure to what key your own correlation expression evaluates at runtime, place a breakpoint into method org.apache.camel.processor.aggregate.DefaultAggregationCollection.add() and debug your Camel route from there. Check the value of the computed correlationKey object.&lt;br /&gt;You can of course define your correlation expression in different expression languages than XPath such as XQuery, SQL and others.&lt;br /&gt;&lt;br /&gt;That should cover the correlation expression part of the aggregator. The second part deals with the aggregation strategy. Remember, the strategy defines how messages are aggregated together. The default strategy used by Camel is the &lt;a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/processor/aggregate/UseLatestAggregationStrategy.html"&gt;UseLatestAggregationStrategy&lt;/a&gt;, which out of x received messages only takes the latest message. If however I want to aggregate multiple messages together into a single message, I need to write my own aggregation strategy. This isn't a big deal and the Camel aggregator documentation shows an example implementation. I have re-used that code for my example as well.&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class MyAggregationStrategy implements AggregationStrategy {&lt;br /&gt; public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {&lt;br /&gt;   Message newIn = newExchange.getIn();&lt;br /&gt;   String oldBody = oldExchange.getIn().getBody(String.class);&lt;br /&gt;   String newBody = newIn.getBody(String.class);&lt;br /&gt;   newIn.setBody(oldBody + newBody);&lt;br /&gt;   return newExchange;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;In this implementation we extract the messages of both Exchanges old and new, then simply concatenate the two messages together and place the result on the new Exchange. Nothing fancy here. We can then instantiate this class and pass its reference into the aggregator:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;.aggregate(…, new MyAggregationStrategy()).&lt;br /&gt;&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;So we are done, right? Well, what we have not defined yet is a criterion as to when the aggregation is done. There are again multiple ways of doing so. If I want to aggregate a fixed number of incoming messages, I can easily use the batch options:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;.aggregate(new MyAggregationStrategy()).&lt;br /&gt; xpath("("/artist/@genre", String.class).&lt;br /&gt; batchSize(5).&lt;br /&gt; to(…);&lt;br /&gt;&lt;/pre&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;In this example the aggregation will finish whenever it has processed 5 incoming messages no matter as to how they got aggregated (into which exchanges). Or I could specify a timeout after which the aggregated message is sent, irrespective of how many message have been aggregated:&lt;br /&gt;&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;.aggregate(new MyAggregationStrategy()).&lt;br /&gt; xpath("("/artist/@genre", String.class).&lt;br /&gt; batchTimeout(5000L).&lt;br /&gt; to(…);&lt;br /&gt;&lt;/pre&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;If I want to finish the aggregation when there are 5 messages aggregated together into one new exchange, then a more complex logic is required, which I can specify using the completedPredicate() expression:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;.aggregate(new MyAggregationStrategy()).&lt;br /&gt; xpath("("/artist/@genre", String.class).&lt;br /&gt; completedPredicate(header("aggregated").isEqualTo(5)).&lt;br /&gt;&lt;/pre&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;The example above assumes that there is a header called "aggregated" set and whenever its value reaches the number 5, the aggregation will finish. Of course some application level code needs to set this header and also increment the counter. This would typically be done in the custom aggregation strategy implementation, where increasing that number can be based on any application logic (see attached demo, which illustrates this approach).&lt;br /&gt;I can also call a particular method on a Spring bean for deciding when to finish the aggregation by using a BeanExpression:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;.aggregate(new MyAggregationStrategy()).&lt;br /&gt; xpath("("/artist/@genre", String.class).&lt;br /&gt; completedPredicate(&lt;br /&gt;   new BeanExpression("aggregatorStrategy", "isCompleted"))&lt;br /&gt; ).&lt;br /&gt; to(...)&lt;br /&gt;&lt;/pre&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;This requires a Spring bean with name "aggregatorStrategy" being defined in the Camel Spring configuration (your camel-context.xml) which exposes a public method called isCompleted().&lt;br /&gt;&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;bean id="aggregatorStrategy" &lt;br /&gt; class="com.progress.cs.camelaggregatortest.MyAggregationStrategy"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;Check the attached demo for an example.&lt;br /&gt;Finally, the entire aggregator code in Java DSL for my use case now reads:&lt;br /&gt;&lt;font color="#365F91"&gt;&lt;b&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;from("…").&lt;br /&gt; aggregate(new MyAggregationStrategy()).&lt;br /&gt; xpath("/artist/@genre", String.class).&lt;br /&gt; batchSize(5).&lt;br /&gt; to("…");&lt;br /&gt;&lt;/pre&gt;&lt;/b&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;Using a Camel aggregator can appear rather complex at first. But once you get to see some working examples it becomes much clearer (as with all things in life). I personally had some troubles getting the aggregator to work with an XPath based correlation expression. That part I wanted to share most of all in this article.&lt;br /&gt;&lt;br /&gt;And finally here is the &lt;a href="http://abloggerscode.googlecode.com/svn/trunk/CamelAggregatorDemo/CamelAggregatorTest.zip"&gt;demo&lt;/a&gt; for this article. After extracting, follow the steps in README.txt to run it quickly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-1424429286139646993?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/1424429286139646993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=1424429286139646993' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/1424429286139646993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/1424429286139646993'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2009/01/using-camel-aggregator-correctly.html' title='Using the Camel Aggregator correctly'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-3097771360169877937</id><published>2008-07-29T17:09:00.003+02:00</published><updated>2008-07-29T17:33:04.967+02:00</updated><title type='text'>WS-Security woes in ServiceMix 3.2</title><content type='html'>Previously I had to get WS-Security UsernameToken based authentication working in ServiceMix 3.2 for a customer. All the customer wanted was to have an external SOAP client connecting securely to a service deployed in ServiceMix and have the client being authenticated and authorized by ServiceMix. Sounds like a straight forward use-case and the fact that there already is a ws-security demo in ServiceMix made me hope this would be a simple project. &lt;br /&gt;As Murphy's Law dictates, it turned out to be the opposite.&lt;br /&gt;&lt;br /&gt;My initial hope was to simply define a CXF-BC consumer that is WS-Security enabled and that authenticates the client and passes on the request to a CXF-SE service. So overall use-case is&lt;br /&gt;External client -&gt; CXF-BC consumer -&gt; CXF-SE service.&lt;br /&gt;This can be set up using Maven in less than 10 minutes. The tricky part was to configure security. The ws-security demo of ServiceMix already shows the configuration for using XML-Signature and XML-Encryption, so I could simply copy that part. For using WS-Security functions ServiceMix simply leverages WSS4J, so it becomes a matter of correctly configuring WSS4J interceptors for the incoming request and outgoing reply.&lt;br /&gt;Adding WS-Security UsernameToken based authentication configuration to the WSS4J interceptor is relatively simple too:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor"&lt;br /&gt;  id="TimestampSignEncrypt_Request"&amp;gt;&lt;br /&gt;  &amp;lt;constructor-arg&amp;gt;&lt;br /&gt;    &amp;lt;map&amp;gt;&lt;br /&gt;      &amp;lt;entry key="action" value="Timestamp Signature Encrypt &lt;span style="font-weight:bold;"&gt;UsernameToken&lt;/span&gt;"/&amp;gt;&lt;br /&gt;      &amp;lt;entry key="signaturePropFile" value="alice.properties"/&amp;gt;&lt;br /&gt;      &amp;lt;entry key="decryptionPropFile" value="bob.properties"/&amp;gt;&lt;br /&gt;      &amp;lt;entry key="passwordCallbackClass" &lt;br /&gt;     value="org.apache.servicemix.samples.cxf_ws_security_usernametoken.KeystorePasswordCallback"/&amp;gt;&lt;br /&gt;    &amp;lt;/map&amp;gt;&lt;br /&gt;  &amp;lt;/constructor-arg&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;I simply had to add UsernameToken to the &amp;lt;action&amp;gt; element in the above WSS4JInInterceptor configuration (config for XML-Signature and XML-Encryption was directly taken from ws-security demo). I won't care about the client configuration here, as this could be any SOAP client but need to add that my client was configured to transmit username "alice" with password "password". &lt;br /&gt;For authorization to work, I had to add these credentials to conf/users-passwords.properties&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;# users-passwords.properties&lt;br /&gt;smx=smx&lt;br /&gt;alice=password&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;and make alice a member of the administrators role in conf/groups.properties (for a real use-case I would have defined a new role):&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;# groups.properties&lt;br /&gt;admin=smx,alice&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Finally to restrict only users of the administration role to invoke my service, I had to change conf/security.xml &lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;sm:authorizationMap id="authorizationMap"&amp;gt;&lt;br /&gt;    &amp;lt;sm:authorizationEntries&amp;gt;&lt;br /&gt;      &amp;lt;sm:authorizationEntry service="*: SOAPServiceWSSecurity" &lt;br /&gt;         roles="admin" /&amp;gt;&lt;br /&gt;    &amp;lt;/sm:authorizationEntries&amp;gt;&lt;br /&gt;  &amp;lt;/sm:authorizationMap&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Easy I thought and went to testing it. But it did not work. There was simply no authentication happening. Only when debugging through the code I realized the CXF-BC component did not delegate these credentials to JAAS for authentication! So there was no authentication possible in CXF-BC! I raised a &lt;a href="https://issues.apache.org/activemq/browse/SM-1361"&gt;bug&lt;/a&gt; report and took a deep breath...&lt;br /&gt;The good news is that by now this bug got resolved and things work as expected. However you need a very recent version of ServiceMix to have this fix included. Now if a client sends a WS-Security header containing username and password, these will be authenticated correctly by JAAS inside ServiceMix. &lt;br /&gt;Still at the time of discovering the bug I had to get things working for the customer and got to know that the HTTB-BC component supports username/password based authentication. So I started to replace my CXF-BC consumer with a HTTP-BC consumer. And this is where the real pain started. &lt;br /&gt;The configuration again is straight forward and does not look much different from the CXF-BC consumer configuration. However, for authentication to work in HTTP-BC, I must set soap="true" in my bc consumer config:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;beans xmlns:http="http://servicemix.apache.org/http/1.0"&lt;br /&gt;       xmlns:greeter="http://apache.org/hello_world_soap_http"&lt;br /&gt;       xmlns:soap="http://servicemix.apache.org/soap/1.0"&amp;gt;&lt;br /&gt;  &amp;lt;http:endpoint service="greeter:SOAPServiceWSSecurityHTTP"&lt;br /&gt;    endpoint="endpoint"&lt;br /&gt;    role="consumer"&lt;br /&gt;    targetService="greeter:SOAPServiceWSSecurity"&lt;br /&gt;    targetEndpoint="endpoint"&lt;br /&gt;    locationURI="http://localhost:9000/"&lt;br /&gt;    defaultMep="http://www.w3.org/2004/08/wsdl/in-out"&lt;br /&gt;    soap="true"&amp;gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;    &amp;lt;http:policies&amp;gt;&lt;br /&gt;      &amp;lt;soap:ws-addressing /&amp;gt;&lt;br /&gt;      &amp;lt;soap:ws-security receiveAction="UsernameToken" keystore="default" /&amp;gt;&lt;br /&gt;    &amp;lt;/http:policies&amp;gt;&lt;br /&gt;  &amp;lt;/http:endpoint&amp;gt;&lt;br /&gt;&lt;/span&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This is because the WSSecurityHandler that is called by the HTTP-BC consumer expects a DOM representation of the SOAP header, which won't get created unless soap="true" is set. With that I got the HTTP-BC component to authenticate the client, but the request failed to be un-marshaled by the CXF-SE runtime. Setting soap="true" in my http consumer had the side effect of stripping off the SOAP header from the request before sending it on to the next component inside ServiceMix. The CXF-SE runtime however requires a valid SOAP request, which it now did not get.  Aargh...&lt;br /&gt;&lt;br /&gt;So what to do with this dilemma? The easiest option I could think of was to insert a Camel component between the HTTP-BC consumer and  the CXF-SE service that adds a default SOAP envelope to the In message using xslt transformation and removes the SOAP envelope from the Out message produced by the CXF-SE component again (as the http-bc component will add an envelope when soap="true" is set.) Not an ideal solution and rather a hack than a proper workaround. Another option would have been to use a custom CXF interceptor that takes care of adding/stripping the SOAP envelope but I felt a Camel XSLT component will be simpler to use. &lt;br /&gt;I inserted the Camel component that did add/remove the SOAP envelope. Still I had a problem with the reply. The reply message had to be signed and encrypted but that was not the case, despite my configuration being correct. After another few hours of debugging (I am new to the codebase) I realized this part had yet not been implemented and I had hit another &lt;a href="http://open.iona.com/issues/browse/ESB-246"&gt;bug&lt;/a&gt;. Because of that bug outgoing SOAP reply message cannot be encrypted nor signed when using the HTTP-BC component. &lt;br /&gt;&lt;br /&gt;I still found some other issues on the way that I raised accordingly. Password digests as defined by the WS-Security UsernameToken spec are currently not &lt;a href="https://issues.apache.org/activemq/browse/SM-1345"&gt;supported &lt;/a&gt;(passwords need to be send in clear text in the SOAP header - but the header can still be encrypted, so this is no security problem). And the call to authorization in ServiceMix does not produce any &lt;a href="http://open.iona.com/issues/browse/ESB-255"&gt;logging&lt;/a&gt;. Finally I raised a few documentation issues.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Lessons learned:&lt;/span&gt; &lt;br /&gt;As you can see I hit a number of issues on the way. But the good news is that these will now be addressed and fixed in future versions of ServiceMix, making the product more stable and easier to use. The most important &lt;a href="https://issues.apache.org/activemq/browse/SM-1361"&gt;bug &lt;/a&gt;is already resolved so there is no need to use a HTTP-BC consumer anymore when doing WS-Security (and I highly recommend against it).&lt;br /&gt;&lt;br /&gt;The demo that I worked on is already incorporated into the cxf-ws-security demo of ServiceMix in the current release.&lt;br /&gt;&lt;br /&gt;The most difficult part for me was to hit very low level error messages that did not tell me much about the real cause of the problem. This can be quite frustrating and the only way I got to understand the error was to debug through the source code. So error reporting needs a hell lot of improvement in ServiceMix.&lt;br /&gt;&lt;br /&gt;Secondly, the low-level XML configuration is highly error-prone. ServiceMix really needs proper tooling that free the developer from configuring xml files. It is not only easy to make mistakes in the config, there are also so many configuration options that have implications unknown to the regular developer (like the soap="true" story).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-3097771360169877937?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/3097771360169877937/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=3097771360169877937' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/3097771360169877937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/3097771360169877937'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2008/07/ws-security-woes-in-servicemix-32.html' title='WS-Security woes in ServiceMix 3.2'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-3878382695191312228</id><published>2008-05-28T09:19:00.005+02:00</published><updated>2008-05-28T09:37:45.817+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CXF'/><category scheme='http://www.blogger.com/atom/ns#' term='ServiceMix'/><title type='text'>... the namespace on the "message" element, is not a valid SOAP version.</title><content type='html'>Recently I was working on a SMX usecase:&lt;br /&gt;external client -&gt; CXF BC consumer -&gt; CXF SE &lt;br /&gt;&lt;br /&gt;All configured nicely it still failed at runtime with &lt;br /&gt;&lt;code&gt;&lt;br /&gt;INFO: Interceptor has thrown exception, &lt;br /&gt;unwinding now org.apache.cxf.binding.soap.SoapFault: &lt;br /&gt;"http://java.sun.com/xml/ns/jbi/wsdl-11-wrapper", &lt;br /&gt;the namespace on the "message" element, is not a valid SOAP version.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;It took me a while to figure out what's wrong. In the end I only had to set useJBIWrapper="true" in the config of my CXF SE component:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;beans xmlns:cxfse="http://servicemix.apache.org/cxfse/1.0"&amp;gt;&lt;br /&gt;  &amp;lt;cxfse:endpoint &lt;span style="font-weight:bold;"&gt;useJBIWrapper="true"&lt;/span&gt;&amp;gt;&lt;br /&gt;    &amp;lt;cxfse:pojo&amp;gt;&lt;br /&gt;      &amp;lt;bean class="org.apache.servicemix.samples.cxf_ws_security.GreeterImpl" /&amp;gt;&lt;br /&gt;    &amp;lt;/cxfse:pojo&amp;gt;&lt;br /&gt;  &amp;lt;/cxfse:endpoint&amp;gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Those error messages really need to get improved in SMX. There are too many low level errors raised that give you no indication of what the real problem is.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-3878382695191312228?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/3878382695191312228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=3878382695191312228' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/3878382695191312228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/3878382695191312228'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2008/05/namespace-on-message-element-is-not.html' title='... the namespace on the &quot;message&quot; element, is not a valid SOAP version.'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-6683050835668417797</id><published>2008-04-15T10:33:00.002+02:00</published><updated>2008-04-15T17:55:34.098+02:00</updated><title type='text'>Chronic - a date and time parser for Ruby</title><content type='html'>I have recently come across &lt;a href="http://chronic.rubyforge.org/"&gt;Chronic&lt;/a&gt;, a very elegant Date and Time parser library for Ruby. It can be easily installed via &lt;a href="http://docs.rubygems.org/"&gt;RubyGems &lt;/a&gt;and can process all sorts of dates and times written in natural language formats. If you need to parse date in Ruby this might be the library you have been looking for.&lt;br /&gt;&lt;br /&gt;There is an interesting post on parsing US and non-US date formats in &lt;a href="http://www.redhillconsulting.com.au/blogs/simon/archives/000419.html"&gt;this post.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-6683050835668417797?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/6683050835668417797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=6683050835668417797' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/6683050835668417797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/6683050835668417797'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2008/04/chronic-date-and-time-parser-for-ruby.html' title='Chronic - a date and time parser for Ruby'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-3018324129219492758</id><published>2008-04-07T12:32:00.005+02:00</published><updated>2008-04-07T12:43:18.986+02:00</updated><title type='text'>Kerberos authentication in Java</title><content type='html'>Have you used Kerberos authentication in Java using &lt;a href="http://www-128.ibm.com/developerworks/java/jdk/security/142/secguides/jgssDocs/users_guide.jgss.ibm.html"&gt;JGSS&lt;/a&gt;? The &lt;a href="http://java.sun.com/javase/6/docs/api/org/ietf/jgss/GSSContext.html"&gt;GSSContext&lt;/a&gt; interface defines the two methods initSecContext() and acceptSecContext() for an initiator and acceptor of a Kerberos authentication request. JGSS is configured in a file typically called &lt;a href="http://java.sun.com/javase/6/docs/jre/api/security/jaas/spec/com/sun/security/auth/module/Krb5LoginModule.html"&gt;jaas.conf&lt;/a&gt;, where you specify the Kerberos keytab files, Kerberos principal name and other properties that configure the authentication process.&lt;br /&gt;&lt;br /&gt;According to the Kerberos authentication algorithm, only the initiator (or client) needs to contact the Kerberos authentication server, asking for a service ticket. The service ticket is later passed on to the server that the client wants to authenticate against and it contains all the information that the server (or acceptor) requires for authenticating the client. That implies the server does not need to communicate with the Kerberos authentication server when authenticating a client, as it is emphasized in pretty much every description of the Kerberos protocol.&lt;br /&gt;&lt;br /&gt;Still when using JGSS you might have noticed that your service does contact the Kerberos authentication server as part of the authentication process. The server will request a ticket granting ticket from the KDC even though this is not needed. This behavior has caused me some headaches in the past as I did not understand why the server would need to contact the KDC.&lt;br /&gt;&lt;br /&gt;There is a not very much &lt;a href="http://java.sun.com/javase/6/docs/jre/api/security/jaas/spec/com/sun/security/auth/module/Krb5LoginModule.html"&gt;documented &lt;/a&gt;property in jaas.conf that will solve this issue. If in your com.sun.security.jgss.accept stanza of jaas.conf you specify isInitiator=false, then the server will not request a TGT. Officially this property is only supported from Java SE 6 b89 onwards, however I verified that the later patches of Java 5 also include it.  &lt;br /&gt;So when setting up jaas.conf, I recommend adding isInitiator=false to the configuration of the acceptor.&lt;br /&gt;&lt;br /&gt;This topic is also discussed &lt;a href="http://forum.java.sun.com/thread.jspa?messageID=4319582&amp;amp;tstart=0"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-3018324129219492758?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/3018324129219492758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=3018324129219492758' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/3018324129219492758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/3018324129219492758'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2008/04/kerberos-authentication-in-java.html' title='Kerberos authentication in Java'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-326027435094328147</id><published>2008-04-04T14:40:00.002+02:00</published><updated>2008-04-04T14:43:02.711+02:00</updated><title type='text'>Let's change the default transport protocol used in ServiceMix 3</title><content type='html'>Today I want to post about a potential issue that I came across recently when running tests using the FUSE ESB  (which is IONA's distribution of Apache ServiceMix).&lt;br /&gt;&lt;br /&gt;Currently ServiceMix 3.2 configures the underlying ActiveMQ broker to simply use tcp as the transport protocol. This is defined in conf/servicemix.properties:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;activemq.url = tcp://${activemq.host}:${activemq.port}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;While this configuration works fine and is sufficient for using ServiceMix in development, it will not recover from any network failures and is therefore not suitable for running in a production system. In case of a network failure or connection inactivity timeout, ActiveMQ will simply raise an exception but won't try to reconnect. You will need to restart ServiceMix in order to recover from such error. For automatic reconnection to happen, the failover protocol should be used instead. Hence the default configuration should be changed to&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;activemq.url = failover://(tcp://${activemq.host}:${activemq.port})&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The failover protocol should really be the default protocol and enabled out of the box. I logged &lt;a href="https://issues.apache.org/activemq/browse/SM-1302"&gt;SM-1302&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-326027435094328147?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/326027435094328147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=326027435094328147' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/326027435094328147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/326027435094328147'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2008/04/lets-change-default-transport-protocol.html' title='Let&apos;s change the default transport protocol used in ServiceMix 3'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-8436363552660858463</id><published>2008-02-29T11:36:00.001+01:00</published><updated>2008-02-29T11:38:53.163+01:00</updated><title type='text'>Bug in gdm under SuSE 10.3 (and perhaps in other Linux distributions)</title><content type='html'>Anyone who is running Linux with GNOME in VMWare might have come across a rather serious problem with gdm lately after doing an upgrade of the system with the latest patches. I am running OpenSuSE 10.3 and installed the latest patches just a few days ago. The patch installation went fine but next morning when I tried to reboot my Linux image, gdm failed to start up. Gdm initially started up but then crashed just before or shortly after showing the login prompt. When gdm was started the first time it ran a few seconds longer before crashing. You won't even have enough time to login. On subsequent restarts, GDM crashed almost instantly for every restart attempt. It attempted 6 restarts, then raised the following error to the console, slept for 2 minutes and started over again:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family: courier new;"&gt;"The display server has been shut down about 6 times in the last 90 seconds, it is likely that something bad is going on. Waiting for 2 minutes before trying again on display:0"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The log in /var/logs/Xorg.0.log should had the following lines at the end:&lt;br /&gt;&lt;span style="font-family: courier new;font-size:78%;" &gt;Backtrace:&lt;br /&gt;0: /usr/bin/X(xf86SigHandler+0x81) [0x80e6d81]&lt;br /&gt;1: [0xffffe420]&lt;br /&gt;2: /usr/bin/X [0x817b185]&lt;br /&gt;3: /usr/bin/X(CompositePicture+0x150) [0x8161be0]&lt;br /&gt;4: /usr/bin/X [0x8167a1f]&lt;br /&gt;5: /usr/bin/X [0x8164d75]&lt;br /&gt;6: /usr/bin/X [0x815809e]&lt;br /&gt;7: /usr/bin/X(Dispatch+0x1af) [0x808f68f]&lt;br /&gt;8: /usr/bin/X(main+0x47e) [0x807717e]&lt;br /&gt;9: /lib/libc.so.6(__libc_start_main+0xe0) [0xb7d1ffe0]&lt;br /&gt;10: /usr/bin/X(FontFileCompleteXLFD+0x1e5) [0x8076501]&lt;br /&gt;&lt;br /&gt;Fatal server error:&lt;br /&gt;Caught signal 11.  Server aborting&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;After various tries I was still unable to resolve the problem but found a way to bring up the X Windows system. I had to login as root from console and run gdm -stop. The next time gdm was restarted (after the 2 min had elapsed) it did come up fine.&lt;br /&gt;&lt;br /&gt;So I went on the web to see if someone else had encountered the same problem as well. When I checked SuSE's bug database, I realized I was not the first one to encounter this issue. A bug was already raised &lt;a href="https://bugzilla.novell.com/show_bug.cgi?id=350318"&gt;https://bugzilla.novell.com/show_bug.cgi?id=350318&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Apparently the culprit is a patch to the Control-Center2 (&lt;a href="https://bugzilla.novell.com/show_bug.cgi?id=337434"&gt;https://bugzilla.novell.com/show_bug.cgi?id=337434&lt;/a&gt;) that seens to break gdm.&lt;br /&gt;&lt;br /&gt;This is quite a severe problem and only seems to affect Linux running inside VMWare. I am not yet sure if other distributions are effected as well, most likely they are.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-8436363552660858463?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/8436363552660858463/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=8436363552660858463' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/8436363552660858463'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/8436363552660858463'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2008/02/bug-in-gdm-under-suse-103-and-perhaps.html' title='Bug in gdm under SuSE 10.3 (and perhaps in other Linux distributions)'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3893978476954864710.post-4673542882114559968</id><published>2008-02-25T11:42:00.006+01:00</published><updated>2008-02-26T10:55:40.141+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby SOAP'/><title type='text'>simple Ruby SOAP client</title><content type='html'>&lt;p class="MsoNormal"&gt;I am fairly new to Ruby and am quite amazed how simple and elegant this language can be. In particular I was surprised how simple it is to write a SOAP client in Ruby. Where in most programming languages even a simple SOAP client takes about two screenshots of code (if not more), a Ruby SOAP client can be boiled down to these few lines of code:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;#soap_client.rb&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;require 'soap/wsdlDriver'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;WSDL_URL="file://C:/hello_world.wsdl"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;soap = SOAP::WSDLDriverFactory.new(WSDL_URL).create_rpc_driver("SOAPService", "SoapPort")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#invoke WSDL operation sayHi&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;result = soap.sayHi()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;printf "Returned message reads: " + result + "\n"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#invoke WSDL operation greetMe&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;result = soap.greetMe("New Ruby User")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;printf "Returned message reads: " + result + "\n"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In this code I am referring to a wsdl definition that defines two WSDL portType operations named sayHi() and greetMe() that both return a string.&lt;br /&gt;In essence the code boils down to 4 lines of code that are of relevance. Of course this code is everything but object oriented and it is somewhat unfair to compare it against a properly implemented SOAP client written in other object oriented programming languages. Still this example is surprisingly simple and straight forward. I have used this code a number of times in order to quickly implement a SOAP test client. All you need to change is the name of the business method you actually want to invoke on (plus their arguments) and the location of the WSDL file. Thanks to Ruby you don't even need to recompile your changes.&lt;br /&gt;Sure, most SOAP toolkits also provide a way to generate a fully working client and server without requiring you to write any code. Still the generated code is tied to the WSDL interface. Changes to one of the operation signatures typically require a regeneration of your test client/server.&lt;br /&gt;Ruby rocks (and I am just starting to hit the tip of the iceberg)!&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;samp&gt;&lt;span style=""&gt;&lt;span style="font-family:arial;"&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/samp&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;samp&gt;&lt;span style=""&gt;&lt;span style="font-family:arial;"&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/samp&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;samp&gt;&lt;span style=""&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/samp&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3893978476954864710-4673542882114559968?l=tmielke.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tmielke.blogspot.com/feeds/4673542882114559968/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3893978476954864710&amp;postID=4673542882114559968' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/4673542882114559968'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3893978476954864710/posts/default/4673542882114559968'/><link rel='alternate' type='text/html' href='http://tmielke.blogspot.com/2008/02/simple-ruby-soap-client.html' title='simple Ruby SOAP client'/><author><name>Torsten Mielke</name><uri>http://www.blogger.com/profile/02631170123809271532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://bp3.blogger.com/_JBjOd55dqhI/R2evrAYegBI/AAAAAAAAAAM/uwl74DJWexU/S220/Me_small.jpg'/></author><thr:total>0</thr:total></entry></feed>
