Sunday, October 14, 2012

Implement XA-Datasource in JBOSS


We have created a sample app which transfers money between two bank account databases. This task is fulfilled by an ejb method.
Lets called first bank as Akila and the other banks as Sithum. We need to create two different databases for two different banks. then we need two create two different data source as describe earlier. But in this case, we used XA-datasource. So lets start implement our sample application.

First we are going to create two datasources for two banks called akila-ds.xml and sithum-ds.xml. I am going to show only one -ds.xml file. But you have to do is, you can change jndi name only. 


<?xml version="1.0" encoding="UTF-8"?>
<datasources>
     <xa-datasource>
         <jndi-name>jdbc/akilads</jndi-name> 
         <xa-datasource-property name="URL">jdbc:mysql://localhost:3306/mazhar_db</xa-datasource-property>
         <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
         <user-name>root</user-name>
         <password></password>
         <track-connection-by-tx>true</track-connection-by-tx>
         <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
         <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLValidConnectionChecker</valid-connection-checker-class-name>
         <min-pool-size>1</min-pool-size>
         <max-pool-size>10</max-pool-size>
         <idle-timeout-minutes>10</idle-timeout-minutes>
         <metadata>
             <type-mapping>mySQL</type-mapping>
         </metadata>
     </xa-datasource>


Above file contains the data source for akila_db.  By editing jndi name and the URL we can create a data source file for the other bank. Main difference of this file with the previous datasource file is that this contains ‘xa-datasource’ instead of ‘local-tx-datasource’. We need ‘xa-datasource’ here because we have to handle a transaction between two databases. Don’t forget to begin the jndi name with ‘jdbc/’ .
In order to make a ‘mysql jdbc connection’ with ‘jboss’ we have to copy and paste ‘mysql-connector-java-5.1.13-bin.jar’ in jbossas/server/xxx/lib folder.

Now we need to do some coding in our application. So create a new enterprise application. Then go to ejb and write down following code.

Context initCnt = new InitialContext ();
DataSource ds = (DataSource) initCnt.lookup("java:jdbc/"+from+"bankds");

Then we have to create a database connection and make use of it.

ds.getConnection().createStatement().executeUpdate("Update user_amount set amount=amount-"+amount+ " WHERE user='"+user1+"'");

This ‘getConnection()’ method gets a connection from connection pool and releases it as configured. Connection pool is created by the ‘-ds.xml’ file definition.
In addition to this we have to handle some sql exceptions.
Not only the ejb but also the web.xml file should be modified to make database connections. Add this code inside the ‘<webapp>’ tag

<resource-ref>
<description>Oracle Datasource</description>
<res-ref-name>jdbc/mazhards</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<resource-ref>
<description>Oracle Datasource</description>
<res-ref-name>jdbc/zaheerds</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

Finally following code should be added to the ‘jboss-web.xml file’

  <resource-ref>
  <res-ref-name>jdbc/akilads</res-ref-name>
<jndi-name>java:/mazhards</jndi-name>
</resource-ref>

<resource-ref>
<res-ref-name>jdbc/sithumds</res-ref-name>
<jndi-name>java:/zaheerds</jndi-name>
</resource-ref>

Now open up your browser and do the transaction.


=================================================

So I know that i can write up to 140 characters in this box.
 http://bit.ly/RgNp89
=================================================












Login module with database connectivity in JBOSS

We need to create a MySQL database to store usernames, passwords and rolls of users. So create a database called akila_db and create two tables called myuser and myuser_roles. Then add following data to database.

myuser table
username      password
akila               akila
sithum            sithum

myuser_roles table
username    role
akila              admin
sithum           guest

Then we have to edit login-config.xml in server/xxx/conf folder.


<application-policy name = "akila_policy">
       <authentication>
          <login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule" flag = "required">
             <module-option name = "unauthenticatedIdentity">guest</module-option>
                                                 <module-option name = "dsJndiName">java:/ifsds</module-option>
             <module-option name = "principalsQuery">SELECT password FROM myuser WHERE username=?</module-option>
             <module-option name = "rolesQuery">SELECT role, 'Roles' FROM myuser_roles WHERE username=?</module-option>
          </login-module>
       </authentication>
    </application-policy>


Remaining things are similar to Basic authentication login module as we discussed earlier. So click here  find out about basic authentication login module.

Data source file in JBOSS

So far, we did not discuss about database connectivity. But in this article, we are going to discussed about database connectivity in JBOSS. In jboss we have three kind of data sources.

1.<local-tx-datasource>
     Identifies a data source that uses transactions, even distributed transactions
     within the local application server, but doesn't use distributed
    transactions among multiple application servers.

2.<no-tx-datasource>

   Identifies a data source that doesn't use transactions. This option
   isn't shown in the example, but would appear in place of the
  <local-tx-datasource> tag.

3.<xa-datasource>

  Identifies a data source that uses distributed transaction among multiple
  application servers. This option isn’t shown in the example, but
  would appear in place of the <local-tx-datasource> tag.

Let's see how we implement those data sources in our applications.


With java applications we can make database connections by adding ‘jdbc’ drivers.  There programmers have to spend a lot of time in database connection management. Every time a ‘getConnection ()’ method is called a new database connection is created and it may result in a connection bottleneck. ‘Jboss’ provides an efficient way for database connection management. It is called connection pooling.
A database is referenced from an enterprise application as a data source.  Depending on whether the database is accessed from web app or ejb configuration details differ.
First of all we should create a data source file to be used by the authentication method.  Name it as akila-ds.xml and save it in server/xxx/deploy folder.  Add the below content to it. (-ds.xml is mandatory here because the server identifies a data source file by that extension)


<?xml version="1.0" encoding="UTF-8"?>
<datasources>
       <local-tx-datasource>
     <jndi-name>akilads</jndi-name>
     <connection-url>jdbc: mysql://localhost:3306/ifs_db</connection-url>
     <driver-class>com.mysql.jdbc.Driver</driver-class>
     <user-name>root</user-name>
     <password></password>
<validconnectioncheckerclassname>org.jboss.resource.adapter.jdbc.vendor.MySQLValidConnectionChecker</valid-connection-checker-class-name>
     <min-pool-size>10</min-pool-size>
     <max-pool-size>100</max-pool-size>
     <metadata>
     <type-mapping>mySQL</type-mapping>
     </metadata>
     </local-tx-datasource>
 </datasources>


Jndi name component must contain the file name without ‘-’. (akila-ds.xml -> akilads)  

Here we are going to use MySQL database. Now we created the data source file. In next article, we will see how we use this file to achieve Basic authentication login module with stored data in a database. 


Enable buddy replication in JBOSS


To enable buddy replication you need to edit a configuration file in the nodes. Go to following directory and open the jboss-cache-manager-jboss-beans.xml file.

{JBOSS_HOME}\server\node3\deploy\cluster\jboss-cache-manager.sar\META-INF\jboss-cache-manager-jboss-beans.xml

Then you need to edit buddy replication mbean. Find the <property name="buddyReplicationConfig"> tag and set following tag to true in all the nodes within the cluster.

<property name="enabled">true</property>

Session Replication in JBOSS


We need to edit some configuration files to achieve session replication.
First go to the application web.xml file then add <distributable/> tag inside the <web-app> tag.
Then open the jboss-web.xml file and add following tag inside the <jboss-web> tag.


<replication-config>
        <replication-trigger>SET_AND_NON_PRIMITIVE_GET</replication-trigger>
        <replication-granularity>SESSION</replication-granularity>
        <replication-field-batch-mode>true</replication-field-batch-mode>
    </replication-config>

Then we need to edit some configuration files in the server. So we need to add jvmroute to server.xml file. Open the server.xml file located in {JBOSS_HOME}\server\node1\deploy\jbossweb.sar\server.xml. 
Find following tag.

<Engine name="jboss.web" defaultHost="localhost">

Then change it as follows.

<Engine name="jboss.web" defaultHost="localhost" jvmRoute="node1">

Then uncomment following tag in the server.xml file.

<Valve className="org.jboss.web.tomcat.service.sso.ClusteredSingleSignOn" />

Do these changes for all the nodes of the cluster. 
Now we completed session replication part also.. 
Cheers.. :)

Farming in JBOSS


We need not to copy the same ear file to all the nodes. There is a method call farming. So we can deploy to 
only one server and  automatically deploy to other nodes also. Go to a node and open farm folder inside “all” 
directory. Then paste into that folder. Then that project automatically deploy to other nodes. Remember, we 
we need to start all the servers to achieve this. Once start the servers, we can copy our ear file in to one 
"farm" folder inside one server. 

Cheerss..!!!


Testing cluster with three computers in JBOSS


First we have to create a cluster with three nodes. One node means one machine. That all three computers should be jboss installed. Then we need to start jboss with all configuration and bind with computer IP address. Therefore open the command prompt and go to the jboss bin directory. Then run following command.
Run.bat –c all –b 192.168.1.140 –Djboss.messaging.ServerPeerID=1
This serverPeerId should be unique within a cluster. Since we have three computers in our cluster, we need to start jboss with different peerIDs and corresponding IP’s by running above code.
Now we have created a cluster. Then we need to create a load balancer. So we need to install apache http server on one of above three machine or separate machine. We need not to install apache on every computers.
Go to the following link to download apache http server. Then download and install win32 MSI installer.  It is better not to install inside program files. Because the is a space between “Program file” directory. So in could be a problem. So create a new folder called apache inside C drive and install into that folder.


We are going to use mod_jk.so connecter for load balancing. We have to download mod_jk.so file from following link.


you need to download tomcat-connectors-1.2.37-windows-i386-httpd-2.2.x.zip. Because we used apache 2.2.22. 
Then unzip the downloaded file and copy that mod_jk.so file into modules folder inside apache installed directory.
Then go to the apache conf folder. Now create a file called mod_jk.conf and add following code to that file.

LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/workers.properties
JkShmFile logs/mod_jk.shm
JkLogFile logs/mod_jk.log
JkLogLevel info
JkMount /FarmTest-war/* loadbalancer

Most important part of above code is jkMount part. /FarmTest-war/* is the URL pattern of the clustered resource. So you need to specify your clustered resource here.
Then create another file called workers.properties inside the conf folder. This is the file that we specify cluster details. Add following code to that file.

# Define list of workers that will be used
     # for mapping requests
       worker.list=loadbalancer,status
     # Define Node1
     # modify the host as your host IP or DNS name.
       worker.node1.port=8009
    worker.node1.host=192.168.1.140
      worker.node1.type=ajp13
      worker.node1.lbfactor=1
       worker.node1.cachesize=10
     # Define Node2
     # modify the host as your host IP or DNS name.
       worker.node2.port=8009
       worker.node2.host= 192.168.1.141
       worker.node2.type=ajp13
       worker.node2.lbfactor=1
       worker.node2.cachesize=10
 #define node3
worker.node3.port=8009
       worker.node3.host=192.168.1.142
       worker.node3.type=ajp13
       worker.node3.lbfactor=1
      #worker.node1.local_worker=1 (1)
       worker.node3.cachesize=10
           
     # Load-balancing behavior
       worker.loadbalancer.type=lb
       worker.loadbalancer.balance_workers=node1,node2,node3
       worker.loadbalancer.sticky_session=1

Then open the httpd.conf file which located inside the conf folder. Then add following line of code to the bottom of that file.

Include conf/mod_jk.conf

Now restart the apache server.
Then start all jboss nodes.
We have created a load balancer and cluster with three nodes. Now we need to deploy an application to the cluster.  Create a small enterprise application and deploy it with one machine. Then go to the deploy folder inside the “all” folder. Now copy the application “war” file and paste it to the farm folder inside the “all” folder.
Now we deployed an application to the cluster. Now open a web browser and go to following link.
This IP address is the IP address of apache installed computer.