Showing posts with label J2EE. Show all posts
Showing posts with label J2EE. Show all posts

Friday, December 5, 2008

JDK Logging

Log4j is widely accepted as a logging component. There is yet another one, the logging component inbuilt in java. This article will discuss about the logging provided by JDK.

Ideal scenario, the entire configuration can be done through the logging.properties file. The logging.properties file should be present in the classpath of the application. In case you want to provide a different properties file, the same can be set using the system property. The command is as shown below

java –Djava.util.logging.config.file=/home/users/mypath/mylogging.properties

The logging.properties file sample is present in the jre/lib folder. This file can be edited to get the necessary logging. The structure of the logging properties file is shown below


#Defines the handlers which can be used by the logger. It can be comma separated. For
# each handler, definition should be provided in the properties file
handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
#Default level of logging in case specific logging level as shown in the last line is not
# mentioned.
.level= INFO
#Details about the filehandler.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

#custom logging level
com.xyz.foo.level = SEVERE

By default the logging happens at the package level of the class when you are using the property file for configuring the logger.

The restrictions here are that we can specify only one log file per logging properties file. So in case you need the log to go to multiple files, may be based on the application, it’s not possible through configuration in the properties file. However, you can perform the above requirement by writing a specific logger class.


private void initialize(String name)
{
Handler fileHandler;
try {
fileHandler = new FileHandler(filePath, true);
fileHandler.setFormatter(new MyFormatter());
logger=Logger.getLogger(name);
logger.addHandler(fileHandler);
}
public static MyLogger getInstance(String someName)
{
//add the necessary synchronization blocks
mylogger = new MyLogger();
mylogger.initializer(someName);
return mylogger;
}
//this is sample method. Like this you need to provide implementation for
//all other methods
public void debug(String sourceClass, String sourceMethod, String msg)
{
logger.logp(Level.FINEST,sourceClass,sourceMethod,msg);
}
//in your application code, use it this way
MyLogger logger = MyLogger.getInstance(“namethatidentifiestheloglevel”);
logger.debug(“classname”,”methodname”,”msg”);

In the above code snippet, the log level is not mentioned. The log level can be mentioned in the properties file that is passed as the java.util.logging.config.file property. In this case, the value will be set as

namethatidentifiestheloglevel=SEVERE

There are various levels available, the important ones being SEVERE, INFO, FINE, FINEST, DEBUG etc … Please refer to the sun documentation site as the priority of the log level does matter in the content that gets logged.

Saturday, November 1, 2008

Class Loader Hierarchy

As per the delegation contract, a class should be attempted to be loaded by the parent class loader. If the parent class loader cannot load the class, the request should then be handed over to the child class loader. The process will continue till the class loader which originally received the request to load the class. Still if the class cannot be located in the classpath, a ClassNotFoundException is thrown. The request will not be transmitted to the child class loaders of the class loader which originally received the request to load the class.

Say we have 4 class loaders with names as shown below. ClassLoaderX, ClassLoaderY, ClassLoaderA, ClassLoaderB. The relations between them are shown below

When the JVM starts, all classes accessible from /x/data can be loaded by the ClassLoaderX. Then the control is transferred to ClassLoaderY, which can load the classes present under /y/data folder. The control is transferred to ClassLoaderA as well as to ClassLoaderB which can load the classes under /a/data and /b/data. The classes loaded by the parent class will not be loaded by the child class loader again as the child class loader will check if the classes are already loaded by any of its parent class loaders.

Now when the ClassLoaderB gets a request to load a class, it will delegate the request to its parent class loader i.e. ClassLoaderY. The ClassLoaderY will delegate the request to its parent classloader ClassLoaderX. Since ClassLoaderX does not have any parent class loader, it will try to load the class from its classpath i.e. /x/data. If the class is present in its classpath, it will load the class. If it cannot find the class in its classpath, the request is delegated to the child classloader i.e. ClassLoaderY. The ClassLoaderY will attempt to load the class from its classpath /y/data. If it finds the class, the class will be loaded by the ClassLoaderY. If it cannot find the class, the request is delegated to the ClassLoaderB. ClassLoaderB will attempt to load the class from its classpath. If it cannot find the class in its classpath, the request cannot be delegated to the child classloader of ClassLoaderB. Instead it will throw a ClassNotFoundException.

Consider a scenario where the following jar packaging is done. Class P is having Class Q as its super class. Class Q refers to Class R. P is packaged in p.jar and placed in /b/data folder. Q is packaged in q.jar file and placed under /x/data folder and R is packaged in r.jar and placed in /b/data folder. Can you guess what happens!

ClassLoaderB will try to load P and it will load the class after ClassLoaderY and X attempts to load it. Since P has Q as the super class, ClassLoaderB will attempt to load it. Q will be loaded by ClassLoaderX as Q is placed in the classpath of ClassLoaderX. Now Q refers to R and hence ClassLoaderX tries to load it. It will give ClassNotFoundException as r.jar is not present in classpath of ClassLoaderX. As per the policy, the loader should not delegate the request to child classloader and hence ClassLoaderB will never be asked to load R.

If a class is already loaded by the parent classloader, the child classloader will not attempt to load the class again. However some application servers have written custom classloaders which override these features. Another point to note is that the same class will be loaded by ClassLoaderA and ClassLoaderB if the class is placed in their classpath. This is because the classloader always checks its parent for loaded classes but not its children or siblings.

Java has got bootstrap classloader, extension classloader and application classloader by default. Bootstrap classloader can be mapped to ClassLoaderX, extension classloader can be mapped to ClassLoaderY and application classloader can be mapped to ClassLoaderB in the example above.

Few pointers

  1. Do not place the jars in the bootstrap classpath or the extension classpath just to make the application work. It will create issues which might surface later.
  2. Packaging the application is important because it impacts the class loading order too. All related classes should be packaged together or the proper documentation should be provided as to what order the jars should be loaded.
  3. Place common utility jars and common files in common classloaders path. However caution should be taken if they are supposed to be used in an independent manner. For e.g.: log4j.properties, if loaded by parent classloader, the properties file present in the child classloader path will never be considered and might give annoying results.

Sunday, July 6, 2008

JSF Configuration Files

JSF being new to the developers, there are lot of questions arising as to where to place the JSF configuration files and also the order in which the files will be loaded by the system. Though the location is based on the JSF implementation, the standard approach that I have noticed is described below

  1. The implementation will search for /META-INF/faces-config.xml in all the JAR files loaded from WEB-INF/lib directory. If the implementation finds any one faces-config.xml, the file will be loaded to be used by the application. If not, it will move to the next step as mentioned in Step 2.

  1. If the files are not found in the above location, it will search for the javax.faces.application.CONFIG_FILES property in the web.xml file. The comma delimited names of the config files are given as the value for this property with the path from the root of the web application. This approach is to be used if different config files need to be loaded for the application which might happen when different modules are developed by different groups and they have all separate configurations file.

javax.faces.application.CONFIG_FILES

/WEB-INF/config1.xml, /WEB-INF/config2.xml

  1. Finally the implementation will search for faces-config.xml adjacent to the WEB.xml file directly under the WEB-INF folder, if it cannot find even a single faces config file in any of the locations mentioned in Step1 and Step 2.

Transport Layer

In this blog I have tried to put across my idea of developing a clustered cache

Without a clustered cache implementation, it is difficult to implement a true Singleton object. The Object created in a particular JVM will not exist in any other JVM’s and hence the other JVM’s will create a different instance of the Singleton object. To avoid these issues in a clustered application, a clustered cache would turn out to be useful.

The idea behind a clustered cache is that the data created in one JVM should be copied to the other JVM’s. The synchronization of data between JVM’s should be the responsibility of the cache itself and transparent to the application. A sample component diagram is shown below. In this approach, application accesses the cache component in JVM1. The Cache component will interact with the Synchronization component in JVM1. The Synchronization component of JVM1 will transport the data using a transport layer. The synchronization component of JVM2 will receive data from the transport layer. Once the data is received by the Synchronization component in JVM2 it needs to update the local cache in JVM2. The synchronization component should implement the following features.

· Identifying instances when the data changes in the local cache.

· Initiate the transfer of cached data to the subscribed JVM’s.

· Ensure that the data is published to other subscribed JVM’s.

· Algorithm to effectively transport data like compressing, collating etc.

· Receive the cache data from other JVM’s.

· Update the local cache based on the data received from other JVM’s.


Some of the possible Transport Layers are described below.

· JMS – Java Messaging Services implementations can be used to transport the data. The disadvantage with this approach is that a transport layer needs to be added to the application framework like IBM MQ. This is definitely a cost addition to the application infrastructure. However in the later versions of Websphere Application Server, a embedded JMS implementation is provided which can be used as transport layer.

· IP Multicasting – Data can be transferred from one machine to other machine using socket connections. In this approach, SocketConnections and SokcetListeners should be developed which will be used to transport data. The disadvantage with this approach is that a particular port should be opened for the machine through which data can be transferred. This is considered as security risks in many bigger corporations.

· Remote Method Invocation – This is an approach where the data is transferred from one JVM to another JVM by using Remote Method Invocations. The marshalling and demarshalling algorithms should be developed for this implementation. The disadvantage with this approach could be the performance based on the network.

· EJB – Enterprise JavaBeans can be deployed in the JVM to transfer the data. This is very much similar to the RMI mode of transport except for the fact that marshalling and demarshalling will be automatically performed. The disadvantage with this approach is the necessity for an EJB Container. Hence the approach will not work on java processes implemented outside any J2EE container.