Introduction to Amazon Code Pipeline with Java part 15: the job processor interface and related objects

Introduction

In the previous post we looked at a helper class that’s responsible to carry out operations related to load tests. We didn’t actually look at any implementation details as those are bound to our business and don’t have much to do with Code Pipeline. However, it is still important to know its role so that we can follow the code examples. We also briefly looked at some other classes like the one that parses the string that describes the load test thresholds into “real” objects.

We are now ready to move on to the job processor interface and a couple of related objects. We’ll look at the implementation in a later post.

The job processor

At the end of the last post we briefly looked at the following line of code in the application entry point:

JobProcessor jobProcessor = new ApicaLoadtestJobProcessor(ltpApiLoadtestJobExecutorService, 
                            new CodePipelineLoadtestThresholdParser());

The JobProcessor interface responsible to process a Code Pipeline job. It has only method:

package com.apica.awscodepipelinebuildrunner;

import com.apica.awscodepipelinebuildrunner.model.WorkItem;
import com.apica.awscodepipelinebuildrunner.model.WorkResult;

public interface JobProcessor
{    
    WorkResult process(WorkItem workItem);
}

We’ll see later on in this series exactly how the process function is called in a different part of the application. It accepts a WorkItem object which contains a number of parameters that describe the code pipeline job. Keep in mind that the term “job” refers to a Code Pipeline job as opposed to the job that is carried out in your system, such as a load test job.

WorkItem looks like this:

package com.apica.awscodepipelinebuildrunner.model;

public class WorkItem
{

    private final String jobId;
    private final String jobNonce;
    private final JobData jobData;
    private final String clientId;
    private boolean workItemRetrievalSuccess;
    private String exceptionMessage;
  
    public WorkItem(final String jobId, final String jobNonce, final JobData jobData, final String clientId)
    {
        this.clientId = clientId;
        this.jobId = jobId;
        this.jobNonce = jobNonce;
        this.jobData = jobData;
        this.exceptionMessage = "None";
        this.workItemRetrievalSuccess = true;
    }

    public boolean isWorkItemRetrievalSuccess()
    {
        return workItemRetrievalSuccess;
    }

    public void setWorkItemRetrievalSuccess(boolean workItemRetrievalSuccess)
    {
        this.workItemRetrievalSuccess = workItemRetrievalSuccess;
    }

    public String getExceptionMessage()
    {
        return exceptionMessage;
    }

    public void setExceptionMessage(String exceptionMessage)
    {
        this.exceptionMessage = exceptionMessage;
    }

    public String getJobId()
    {
        return jobId;
    }

    public String getJobNonce()
    {
        return jobNonce;
    }

    public JobData getJobData()
    {
        return jobData;
    }

    public String getClientId()
    {
        return clientId;
    }
}

Here are the various components of the class:

  • jobId: this is the ID that Code Pipeline assigns to the job. We talked about it briefly before. Our third party action doesn’t use it for anything “meaningful” other than saving it in the database. It’s a long string that can look like the following example: eyJlbmNyeXB0ZWREYXRhIjoiK2JNNzd4Q0NiUU12VjVySEhhZlIvelhha3haa1JveS9iV0pSRGY3RGhodzRxTUczMmpDa3hqcHFjaDdFd3UrSGxkRzA2dGlGQXFaMldkOGFLV0w1THE3cnBIZ1BZeG96TDU4U0FvemU3QmlCWWdXUmlnMDMrY2loQmV5RmdCSHJlWnZyV2pOVVRFMDE2dVVsRW9ESHlnM1ZjWXc9IiwiaXZQYXJhbWV0ZXJTcGVjIjoiVWZVbWFPcnl5ckNncUlCYiIsIm1hdGVyaWFsU2V0U2VyaWFsIjoxfQ==
  • jobNonce: the nonce is a random string generated by CP and it is sent to the third party action among the job parameters. We don’t need to do anything with it other than send it back to CP in our response later on. It has a role within Code Pipeline so that it can make sure that the job is only executed by a single worker. Other than that we don’t need to worry about it
  • jobData: the object that holds the data specific to a CP job, we’ll look at it further down
  • clientId: we know this quite well by now I hope
  • workItemRetrievalSuccess: whether the work item was successfully retrieved. In the above code we simply set it to true.
  • exceptionMessage: we can store any exception in this parameter

Here are the details of the JobData object:

package com.apica.awscodepipelinebuildrunner.model;

import java.util.Collections;
import java.util.List;
import java.util.Map;

public class JobData
{

    private final Map<String, String> actionConfiguration;
    private final List<Artifact> inputArtifacts;
    private final List<Artifact> outputArtifacts;
    private final AWSSessionCredentials artifactCredentials;
    private final String continuationToken;
   
    public JobData(final Map<String, String> actionConfiguration,
            final List<Artifact> inputArtifacts,
            final List<Artifact> outputArtifacts,
            final AWSSessionCredentials artifactCredentials,
            final String continuationToken)
    {
        if (actionConfiguration == null)
        {
            this.actionConfiguration = Collections.emptyMap();
        } else
        {
            this.actionConfiguration = Collections.unmodifiableMap(actionConfiguration);
        }

        this.inputArtifacts = initArtifacts(inputArtifacts);
        this.outputArtifacts = initArtifacts(outputArtifacts);
        this.artifactCredentials = artifactCredentials;
        this.continuationToken = continuationToken;
    }

    private List<Artifact> initArtifacts(final List<Artifact> artifacts)
    {
        if (artifacts == null)
        {
            return Collections.emptyList();
        } else
        {
            return Collections.unmodifiableList(artifacts);
        }
    }
    
    public Map<String, String> getActionConfiguration()
    {
        return actionConfiguration;
    }
    
    public List<Artifact> getInputArtifacts()
    {
        return inputArtifacts;
    }
    
    public List<Artifact> getOutputArtifacts()
    {
        return outputArtifacts;
    }

    public AWSSessionCredentials getArtifactCredentials()
    {
        return artifactCredentials;
    }

    public String getContinuationToken()
    {
        return continuationToken;
    }
}
  • actionConfiguration: this is a loosely typed container that holds the values that the user stored when he or she set up your third part action. It can be key-value pairs like “user-count”: “100”, “executing-agent” : “AWS Tokyo” etc.
  • input artifacts: these are the artifacts that your third party action may use as input to the action. A typical example is source code checked out from S3
  • output artifacts: these are the artifact that your third party action produces so that the next action in the pipeline can use it, e.g. the compiled and unit tested source code which then can be deployed to a server
  • AWSSessionCredentials: the AWS credential details
  • continuationToken: we have an entire post dedicated just to this token

We don’t use artifacts in our own load test third party action but here’s the Artifact class nonetheless:

package com.apica.awscodepipelinebuildrunner.model;

public class Artifact
{

    private final String name;
    private final String revision;
    private final String s3BucketName;
    private final String s3ObjectKey;

    public Artifact(final String name, final String revision, final String s3BucketName, final String s3ObjectKey)
    {
        this.name = name;
        this.revision = revision;
        this.s3BucketName = s3BucketName;
        this.s3ObjectKey = s3ObjectKey;
    }

    public String getName()
    {
        return name;
    }

    public String getRevision()
    {
        return revision;
    }

    public String getS3BucketName()
    {
        return s3BucketName;
    }

    public String getS3ObjectKey()
    {
        return s3ObjectKey;
    }
}

…and also here we have the AWSSessionCredentials class:

package com.apica.awscodepipelinebuildrunner.model;

import com.apica.awscodepipelinebuildrunner.Validator;

public class AWSSessionCredentials
{

    private final String accessKeyId;
    private final String secretAccessKey;
    private final String sessionToken;
    
    public AWSSessionCredentials(final String accessKeyId, final String secretAccessKey, final String sessionToken)
    {
        Validator.notNull(accessKeyId);
        Validator.notNull(secretAccessKey);
        Validator.notNull(sessionToken);
        this.accessKeyId = accessKeyId;
        this.secretAccessKey = secretAccessKey;
        this.sessionToken = sessionToken;
    }

    public String getAccessKeyId()
    {
        return accessKeyId;
    }

    public String getSecretAccessKey()
    {
        return secretAccessKey;
    }

    public String getSessionToken()
    {
        return sessionToken;
    }
}

There’s one more object we need to look at before we move on. The process function of the JobProcessor interface returns a WorkResult object by which we can send back the execution result of a Code Pipeline job. We’ll take a look at that class in the next post.

View all posts related to Amazon Web Services and Big Data here.

Advertisements

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

Robin Sedlaczek's Blog

Developer on Microsoft Technologies

HarsH ReaLiTy

A Good Blog is Hard to Find

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

the software architecture

thoughts, ideas, diagrams,enterprise code, design pattern , solution designs

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

Anything around ASP.NET MVC,WEB API, WCF, Entity Framework & AngularJS

Cyber Matters

Bite-size insight on Cyber Security for the not too technical.

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: