Monday, May 23, 2011

A Guide to Log4j in JBoss


Every application needs to log various levels of information when the application is running. We can do this either through the application or also by server to do the logging. In this article we will see how we can work with log4j in JBoss. We use JBoss 5 as our server.
The file for configuring the log4j in JBoss is available in JBOSS_HOME\server\<Server Instance>\conf\jboss-log4j.xml.the file defines a set of appender specifying the log files ,the category of messages to go to that file, format of the message and level of filtering.
This is an excerpt from the file
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
   <appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender">
      <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
      <param name="File" value="${jboss.server.log.dir}/server.log"/>
      <param name="Append" value="true"/>
      <param name="DatePattern" value="'.'yyyy-MM-dd"/>
      <param name="DatePattern" value="'.'yyyy-MM-dd-HH"/>
      <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
      <param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
      </layout>
   </appender>

<category name="org.apache">
      <priority value="INFO"/>
   </category>
</log4j: configuration>

As we can the configuration is split into 2 parts, appender and category.

Appender: This is the actual class file which does the logging, whether it may be to a console of a file depending on the destination that we choose.

JBoss provides two appender, Console and File. The logging Threshold in JBoss is INFO which means we can see information messages, warning messages and error messages on the console. If we want to change the default logging level on the log4j, we can use
-Djboss.server.log.threshold=WARN with the startup command

Category: category is the one which helps in connecting the classes (classes from a package) to the appender to perform the actual logging.

Logging Level: Various levels of logging levels are available including FATEL, ERROR, INFO, DEBUG, TRACE and WARN. We can use any type of logging level depending on our requirement.

Faster Appender
The File appender is said to be the faster than console appender, since writing to a console takes log of OS activity. So it is important to disable logging to a console in production and use File logging.

Log4JService
JBoss uses org.jboss.logging.Log4jService MBean to handle Log4j configuration. The MBean is available in JBOSS_HOME\server\<Server Instance> \conf\jboss-service.xml.This is how the MBean looks


<mbean code="org.jboss.logging.Log4jService"
      name="jboss.system:type=Log4jService,service=Logging"
      xmbean-dd="resource:xmdesc/Log4jService-xmbean.xml">
      <attribute name="ConfigurationURL">resource:jboss-log4j.xml</attribute>
      <attribute name="Log4jQuietMode">true</attribute>
      <attribute name="RefreshPeriod">60</attribute>
      <attribute name="DefaultJBossServerLogThreshold">INFO</attribute>
   </mbean>


ConfigurationURL: URL of the log4J configuration file.
RefreshPeriod:the time for checking the file specified by the configurationURL for any changes. The default is 60 seconds.

Now let see how we can configure logging for our application. I wrote a sample web application which contains a sample Servlet that does the logging. Once we develop the application we need to make some changes to the jboss-log4j.xml file that meets our requirement.

So the first thing we need to add is the appender to the jboss-log4j.xml file like,

<appender name="MYSAMPLEAPPENDER" class="org.jboss.logging.appender.RollingFileAppender">
        <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
        <param name="File" value="C:/log/mySample.log"/>
        <param name="Append" value="false"/>
        <param name="MaxFileSize" value="500KB"/>
        <param name="MaxBackupIndex" value="1"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
   </layout>
</appender>

The appender was a simple one , we will use c:/log/mySample.log for all our logging purposes. We have
FILE:the destination of the log statements.
Append: append the contents
MaxFileSize:The maximum file size
MaxBackupIndex:backup when the max file size is reached

Once the Appender is configured , we need to create a category for out classes like

<category name="com.DemoSample">
        <priority value="INFO" />
        <appender-ref ref="MYSAMPLEAPPENDER"/>
</category>
We created a category for our package and the priority is the INFO. We made the category to refer the appender that we configured.

Just copy both the appender and the category and paste then in the jboss-log4j.xml file. We don’t need any restart of the server, since the changes to the file are checked for every 60 seconds.

Pattern Layout
JBoss also provides various pattern layouts for formatting the log messages, for example

<param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>

This means that the current format date is first printed, then the priority of the message should be justified by 5 characters. The %C is used to output the category of the logging event. Finally the %M outputs the application supplied message along with a carriage return.

It is always better to use log4j specific date formatters.They can used by specifying ABSOLUTE and Date like

<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c] %m%n"/>

More articles to Come, So Happy coding….
Read More

Thursday, May 19, 2011

Closing a ResultSet and PreparedStatement In JBoss


It is very important to close the Resultset and PreparedStatements that are opened while working with Database. These needs to be closed if we want to use PreparedStatementCache in our application Server.
JBoss application servers provides us options in closing the ResultSet and PreparedStatement if we miss to close them. We need to add
<track-statements>true</track-statements>
To the Datasource-ds.xml files. This allows the application Server to close any ResultSet and PreparedStatement by itself if we miss them. Once enabling this feature, the console shows various exceptions if it finds any Unclosed ResultSet and PreparedStatement.
01:21:26,466 WARN  [WrappedConnection] Closing a statement you left open, please do your own housekeeping java.lang.Throwable: STACKTRACE         at org.jboss.resource.adapter.jdbc.WrappedConnection.registerStatement(WrappedConnection.java:894) at org.jboss.resource.adapter.jdbc.WrappedStatement.<init>(WrappedStatement.java:59) at  org.jboss.resource.adapter.jdbc.jdk6.WrappedStatementJDK6.<init>(WrappedStatementJDK6.java:41)         at org.jboss.resource.adapter.jdbc.jdk6.WrappedConnectionJDK6.wrapStatement(WrappedConnectionJDK6.java:65)         at org.jboss.resource.adapter.jdbc.WrappedConnection.createStatement(WrappedConnection.java:176) at SamplePoolTestServlet.doPost(SamplePoolTestServlet.java:42)

The application server closes a Statement which is opened at SamplePoolTestServlet:42 and

01:21:26,466 WARN  [WrappedConnection] Closing a result set you left open! Please close it yourself.java.lang.Throwable: STACKTRACE         at org.jboss.resource.adapter.jdbc.WrappedStatement.registerResultSet(WrappedStatement.java:909)         at org.jboss.resource.adapter.jdbc.WrappedStatement.executeQuery(WrappedStatement.java:227)  at SamplePoolTestServlet.doPost(SamplePoolTestServlet.java:43)
Closes ResultSet which is opened at SamplePoolTestServlet:43

This feature can be very useful in development which finds unclosed ResultSets and PreparedStatements, But they would be costly when used in production.

More Articles to Come . Happy Coding ...
Read More

Detecting Connection Leaks In JBoss


Now a day’s applications need to access database in their daily operations. Accessing a database is quite a critical piece of functionality. In this article we will see how we can handle the connection leaks in our application using JBoss application server.
Consider the sample servlet,
public ArrayList<Connection> connectionList=new ArrayList<Connection>();
     
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

try {
           
      Context initCtx = new InitialContext();
      DataSource bean = (DataSource) initCtx.lookup("StudentDB");
                 
      for(int i=0;i<=10;i++) {
                  connectionList.add(bean.getConnection());
      }
                 
     
      for(int i=0;i<=10;i++) {
      response.getWriter().println(connectionList.get(i).isClosed()+"\t\n");
      }
                 
      }catch(Exception e){
            e.printStackTrace();
      }
           
    }

}
I have created an ArrayList which hold 10 connections. Now iam not closing the connections in my finally block. Now we are sure that the connections are not closed by us. JBoss application server sorts us out in closing the connections for the application. Once you access the application, you can see there are exceptions in the console like,
00:51:09,891 INFO  [CachedConnectionManager] Closing a connection for you.  Please close them yourself: org.jboss.resource.adapter.jdbc.j
dk6.WrappedConnectionJDK6@ba2e7
java.lang.Throwable: STACKTRACE
at org.jboss.resource.connectionmanager.CachedConnectionManager.registerConnection(CachedConnectionManager.java:278) at org.jboss.resource.connectionmanager.BaseConnectionManager2.allocateConnection(BaseConnectionManager2.java:524)     at org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.allocateConnection(BaseConnectionManager2.java:941)  at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:89) at SamplePoolTestServlet.doPost(SamplePoolTestServlet.java:46)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
  at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

You can see in the exceptions that JBoss closes the connection for the application. It also gives us some more information as where the connections are created.
org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:89) at SamplePoolTestServlet.doPost(SamplePoolTestServlet.java:46)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
       
It says that the connections are created at SamplePoolTestServlet.java:46.Its in the SamplePoolTestServlet and at line 46.
The MBean that helps us in identifying the connections leaks is available in Server Instance/deploy/ jca-jboss-beans.xml.The MBean is CachedConnectionManager.The MBean looks like
<bean name="CachedConnectionManager" class="org.jboss.resource.connectionmanager.CachedConnectionManager">
<!-- Expose via JMX --> 
     <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX
(name="jboss.jca:service=CachedConnectionManager",
exposedInterface=org.jboss.resource.connectionmanager.CachedConnectionManagerMBean.class)</annotation>

<!-- Whether to track unclosed connections and close them -->
<property name="debug">true</property>

<!-- Whether to throw an error for unclosed connections (true) or just log a warning (false) -->
<property name="error">false</property>
   
<!-- The transaction manager -->
<property name="transactionManager"><inject bean="TransactionManager" property="transactionManager"/></property>

</bean>
The Main Use of this MBean is to track which application has which connections open. The attributes are self-explanatory.
The connections that are in use can also be obtained for the Jmx-console provided by JBoss application server,
Go to jboss.jca à service=CachedConnectionManager.we can check the ”listInUseConnections”  which list the stack traces showing the point of allocation for unclosed connections.

More Articles To Come .  Happy Coding ....

Read More