tag:blogger.com,1999:blog-47640969731174097802024-03-08T08:51:36.880+00:00corecanariasCTO and lead developer. Focused on cloud computing and renderfarm. Involved development methodologies and platforms includes TDD (CI integration using Git, Jenkins and Sonar); Java JEE (JBoss AS, Hibernate ORM, JMS); remoting (REST, RMI); Javascript (deep knowledge of Sencha platform)corehttp://www.blogger.com/profile/06975332876002458864noreply@blogger.comBlogger3125tag:blogger.com,1999:blog-4764096973117409780.post-74215359872194711952013-07-15T16:31:00.004+01:002013-07-15T16:31:54.279+01:00@TransactionManagement doesn't work in JBoss 6 FinalOnly for the record. Here it is a link of a post in the Jboss community about a bug I've found. This cause me some headache. ;)<br />
<br />
<a href="https://community.jboss.org/message/588983">https://community.jboss.org/message/588983</a><br />
<br />
Here it is the bug filled: <a href="https://issues.jboss.org/browse/EJBTHREE-2238">https://issues.jboss.org/browse/EJBTHREE-2238</a><br />
<br />corehttp://www.blogger.com/profile/06975332876002458864noreply@blogger.com0tag:blogger.com,1999:blog-4764096973117409780.post-57047411225826973292013-03-08T15:52:00.000+00:002014-06-03T20:58:11.103+01:00JAAS Persistent sessions with JBoss 6A common issue you can found when your web application is becoming more popular is how to update it without disturbing your users.<br />
Redeploying a standard application could take arround 5-10 secs in a JBoss6, so we could assume that down-time for a monthly basis update.<br />
<br />
But, what happens with logged-in users when you update your application? Well, they will loose their session and will need to login again. We could assume that for a couple of redeploys, but at the end you will notice that you are very reticent to update your application because your users will suffer it.<br />
<br />
If you look at google for <i>jboss persistent sessions</i>, you will found that it is so easy solve this problem. In most tutorials you will be encouraged to save the session data to disk, so when you redeploy your application, the session will not be lost. Configuring jboss for that is very simple: In <i>server/default/deploy/jbossweb.sar/context.xml</i> you will see a comment saying that session persistence is disabled and what you need to enable it is uncomment the following line:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> <Manager pathname="SESSIONS.ser" /></span><br />
<br />
Now, the session will be serialized to that file, you should take in account that your session data must be serializable, but in most cases it is. You could even change the path of the SESSIONS.ser since it is saved on a temporary directory and it will be deleted on jboss restarts. To avoid this, simply set an absolute path:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"> <Manager pathname="/opt/app/data/SESSIONS.ser" /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span>
<span style="font-family: inherit;">That is all, so easy isn't it? Well, but... This doesn't work if you are using JAAS to authenticate your users. The reason is because the session is stored correctly but the JAAS principal is not, and JAAS will discard the session for users without a principal. So at this point, you have two options:</span><br />
<ul>
<li><span style="font-family: inherit;">Not use JAAS as authentication framework.</span></li>
<li><span style="font-family: inherit;">Assume that your users will loose their session when you redeploy your application.</span></li>
<li><span style="font-family: inherit;">Or...</span></li>
</ul>
<div>
<span style="font-family: inherit;">Create a jboss cluster. I haven't evaluate this option before because seemed I was complicating a lot the infrastructure for a simple web app. But I was really frustrated by the fact I was unable to update the application without disturbing my users. So I decided to give it go.</span><br />
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">I starting reading a couple of tutorial on how to setup a cluster and seemed to be very easy.</span></div>
<div>
<span style="font-family: inherit;">Since my intention with the cluster was only maintain the users logged in when redeploy my application it's </span>required<span style="font-family: inherit;"> only two nodes on the cluster. If I use two ethernet interfaces I could maintain the two nodes in the same server, simplifying the overhead of this configuration.</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">This is the recipe I've used to configure two nodes of a JBoss Cluster to avoid JAAS principal loss:</span></div>
<h4>
<span style="font-family: inherit;">Changes in the application</span></h4>
<div>
<span style="font-family: inherit;">We don't need to change any code on our application, simple add this line to the web.xml to inform to jboss that the application is clusterizable:</span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> <distributable /></span></div>
<div>
<span style="font-family: inherit;">In most cases you need to do nothing else in your application.</span></div>
</div>
<h4>
<span style="font-family: inherit;">Changes in the server</span></h4>
<div>
<span style="font-family: inherit;">Simply configure a virtual ethernet interface assigning an additional IP:</span></div>
<div>
<span style="font-family: inherit;">For ubuntu/debian, in </span>/etc/network/interfaces</div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">auto eth0</span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">iface eth0 inet static</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> address 172.26.1.1</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> netmask 255.255.255.0</span></div>
</div>
<span style="font-family: 'Courier New', Courier, monospace;">auto eth0:2</span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">iface eth0:2 inet static</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> address 172.26.1.2</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> netmask 255.255.255.0</span></div>
</div>
<h4>
Configuring the JBoss</h4>
<div>
There is not so much to configure, create two separate installations of jboss, for example:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">/opt/jboss-node1</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">/opt/jboss-node2</span></div>
<div>
<br /></div>
<div>
And use the following run scripts for each one:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">/opt/jboss-node1/bin/run.sh -c all -b eth0 -g <cluster_name> -Djboss.messaging.ServerPeerID=1 -Djboss.jvmRoute=<node1_name></span><br />
<span style="font-family: Courier New, Courier, monospace;">/opt/jboss-node2/bin/run.sh -c all -b eth0:2 -g <cluster_name> -Djboss.messaging.ServerPeerID=2 -Djboss.jvmRoute=<node2_name></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
You must replace the values between <> with your specific values.</div>
<div>
<b>Cluster_name</b> Is a name you want to give to your cluster. Since the cluster will autodiscover all nodes in the network with the same cluster name, you will want to have a special name to separate dev and production clusters in the same network.</div>
<div>
The <b>ServerPeerID</b> and <b>node_name</b> are unique for each node, you can select whatever you want.<br />
The <b>jvmRoute</b> name allows us to associate all request from a specific user to the same server. In <span style="font-family: inherit;"><i>server/all/deploy/jbossweb.sar/server.xml</i> locate the line:</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> <Engine name="jboss.web" defaultHost="localhost"></span><br />
<br />
and change it as:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> <Engine name="jboss.web" defaultHost="localhost" jvmRoute="${jboss.jvmRoute}"></span><br />
<h4>
<div>
<div style="font-weight: normal;">
Finally, you need to enable the <i>ClusteredSingleSignOn</i> valve in jboss.web to activate the JAAS principal propagation. Go to <i>server/all/deploy/jbossweb.sar/server.xml</i> and uncomment the line:</div>
<br />
<span style="font-weight: normal;"><span style="font-family: Courier New, Courier, monospace;"><Valve className="org.jboss.web.tomcat.service.sso.ClusteredSingleSignOn" /></span></span><br />
<br />
<div>
<span style="font-weight: normal;">Now, you can deploy your application on server/</span>all<span style="font-weight: normal;">/deploy, this should work as usual.</span></div>
</div>
</h4>
<h4>
Configuring the balancer</h4>
If you have deployed your application on both servers you will be able to reach your application by pointing your browser to 172.26.1.1 or 172.26.1.2 On that point, you only need to balance the incoming users to each node, and of course if one of the nodes goes down the users on that node will be moved to the other node. And the most important: The users won't notice the change.<br />
<br />
The balancer I'm using is <i><a href="http://tomcat.apache.org/connectors-doc/index.html" target="_blank">mod_jk</a>, </i>you can install it on debian/ubuntu with:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">apt-get install libapache2-mod-jk</span><br />
<br />
Then, proceed as usual to enable the module on your <i>apache-httpd</i>.<br />
Configuring the <i>mod_jk</i> to register the nodes on the cluster and how will be reached:<br />
<b><br /></b>
<b>workers.properties:</b><br />
<span style="font-family: Courier New, Courier, monospace;">worker.<node1_name>.type=ajp13</span><br />
<span style="font-family: Courier New, Courier, monospace;">worker.<node1_name>.host=172.26.1.1</span><br />
<span style="font-family: Courier New, Courier, monospace;">worker.<node1_name>.port=8009</span><br />
<span style="font-family: Courier New, Courier, monospace;"># worker.<node1_name>.fail_on_status=404</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">worker.<node2_name>.type=ajp13</span><br />
<span style="font-family: Courier New, Courier, monospace;">worker.<node2_name>.host=172.26.1.2</span><br />
<span style="font-family: Courier New, Courier, monospace;">worker.<node2_name>.port=8009</span><br />
<span style="font-family: Courier New, Courier, monospace;"># worker.<node2_name>.fail_on_status=404</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">worker.mycluster.type=lb</span><br />
<span style="font-family: Courier New, Courier, monospace;">worker.mycluster.balance_workers=<node1_name>,<node2_name></span><br />
<span style="font-family: Courier New, Courier, monospace;">worker.mycluster.sticky_session=1</span><br />
<div>
<br /></div>
<div>
As you can see, we have defined our two jboss nodes, and a cluster called <i>mycluster</i> that will balance the incoming requests alternatively to both nodes node1 and node2. If a node is unreachable it will be marked as down and won't receive requests anymore until becomes active again. We can also use the fail_on_status to force a node status down when the node returns the specified error codes. (can be a comma separated list).</div>
The sticky_session will maintain the users in the same server.<br />
<br />
Now, we can mount <i>mycluster</i> to a specific url on our <i>apache-httpd</i> with the following configuration. You can put it in your virtual server configuration:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> JkMount /yourapp </span><span style="font-family: 'Courier New', Courier, monospace;">mycluster</span><br />
<span style="font-family: Courier New, Courier, monospace;"> JkMount /</span><span style="font-family: 'Courier New', Courier, monospace;">yourapp</span><span style="font-family: 'Courier New', Courier, monospace;">/* </span><span style="font-family: 'Courier New', Courier, monospace;">mycluster</span><br />
<br />
As you can see, we have made available our cluster in the http://apache_url/yourapp url. If you access to that url, <i>mod_jk</i> will redirect you to any of the two server nodes. If that node fails it will redirect to the other node.<br />
<br />
The advantage here is the jboss cluster will maintain http session and JAAS principals in all cluster nodes, so if one node goes down, the other node can maintain the users authenticated.<br />
<br />
I've used this configuration for a while and works really well, and doesn't requires more maintenance or attention that a simple jboss. </div>
corehttp://www.blogger.com/profile/06975332876002458864noreply@blogger.com0tag:blogger.com,1999:blog-4764096973117409780.post-58958047051147403032012-11-08T10:36:00.001+00:002013-07-25T15:41:28.015+01:00Jasig CASIn most cases the login code of your application does not require thinking a lot. Simply use the standard module available on your framework, that is all you need.<br />
<br />
But sometimes, you need to integrate third-party applications with your own. For example a cms, forums, ticketing systems, etc. Your users can stand a couple of months (in the best case) entering two times the user/password. But you know it is something you need to change.<br />
<br />
At the beginning someone could be tempted to implement your own solution because seems it is very simple. Simply read one cookie from here and put there, and then redirect to there and back to... Well, at the end you will see yourself hacking every third-party application, and learning new concepts as man-in-the-middle, spoofing, etc. That is good, of course. But could be even more good if you can learn it with a bit less pressure because you have been so optimistic when you schedule this feature.<br />
<br />
What I use in that cases is a SSO server. This allows me to leverage of SSO functionality on my application in a fraction of time if I'd try to implement by myself. <br />
J<a href="http://www.jasig.org/cas" target="_blank">asig CAS</a> (Central Authentication System) lets you to integrate it easily on your java web applications, but also in other platforms as PHP, .NET an others. The protocol is well documented and can be implemented in any platform if it is not available. On the other side, you have a lots of <a href="https://wiki.jasig.org/display/CAS/CASifying+Applications" target="_blank">CASified applications</a> which is how they name the clients that are been integrated into CAS.<br />
<br />
Here we will see how can we use CAS on our JBoss6 applications. But, first of all you should start reading <a href="https://wiki.jasig.org/display/CASUM/Demo">https://wiki.jasig.org/display/CASUM/Demo</a> and try to become familiar with the CAS use.<br />
<br />
Then, when you feel prepared to try it out with your JBoss/JAAS application follow the next steps. Remember you need to have a CAS server already up and running and reachable from <span style="background-color: white; font-family: 'Courier New', Courier, monospace; font-size: 13px; line-height: 17.33333396911621px;">http://yourcasserver/cas </span>so, lets go:<br />
<ul>
<li><span style="background-color: white;">Copy the cas-client-core-<version>.jar and cas-client-integration-jboss-<version>.jar </span>to the server/default/lib dir.</li>
<li><span style="background-color: white;">Configure de JAAS login-config module as follows:</span><br /><pre style="background-color: white; font-size: 13px; line-height: 17.33333396911621px; margin-bottom: 10px; margin-top: 10px; overflow: visible; padding: 0px;"><span style="font-family: Courier New, Courier, monospace;"><application-policy name="cas">
<authentication>
<login-module code="org.jasig.cas.client.jaas.CasLoginModule" flag="required">
<module-option name="ticketValidatorClass">
org.jasig.cas.client.validation.Cas20ServiceTicketValidator
</module-option>
<module-option name="casServerUrlPrefix">
http://yourcasserver/cas
</module-option>
</span><span style="font-family: 'Courier New', Courier, monospace;"> <module-option name="tolerance">20000</module-option>
</span><span style="font-family: 'Courier New', Courier, monospace;"> <module-option name="defaultRoles">admin,user</module-option>
</span><span style="font-family: 'Courier New', Courier, monospace;"> <module-option name="roleAttributeNames">role,list</module-option>
</span><span style="font-family: 'Courier New', Courier, monospace;"> <module-option name="principalGroupName">CallerPrincipal</module-option>
</span><span style="font-family: 'Courier New', Courier, monospace;"> <module-option name="roleGroupName">Roles</module-option>
</span><span style="font-family: 'Courier New', Courier, monospace;"> <module-option name="cacheAssertions">true</module-option>
</span><span style="font-family: 'Courier New', Courier, monospace;"> <module-option name="cacheTimeout">480</module-option>
</span><span style="font-family: 'Courier New', Courier, monospace;"> </login-module>
</span><span style="font-family: 'Courier New', Courier, monospace;"> </authentication>
</span><span style="font-family: 'Courier New', Courier, monospace;"></application-policy></span></pre>
</li>
<li><span style="background-color: white;">Modify the deploy/jbossweb.sar/server.xml and uncomment:</span><span style="font-family: Arial, Helvetica, FreeSans, sans-serif; font-size: x-small;"><br /><pre style="background-color: white; font-size: 13px; line-height: 17.33333396911621px; margin-bottom: 10px; margin-top: 10px; overflow: visible; padding: 0px;"><Valve className="org.apache.catalina.authenticator.SingleSignOn" /></pre>
</span></li>
<li><span style="background-color: white;">Finally in the web.xml of your xml you need to configure the servlet filters:</span><br /><div class="line number7 index6 alt2" style="background-color: white; background-image: none !important; border-bottom-left-radius: 0px !important; border-bottom-right-radius: 0px !important; border-top-left-radius: 0px !important; border-top-right-radius: 0px !important; border: 0px !important; bottom: auto !important; box-sizing: content-box !important; float: none !important; height: auto !important; left: auto !important; margin: 0px !important; min-height: auto !important; outline: 0px !important; overflow: visible !important; padding: 0px 1em 0px 0em !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">
<span style="font-family: Courier New, Courier, monospace;"><span style="font-size: x-small;"><span style="line-height: 15.600000381469727px; white-space: pre-wrap;"><!-- Facilitates CAS single sign-out -->
<listener>
<listener-class>
org.jasig.cas.client.session.SingleSignOutHttpSessionListener
</listener-class>
</listener>
<!-- Following is needed only if CAS single-sign out is desired -->
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<!-- Only 2 CAS filters are required for JAAS support -->
<filter>
<filter-name>CASWebAuthenticationFilter</filter-name>
<filter-class>org.jasig.cas.client.jboss.authentication.WebAuthenticationFilter</filter-class>
</filter>
<filter>
<filter-name>CASAuthenticationFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>https://cas.example.com/cas/login</param-value>
</init-param>
</filter>
<!-- Other filters as needed -->
<!-- CAS client filter mappings -->
<!-- The order of the following filters is vitally important -->
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CASWebAuthenticationFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-mapping>
<filter-name>CASAuthenticationFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping></span></span><span style="font-size: 13px; line-height: 15.183333396911621px; white-space: pre-wrap;">
</span></span></div>
<div style="background-color: white;">
<br /></div>
<div class="line number50 index49 alt1" style="background-color: white; background-image: none !important; border-bottom-left-radius: 0px !important; border-bottom-right-radius: 0px !important; border-top-left-radius: 0px !important; border-top-right-radius: 0px !important; border: 0px !important; bottom: auto !important; box-sizing: content-box !important; float: none !important; height: auto !important; left: auto !important; margin: 0px !important; min-height: auto !important; outline: 0px !important; overflow: visible !important; padding: 0px 1em 0px 0em !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">
In your WEB-INF/jboss-web.xml select the appropriate security domain: <br />
<span style="font-family: Consolas, Bitstream Vera Sans Mono, Courier New, Courier, monospace;"><span style="line-height: 15.600000381469727px; white-space: pre-wrap;"><jboss-web></span></span></div>
<div class="line number50 index49 alt1" style="background-color: white; background-image: none !important; border-bottom-left-radius: 0px !important; border-bottom-right-radius: 0px !important; border-top-left-radius: 0px !important; border-top-right-radius: 0px !important; border: 0px !important; bottom: auto !important; box-sizing: content-box !important; float: none !important; height: auto !important; left: auto !important; margin: 0px !important; min-height: auto !important; outline: 0px !important; overflow: visible !important; padding: 0px 1em 0px 0em !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">
<code class="xml plain" style="background-image: none !important; border-bottom-left-radius: 0px !important; border-bottom-right-radius: 0px !important; border-top-left-radius: 0px !important; border-top-right-radius: 0px !important; border: 0px !important; bottom: auto !important; box-sizing: content-box !important; float: none !important; height: auto !important; left: auto !important; margin: 0px !important; min-height: auto !important; outline: 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"><span style="font-family: Consolas, Bitstream Vera Sans Mono, Courier New, Courier, monospace;"><span style="line-height: 15.600000381469727px; white-space: pre-wrap;"> <security-domain>java:/jaas/cas</security-domain>
</jboss-web>
</span></span>
</code></div>
</li>
<li>The first time, may be you could want to activate the trace logging to inspect any error you could get in your JBoss app. In server/default/<span style="background-color: white; font-family: Arial, Helvetica, FreeSans, sans-serif; font-size: 13px; line-height: 17.33333396911621px;">deploy/jboss-logging.xml do it by adding:<br /><pre style="margin-bottom: 10px; margin-top: 10px; overflow: visible; padding: 0px;"><logger category="org.jasig">
<level name="TRACE" />
</logger></pre>
</span></li>
</ul>
<div>
<span style="font-family: Arial, Helvetica, FreeSans, sans-serif; font-size: x-small;"><span style="line-height: 17.33333396911621px;">That is all. Start the server and make some tests. You have all of this more detailed in:</span></span></div>
<div>
<a href="https://wiki.jasig.org/display/CASC/JAAS+Integration">https://wiki.jasig.org/display/CASC/JAAS+Integration</a></div>
<br />corehttp://www.blogger.com/profile/06975332876002458864noreply@blogger.com0