Friday, February 24, 2012

Container Configuration - JBoss 7.1.0

Well, when I started this blog and promised to configure multiple containers, I didn't realize I was on the bleeding edge.  That is what you get for assuming everything is going to work.  In this post, we'll discuss some of the issues with JBoss 7, demonstrate how to configure it, and deploy an application with Eclipse and Netbeans.

First, JBoss 7.0.2 does not include support for the JSF EL call for a parameterized method.  i.e. #{bean.method()}.  Because we use this in a couple places, our app will not run on JBoss 7.0.2.  The good news is JBoss 7.1.0 does support it, was released a week ago, and is certified JEE 6.  So, there is no reason to continue to use JBoss 7.0.2 since it wasn't certified in the first place and who knows all the issues you'll run into trying to run JEE 6 in it.  In any case, the configuration is the same.

You will need to download the mysql-connector-java-5.x.x-bin.jar located at: http://dev.mysql.com/downloads/connector/j/

Create the needed directories, and unzip this file into: C:\jboss-as-7.1.0.Final\modules\com\mysql\main where C:\jboss-as-7.1.0.Final is your JBoss installation directory.

In that same directory, you will need to put in an xml file called: module.xml
In module.xml, you will have the contents of:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="com.mysql">
        <resources>
                <resource-root path="mysql-connector-java-5.1.18-bin.jar"/>
        </resources>
        <dependencies>
                <module name="javax.api"/>
                <module name="javax.transaction.api"/>
        </dependencies>
</module>

This of course means the the directory will contain 2 files. module.xml and mysql-connector-5.x.x-bin.jar.  Once you start JBoss, if everything is configured correctly with the module, you will get a third file added to the directory called mysql-connetor-5.x.x-bin.jar.index.  Note: in the module.xml above, it has the specific version I downloaded.  Be sure to keep all the x.x changed to whatever version you are using.

This will register your connector for use in the datasource.  Remember, there are several ways to get this job done, this is just one of them, but it works.  Once you have a complete working system, you can then decide how best to deploy it.

Next you need to modify the xml file of the type of JBoss server you are going to run.  i.e. Domain or Standalone.  Since I am doing development, I modified standalone.xml.  The modifications are the same for any of the configurations.

The standalone.xml file is located at: C:\jboss-as-7.1.0.Final\standalone\configuration\standalone.xml
Now, I'd show you the whole file, but JBoss has put the entire configuration into this one file.  So, I will only post the snipets that I modified.  First in one of the subsystems, you will find datasources.  It comes with the H2 datasource defined.  I left the H2 datasource in and added the MySQL datasource as follows:

            <datasources>
                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
                    <driver>h2</driver>
                    <security>
                        <user-name>sa</user-name>
                        <password>sa</password>
                    </security>
                </datasource>
                <datasource jta="true" jndi-name="java:/JSFDemoJNDI" pool-name="my_pool" enabled="true" use-java-context="true" use-ccm="true">
                    <connection-url>jdbc:mysql://localhost:3306/jsfdemodb</connection-url>
                    <driver>mysql</driver>
                    <pool>
                        <min-pool-size>5</min-pool-size>
                        <max-pool-size>20</max-pool-size>
                        <prefill>false</prefill>
                        <use-strict-min>false</use-strict-min>
                        <flush-strategy>FailingConnectionOnly</flush-strategy>
                    </pool>
                    <security>
                        <user-name>JSFDemoUser</user-name>
                        <password>ItWorks!</password>
                    </security>
                    <timeout>
                        <idle-timeout-minutes>5</idle-timeout-minutes>
                        <query-timeout>600</query-timeout>
                    </timeout>
                </datasource>
                <drivers>
                    <driver name="h2" module="com.h2database.h2">
                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                    </driver>
                    <driver name="mysql" module="com.mysql"/>
                </drivers>
            </datasources>

Notice, I did not use an xa datasource.  If you are in an xa environment, you will have to change the driver and the datasource to reflect xa, but in a development environment, this is sufficient.  Also, remember you can delete the H2 stuff, I left it in to demonstrate the difference between what we added, and what is already there.

JBoss is a little pickier with the JNDI name then Glassfish was and I had to follow the java:/ convention.  So you will see in the code, that the persistence unit reflects the updated JNDI name.

Also note: we included the driver name to be used in the JNDI and it references the module we created previously.

A side note:  since I am running both the Glassfish Appserver and JBoss on the same box, I had to move one of them to a different port.  In the JBoss standalone.xml file, I changed the port 8080 to port 80 making JBoss respond to your typical web port.  Both app servers can run simultaneously on the same box.  

Eclipse supports JBoss 7 and will deploy directly to it.  But, once you have deployed, it does not always redeploy depending on.... well, seems like random events, but failure, success, etc. all play a part.  If you want to redeploy, just create a file, or change the app.status file to app.dodeploy.  i.e. You deploy JSFDemoApp.war, a file is created JSFDemoApp.war.deployed.  You want to refresh the deployment, and it didn't do it automatically for you.  Save your files in eclipse, they should automatically goto: C:\jboss-as-7.1.0.Final\standalone\deployments\JSFDemoApp.war and create a file C:\jboss-as-7.1.0.Final\standalone\deployments\JSFDemoApp.war.dodeploy.

Another note:  JBoss doesn't like persistence units it can't handle.  Meaning, your application won't run if the persistence.xml file is not completely to JBoss' liking.  So, in our first project, we had a persistence.xml file that contained a local persistence unit for testing.  Don't include that in our deployment to JBoss.

Lastly, Netbeans.  Netbeans 7.0.1 does not contain support for JBoss 7 servers.  You cannot directly deploy to a JBoss 7 server.  Let me tell you the quick and dirty trick I used and from there you can see how you would support it.  First, a war, jar, ear, etc. file is basically a zip file.  I could have used the directory structure in the build directory from netbeans and copied that over, but since my Glassfish server was using those, I just renamed the war file in the dist directory to be zip.  Used winzip to open it up and deleted the hibernate files, since I had a newer version of hibernate in my JBoss server, and I replaced the persistence.xml file with the JBoss persistence file.  Because I didn't want web services running on the JBoss server at that time, I deleted that as well.  Then I copied the war file to the C:\jboss-as-7.1.0.Final\standalone\deployments directory, and away it went.  So, although Netbeans doesn't support it, you can accomplish the support by setting up a maven project, an ant build script, or simply by doing what I did to get your war to be JBoss compliant.  Here is the persistence.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="JSFDemoPU" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:/JSFDemoJNDI</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="hibernate.hbm2ddl.auto" value="update"/>
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
      <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
    </properties>
  </persistence-unit>
</persistence>

Hopefully, I didn't leave out a step, but the same JSFDemoApp that we used in project-1 runs on both Glassfish 3.x and JBoss 7.1.0.  The manual said to ignore the Transaction Manager Lookup, but I didn't try it without it, I was having enough problems with the Transaction Manager already.  If you get one thing wrong, generally speaking, nothing will work.

No comments:

Post a Comment