This problem is usually caused by specifying an incorrect
classpath when configuring the CustomService using the administrative
console. For example, the classpath does not contain the user's
CustomService implementation class, or some of its dependent classes.
Sometimes, however, the problem is more subtle and requires an
understanding of how CustomService classes interact with the WebSphere
Application Server runtime environment, and more specifically, the
WebSphere Classloaders. |
Tip: To resolve this problem, ensure
that all CustomService-related artifacts (JARs, classes, and so forth) are
in the classpath specified in the Custom Service's configuration in the
administrative console. If not, refactor the CustomService artifacts or
reconfigure the classpath of your CustomService to satisfy this condition.
Save your changes and restart the server to verify your fix.
If you still encounter the problem, read the following discussion before
adopting the plausible solution of placing your CustomService artifacts in
the JVM™ classpath to resolve the NoClassDefFoundError. This will only
cause the server to fail with the same error, only for the class
com.ibm.websphere.runtime.CustomService. If you are still confused, read
the following.
The classpath setting you specified for your CustomService is added to
the local classpath of the WebSphere Extensions classloader (WSExtCL)
early in the start sequence of the application server. Next in the
sequence, the server instantiates user-specified CustomServices and
invokes the services' initialize method. The context classloader of the
thread executing the initialize method is still the WSExtCL. Finally,
during server quiesce the runtime environment invokes the CustomServices'
shutdown method. Again, the context classloader for the shutdown method is
the WSExtCL.
The WebSphere Extensions classloader resides between the Java™
classloader (JavaCL) and the WebSphere Application classloader (WSAppCL).
That is, the JavaCL is the parent of the WSExtCL, and the WSExtCL is the
parent of the WSAppCL.
The WSAppCL is actually a tree of classloaders that load your
applications EAR, EJB™ and WAR artifacts. This tree will change structure
depending on classloader policy settings. Also, the JavaCL is fixed
lineage of three classloaders. For this discussion, JavaCL and WSAppCL are
represented as single composite entities:
[JavaCL] -- Java artifacts loaded here.
|
WSExtCL -- Application server and CustomService artifacts loaded here.
|
[WSAppCL] -- Application artifacts loaded here.
So, what does all this mean to developing a CustomService?
First, the classes comprising a CustomService scope to the application
server, meaning that ALL applications hosted by that server can utilize
your CustomService classes. Also, these classes will persist in the
WSExtCL cache over the lifecycle of the application server.
Second, because of the location of the WSExtCL in the preceding
classloader structure, and because classloading only delegates upward, the
WSExtCL cannot locate application classes appearing in the local
classpaths of the classloaders below it. Thus, your
CustomService classes cannot have dependencies on application classes.
This agrees with the concept of a CustomService, which is a pluggable
extension of the WebSphere server environment.
This also explains why you will get a NoClassDefFoundError when placing
your CustomService classes on the JVM classpath of the application server.
Your CustomService classes will be loaded by the JavaCL, which cannot
resolve the dependencies on WebSphere runtime classes visible only in the
WSExtCL local classpath, namely interface
com.ibm.websphere.runtime.CustomService.
Tip: Your CustomService classes
cannot not have dependencies on any application classes; but conversely,
your application classes might have dependencies on CustomService classes.
Ensure that your CustomService classes have no dependencies on application
classes, and refactor the CustomService and Application artifacts as
necessary. Using the administrative console, reconfigure your
CustomService, save your changes, and restart the server to verify your
fix.
This should resolve the problem, but here is a little more...
From the preceding discussion, it seems plausible that changing the
context classloader in your CustomService code could alleviate
class-visibility problems. Do not attempt this -- IBM WebSphere absolutely
will not support this solution, and it is dangerous!
Finally, you cannot control the ranking of a Custom Service's creation or
initialization and shutdown within the server's start and shutdown
sequences. Thus, for instance, you cannot assume WebSphere services are
available for use within CustomService initialization. |