Java Environmental Variables for Azure DevOps Server Agents

On January 28, 2020, in devops, by Chris Thomson

Recently I setup a new Ubuntu 18.04 server to hold build agents for my Azure DevOps Server. We’re moving towards building with Docker images but I wanted to have locally installed Java as well as sometimes it’s easier and the built in Maven task integrates nicely with SonarQube. But I had some issues running a maven build task as it was looking for JAVA_HOME_11_X64.

The really great thing about building with Docker containers is that the developer never has to worry about what version of Java/Maven is installed on the build server. This has become particularly relevant now that Oracle charge for their JVM. There are some minor incompatibilities between JVM implementations and major ones between Java versions. We’ve seen issues where an application fails to run in production because the JVM was slightly different to the one used to test it.

Building with Docker containers removes all those issues and I’ll write more about that soon, but my challenge today was to have both Java 8 and Java 11 available on the build server for use by the Maven task.

The Maven task in Azure DevOps gives us the option of choosing a JDK Version, which sounds perfect. I installed both 8 and 11 using the adoptopenjdk repositories. To do this run the following:

wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | sudo apt-key add -
sudo add-apt-repository --yes https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/
sudo apt-get install adoptopenjdk-8-hotspot
sudo apt-get install adoptopenjdk-11-hotspot

The above is taken from https://adoptopenjdk.net/installation.html#linux-pkg and the last two lines will install your jdk 8 and 11. When done java 11 will be your default. You can update this using update-java-alternatives:

christ@server:~$ update-java-alternatives -l
adoptopenjdk-11-hotspot-amd64  1111       /usr/lib/jvm/adoptopenjdk-11-hotspot-amd64
adoptopenjdk-8-hotspot-amd64   1081       /usr/lib/jvm/adoptopenjdk-8-hotspot-amd64

This will listed your install Java versions, and you can switch to Java 8 by typing:

sudo update-java-alternatives -s adoptopenjdk-8-hotspot-amd64

Now a simple ‘java -v’ will confirm that your default version has changes from 11 to 8.

That’s all very well for interactive use, but bear in mind this change takes effect system wide due to update-alternatives changing where the executable at /usr/bin/java points to.

Now that we have both versions of Java installed, if we configure a Maven task to use one of them, it will fail with the following error:

##[error]Unhandled: Failed to find the specified JDK version. Please ensure the specified JDK version is installed on the agent and the environment variable 'JAVA_HOME_11_X64' exists and is set to the location of a corresponding JDK or use the [Java Tool Installer](https://go.microsoft.com/fwlink/?linkid=875287) task to install the desired JDK.

This is because we don’t have the environmental cariable JAVA_HOME_11_X64 or JAVA_HOME_8_X64 set.

This would seem fairly trivial at first, we just need to set these variables, the question is where do we set them? I did some research and found that these variables are generally used by the Hosted Agents and aren’t intended for use by the on-premise Azure DevOps server.

We could set them in our build pipeline yaml, but really this is specific to the build agent. Different build servers could very well have their java installed in a different location so they should be set on the server.

I tried the obvious options of adding them to /etc/environments and /home/agent/.bash_profile but it seems that the agent does not include the variable from either of these locations.

The correct place to add it is to the .env file inside each agent’s home directory. Then it will be correctly detected and show up in the agents capabilities.

JAVA_HOME_11_X64=/usr/lib/jvm/adoptopenjdk-11-hotspot-amd64
JAVA_HOME_8_X64=/usr/lib/jvm/adoptopenjdk-8-hotspot-amd64

This is a little cumbersome as we have to add it to all agents running on that server. As i use a build server with several agents it would be preferable to have a single file for the server, sourced for environmental variables. Nevertheless, once the .env file is set for each agent on your server your should be good to go using the Maven build task to chose which JVM to use when building.

Leave a Reply

Your email address will not be published. Required fields are marked *