• Bug
  • Status: Open
  • 2 Major
  • Resolution:
  • DSO:L1
  • prodmgmt
  • Reporter: wharley
  • July 01, 2009
  • 3
  • Watchers: 4
  • March 19, 2010

Description

See forum issue http://forums.terracotta.org/forums/posts/list/2271.page#13405.

If an app group contains multiple webapps as well as a named classloader for the standard system loader, class sharing between the web apps is not working. For example:

C1 C2 C3 Standard.system

With this config, POJO apps and the first web app (C1) will correctly access the shared root, but C2 and C3 will not.

My guess is that this is a problem with the class provider fallback algorithm; or possibly with the code that reads the config file.

Comments

Walter Harley 2009-07-01

This use case was not anticipated in the design. The classloader selection algorithm looks like this:

// case 1 if (the DNA specifies an app-group, and there is a loader that exactly matches both the app-group and the name, and there is exactly one loader registered in that app-group that is a child of the exact match) { use the child; } // case 2 else if (there is a loader that matches the registered name) { use it; } // case 3 else if (the DNA specifies an app-group and there is exactly one loader that matches the app-group) { use it; } // case 4 else { throw an exception; }

The problem here is that on the C2 web app node, we are trying to load a class from C1 in app group “theGroup”, but there are two candidate loaders in that group: Standard.system and C2. This algorithm provides no way to choose between them; it’s basically the same situation as when two web apps in the same app group are running on the same node.

The answer is probably that we need to again take the classloader hierarchy into account in case 3. We need to soften the “there is exactly one” criterion: instead, it should be more like case 1, and indeed should probably be coalesced with case 1. Basically, if the DNA specifies an app group, and we can identify a unique match in that group, we should use it.

A “unique match” in this sense means that either the hierarchy of classloaders in the appgroup contains exactly one leaf (in which case we use it), or that it contains a classloader whose name exactly matches and that either has or is a unique leaf (in which case we use the leaf).

Abhishek Singh 2009-07-02

I think i faced the same problem when trying to cluster 2 EARs in glassfish (this was during fixing glassfish for unibet). Quoting from the mail some time ago, actually 30 Apr 2009:

– start quote –

And this is the relevant tc-config portion (for both EAR nodes):

Glassfish.ApplicationClassloader:test.ear Glassfish.ApplicationClassloader:my-app.ear Glassfish.ConnectorClassloader Glassfish.sharedLoader

Started the test.ear, populated data in the roots. Started up my-app.ear and tried to access the roots. At this point gettting “No registered loader for description:” exception. Here’s the stacktrace: java.lang.ClassNotFoundException: No registered loader for description: earGroup%%Glassfish.ApplicationClassloader:test.ear, trying to load com.example.ValueObject at com.tc.object.loaders.StandardClassProvider.getClassFor(StandardClassProvider.java:74) at com.tc.object.ClientObjectManagerImpl.lookup(ClientObjectManagerImpl.java:528) at com.tc.object.ClientObjectManagerImpl.lookupObject(ClientObjectManagerImpl.java:431) at com.tc.object.ClientObjectManagerImpl.lookupObject(ClientObjectManagerImpl.java:419) at com.tc.object.bytecode.ManagerImpl.lookupObject(ManagerImpl.java:724) at com.tc.object.bytecode.ManagerUtil.lookupObject(ManagerUtil.java:357) at java.util.HashMap.lookUpIfNecessary(Unknown Source) at java.util.HashMap.lookUpAndStoreIfNecessary(Unknown Source) at java.util.HashMap.access$500(Unknown Source) at java.util.HashMap$EntryWrapper.getValue(HashMap.java:513) at org.apache.jsp.index_jsp._jspService(index_jsp.java:98)

A little debugging is showing that, the first ear (test.ear) created the roots with loader description “earGroup%%Glassfish.ApplicationClassloader:test.ear” Now on the second node (my-app.ear), when its faulting in the roots, its trying to look up a loader with “earGroup%%Glassfish.ApplicationClassloader:test.ear” which is giving null. In this node (of my-app.ear), there is no loader registered with description “earGroup%%Glassfish.ApplicationClassloader:test.ear”, though it has one with the description “earGroup%%Glassfish.ApplicationClassloader:my-app.ear” and capable of loading the root classes (along with other loaders in the same app-group). Looking at StandardClassProvider.lookupLoaderWithAppGroup(..) it seems we need to tweak up the class-loader look-up algo a little bit to support this use-case. Seems like the LAST else clause needs a little bit of massaging (Walter can comment better of course)

The use-case of looking up the class-loader here boils down to this: 1) the dna has an app-group for the class-loader 2) there is no loader registered which is exactly matching the app-group and the loader name 3) there is no loader that matches only the name exactly 4) there is a matching app-group a) there are multiple loaders in the app-group b) which one to choose to load the current class?

The problem particularly in this use-case, as I understand is, which loader to choose in #4-a

– end quote –

I don’t remember filing a jira for that!