Module Java Jenkins

De EjnTricks

Suite à la mise à jour de Ubuntu en 18.04, des erreurs sont enregistrées lors du démarrage de l'application. Celle-ci était disponible, mais certaines fonctions / plugins entraînaient des erreurs.


Hand-icon.png Votre avis

Nobody voted on this yet

 You need to enable JavaScript to vote


Study icon.png Etude

Start-icon.png Démarrage Tomcat (18.04)

Dans le cadre de cet article, Wisemapping est déployé sur un serveur Tomcat. Suite à la mise à jour de Ubuntu en 18.04, la version de openjdk est mise à jour. Pour rappel, le service est démarré à l'aide du script /etc/init.d/tomcat8 contenant le code suivant.

# this is a work-around until there is a suitable runtime replacement
# for dpkg-architecture for arch:all packages
# this function sets the variable JDK_DIRS
find_jdks()
{
    for java_version in 9 8
    do
        for jvmdir in /usr/lib/jvm/java-${java_version}-openjdk-* \
                      /usr/lib/jvm/jdk-${java_version}-oracle-* \
                      /usr/lib/jvm/jre-${java_version}-oracle-* \
                      /usr/lib/jvm/java-${java_version}-oracle
        do
            if [ -d "${jvmdir}" ]
            then
                JDK_DIRS="${JDK_DIRS} ${jvmdir}"
            fi
        done
    done
}

# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not
# defined in $DEFAULT)
JDK_DIRS="/usr/lib/jvm/default-java"
find_jdks

Or sur le répertoire /usr/lib/jvm contient les installations suivantes.

#ll /usr/lib/jvm
total 108
drwxr-xr-x   6 root root  4096 mai   13 10:49 ./
drwxr-xr-x 110 root root 69632 juin  15 17:14 ../
lrwxrwxrwx   1 root root    25 avril  8 15:16 default-java -> java-1.11.0-openjdk-amd64/
lrwxrwxrwx   1 root root    21 avril 21 15:41 java-1.11.0-openjdk-amd64 -> java-11-openjdk-amd64/
-rw-r--r--   1 root root  2619 avril 21 15:41 .java-1.11.0-openjdk-amd64.jinfo
drwxr-xr-x   7 root root  4096 mai    6 18:25 java-11-openjdk-amd64/
lrwxrwxrwx   1 root root    20 avril 13  2016 java-1.8.0-openjdk-amd64 -> java-8-openjdk-amd64/
-rw-r--r--   1 root root  2600 avril 26 17:59 .java-1.8.0-openjdk-amd64.jinfo
drwxr-xr-x   8 root root  4096 mai   11  2016 java-7-oracle/
-rw-r--r--   1 root root  2543 mai   11  2016 .java-7-oracle.jinfo
drwxr-xr-x   5 root root  4096 avril 24  2016 java-8-openjdk-amd64/
drwxr-xr-x   8 root root  4096 avril 24  2017 java-8-oracle/
-rw-r--r--   1 root root  2643 avril 24  2017 .java-8-oracle.jinfo

Donc d'après le script de démarrage c'est /usr/lib/jvm/default-java, lien sur /usr/lib/jvm/java-1.11.0-openjdk-amd64/, qui est utilisé.

Or avec les versions récentes de Java, la notion de module est introduite et certaines fonctionnalités ne sont plus activées par défaut.

Start-icon.png Démarrage Tomcat (18.10)

Suite à la version 18.10, le serveur Tomcat est démarré à l'aide de systemd. Le fichier de configuration /lib/systemd/system/tomcat8.service déclare la variable ExecStart pour spécifier le script à exécuter.

#
# Systemd unit file for Apache Tomcat
#

[Unit]
Description=Apache Tomcat 8.5 Web Application Server
Documentation=https://tomcat.apache.org/tomcat-8.5-doc/index.html
After=network.target

[Service]

# Configuration
Environment="CATALINA_HOME=/usr/share/tomcat8"
Environment="CATALINA_BASE=/var/lib/tomcat8"
Environment="CATALINA_TMPDIR=/tmp"
Environment="JAVA_OPTS=-Djava.awt.headless=true"
EnvironmentFile=-/etc/default/tomcat8

# Lifecycle
Type=simple
ExecStartPre=+/usr/libexec/tomcat8/tomcat-update-policy.sh
ExecStart=/bin/sh /usr/libexec/tomcat8/tomcat-start.sh
SuccessExitStatus=143

# Logging
SyslogIdentifier=tomcat8

# Security
User=tomcat8
Group=tomcat8
PrivateTmp=yes
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target

Le contenu du script est le suivant et un le script /usr/libexec/tomcat8/tomcat-locate-java.sh est exécuté au démarrage.

#!/bin/sh
#
# Startup script for Apache Tomcat with systemd
#

set -e

# Find the Java runtime and set JAVA_HOME
. /usr/libexec/tomcat8/tomcat-locate-java.sh

# Set the JSP compiler if configured in the /etc/default/tomcat8 file
[ -n "$JSP_COMPILER" ] && JAVA_OPTS="$JAVA_OPTS -Dbuild.compiler=\"$JSP_COMPILER\""

export JAVA_OPTS

# Enable the Java security manager?
SECURITY=""
[ "$TOMCAT_SECURITY" = "yes" ] && SECURITY="-security"


# Start Tomcat
cd $CATALINA_BASE && exec $CATALINA_HOME/bin/catalina.sh run $SECURITY

Et c'est dans ce script, /usr/libexec/tomcat8/tomcat-locate-java.sh, que la recherche de la JVM a été déplacé.

#!/bin/sh
#
# Script looking for a Java runtime suitable for running Tomcat
#
# The script looks for the default JRE/JDK, OpenJDK and Oracle JDK
# as packaged by java-package. The Java runtime found is exported
# in the JAVA_HOME environment variable.
#

set -e

# Find the Java runtime if JAVA_HOME isn't already defined
if [ -z "$JAVA_HOME" ]; then
    # This function sets the variable JDK_DIRS
    find_jdks()
    {
        for java_version in 11 10 9 8
        do
            for jvmdir in /usr/lib/jvm/java-${java_version}-openjdk-* \
                          /usr/lib/jvm/jdk-${java_version}-oracle-* \
                          /usr/lib/jvm/jre-${java_version}-oracle-* \
                          /usr/lib/jvm/java-${java_version}-oracle \
                          /usr/lib/jvm/oracle-java${java_version}-jdk-* \
                          /usr/lib/jvm/oracle-java${java_version}-jre-*
            do
                if [ -d "${jvmdir}" ]
                then
                    JDK_DIRS="${JDK_DIRS} ${jvmdir}"
                fi
            done
        done
    }

    # The first existing directory is used for JAVA_HOME
    JDK_DIRS="/usr/lib/jvm/default-java"
    find_jdks

    # Look for the right JVM to use
    for jdir in $JDK_DIRS; do
        if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
            JAVA_HOME="$jdir"
        fi
    done
    export JAVA_HOME
fi

if [ -z "$JAVA_HOME" ]; then
    echo "<2>No JDK or JRE found - Please set the JAVA_HOME variable or install the default-jdk package"
    exit 1
fi

Mylogs-icon.png Messages erreur

Lors du démarrage de Tomcat, les messages suivants sont constatés.

AVERTISSEMENT [Jenkins initialization thread] hudson.ExtensionFinder$GuiceFinder$FaultTolerantScope$1.error Failed to instantiate Key[type=org.jenkinsci.main.modules.sshd.SSHD, annotation=[none]]; skipping this component
 com.google.inject.ProvisionException: Unable to provision, see the following errors:

1) Error injecting constructor, java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
  at org.jenkinsci.main.modules.instance_identity.InstanceIdentity.<init>(InstanceIdentity.java:40)
  while locating org.jenkinsci.main.modules.instance_identity.InstanceIdentity
    for field at org.jenkinsci.main.modules.sshd.SSHD.identity(SSHD.java:38)

1 error
        at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:52)
        at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:145)
        at hudson.ExtensionFinder$GuiceFinder$FaultTolerantScope$1.get(ExtensionFinder.java:432)
        at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41)
        at com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:54)
        at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:132)
        at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:114)
        at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:85)
        at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:267)
        at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
        at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)
        at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
        at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:145)
        at hudson.ExtensionFinder$GuiceFinder$FaultTolerantScope$1.get(ExtensionFinder.java:432)
        at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41)
        at com.google.inject.internal.InjectorImpl$2$1.call(InjectorImpl.java:1016)
        at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1092)
        at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1012)
        at hudson.ExtensionFinder$GuiceFinder._find(ExtensionFinder.java:394)
        at hudson.ExtensionFinder$GuiceFinder.find(ExtensionFinder.java:385)
        at hudson.ClassicPluginStrategy.findComponents(ClassicPluginStrategy.java:493)
        at hudson.ExtensionList.load(ExtensionList.java:380)
        at hudson.ExtensionList.ensureLoaded(ExtensionList.java:318)
        at hudson.ExtensionList.iterator(ExtensionList.java:172)
        at jenkins.model.Jenkins.<init>(Jenkins.java:969)
        at hudson.model.Hudson.<init>(Hudson.java:85)
        at hudson.model.Hudson.<init>(Hudson.java:81)
        at hudson.WebAppMain$3.run(WebAppMain.java:233)
Caused by: java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
        at org.jenkinsci.main.modules.instance_identity.pem.PEMHelper.extractBinaryPEM(PEMHelper.java:130)
        at org.jenkinsci.main.modules.instance_identity.pem.PEMHelper.decodePEM(PEMHelper.java:61)
        at org.jenkinsci.main.modules.instance_identity.InstanceIdentity.read(InstanceIdentity.java:78)
        at org.jenkinsci.main.modules.instance_identity.InstanceIdentity.<init>(InstanceIdentity.java:60)
        at org.jenkinsci.main.modules.instance_identity.InstanceIdentity.<init>(InstanceIdentity.java:40)
        at org.jenkinsci.main.modules.instance_identity.InstanceIdentity$$FastClassByGuice$$af33f6d9.newInstance(<generated>)
        at com.google.inject.internal.cglib.reflect.$FastConstructor.newInstance(FastConstructor.java:40)
        at com.google.inject.internal.DefaultConstructionProxyFactory$1.newInstance(DefaultConstructionProxyFactory.java:61)
        at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:105)
        at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:85)
        at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:267)
        at com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:54)
        at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:132)
        at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:114)
        at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:85)
        at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:267)
        at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
        at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)
        at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
        ... 27 more

L'accès à la classe javax/xml/bind/DatatypeConverter nécessite l'activation du module java.xml.bind.

Icon-Configuration-Settings.png Ajout module

Afin d'activer le module, il suffit d'ajouter l'argument --add-modules avec la valeur java.xml.bind à l'exécution de Java. Etant sur Tomcat8, ceci s'effectue dans le script /var/lib/tomcat8/bin/setenv.sh comme expliqué dans l'article suivant.

#!/bin/sh

export CATALINA_OPTS="-Xms256m -Xmx512m"

export MAVEN_OPTS="-Xmx512m"

export JAVA_OPTS="$JAVA_OPTS --add-modules java.xml.bind -DJENKINS_HOME=$CATALINA_HOME/.jenkins"