This blog post will be closely related to java development and deployment. It is based on a story about a Weblogic upgrade. Actually it is about a custom application that couldn't be to deployed to a Weblogic 12.2.1.3.
We had a mission critical custom application running on Weblogic 10.3.6, and we decided to upgrade this Weblogic 10.3.6 to 12.2.1.3.
The application was also using the BI Publisher.. So we had to upgrade the BI Publisher as well.
Here is quick note, BI Publisher 12.2.1.3 or 12.2.1.4 is not currently certified with Weblogic 12.2.1.4 and that's why we choosed Weblogic 12.2.1.3 as our target Weblogic release.
The upgrade was done out of place.. I mean we installed a fresh Weblogic 12.2.1.3 and BI Publisher 12.2.1.3 to a new server and then deployed our application to this new environment.
The problem was in the deployment.. I mean, we just couldn't deploy our custom application using the WAR file. When we tried to deploy it, the Weblogic console was throwing the following error;
java.lang.NoSuchMethodError: com.google.common.collect.MapMaker.makeComputingMap (Lcom/google/common/base/Function;)Ljava/util/concurrent/ConcurrentMap;
Well, when we analyzed the error, we saw that our code was trying to use makeComputingMap method of the MapMaker class, but the version of that class in Weblogic 12.2.1.3 was high and this makeComputingMap class was already deprecated and removed from the class.
The following was the statement we found in GUAVA Dev.
Deprecated. Caching functionality in MapMaker is being moved to CacheBuilder, with makeComputingMap(com.google.common.base.Function) being replaced by CacheBuilder.build(com.google.common.cache.CacheLoader). See the MapMaker Migration Guide for more details. This method is scheduled for deletion in February 2013.
This wasn't the only error actually, there were also different errors related with Java faces and so on..
So, we needed to change the code, but it wasn't so easy.
That's why we decided to find a workaround, rather than playing with the code.
I will keep it short and directly jump to the workaround we applied..
We needed to find a way to make our code use the old versions of those classes. However; we also needed to upgrade some of the classes to the versions supported by Weblogic 12.2.1.3.
So what we did was the following;
We imported some of the jar files (for instance com.google.common) into our WAR file and told Weblogic to use the jar files inside our WAR file rather than the jar files present in its own library.
Note that, we can import (including jar files) into a WAR using Linux zip command.. Similary, we can also remove any files from a WAR using the zip command.
In order to make Weblogic to use the jar files ( the classes are inside these jar files), we imported related jar files into to WAR file and updated weblogic.xml (WEB-INF/weblogic.xml) We used wls:prefer-application-packages, wls:prefer-application-resources tags to tell Weblogic to use the jar files present in our WAR.
Here is the related part of weblogic.xml:
<wls:weblogic-version>12.2.1</wls:weblogic-version>
<wls:context-root>ErmanWEB</wls:context-root>
<wls:container-descriptor>
<wls:prefer-application-packages>
<wls:package-name>com.google.common.*</wls:package-name>
<wls:package-name>javax.faces.*</wls:package-name>
<wls:package-name>com.sun.faces.*</wls:package-name>
<wls:package-name>com.bea.faces.*</wls:package-name>
</wls:prefer-application-packages>
<wls:prefer-application-resources>
<wls:package-name>com.google.common.*</wls:package-name>
<wls:resource-name>javax.faces.*</wls:resource-name>
<wls:resource-name>com.sun.faces.*</wls:resource-name>
<wls:resource-name>com.bea.faces.*</wls:resource-name>
</wls:prefer-application-resources>
</wls:container-descriptor>
</wls:weblogic-web-app>
Attention: we used prefer-application-resources as well.. (not oly prefer-application-packages)
As the names suggest, these instructions made Weblogic to prefer the classes inside the WAR in the first place..
Also, as I mentioned we updated some of the jar files, as the classes they had wasn't supported by Weblogic 12.2... (we updated those jar files, by importing the new jar files with all their dependencies and removing the old ones with all their dependencies.)
In our case, we also upgraded the Richfaces because the current version of the Richfaces jar inside our WAR file, wasn't supported by Oracle Weblogic 12.2.1.3.
Note that, Richfaces which is a component library for JavaServer Faces. So we downloaded the RichFaces 4.5 (with all its dependencies.. some other jars I mean.. ) and bundled with our application (using weblogic.xml), and used filtering classloader to ensure the correct version is used.. ( I mean we used zip command to import the jar into WAR and used prefer-application-packages and prefer-application-resources to ensure that our newly imported version is used.. Also removed the old RichFaces jar file with all its dependencies from the WAR file.)
After these changes, we redeloyed the application without any errors and certified it with Weblogic 12.2.1.3 without touching the code :)
Note that, code change may still be required, especially for the runtime.. But in our case, we didn't change almost anything in the code :)