Pitfalls when using libraries of newer version than shipped with JDeveloper or WebLogic Server

A question on JDeveloper & ADF OTN forum cought my attention. A user wanted to use a method of the Apache Commons-IO library named FileUtils.getTempDiretory() but got an error when he tried to use code completion or when he tried to compile the code. The problem was that the compiler (or code completion) did not pick up the right java class from the library even as it was installed in the project a library.
As the original code used belongs to one of my samples I was interested in finding a reason for this behavior as I could see no obvious reason for this behavior.

An inspection of a provided test case quickly revealed the problem and a solution was found too. This blog is about the problem and the solution to it. Lets start with building a test case:

The test case had a model project which used a couple of libraries which we add too to make this sample as close as possible to the test case.
 Model Project Properties

Model Project Properties

There is no code whatsoever used in the model project just the libraries are defined!

To make use of the FileUtils.getTempDiretory() method we have to first download the Apache Commons-IO in a version higher then 2.0. The current version is 2.4 which you get from the given link. Once you unzip the zip (or tar.gz) to a directory of your choice we create a new library for JDeveloper (Tools->Manage Libraries…)

We add This new library to the view controller project

Next is to create a java bean where we try to use the FileUtils.getTempDiretory() method

Here we see the problem mentioned in the OTN question. The FileUtils.getTempDiretory() does not show up at all. The JavaDoc of the Apache Commons-IO 2.4 package shows that the method is available since version 2.0
JavaDoc of FileUtils Class

JavaDoc of FileUtils Class

If we try to compile the code we get an compilation error as seen in the last image.

What is the problem?
Well, it looks like there is another version of the Apache Commons-IO library already loaded in the classpath which gets loaded first. Once a library or class is loaded, another version of the same class will not overwrite the existing one.
First thing we can try is to move the new commons-io library to the top of the list of libraries.
In the test case presented here, this doesn’t work. We still get the same error. So there are libraries loaded before the view controller project libraries come to play.
Remember we added some libraries to the model project even as there is no code in the project at all?
Because the view controller project has dependency defined to the model project when we create an Fusion Web Application by default, libraries of the model project are loaded before the view controller projects.
We have can solve the problem in multiple ways:
1. remove the dependency to the model project. This is not recommended as it would mean that we have to build the model project ourselves if we have to change something in the model and want to run the application.
2. find the library which loads the FindUtils class and see if we can remove it (not all libraries are needed).
3. add the new Apache Commons-IO library to the model project and move it up front. This should load the newer version of the FindUtils class before any other.

Solution 1 isn’t really one. Solution 2 is possible and I’ll blog about it later. For this blog we use solution 3.

All we have to do is to add the Apache Commons-IO 2.4 library to the model project and move to the top of the list.

Model Project Properties with Commons-IO

Model Project Properties with Commons-IO

If we now rebuild the workspace we see that to error is gone
No Compilation Error

No Compilation Error

The code completion still shows the method red underlined. This is a bug in JDeveloper which doesn’t pick up the right library. Anyway, the compiler will use the right library and we can compile the application.

Now we add another method to the FileBean which returns the path to the temporary directory. This we use in a page index.jsf to show it on the ui.

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html>
<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <af:document title="index.jsf" id="d1">
    <af:form id="f1">
      <af:panelGridLayout id="pgl1">
        <af:gridRow height="50px" id="gr2">
          <af:gridCell width="100%" halign="stretch" valign="stretch" id="gc1">
            <!-- Header -->
            <af:outputText value="Preferred Package Test" id="ot1" inlineStyle="font-size:x-large;"/>
        <af:gridRow height="100%" id="gr1">
          <af:gridCell width="100%" halign="stretch" valign="stretch" id="gc2">
            <!-- Content -->
            <af:outputText value="Tempdir path = #{FileBean.tempDir}" id="ot2"/>

When we run the application we get an exception

    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:311)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:263)
Caused by: java.lang.NoSuchMethodError: org.apache.commons.io.FileUtils.getTempDirectoryPath()Ljava/lang/String;
    at de.hahn.blog.preferredpackages.view.beans.FileBean.getTempDir(FileBean.java:16)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)

Why’s that?
The application compiled without an error and we still get a NoSuchMethodError. The reason for this is that when we start the WebLogic Server the older version of the Apache Commons-IO jar is loaded first, blocking loading of the newer version we need to get to the FileUtils.getTempDirectoryPath() method.
To allow the server to load our newer version of the jar we need to change a descriptor named weblogic-application.xml which is specific for WebLogic Server. For other servers there exist other descriptors allowing the same.
In this descriptor we add a preferred package for the org.apache.commons.io package. Open the weblogic-appliaction.xml descriptor and select the ‘Class Loading…’ node.

Application Descriptors: weblogic-application.xml

Application Descriptors: weblogic-application.xml

Here we enter the package name org.apache.commons.io to the ‘Application Preferred Libraries’ section.

to get this result in the source view of the descriptor:


After restarting the application the index.jsf page show up OK

Running Test Page

Running Test Page

You can download the sample application which was build using JDeveloper 12.1.3 from GitHub.

4 thoughts on “Pitfalls when using libraries of newer version than shipped with JDeveloper or WebLogic Server

  1. Pingback: WebLogic Partner Community Newsletter June 2015 | WebLogic Community

  2. Pingback: Pitfalls when using libraries of newer version than shipped with JDeveloper or WebLogic Server by Timo Hahn | WebLogic Community

  3. Pingback: Pitfalls when using libraries of newer version than shipped with JDeveloper or WebLogic Server | Dinesh Ram Kali.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s