Skip to Content
0
Former Member
Jan 17, 2005 at 09:02 AM

Isolating a portal component using custom classloaders (hard!)

35 Views

Tough problem coming up.

If you haven't read the thread Inqmyxml.jar exclusing at https://forums.sdn.sap.com/thread.jspa?forumID=41&threadID=22479&messageID=202313#202313

please do that first.

Due to recent problems with webservices in early version of the portal, I'm currently doing a proof of concept on using AXIS to call webservices in the portal.

Of course the classloader problem shows up here, since the xml parser classes are allready loaded by through the classloader of the portal component.

I have however managed to successfully implement total isolation with two different methods, but I feel none of them are good enough for using in a production system.

1. The first thing I did was to place all the jar files I needed for AXIS (including xerces) in a folder AxisEPPoC\dist\PORTAL-INF\lib_internal.

This only so that the portal component classloader doesn't know of them

2. Then I made a fucntion which starts on the private resource path and retrieves all the jar files under it as URL's

3. This was then feed into my own custom parent last classloader (but it also works with the URLClassloader if you set the parent to null). My own custom parent last classloader, basically loads the class in the current classloader if it exist and the class is not a part of the java package, other wise it delegates up to the parent if any parent is set (but I used it without a parent)

4. Then I use the tip from Armin by calling

Thread thread = Thread.currentThread();		ClassLoader orgContextClassLoader =thread.getContextClassLoader();
//myClassloader is my custom parent last classloader
thread.setContextClassLoader(myClassLoader);

//in finally clause of the try I revert
} finally {			thread.setContextClassLoader(orgContextClassLoader);
}

I had hoped this was enough, but I still get an exception when I instansiate the DirectoryLocator of Axis indicating that it is using the xml parser of the portal

Caused by: java.lang.ExceptionInInitializerError: java.lang.ClassCastException: com.inqmy.lib.jaxp.SAXParserFactoryImpl

at javax.xml.parsers.SAXParserFactory.newInstance(Unknown Source)

at org.apache.axis.utils.XMLUtils.initSAXFactory(XMLUtils.java:218)

at org.apache.axis.utils.XMLUtils.<clinit>(XMLUtils.java:119)

at org.apache.axis.configuration.FileProvider.configureEngine(FileProvider.java:209)

at org.apache.axis.AxisEngine.init(AxisEngine.java:187)

at org.apache.axis.AxisEngine.<init>(AxisEngine.java:172)

at org.apache.axis.client.AxisClient.<init>(AxisClient.java:88)

at org.apache.axis.client.Service.getAxisClient(Service.java:143)

at org.apache.axis.client.Service.<init>(Service.java:152)

at org.tempuri.DirectoryLocator.<init>(DirectoryLocator.java:10)

at java.lang.Class.newInstance0(Native Method)

at java.lang.Class.newInstance(Class.java:232)

at com.company.portal.component.AxisEPPoC.doContent(AxisEPPoC.java:47)

5. Since the above failed, I implemented the solution using the java.reflection API on my custom classloader

Basically doing calls like

Class directoryLocatorClass = myClassLoader.loadClass("org.tempuri.DirectoryLocator") ; 
Object directoryLocatorObj =  directoryLocatorClass.newInstance();

Method getDirectorySoapMethod = directoryLocatorClass.getMethod("getDirectorySoap", null);
Object directorySoapObj = getDirectorySoapMethod.invoke(directoryLocatorObj, null);

This works without a problem.

But coding with reflection is not very practical, you lose compile time checking and there is no way to get results in any complex data type (only java.lang types).

6. So I tried one more thing.

This time I created a class which extends a thread and put the webservice call in the run method.

Then I used Armin's trick from 4. and afterwards created a new thread.

Thread axisThread = ((Thread)myClassLoader.loadClass("com.company.portal.component.AxisThread").newInstance());
axisThread.run();

And this worked!

But then it hit me that all this was to no avail, as communicating with the thread in any orderly fashion was impossible (as far as I could think of).

Anyone have any ideas how to solve this (or if it is solvable?)