8bitjunkie
8bitjunkie

Reputation: 13245

Weblogic 10.3.5: <prefer-web-inf-classes> in weblogic.xml not working VS. server classpath JAR files

Weblogic version: 10.3.5

JSF version (interfaces, impl) : Mojarra 2.0.3

I have a JSF EAR application which is made up of a WAR file and a JAR file.

The WAR file contains the following two Maven dependencies:

 <dependency>
        <groupId>javax.faces</groupId>
        <artifactId>jsf-api</artifactId>
        <version>2.0.3</version>
    </dependency>

    <dependency>
        <groupId>com.sun.faces</groupId>
        <artifactId>jsf-impl</artifactId>
        <version>2.0.3</version>
    </dependency>

When running, the following code snippet correctly reports the current in-service version of Mojarra as v2.0.3:

public void getMojarraVersion() {
    Package p = FacesContext.class.getPackage();
    System.out.println("Mojarra version: " + p.getImplementationTitle() + " " + p.getImplementationVersion());
}

The weblogic startup log, however reports that a different, far older version provided by the container, is used when the application is started:

INFO: Initializing Sun's JavaServer Faces implementation (1.2_03-b04-FCS) for context '/myApp'

This is despite the following weblogic.xml configuration, deployed alongside the WAR file's web.xml file in WEB-INF, which inverts the classloader:

<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
     <wls:container-descriptor>
        <wls:prefer-web-inf-classes>true</wls:prefer-web-inf-classes>
     </wls:container-descriptor>
</wls:weblogic-web-app>

After a couple of days of digging, I discovered the following two JAR Files are being included in the server classpath:

${WEBLOGIC_HOME}/wlserver_10.3/server/lib/consoleapp/webapp/WEB-INF/lib/jsf-api.jar

${WEBLOGIC_HOME}/wlserver_10.3/server/lib/consoleapp/webapp/WEB-INF/lib/jsf-impl.jar

These files are provided by a vanilla install of Weblogic 10.3.5.

Temporarily removing these two JAR files and restarting the server caused the log to start reporting that the new version is in use:

INFO: Initializing Mojarra 2.0.3 for context '/myApp'

The above evidence therefore demonstrates that Weblogic configuration to subvert the classloader hierarchy does not work for any resources that are provided by the server classpath (i.e. ${WEBLOGIC_HOME}/wlserver_10.3/server/lib) when an application is loaded.

As an interesting aside, I can delete the weblogic.xml file and I find that:

  1. The wrong version of the dependency continues to be reported in the startup log.
  2. The correct version of the dependency continues to be used at runtime.

Upvotes: 3

Views: 23100

Answers (3)

vicky77
vicky77

Reputation: 19

8bitjunkie- Hi. I believe that your third party jar files are included to your EAR by the framework and the in-built listener/classes addition logic used in your application or in your application's third party libraries. The framework may be spring in your case. If this is the case, then either,

  1. You need to modify the main application's configuration before creating the EAR in such a way that the third party library's dependency be removed. for eg: in Ivy.xml, used for all the dependencies that downloads this 'jsf-impl' jar.

  2. You need to modify the main application's code logic to implement either servletcontextlistener class or servletcontainerInitializer class based on the context i.e., former must be used if your classes form a part integral to your own web application and letter must be used if jar is packaged to WAR which in turn bundled into EAR and deployed in server as EAR application. Hope this helps

Upvotes: -1

Michelle
Michelle

Reputation: 56

Sometime <wls:prefer-web-inf-classes>true</wls:prefer-web-inf-classes> can't specify the lib. You need to use: <wls:prefer-application-packages> and <wls:prefer-application-resources>. Below is an example (remove wls: for old weblogic version):

<wls:container-descriptor>
    <wls:prefer-application-packages>
        <wls:package-name>META-INF/services/javax.xml.bind.JAXBContext</wls:package-name>
        <wls:package-name>com.google.common.*</wls:package-name>
        <wls:package-name>org.slf4j.*</wls:package-name>
        <wls:package-name>org.apache.logging.log4j.*</wls:package-name>
    </wls:prefer-application-packages>
    <wls:prefer-application-resources>
        <wls:resource-name>META-INF/services/javax.xml.bind.JAXBContext</wls:resource-name>
        <wls:resource-name>com.google.common.*</wls:resource-name>
        <wls:resource-name>org.slf4j.*</wls:resource-name>
        <wls:resource-name>org.apache.logging.log4j.*</wls:resource-name>
    </wls:prefer-application-resources>
</wls:container-descriptor>

On top of weblogic.xml use this: <wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.2/weblogic-web-app.xsd">

Upvotes: 3

beaston
beaston

Reputation: 21

The prefer-web-inf-classes setting only applies to the web application level.
I can't tell from the output provided, but it looks like the classloader for your ear is loading the other jar files. The classloader for your war will load and use the newer jar based on your setting, even though the root application loaded the others.

If you want to see this happen at the ear level, you can add a classloader filter. WebLogic 12c allows this at both the war and ear level: Link

I've only read about 10.3.5 allowing the filter at the ear level: Link

Upvotes: 2

Related Questions