How to manage classpath when using shared-lib?

Jenkins setup:

  1. OS: RHEL 9
  2. Jenkins: 2.516.2
  3. Java: OpenJDK 21
  4. Installation: RPM, systemd service
  5. JENKINS_HOME: /lun/data1/jenkins
  6. Shared Library: Git-based, with src/ and vars/

Configuration:

In my systemd override (systemctl edit jenkins):

[Service]
Environment="JENKINS_HOME=/lun/data1/jenkins"
Environment="JAVA_OPTS=-Djava.awt.headless=true -cp /lun/data1/jenkins/.jenkins/lib/"
Environment="JENKINS_PORT=8080"
User=jenkins
  • JARs are in /lun/data1/jenkins/.jenkins/lib/ (permissions: chown jenkins:jenkins, chmod 750).

  • Shared library tries to use classes from these JARs (e.g., Class.forName(‘com.external.MyClass’)).

Issue:

Pipelines fail with:

java.lang.ClassNotFoundException: com.external.MyClass

 No suitable driver found for jdbc:postgresql

Tried:

  1. Added JARs to /lun/data1/jenkins/.jenkins/lib/ and updated JAVA_OPTS.

  2. Tested Grape (@Grapes(@Grab(‘org.apache.commons:commons-lang3:3.12.0’))), but slow and needs sandbox approvals.

  3. Considered addToClasspath (Pipeline Classpath Step plugin), but it’s deprecated.

  4. Checked logs (/var/log/jenkins/jenkins.log): No errors except class loading failures.

Questions:

  • Why aren’t JARs in /lun/data1/jenkins/.jenkins/lib/ loaded?

Hello and welcome to this community, @sngbango. :waving_hand:

Jenkins doesn’t automatically load JARs from arbitrary directories (like /lun/data1/jenkins/.jenkins/lib/) into the Groovy sandbox or the pipeline shared library classpath.

Things like -cp or setting CLASSPATH in JAVA_OPTS only affect the initial JVM classpath when Jenkins starts. They don’t influence what’s visible to pipeline or shared library code later on.

A few reasons why this happens:

  • Pipeline and shared library code runs inside a restricted Groovy sandbox, which is intentionally isolated from the main Jenkins JVM classpath for security.
  • The pipeline shared library mechanism doesn’t inherit the JVM classpath or pick up JARs from custom paths.
  • By default, only Jenkins core and installed plugin classes are available.

If you want to use external JARs in a pipeline, here are the supported options:

  • Grape / @Grab annotations in Groovy — though this can be slow and often requires sandbox approvals.
  • Pipeline: Classpath Step — exists but is deprecated and not recommended anymore.
  • Build a Jenkins plugin that bundles your JARs and install it.
  • Global shared libraries — but note they only load Groovy/Java code from src/ and vars/, not standalone JARs.
  • Call your Java code externally from the pipeline using sh or bat steps, and provide the JARs there.

So, in short: Jenkins won’t pick up JARs you drop into /lun/data1/jenkins/.jenkins/lib/ for pipeline libraries. To make them available, you’ll need to use one of the supported mechanisms like a plugin, Grape, or an external process.

If it is about postgres there are plugins available that provide the jars

1 Like