Skip to content

Implementing Encapsulation, Inheritance, and Polymorphism in Jenkins Shared Library Pipelines using Groovy

Jenkins shared libraries provide an excellent way to encapsulate code for use across multiple pipelines. By leveraging Java’s object-oriented principles—encapsulation, inheritance, and polymorphism within a groovy script context (like the jenkinsfile) — you can create reusable pipeline components that exhibit these characteristics. Below is an example of how to apply each concept using Jenkins shared libraries:

Encapsulation Example in Groovy with Shared Libraries

Encapsulation hides data within classes, providing controlled access through methods (getters and setters). Here’s a simple demonstration adapted for use in pipeline code. We have an abstract class that defines properties which are then implemented by subclasses:

package com.examplecompany.builders

abstract class AbstractWidgetBuilder {
    protected String color = null // Encapsulated property, initialized to `null`
    
    public def build() {
        throw new Exception("Build method must be defined in concrete classes")
    }
}

Inheritance can then extend these abstract concepts:

File: WidgetXBuilder.groovy (inherits from AbstractWidgetBuilder)

package com.examplecompany.builders
import org.jenkinsci.plugins.workflow.cps.CpsDirtyContext
class WidgetXBuilder extends AbstractWidgetBuilder {
    public def build() {
        super.color = "blue" // Accessing encapsulated property from base class
        
        echo "${super.shape} widget with ${this.numLegs} legs." 
    }
    
    protected String shape = 'round' // Additional attribute specific to WidgetXBuilder, inheriting the concept of polymorphism where both classes can have different shapes but a common interface (build method)
}

The same goes for WidgetYBuilder: File: WidgetYBuilder.groovy

package com.examplecompany.builders
import org.jenkinsci.plugins.workflow.cps.CpsDirtyContext
class WidgetYBuilder extends AbstractWidgetBuilder {
    public def build() {
        super.color = "green" // Accessing encapsulated property from base class
        
        echo "${super.shape} widget with ${this.numLegs} legs." 
    each attribute like `shape` would differ between subclasses, demonstrating polymorphism as these different classes will respond differently to the same method call due to their inheritance hierarchy and overridden methods:
```groovy
def obj = new WidgetYBuilder("red", 4) // Creates a specific instance of our object with inherited properties. Here 'yellow' would be its unique shape if such is defined within `WidgetYBuilder`.
obj.build()         # Builds as per the subclass implementation, showcasing polymorphism (different behavior for WidgetX and Y build processes).

To use this in a Jenkins pipeline (Jenkinsfile), import these classes from your shared library:

File: jenkinsfile

@Library('shared-library') _ // Load the Maven Shared Library plugin. Replace 'examplecompany' with actual company name and adjust paths as necessary for local installation or repository location of artifacts 
import com.examplecompany.builders.WidgetXBuilder   
import com.examplecompany.builders.WidgetYBuilder     
    
node { // Define a pipeline within the Jenkins environment            
    def obj = new WidgetXBuilder("blue",2)           # Instantiate our build object             
    echo "Building widget: ${obj}"                  
    sh(returnStdio: true, script: "${obj.build()}")  // Invoke built method and pass through the pipeline steps           
}               

Here we’ve implemented encapsulation by allowing base class properties to be set within subclasses (inheritance) while also demonstrating polymorphism when different types of Widget builders respond differently due their unique attributes or behavior, yet they share a common interface for building objects.

Note that the exact structure and methods will depend on your specific requirements but this example should give you an idea about encapsulating code within Jenkins shared libraries to provide reusable constructs with inheritance and polymorphism in mind. Remember always to keep sensitive data private as needed, which is a core principle of object-oriented programming — for instance by marking properties like color or build parameters as final where appropriate (thus not allowing them from being changed after construction), using getters/setters properly within your classes and limit their visibility (private, protected), etc.

Happy building!


Previous Post
Resolving Cannot Create Workspace Error in Spacel
Next Post
Why is my private worker crashing on Spacelift