users@glassfish.java.net

EE/EJB spec. conflict regarding classloading?

From: Laird Nelson <ljnelson_at_gmail.com>
Date: Tue, 8 Nov 2011 10:33:35 -0500

Hello; I've been having a very interesting conversation with Jean-Louis
Monteiro over on Twitter (http://twitter.com/chuggid). It centers on the
interaction between the EJB and Java EE 6 specifications in the area of
classloading and what the two specifications permit and deny. Since
Glassfish is the reference implementation for both specifications I wanted
to ask some of the questions here.

Briefly: I want to read a resource on the classpath from library code used
by an EJB's business method. May I?

The EJB specification as everyone knows goes to great length to prohibit
file access. I understand that. Such IO is not transactional or "cloud
friendly". But it seems to tread very carefully in the area of
ClassLoader#getResource(String). Despite being very clear about what is
prohibited, it does not single out this very common operation as one that
is prohibited.

Section 21.2.2 says, among other things, this:

>
> - An enterprise bean must not use the java.io package to attempt to
> access files and directories in the file system.
>
> (Bullet point #4, numbered starting with 1.)

That's fine; I'm not interested in using java.io to access files and
directories.

Then it says this:

>
> - The enterprise bean must not attempt to directly read or write a
> file descriptor.
>
> (Bullet point #10.)

That's fine; I'm not doing that either.

But it also says this:

>
> - The enterprise bean must not attempt to create a class loader; *obtain
> the current class loader*; set the context class loader; set security
> manager; create a new security manager; stop the JVM; or change the input,
> output, and error streams.
>
> Note the "obtain the current class loader" bit. I am assuming that the
"current class loader" is *not* the ClassLoader returned by
Thread.currentThread().getContextClassLoader(), but is, instead, the
ClassLoader that is returned by this.getClass().getClassLoader(). In any
event this seemed kind of surprising. I would appreciate clarification
here. May I really not call getClass().getClassLoader() from within an EJB?

Then I read the EE 6 specification, section EE.6.2.4.7:

This specification requires that Java EE containers provide a per thread
> context class loader for the use of system or library classes in
> dynamically loading classes provided by the application. The EJB
> specification requires that all EJB client containers provide a per thread
> context class loader for dynamically loading system value classes. The per
> thread context class loader is accessed using the Thread method
> getContextClassLoader. [...]
>

So that seems like I should be able to get the context ClassLoader in this
fashion just fine.

Then section EE.8.2.5 says:

...libraries that need to dynamically load classes that have been provided
> as a part of the application need to use the context class loader to load
> the classes. Access to the context class loader requires
> RuntimePermission(“getClassLoader”), which is not normally granted to
> applications, but should be granted to libraries that need to dynamically
> load classes. Libraries can use a method such as the following to assert
> their privilege when accessing the context class loader.
>

So that sounds like in a Java EE 6 application it should be legal to obtain
a ClassLoader via Thread.currentThread().getContextClassLoader(),
and--reading the Java EJB specification section 21.2.2 very
carefully--legal to call getResourceAsStream() on it, provided that--again,
conforming to the EE specification--my library actually doing this resource
access has been granted the appropriate RuntimePermission and has performed
the class load as a privileged action.

Is that correct?

Best,
Laird

-- 
http://about.me/lairdnelson