users@glassfish.java.net

Re: Problem using CXF on Glassfish 3.1.1: keep getting the Metro framework

From: Andreas Loew <Andreas.Loew_at_oracle.com>
Date: Wed, 11 Jan 2012 01:03:21 +0100

Hi Fabien,

Am 11.01.2012 00:00, schrieb forums_at_java.net:
> the structure of the EAR is:
>
> - ejb.jar
> - lib
> - WAR
>
> The lib directory contains all the necessary libraries, and also a common
> application module called commons.jar.
>
> The webapp uses a ServletContextListener to initialize a holder for the
> properties read from a properties file. The class ConfigProperties
> holds the
> properties via a static attribute, and both ConfigProperties and the
> properties file are in JAR commons.jar in the EAR's lib directory. In the
> webapp, the ServletContextListener does the following :
(...)
> The ConfigProperties class is then used throughout the application to
> retrieve the values of the properties, including from the EJBs.
>
> This works fine when we don't have delegate=false in the
> glassfish-web.xml
> descriptor.
>
> However, when I set delegate=false, a call made from within an EJB to
> ConfigProperties.getConfigProperties().getProperty("myProperty") now
> returns
> null, whereas it is working when we don't add the glassfish-web.xml
> descriptor containing delegate=false.
as I expected, the issue is related to your usage of classloaders:

When your ServletContextListener loads the properties file, it does this
by using the web app classloader.

As long as this is set to delegate=true (the default), all is fine,
because it asks its parent first and loads the properties via the
EAR/EJB classloader.

When you set delegate=false, the troubles start - I am not exactly sure
why, but I'd probably assume that either class ConfigProperties might be
packaged twice in your application by accident, or it this might be a
strange side effect of the properties file being loaded as common
application module.

But the cure should be pretty simple:

You need to make sure that the class which loads the properties from the
classloader - i.e. the code that calls

this.getClass().getClassLoader().getResourceAsStream("config.properties")

indeed definitely uses the EAR/EJB classloader to do so and not the web
app classloader (you can check which classloader is being used by
logging the result of

this.getClass().getClassLoader()

just to make sure).

One way to do that in EE6 is to make class ConfigProperties a stateful
Singleton EJB and have it load the properties itself rather than passing
it an input stream, and then have the container inject your
ConfigProperties EJB into all the classes which need it.

(And also please double-check that you won't have a second class file
for ConfigProperties being contained in one of the WEB-INF/lib JARs by
accident.)

Hope this helps & best regards,

Andreas

-- 
Andreas Loew | Senior Java Architect
Oracle Advanced Customer Services
ORACLE Germany