Saturday, December 06, 2008

JBossAS-5.0 goes GA

JBossAS-5.0 GA community edition has been released a few days back!!! Many of you might be knowing that the JBoss-5.0 development was going on for a few years now. After 4 Betas and 2 CRs the application server is now GA. JBossAS-5.0 GA complies with JavaEE5.

Some of you who keep an watch on the JBoss forums and mailing lists, might already be aware that JBoss-5 was completely rearchitectured. There have been a variety of architectural changes that have been introduced in JBoss-5. So what does this mean to a developer who's been using JBoss-4.x so far? The purpose of this article is to highlight the changes that have come in as part of JBoss-5. I won't be dwelling a lot into the technical details (i will leave it to the experts), but will try to give an overview of changes in this version from JBoss-4.x. This article is aimed at making you aware about things to keep in mind when you start using JBoss-5.

So let's start!

1) Additional server profiles/configurations :

JBoss-4.x AS community users will be used to seeing 3 server profiles being shipped by JBoss in the %JBOSS_HOME%/server folder. The "all", "default" and the "minimal". JBoss-5.0 GA adds couple of more profiles to this. Now in JBoss-5 you have "all", "default", "minimal", "web" and "standard".

* The "web" profile is meant to contain services which will allow simple web applications (servlet, jsps) to be deployed. It also has support for JTA, JCA and JPA. Some of you might ask how is it different from the "minimal" configuration. If you look in the deployers folder of "minimal" profile, you will find that there are no deployers available in the "deployers" folder nor any applications in the "deploy" folder. The "minimal" profile is mainly meant for letting the developers decide what services they want to be available. The "minimal" is just an empty profile which the users can build upon depending on their needs, whereas the "web" is a subset of the "default" and allows deploying web applications.

* The "standard" profile is the one against which the tests for JavaEE support were run against.


2) Separation of "deployers" and "deploy" :

If you look in the "deploy" folder of a JBoss-4.x system, you will notice that it contains two types of deployables. Some of the deployables are meant to deploy other applications. For example: The jbossweb.deployer in the deploy folder is actually used for deploying web applications (WAR). With JBoss-5, there is now a clear separation between the deployer and the deployable. You will notice that in JBoss-5, there is a "deployers" folder under each server profile %JBOSS_HOME%/server/< serverName>/deployers. The jbossweb.deployer, which i used as an example earlier, is now in this "deployers" folder along with various other deployers. The actual applications that are to be deployed reside in the "deploy" folder %JBOSS_HOME%/server/< serverName>/deploy.


3) Libraries are now moved to a common/lib folder:

In JBoss-4.x, you will notice that the lib folder under each server profile contains almost the same set of jar files. This obviously leads to increased disk space usage. In JBoss-5.0 GA, these common jar files which are required by all these server profiles is now moved to %JBOSS_HOME%/common/lib folder. This common/lib will act as a parent to all server/< serverName>/lib folders. If you want to add any jar for a specific server profile, then you can add it to the %JBOSS_HOME%/server/< serverName>/lib folder. For example: The database drivers that are required by the datasources can be placed in the server profile specific lib folder (%JBOSS_HOME%/server/< serverName>/lib). With the addition of this new common/lib folder, two new JBoss system properties have been introduced:


* jboss.common.base.url - This evaluates to ${jboss.home.url}/common
* jboss.common.lib.url - This evaluates to ${jboss.common.base.url}/lib


All other JBoss system properties available in JBoss-4.x http://www.jboss.org/community/docs/DOC-10730 continue to remain in JBoss-5.

4) For Windows users, its now one step easier to run JBoss as a service :

For JBoss-4.x Windows users, running the server as a service required downloading an appropriate version of JBoss Native and then using the service.bat in the JBoss Native to install the service. In JBoss-5.0 GA, its now one step less. JBossAS comes with JBoss Native installed by default. This way, the user no longer has to download the JBoss Native package separetely. The service.bat for installing the service can be found in the %JBOSS_HOME%/bin folder.

5) New jmx-console :

The jmx-console now comes with a better "professional looking" look :-)

As i mentioned earlier, in this article, i'am going to leave out all the technical details about the changes that have come in JBoss-5. I'll leave it for my next articles, which i plan to do pretty soon after spending some time on this new GA version :-) But in the meantime, JBossAS enthusiasts can start playing with the GA version by downloading it from here

And yes, if you run into any issues using JBossAS-5, feel free to post in the AS-5 dedicated forum here

Wednesday, August 20, 2008

How to upgrade Hibernate in JBoss

JBoss comes shipped with Hibernate by default. Upgrading Hibernate is similar to upgrading any other 3rd party library in your application deployed on JBoss. As long as you understand how the classloading works in JBoss, the upgrading should be pretty straightforward.

For a brief (well not so brief) background about classloaders in JBoss, have a look at these wiki articles:

How classloading works in JBoss

How to configure classloaders in JBoss

Once you read through these wiki articles, you will understand that if your application needs to have its own version of a library (does not matter if it is Hibernate or some other 3rd party library), you will have to configure classloader scoping through the xml file.

So why am i writing this stuff all over again, when these two wiki articles have enough details about classloading scoping? Its mainly because of some tricky issues, which have been reported in the JBoss forums, with upgrading Hibernate (specifically to Hibernate version 3.2.6) on JBoss-4.2.x (specifically JBoss-4.2.2 GA). The rest of the article tries to explain these issues and way to fix them. Though this is written to be more oriented towards upgrading Hibernate, whatever has been explained here will apply to almost every 3rd party library upgrade on JBoss.

So let's start then!

Details about the default installation of JBoss-4.2.2 GA:

JBoss-4.2.2 GA ships with

 

Hibernate EntityManager 3.2.1.GA
Hibernate Annotations 3.2.1.GA
Hibernate 3.2.4.sp1


What we intend to do is, upgrade Hibernate to use 3.2.6 GA. Let's assume, we have an EAR which will be deployed to JBoss:


MyApp.ear
 |
 |--- META-INF
 |      |
 |      |
 |      |--- application.xml
 |      | 
 |      |--- jboss-app.xml
 |
 |
 |--- lib
 |    |
 |    |--- [some jar files required by my app]
 |
 |
 |--- MyApp.war


So first step would be package the upgraded Hibernate jar files in the application (MyApp.ear). Its crucial to understand that you have to be absolutely sure that you have packaged all the required hibernate jars and the correct versions of those jars in your application. This Hibernate compatibility matrix will help you in picking up the correct versions. However, you still have to know "which" hibernate jars you need to package in the application.

Based on what i have seen in the forums, the issues faced while upgrading Hibernate were more related to users missing out certain dependent hibernate jar files. Debugging such issues was not very easy since, the errors that got thrown were not simple ClassNotFoundException (which you usually associate with a missing jar). Various errors like ClassCastException, NoSuchMethodException were thrown mainly because Hibernate in this version (3.2.6 GA) refactored a lot of their code to move them to different "projects". For example, the org.hibernate.search package was earlier in the "Hibernate Annotations" project (hibernate-annotations.jar) but with this new release, it was moved to a separate "Hibernate Search" project (hibernate-search.jar). Same applies to org.hibernate.validator package which earlier was in the "Hibernate Annotations" project (hibernate-annotations.jar) but with this new release, it was moved to a separate "Hibernate Validator" project.

So how does it matter if those hibernate packages were moved to a different project (jar)? Here's a very brief explanation of what happens:

- JBoss, in its lib folder, has an older version of Hibernate (3.2.4) and other hibernate related jar files, including the hibernate-annotations.jar. In this version, the hibernate-annotations.jar contained the org.hibernate.search and org.hibernate.validator and various other packages.

- You decide to upgrade Hibernate in your application by packaging the hibernate jars in your application and enabling classloader configuration. You package *only* the latest version of core hibernate jar, the hibernate-annotations.jar and maybe even the hibernate-entitymanager.jar.
Note: You have NOT packaged the hibernate-validator.jar nor the hibernate-search.jar.

- You start JBoss and the server tries to deploy your application. While deploying, for configuring Hibernate, various Hibernate classes are used, which includes the classes belonging to core hibernate jar and also org.hibernate.validator and org.hibernate.search packages.

- Since you have configured classloader scoping for your application, JBoss loads the hibernate core classes, the hibernate entitymanager classes and the hibernate annotation classes from the upgraded jars packaged in your application.

- But when a class belonging to org.hibernate.validator or org.hibernate.search package is being requested for, JBoss sees that these classes are not present the jars packaged in your application. So it delegates the classloading to the parent classloader which looks for the classes in the jar files present in the JBoss lib folder (%JBOSS_HOME%/server/< serverName>/lib folder). Here it finds that these packages are present in the hibernate-annotations.jar (older version) and loads those classes from there. While doing so, it also loads the related classes from various other hibernate packages (which might already have been loaded by a different classloader - remember the classes loaded from the jars in your application). Ultimately, this results to the same classes being loaded twice by different classloaders. Later on when you access these classes in your application you might run into ClassCastExceptions.

This is just one example of what might go wrong. Infact, you might not get a clear picture based on this brief explanation. So if you are interested in understanding better (and have some time), then go through these forum discussions which have a lot more details (and which actually made me come up with this article):

ClassCastException for org.hibernate.search.event.FullTextIndexEventListener

Again the ClassCastException for org.hibernate.search.event.FullTextIndexEventListener

This time a NoSuchMethodException: org.hibernate.validator.ClassValidator.


So now that we have seen what kind of issues you might run into while upgrading, let's now come back to our original plan of upgrading hibernate :)

1) Enable classloader scoping through jboss-app.xml:


<jboss-app>

<loader-repository>
   org.myapp:loader=SomeClassloader
   <loader-repository-config>
      java2ParentDelegation=false
   </loader-repository-config>
 </loader-repository> 

  
</jboss-app>


Note: The string org.myapp:loader=SomeClassloader is any unique ObjectName

2) Include the following jar files in the application package:



Hibernate Core jar (3.2.6 GA)
Hibernate Annotations jar (3.2.x or 3.3.x)
Hibernate EntityManager jar (3.2.x or 3.3.x)
Hibernate Validator jar (3.0.x)
Hibernate Search jar (3.0.x)
and maybe even Lucene Core jar (lucene-core-2.2.0.jar)


Note: Please follow this page for downloading and figuring out the correct version of hibernate jars required (compatibility matrix).

So this is how your application packaging will look like finally:


MyApp.ear
 |
 |--- META-INF
 |     |
 |     |
 |     |--- application.xml
 |     | 
 |     |--- jboss-app.xml
 |
 |
 |--- lib
 |     |
 |     |--- [some jar files required by my app]
 |     |
 |     |--- hibernate3.jar (the hibernate core jar)
 |     | 
 |     |--- hibernate-annotations.jar 
 |     |
 |     |--- hibernate-entitymanager.jar 
 |     |  
 |     |--- hibernate-validator.jar 
 |     |
 |     |--- hibernate-search.jar 
 |     |
 |     |--- lucene-core-2.2.0.jar
 | 
 |
 |--- MyApp.war





That's it! The upgrade itself is simple enough. Note that, in this article, i have used an EAR as an example, but this applies to WAR files too. In WAR files, the jars will be placed in the WEB-INF/lib folder and the classloader configuration will be done through the jboss-web.xml file which will be in WEB-INF folder.

Saturday, July 12, 2008

SyntaxHighlighter - Great and simple to use javascript utility

This had been on my todo list for a long time now. I finally got the SyntaxHighlighter integrated in this blog.


Most of my posts in this blog include java code or xml content. And i always used to spend most of my time formatting the way the java code was rendered in the blog. I wont have to worry about that anymore. I am very much impressed by this excellent yet simple piece of utility! I have edited some of my earlier posts in the blog to make use of the SyntaxHighlighter. Editing wasn't a big deal. It was as simple as adding a "name" and "class" attribute to the "pre" tags.

Saturday, April 19, 2008

How do i use my own log4j properties or xml file in JBoss

This article is mainly for those who had a hard time configuring "their own" log4j.properties or log4j.xml within their application on JBoss. For a brief background on this, please read through this JBoss wiki. As explained in that wiki, JBoss uses its own version of log4j.xml and log4j jar, making it difficult to use your own version of the log4j properties/xml files. The wiki also lists down the steps required to configure your application to use its own log4j config file. However, i have seen people complain in the forums that those steps either dont work for them or the steps are too involved and not worth a try.

People at JBoss had taken note of these issues (see the related JIRA) and starting JBoss-4.2.x, the steps involved to configure your own log4j config file in JBoss are pretty simple and straight-forward. In this example, i will try to explain these steps for a EAR file as well as a WAR file. The version that i am using here is JBoss-4.2.2GA (which is the latest stable version at this point). In the examples here, i use a log4j.properties file. The steps are the same even for a log4j.xml.

So here's what is required to get it working in a EAR file:

1) Create a log4j.properties and package it with your application and make it available in the classpath (i placed the log4j.properties file at the root of the EAR file).

2) Also package the appropriate version of log4j jar with your application (this step and the next step are important because you will have to ensure that log4j initializes separately for your application and picks up the log4j.properties file). Place this log4j jar file in the application package so that it is made available in the classpath (i placed it in a folder named lib of the EAR file - remember that any jars in the lib folder of the EAR are by default added to the classpath and made available to the entire application, starting JBoss-4.2.x version).

3) Enable classloader isolation for your application. This is necessary as explained in step#2. You will have to create a jboss-app.xml file and place it in the META-INF folder of the EAR. The jboss-app.xml looks like:


<jboss-app>
<loader-repository>
org.myapp:loader=MyClassLoader
<loader-repository-config>
java2ParentDelegation=false
</loader-repository-config>
</loader-repository>

</jboss-app>






This is how the EAR file would look like:



myApp.ear
|
|--- log4j.properties
|
|--- META-INF
| |
| |--- application.xml
| |
| |--- jboss-app.xml
|
|--- lib
| |
| |--- log4jxxx.jar






That's it! Your application now will use it own version of log4j config file as well log4j jar.

Steps involved for a WAR file are similar (If the WAR file is part of an EAR file, then you don't have to follow the steps below. The steps mentioned above for an EAR file are sufficient for a WAR inside an EAR):

1) Create a log4j.properties and package it with your application and make it available in the classpath (i placed the log4j.properties file in the WEB-INF/classes folder of the WAR).

2) Also package the appropriate version of log4j jar with your application (this step and the next step are important because you will have to ensure that log4j initializes separately for your application and picks up the log4j.properties file). Place this log4j jar file in the application package so that it is made available in the classpath (i placed it in a WEB-INF/lib of the WAR file).

3) Enable classloader isolation for your application. This is necessary as explained in step#2. You will have to create a jboss-web.xml file and place it in the WEB-INF folder of the WAR. The jboss-web.xml looks like:



<jboss-web>
<class-loading java2ClassLoadingCompliance="false">
<loader-repository>
org.myapp:loader=MyClassLoader
<loader-repository-config>java2ParentDelegation=false</loader-repository-config>
</loader-repository>
</class-loading>
</jboss-web>





This is how the WAR file would look like:


myApp.war
|
|--- WEB-INF
| |
| |--- web.xml
| |
| |--- jboss-web.xml
| |
| |--- classes
| | |
| | |--- log4j.properties
|
|
|--- lib
| |
| |--- log4jxxx.jar