[Logo] Terracotta Discussion Forums
  [Search] Search   [Recent Topics] Recent Topics   [Members]  Member Listing   [Groups] Back to home page 
[Register] Register / 
[Login] Login 
[Expert]
Mix jetty webapp and console application - exception  XML
Forum Index -> Terracotta Platform
Author Message
jocsch

neo

Joined: 10/01/2007 14:23:43
Messages: 4
Offline

Hi all,
I get the following exception when I try to share a root between a web application running in a jetty server and a console application (it works well if I connect two console applications).

To get the classloader in jetty working I had to put
Code:
   <modules>
         <module name="clustered-jetty-6.1" version="1.0.0"/>
     </modules>

in the tc-config.xml for the jetty server.

If I start the console application later on I get the following exception:
Code:
 com.tc.exception.TCClassNotFoundException: java.lang.ClassNotFoundException: No registered loader for description: Jetty.path:/test-web, trying to load com.test.core.shared.DistributionManager
         at com.tc.object.ClientObjectManagerImpl.lookupOrCreateRoot(ClientObjectManagerImpl.java:585)
         at com.tc.object.bytecode.ManagerImpl.lookupOrCreateRoot(ManagerImpl.java:286)
         at com.tc.object.bytecode.ManagerImpl.lookupOrCreateRoot(ManagerImpl.java:265)
         at com.tc.object.bytecode.ManagerUtil.lookupOrCreateRoot(ManagerUtil.java:84)
         at com.test.core.shared.DistributionManagerWrapper.__tc_setmgr(DistributionManagerWrapper.java)
         at com.test.core.shared.DistributionManagerWrapper.<init>(DistributionManagerWrapper.java:10)
         at com.test.core.shared.TestClient.main(TestClient.java:13)
 Caused by: java.lang.ClassNotFoundException: No registered loader for description: Jetty.path:/test-web, trying to load com.test.core.shared.DistributionManager
         at com.tc.object.loaders.StandardClassProvider.getClassFor(StandardClassProvider.java:41)
         at com.tc.object.ClientObjectManagerImpl.lookup(ClientObjectManagerImpl.java:507)
         at com.tc.object.ClientObjectManagerImpl.lookupObject(ClientObjectManagerImpl.java:409)
         at com.tc.object.ClientObjectManagerImpl.lookupRootOptionallyCreateOrReplace(ClientObjectManagerImpl.java:817)
         at com.tc.object.ClientObjectManagerImpl.lookupOrCreateRoot(ClientObjectManagerImpl.java:600)
         at com.tc.object.ClientObjectManagerImpl.lookupOrCreateRoot(ClientObjectManagerImpl.java:583)
         ... 6 more
 

Any ideas what could help or if it is even possible?

Thanks,
Markus
zeeiyer

consul

Joined: 05/24/2006 14:28:28
Messages: 493
Offline

Hi:

Object identity in Terracotta is dependent on the classLoaderName + fully qualified reference name.

In the case you describe the Jetty-config-bundle names the Jetty classloader - so to share correctly with the console application, the console application classloader needs to be named identically. However it is likely that the console application is using the System Classloader to load classes (and the System Classloader may not be named).

So the trick is to then run your console application within another classloader and name that classloader identical to the classloader-name in the jetty config (Look at the Jetty config bundle for the exact name).

Here is code that might help - i.e you will invoke your Console App via CustomLoader and then you would be able to cluster between the console-App and the Jetty-App.

Code:
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.net.URLClassLoader;
 import com.tc.object.bytecode.hook.impl.ClassProcessorHelper;
 import com.tc.object.loaders.NamedClassLoader;
 
 public class CustomLoader {
 
     // usage: java CustomLoader com.example.MyRealMainClass [arg1] [arg2]
 
     public static void main(String[] args) throws Exception {
         URL[] systemURLs = ((URLClassLoader) ClassLoader.getSystemClassLoader())
                 .getURLs();
 
         ClassLoader loader = new URLClassLoader(systemURLs, ClassLoader
                 .getSystemClassLoader().getParent());
         ((NamedClassLoader) loader).__tc_setClassLoaderName("com/caucho/loader/EnvironmentClassLoader");
         ClassProcessorHelper.registerGlobalLoader((NamedClassLoader) loader);
 
         Class mainClass = loader.loadClass(args[0]);
 
         Method main = mainClass.getMethod("main",
                 new Class[] { args.getClass() });
 
         String[] nextArgs = new String[args.length - 1];
         System.arraycopy(args, 0, nextArgs, 0, nextArgs.length);
         main.invoke(null, new Object[] { nextArgs });
     }
 
 }
 



Hope that helps.
Iyer.

Sreeni Iyer, Terracotta.
Not a member yet - Click here to join the Terracotta Community
jocsch

neo

Joined: 10/01/2007 14:23:43
Messages: 4
Offline

Hi lyer,

thanks. It works. Classloader trickery is an area I haven't been into so far.

Is there another way to deal with these naming issues? The reason I ask is because the code that currently runs in the console application will finally be deployed as a plugin in another server where I don't have that much control over the classloader, I guess. But as I said: I am not into that topic so I might be wrong.

Regards,
Markus
njain

jedi

Joined: 01/03/2007 06:43:24
Messages: 116
Offline

Another way of getting around is to include the shared classes in jetty's classpath so that shared classes are loaded by SystemClassLoader instead of jetty's web application classloader.

In addition to including the classes in classpath you need to do one of the following

1) Remove shared classes from web application (.war), otherwise they would still be loaded by web application loader
2) Include following line in jetty.xml and context.xml files
<Set name="parentLoaderPriority">true</Set>
bl

neo

Joined: 11/25/2007 06:04:06
Messages: 8
Offline

Hi,

In one of the previous posts, the code is:

zeeiyer wrote:

Code:
         ClassLoader loader = new URLClassLoader(systemURLs, ClassLoader
                 .getSystemClassLoader().getParent());
 

Iyer.  


I wonder why there is a call to getParent() on system class loader. Why not :

Code:
         ClassLoader loader = new URLClassLoader(systemURLs, ClassLoader
                 .getSystemClassLoader());
 


Thanks,
BL
njain

jedi

Joined: 01/03/2007 06:41:59
Messages: 107
Offline

If you define SystemClassLoader as parent of new URLClassLoader, it would be almost same as old scenario (no registered classloader). Reason being URLClassLoader will delegate the class load to its parent first and since it is SystemClassLoader, the application classed would still be loaded by the same old SystemClassLoader and hence will not make any difference.

By using getParent(), your application classes will be loaded by new URLClassLoader which is registered by terracotta and system classes (ext and rt.jar) will be loaded by parent classloader.

Regards,

Nitin Jain
Terracotta, Inc.

Join the Terracotta Community
hankli

journeyman

Joined: 11/20/2007 16:03:04
Messages: 17
Offline

Any easy way to get two hibernate+ehcache applications works in tomcat?
desirazu

neo

Joined: 02/04/2008 20:31:00
Messages: 7
Offline

Under some circumstances you may need to change the CustomLoader describe above to add

Thread.currentThread().setContextClassLoader(loader);

Please see last post in

http://forums.terracotta.org/forums/posts/list/805.page
 
Forum Index -> Terracotta Platform
Go to:   
Powered by JForum 2.1.7 © JForum Team