Infrastructure at your Service

If you are used to Java, you probably know that there are really important security fixes published every quarter in the Java Critical Patch Update (CPU) and it’s really important to keep it up to date. It’s always easy to upgrade your Java installation, you just have to deploy the new version entirely. In most cases, it’s also pretty easy to update the Components that are using Java (E.g.: Application Servers like Apache Tomcat), since they are – most of the time – relying on an environment variable (JAVA_HOME) to know which Java should be used. On the other hand, there is the WebLogic case and that’s where all the “fun” is…

In a previous blog, I talked about the JAVA_HOME management inside the WebLogic Server files. If you want to upgrade the Java version that is used by your WebLogic Server, then you basically have three choices so let’s see that in detail:

 

I. Use a symlink for the JAVA_HOME

You might be tempted to do something like that:

[[email protected]_server_01 ~]$ cd /app/Java/
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ ls -l
total 0
drwxr-xr-x. 1 weblogic weblogic 17 May 18 13:55 jdk1.8.0_151
drwxr-xr-x. 1 weblogic weblogic 17 May 18 14:02 jdk1.8.0_192
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ ln -s jdk1.8.0_151/ jdk
[[email protected]_server_01 Java]$ ls -l
total 0
lrwxrwxrwx. 1 weblogic weblogic 13 May 18 14:05 jdk -> jdk1.8.0_151/
drwxr-xr-x. 1 weblogic weblogic 17 May 18 13:55 jdk1.8.0_151
drwxr-xr-x. 1 weblogic weblogic 17 May 18 14:02 jdk1.8.0_192
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ JAVA_HOME=/app/Java/jdk
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ $JAVA_HOME/bin/java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ rm jdk
[[email protected]_server_01 Java]$ ln -s jdk1.8.0_192/ jdk
[[email protected]_server_01 Java]$ ls -l
total 0
lrwxrwxrwx. 1 weblogic weblogic 13 May 18 14:06 jdk -> jdk1.8.0_192/
drwxr-xr-x. 1 weblogic weblogic 17 May 18 13:55 jdk1.8.0_151
drwxr-xr-x. 1 weblogic weblogic 17 May 18 14:02 jdk1.8.0_192
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ $JAVA_HOME/bin/java -version
java version "1.8.0_192"
Java(TM) SE Runtime Environment (build 1.8.0_192-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode)
[[email protected]_server_01 Java]$

 

And then you would use “/app/Java/jdk” (a symlink) for WebLogic. Please don’t, it’s a terrible idea!

You might think that using a symlink is a good idea and I thought that too at the beginning… But Oracle officially doesn’t support it and worse than that, it will actually not stay. You can technically use a symlink for your WebLogic Server, it will run (even if it’s not officially supported) but as soon as you are going to run an installer/configurator, it will actually overwrite and replace the symlink path (“/app/Java/jdk“) in WebLogic files with the path of the target folder (“/app/Java/jdk1.8.0_192“).

It’s unfortunate, really, but WebLogic will run as planned and it will use “/app/Java/jdk/bin/java” at the beginning and as soon as you upgrade WebLogic or when you will run an installer, you will find out that WebLogic switched to “/app/Java/jdk1.8.0_192/bin/java” on its own and it overwritten the configuration that you put in place.

If you are using WLS 12.2.1.3 and you therefore have access to the setProperty.sh script (see section II.a below), it will also not accept a symlink, it will just set the JAVA_HOME value to the target folder behind the symlink:

[[email protected]_server_01 bin]$ ./setProperty.sh -name JAVA_HOME -value /app/Java/jdk
Property JAVA_HOME successfully set to "/app/Java/jdk1.8.0_192"
[[email protected]_server_01 bin]$

 

So, in summary, don’t use symlink, it will be pretty for a few minutes/hours/days but in the end, it won’t work anymore and you will therefore loose the purpose of using that.

 

II. Manually replace file content with the new JAVA_HOME

Here you have two choices again:

a. Minimal update

As mentioned in my previous blog, there are some specific configuration files that are used when starting components. If you want to change the path of your JAVA_HOME without too much work, a quick (& a little bit dirty) way is to update only the necessary files:

  • ${DOMAIN_HOME}/bin/setDomainEnv.sh
  • ${DOMAIN_HOME}/nodemanager/nodemanager.properties
  • (WLS 12.1.x) ${MW_HOME}/oracle_common/common/bin/commEnv.sh
  • (WLS 12.2.x) ${DOMAIN_HOME}/bin/setNMJavaHome.sh
  • (WLS 12.2.1.2 and below) ${MW_HOME}/oracle_common/common/bin/commBaseEnv.sh
  • (WLS 12.2.1.3 and above) ${MW_HOME}/oui/.globalEnv.properties

So, as you can see, if you want to update the JAVA_HOME in a very simple WebLogic Server, you need to change three or four files which will change depending on the version of WebLogic that you are using…

If you are using WLS 12.2.1.3, you don’t have to update the file “${MW_HOME}/oui/.globalEnv.properties” directly, there is actually an utility provided since 12.2.1.3 that will do it for you (more information here):

[[email protected]_server_01 ~]$ cd ${MW_HOME}/oui/bin/
[[email protected]_server_01 bin]$
[[email protected]_server_01 bin]$ cat ../.globalEnv.properties
#This file is automatically generated
#Sat May 18 14:34:24 UTC 2019
JAVA_HOME=/app/Java/jdk1.8.0_151
JAVA_HOME_1_8=/app/Java/jdk1.8.0_151
JVM_64=
[[email protected]_server_01 bin]$
[[email protected]_server_01 bin]$ ./getProperty.sh JAVA_HOME
/app/Java/jdk1.8.0_151
[[email protected]_server_01 bin]$
[[email protected]_server_01 bin]$ ./setProperty.sh -name JAVA_HOME -value /app/Java/jdk1.8.0_192
Property JAVA_HOME successfully set to "/app/Java/jdk1.8.0_192"
[[email protected]_server_01 bin]$
[[email protected]_server_01 bin]$ cat ../.globalEnv.properties
#This file is automatically generated
#Sat May 18 15:02:54 UTC 2019
JAVA_HOME=/app/Java/jdk1.8.0_192
JAVA_HOME_1_8=/app/Java/jdk1.8.0_151
JVM_64=
[[email protected]_server_01 bin]$

 

This solution is working but it’s not very clean. You will remain with references to the old path in a lot of files so at some point, you (or someone else) might wonder which Java is actually used. That’s why I personally don’t really like this solution.

b. Cleaner update

Instead of updating only the minimal files, what about being more thorough and update all the files with the mention of the Java path from the old one to the new one? This requires some (not so complicated) commands to find all relevant files, excluding logs, excluding previous patch files, excluding binaries and a few other things and then you can just replace the old Java with the new one.

This is a better solution but it has a few drawbacks:

  • You absolutely need to know what you are doing and you need to test it thoroughly. Don’t try sed commands (or whatever you prefer) to update files directly if you aren’t sure about what you are doing in the first place
  • It takes some time to list all files and update them properly, especially if there is a lot of files under $DOMAIN_HOME or $MW_HOME/$ORACLE_HOME. Even if you automated it, since your Operating System still needs to go through all the existing files and since this needs to be done while WebLogic isn’t running, it will increase the downtime needed
  • This would need to be done for each and every Java patch/update

Despite these drawbacks, I still prefer this solution because it’s much cleaner. No end-user would care if there are still references to an old Java in the WebLogic files, as long as the Application is working for them but I would know that it’s there and it would drive me crazy (a little bit :D).

Below are some example commands that can be used to do that. Please test them and update them as per your need! If you are using different components or additional ones, you might want to take that into account.

[[email protected]_server_01 ~]$ OLD_JAVA="/app/Java/jdk1.8.0_151"
[[email protected]_server_01 ~]$ NEW_JAVA="/app/Java/jdk1.8.0_192"
[[email protected]_server_01 ~]$
[[email protected]_server_01 ~]$ grep -R "${OLD_JAVA}" $DOMAIN_HOME | grep -vE "^[^:]*.log:|^[^:]*/logs/|^[^:]*/nohupLogs/|^[^:]*/.patch_storage/|^Binary file " > ~/listJavaBefore_DOMAIN_HOME
[[email protected]_server_01 ~]$
[[email protected]_server_01 ~]$ grep -R "${OLD_JAVA}" $ORACLE_HOME | grep -vE "^[^:]*.log:|^[^:]*/logs/|^[^:]*/nohupLogs/|^[^:]*/.patch_storage/|^Binary file " > ~/listJavaBefore_ORACLE_HOME
[[email protected]_server_01 ~]$
[[email protected]_server_01 ~]$ awk -F':' '{print $1}' ~/listJavaBefore_DOMAIN_HOME | sort -u; echo
...

[[email protected]_server_01 ~]$
[[email protected]_server_01 ~]$ awk -F':' '{print $1}' ~/listJavaBefore_ORACLE_HOME | sort -u; echo
...

[[email protected]_server_01 ~]$
[[email protected]_server_01 ~]$ while read line; do FILE_TO_UPDATE=`echo ${line} | awk -F':' '{print $1}'`; sed -i "s,${OLD_JAVA},${NEW_JAVA},g" ${FILE_TO_UPDATE}; done < ~/listJavaBefore_DOMAIN_HOME
[[email protected]_server_01 ~]$
[[email protected]_server_01 ~]$ while read line; do FILE_TO_UPDATE=`echo ${line} | awk -F':' '{print $1}'`; sed -i "s,${OLD_JAVA},${NEW_JAVA},g" ${FILE_TO_UPDATE}; done < ~/listJavaBefore_ORACLE_HOME
[[email protected]_server_01 ~]$

 

The grep commands above list all occurrences of the $OLD_JAVA path, the awk commands list all the files that contain one or more occurrences and the while loop replace all occurrences with the value of the $NEW_JAVA. Once that’s done, you can check again with the grep command using both OLD_JAVA and NEW_JAVA to ensure that all references to the old JAVA_HOME are now all properly replaced with the new JAVA_HOME. Instead of OLD_JAVA, you can also use a regex, if you prefer, in case you had several Java versions in the past so it matches all of them and not just the last one. Something like ‘grep “${JAVA_BASE}/[a-zA-Z0-9._]*” …‘ for example or ‘grep “${JAVA_BASE}/jdk[0-9._]*” …

 

III. Use a generic folder

From my opinion, none of the above solutions matter because this one is the best solution and it should be the one that everybody uses. What I mean by a “generic folder” is simply a folder whose name never changes. For that purpose, I’m usually very happy with symlinks for other Application/Application Server but for WebLogic this needs to be a real folder.

In case of an upgrade, you will need to execute both this section III as well as the section II.b so that all references points to the generic folder. On the other hand, in case of a new installation, it’s just all about using the generic folder’s path while installing WebLogic and then you will never have anything else to do. You can see this section III as being somehow the opposite of the section I.

Below, I’m just taking the status at the section I where we have a symlink named “jdk” that point to “jdk1.8.0_192“. I’m changing that, removing the symlink, renaming the folder “jdk1.8.0_151” into “jdk” and then creating a new symlink named “jdk1.8.0_151” that points to “jdk” so it’s the other way around. With that, we have a generic folder named “jdk” that can old all/any Java version and we will never have to change the JAVA_HOME again:

[[email protected]_server_01 Java]$ ls -l
total 0
lrwxrwxrwx. 1 weblogic weblogic 13 May 18 14:06 jdk -> jdk1.8.0_192/
drwxr-xr-x. 1 weblogic weblogic 17 May 18 13:55 jdk1.8.0_151
drwxr-xr-x. 1 weblogic weblogic 17 May 18 14:02 jdk1.8.0_192
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ $JAVA_HOME/bin/java -version
java version "1.8.0_192"
Java(TM) SE Runtime Environment (build 1.8.0_192-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode)
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ rm jdk
[[email protected]_server_01 Java]$ mv jdk1.8.0_151 jdk
[[email protected]_server_01 Java]$ ln -s jdk/ jdk1.8.0_151
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ ls -l
total 0
drwxr-xr-x. 1 weblogic weblogic 17 May 18 13:55 jdk
lrwxrwxrwx. 1 weblogic weblogic 13 May 18 16:22 jdk1.8.0_151 -> jdk/
drwxr-xr-x. 1 weblogic weblogic 17 May 18 14:02 jdk1.8.0_192
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ $JAVA_HOME/bin/java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
[[email protected]_server_01 Java]$

 

As mentioned above, at this point, if you are going to install a new WebLogic Server, then just use “/app/Java/jdk” as the JAVA_HOME and you will never have to touch any WebLogic files. If you have already a WebLogic Server installed and using something else than “/app/Java/jdk“, then you will have to do the section II.b. Section II.b is designed to be executed each time you change your Java version but here, since the folder name will always stay the same, you can do it once only.

To upgrade your version of Java once you are using the generic folder, it’s that simple:

[[email protected]_server_01 Java]$ ls -l
total 0
drwxr-xr-x. 1 weblogic weblogic 17 May 18 13:55 jdk
lrwxrwxrwx. 1 weblogic weblogic 13 May 18 16:22 jdk1.8.0_151 -> jdk/
drwxr-xr-x. 1 weblogic weblogic 17 May 18 14:02 jdk1.8.0_192
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ $JAVA_HOME/bin/java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ rm jdk1.8.0_151
[[email protected]_server_01 Java]$ mv jdk jdk1.8.0_151
[[email protected]_server_01 Java]$ mv jdk1.8.0_192 jdk
[[email protected]_server_01 Java]$ ln -s jdk/ jdk1.8.0_192
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ ls -l
total 0
drwxr-xr-x. 1 weblogic weblogic 17 May 18 14:02 jdk
drwxr-xr-x. 1 weblogic weblogic 17 May 18 13:55 jdk1.8.0_151
lrwxrwxrwx. 1 weblogic weblogic 13 May 18 16:28 jdk1.8.0_192 -> jdk/
[[email protected]_server_01 Java]$
[[email protected]_server_01 Java]$ $JAVA_HOME/bin/java -version
java version "1.8.0_192"
Java(TM) SE Runtime Environment (build 1.8.0_192-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode)
[[email protected]_server_01 Java]$

 

Once that’s done, simply restart the WebLogic processes and you are done, Java has been upgraded without effort, the WebLogic files are still referencing the correct JAVA_HOME and it will stay clean, efficient and working, forever.

 

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Morgan Patou
Morgan Patou

Senior Consultant & Technology Leader ECM