Tuesday, August 12, 2008

Controlling class loading in j2ee application

In some cases, we might have to change the order of class loading from different jar. This can be easily controlled for stand alone applications, Change the CLASSPATH to add a jar which need precedence in the first place. For example,

old.jar conatins Function.class file, this has to be modified to use new functionality. So team has developed new.jar with Function.class file. To keep backward compatability we need to maintain both the jars. To make new.jar Function.class precedence add them to class path as below

CLASSPATH=new.jar;old.jar;other.jar

This works great, simple and easy!!!

What happens if we need to follow same in J2EE application? Can you control order of classloading? Yes you can, but need to follow few steps. Before moving on lets consider ear package as below

j2eestandard.ear
ejb.jar
web.war
lib/old.jar
lib/new.jar
lib/other.jar

In this sample package, APP server loads calsses in following order
  1. First it loads all the classes under lib folder (the jar file order can vary to environment to environment, so we cannot predict old.jar or new.jar gets loaded?). Then appserver refers any manifest:classpath is specified in the jar files under lib folder. If it is specified that will be loaded
  2. Second step, ejb jars will be loaded (in this case ejb.jar). If there is any manifest:classpath in ejb.jar then that will also be loaded
  3. Finally web app will be loaded (web.war), If there is any manifest:classpath in web.war, that will also be loaded.

So now we have got an overview, now time to tweak a bit to make sure to load new.jar first. As per step 1, all the jars in /lib/ will be loaded first. So keep new.jar under lib folder. Move old.jar to root. Add manifest to ejb.jar and mention about old.jar, as below




j2eemodified.ear
ejb.jar
MANIFEST.MF
Manifest-Version: 1.0
Class-Path: old.jar
web.war
lib/new.jar
lib/other.jar
old.jar

The classes will be loaded in below order now,

  1. All the jars under lib folder, so new.jar and other.jar
  2. ejb.jar, there is manifest info so
  3. old.jar will be loaded
  4. web.war will be loaded

Its solved now. Happy packaging !!! :)

Wednesday, July 16, 2008

JDK1.4 & WL10.1 backward compatability

We needed to support JDK1.4 clients connecting to WL 10.1 which is JDK 1.5. But ran into run time error,

java.lang.IncompatibleClassChangeError: Implementing class
java.lang.ClassLoader.defineClass0(Native Method)
java.lang.ClassLoader.defineClass(ClassLoader.java:539)
java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123)
weblogic.utils.classloaders.GenericClassLoader.findLocalClass(GenericClassLoader.java:476)
weblogic.utils.classloaders.GenericClassLoader.findClass(GenericClassLoader.java:181)
java.lang.ClassLoader.loadClass(ClassLoader.java:289)
java.lang.ClassLoader.loadClass(ClassLoader.java:235)
weblogic.utils.classloaders.GenericClassLoader.loadClass(GenericClassLoader.java:223)
java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)
java.lang.ClassLoader.defineClass0(Native Method)
java.lang.ClassLoader.defineClass(ClassLoader.java:539)
java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123)
weblogic.utils.classloaders.GenericClassLoader.findLocalClass(GenericClassLoader.java:476)
weblogic.utils.classloaders.GenericClassLoader.findClass(GenericClassLoader.java:181)
java.lang.ClassLoader.loadClass(ClassLoader.java:289)
java.lang.ClassLoader.loadClass(ClassLoader.java:235)
weblogic.utils.classloaders.GenericClassLoader.findOrCreateSingleSourceClass(GenericClassLoader.java:640)
weblogic.rmi.internal.StubGenerator.getStubOnClient(StubGenerator.java:782)
weblogic.rmi.internal.StubGenerator.getStubClass(StubGenerator.java:758)
weblogic.rmi.internal.StubGenerator.generateStub(StubGenerator.java:803)
weblogic.rmi.internal.StubGenerator.generateStub(StubGenerator.java:790)
weblogic.rmi.extensions.StubFactory.getStub(StubFactory.java:79)
weblogic.rmi.utils.io.RemoteObjectReplacer.resolveObject(RemoteObjectReplacer.java:237)
weblogic.rmi.internal.StubInfo.readResolve(StubInfo.java:142)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:324)
java.io.ObjectStreamClass.invokeReadResolve(ObjectStreamClass.java:925)
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1655)
java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1274)
java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
weblogic.common.internal.ChunkedObjectInputStream.readObject(ChunkedObjectInputStream.java:119)
weblogic.rjvm.MsgAbbrevInputStream.readObject(MsgAbbrevInputStream.java:112)
weblogic.rmi.internal.ObjectIO.readObject(ObjectIO.java:56)
weblogic.rjvm.ResponseImpl.unmarshalReturn(ResponseImpl.java:159)
weblogic.rmi.cluster.ReplicaAwareRemoteRef.invoke(ReplicaAwareRemoteRef.java:285)
weblogic.rmi.cluster.ReplicaAwareRemoteRef.invoke(ReplicaAwareRemoteRef.java:244)
weblogic.jndi.internal.ServerNamingNode_812_WLStub.lookup(Unknown Source)
weblogic.jndi.internal.WLContextImpl.lookup(WLContextImpl.java:343)
weblogic.jndi.internal.WLContextImpl.lookup(WLContextImpl.java:336)
javax.naming.InitialContext.lookup(InitialContext.java:347)

There was not any documentation about backward compatability in WL. Then found that weblogic.jar of WL8.1SP2 has this problem. But with webloigc.jar WL8.1SP4 just worked fine. So in case needed just play with different version of weblogic jars :)

Thursday, May 22, 2008

initial context - OOM

Creating intial context and not closing the context can lead to OOM condition based on the load. Either this needs to be cached or closed immediately after usage. Caching may not be possible when application connects to multiple App Server. Even though this is the better solution, some time forced to use close option. InitialContext.close makes that object GC collectable immediately. So it does not move tenured space, will be collected from new generation space.

Tuesday, April 29, 2008

How to find HP system version

uname -a

provides version of HP unix

getconf KERNEL_BITS

to find out 32 / 64 bit processor

Saturday, April 12, 2008

Relook logic

Its good to put some of the problems/issues for a small gap (say 5 to 7 days) and take a look again, it sure gives solution.

Wednesday, February 27, 2008

Weblogic server status check - UNIX command

To automate weblogic managed server startup steps, need to check Admin server status first. Then start managed server. Check managed server status before continuing next steps like bringing up services deployed. Found to be useful to use weblogic.Admin option to achieve this easily,

Here is the step to check Admin server status

. setEnv.sh
$JAVA_HOME/bin/java weblogic.Admin -url $admin_server PING 1 >/dev/null 2>&1
admin_server_status=$?

Step to check Managed server status

ms_server_status=`$JAVA_HOME/bin/java weblogic.Admin -url $admin_server GETSTATE $app_name grep -c RUNNING `

Tuesday, February 12, 2008

write small script to simplify deployment/bounce

Its good to automate all the process related to component bounce, application server bounce, deployment steps etc. It may look like a simple steps and need not require automation. But when we work on the same component for quite a long time we would have spent more time for just copy/pasting comments.

Making it as a simple script has several advanatges,
1. we dont need to remember each and individual commands and dont need to remember authentication details
2. all typo can be avoided
3. In the long run this can save lot of time
4. anyone can easily manage

example of scripting managed weblogic server:

startDemoApp1.sh

umask 002
WLS_USER=admin
WLS_PW=admin123
export WLS_USER
export WLS_PW
nohup ./startManagedWebLogic.sh demoapp1 t3://localhost:7200 $* > demoapp1.out 2>&1 &

stopDemoApp1.sh

./stopWebLogic.sh admin admin123 demoapp1 t3://localhost:7200