Docker Java Client

No questions about containers been one of the latest big things. They are everywhere, everyone use them or want to use them and the truth is they are very useful and they have change the way we develop.

We have docker for example that provides us with docker and docker-compose command line tools to be able to run one or multiple containers with just a few lines or a configuration file. But, we, developers, tend to be lazy and we like to automize things. For example, what about when we are running our application in our favorite IDE the application starts the necessary containers for us? It will be nice.

The point of this article was to play a little bit the a docker java client library, the case exposed above is just an example, probably you readers can think about better cases but, for now, this is enough for my learning purposes.

Searching I have found two different docker java client libraries:

I have not analyze them or compare them, I have just found the one by GitHub before and it looks mature and usable enough. For this reason, it is the one I am going to use for the article.

Let’s start.

First, we need to add the dependency to our pom.xml file:

<dependency>
    <groupId>com.github.docker-java</groupId>
    <artifactId>docker-java</artifactId>
    <version>3.1.1</version>
</dependency>

The main class we are going to use to execute the different instructions is the DockerClient class. This is the class that establishes the communication between our application and the docker engine/daemon in our machine. The library offers us a very intuitive builder to generate the object:

DockerClient dockerClient = DockerClientBuilder.getInstance().build();

There are some options that we can configure but for a simple example is not necessary. I am just going to say there is a class called DefaultDockerClientConfig where a lot of different properties can be set. After that, we just need to call the getInstance method with our configuration object.

Image management

Listing images

List<Image> images = dockerClient.listImagesCmd().exec();

Pulling images

dockerClient.pullImageCmd("postgres")
                .withTag("11.2")
                .exec(new PullImageResultCallback())
                .awaitCompletion(30, TimeUnit.SECONDS);

Container management

Listing containers

// List running containers
dockerClient.listContainersCmd().exec();

// List existing containers
dockerClient.listContainersCmd().withShowAll(true).exec();

Creating containers

CreateContainerResponse container = dockerClient.createContainerCmd("postgres:11.2")
                .withName("postgres-11.2-db")
                .withExposedPorts(new ExposedPort(5432, InternetProtocol.TCP))
                .exec();

Starting containers

dockerClient.startContainerCmd(container.getId()).exec();

Other

There are multiple operations we can do with containers, the above is just a short list of examples but, we can extended with:

  • Image management
    • Listing images: listImagesCmd()
    • Building images: buildImageCmd()
    • Inspecting images: inspectImageCmd("id")
    • Tagging images: tagImageCmd("id", "repository", "tag")
    • Pushing images: pushImageCmd("repository")
    • Pulling images: pullImageCmd("repository")
    • Removing images: removeImageCmd("id")
    • Search in registry: searchImagesCmd("text")
  • Container management
    • Listing containers: listContainersCmd()
    • Creating containers: createContainerCmd("repository:tag")
    • Starting containers: startContainerCmd("id")
    • Stopping containers: stopContainerCmd("id")
    • Killing containers: killContainerCmd("id")
    • Inspecting containers: inspectContainerCmd("id")
    • Creating a snapshot: commitCmd("id")
  • Volume management
    • Listing volumes: listVolumesCmd()
    • Inspecting volumes: inspectVolumeCmd("id")
    • Creating volumes: createVolumeCmd()
    • Removing volumes: removeVolumeCmd("id")
  • Network management
    • Listing networks: listNetworksCmd()
    • Creating networks: createNetworkCmd()
    • Inspecting networks: inspectNetworkCmd().withNetworkId("id")
    • Removing networks: removeNetworkCmd("id")

And, that is all. There is a project suing some of the operations listed here. It is call country, it is one of my learning projects, and you can find it here.

Concretely, you can find the code using the docker java client library here, and the code using this library here, specifically in the class PopulationDevelopmentConfig.

I hope you find it useful.

Docker Java Client

Java reflection: Accessing a private field

Sometimes, when we import 3rd-party libraries, we can find cases where the information we want is has been populated in an object but, the property is a private one and there are no methods to recover it. Here, it is where the Java reflection capabilities can help us.

Note: Use reflection carefully and, usually, as a last resource.

Let’s say we have a simple class with a private property:

class A {
    private String value = "value";
}

We want to access the property “value” but, for obvious reasons, we cannot do it.

We can implement our reflection method to access the property value:

import java.lang.reflect.Field;

public class Reflection {

   public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
      final A a = new A();
      final Field secureRenegotiationField = a.getClass().getDeclaredField("value");

      secureRenegotiationField.setAccessible(true);

      System.out.println((String) secureRenegotiationField.get(a));
   }
}

With these few lines of code, we will be able to access the value.

Java reflection: Accessing a private field

Groups in Regular Expressions

We cannot discuss the power of regular expression, an amazing tool with unlimited (usually our imagination) capabilities to progress strings. Every developer should, at least, have a basic understanding of them. But, lately, I have realized not a lot of people knows the possibility of creating and labeling “groups”. Groups allow us to access in a very  simple and clear way to the expressions matching our regular expression.

Regular expressions allow us to not just match text but also to extract information for further processing. This is done by defining groups of characters and capturing them using the special parentheses “(” and “)” metacharacters. Any subpattern inside a pair of parentheses will be captured as a group. In practice, this can be used to extract information like phone numbers or emails from all sorts of data.

Here, I am just going to write a little example to show the basic behavior and, I leave to all of you to find the appropriate use cases. In the example, I am going to extract some different hashes for further processing.

public static void main(String[] args) {
    final Pattern HASH_PATTERN = Pattern.compile("^(?<md5>[0-9a-f]{32})(?:/)(?<sha1>[0-9a-f]{40})(?:/)(?<sha256>[0-9a-f]{64})$");
    final Matcher matcher = HASH_PATTERN.matcher("ce114e4501d2f4e2dcea3e17b546f339/a54d88e06612d820bc3be72877c74f257b561b19/c7be1ed902fb8dd4d48997c6452f5d7e509fbcdbe2808b16bcf4edce4c07d14e");

    if (matcher.matches()) {         
        final String md5 = matcher.group("md5");         
        final String sha1 = matcher.group("sha1");         
        final String sha256 = matcher.group("sha256");         
        ...
    }     
    ... 
}

As you can see, the example is pretty simple, it takes one line that contains a string and extracts the MD5, SHA1 and SHA256 hashes. We can see the code is easy to read and understand because everything is using human readable labels not just numbers to access the groups and there is no need to process the string with split operations or similars.

The syntax for the groups is:

(?<name>X)– X, as a named-capturing group

(?:X) – X, as a non-capturing group

With this, we can easily make our code easier to read and maintain when we are extracting information or doing some text processing.

For further information, check the Java documentation: Pattern (Java SE 10 & JDK 10)

Groups in Regular Expressions

Error Prone

We, as a developers, sometimes, make mistakes or add bugs to our code without realizing. For this reason static analyzers are a handy tool to apply during our builds or during our code verification processes.

One of these tools is Error Prone.

Error Prone is Google’s Java bug detection and static analysis tool. It is integrated into the Java compiler and catches bugs at compile time. It supports plugin checks for project-specific enforcement.

Basically, it is a tool created by Google for code analysis and error detection for the Java language. It is integrated inside the compiler and tries to detect bugs in compilation time.

But, let’s see and example. Imagine we have a program with the next line of code:

String.format("Param A: {}, param B: {}, param C: {}", paramA, paramB, paramC);

Obviously, it is not correct and the error comes from, maybe, a transformation between a previous log message to a different kind of message. The compiler is not going to complain because it is a string message and it is not a syntax error. But, the truth is there is an error.

When we try to compile the program with Error Prone, we are going to receive a compilation error message like this:

error: [FormatString] extra format arguments: used 0, provided 3
String.format("Param A: {}, param B: {}, param C: {}", paramA, paramB, paramC);              ^
(see http://errorprone.info/bugpattern/FormatString)

We can see clearly and without any doubts there is an error. Even, a link to the error description is provided.

The proper code should be:

String.format("Param A: %s, param B: %s, param C: %s", paramA, paramB, paramC);

The easiest way to start using the tool, it is to add the maven plugin to our pom.xml file:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.3</version>
    <configuration>
        <compilerId>javac-with-errorprone</compilerId>
        <forceJavacCompilerUse>true</forceJavacCompilerUse>
        <source>8</source>
        <target>8</target>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>org.codehaus.plexus</groupId>
            <artifactId>plexus-compiler-javac-errorprone</artifactId>
            <version>2.8.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.errorprone</groupId>
            <artifactId>error_prone_core</artifactId>
            <version>2.0.19</version>
        </dependency>
    </dependencies>
</plugin>

For more options, just go to the installation instructions page.

The project is open source and you can see all the code in the official repository: error-prone.

I am not saying that it is going to solve all your problems but, at least, it is another tool to increase our code quality and avoid silly mistakes.

Error Prone

Customized date format in JAXB

Nowadays, it is very common to work with JAXB to help us to marshal and unmarshal objects into XML or XML into objects. These objects can be simple object or objects created by us if we use the correct annotations. It is clear that JAXB is very useful but, sometimes, it is not enough with the default values the API is offering us.

Recently, we had a problem with the date format. The external system where we were trying to send information was expecting a very concrete pattern for the date objects in the XML, and the default format JAXB was offering us was not correct. After test a couple of solutions, we find one that it was working very good and it was quite simple to implement.

The idea was to rewrite the adapter with the desired format and after that, using the correct annotation, tell JAXB be the correct format. Easier than it sounds.

The first step is to write our adapter object extending the object XmlAdapter. In there, we can define the exact format we want to use when the marshalling operation is performed.

package com.wordpress.binarycoders.services.jaxb.utils;
 
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
 
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
 
public class DateAdapter extends XmlAdapter<String, XMLGregorianCalendar> {
 
    private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
 
    @Override
    public String marshal(XMLGregorianCalendar v) throws Exception {
        Calendar calendar = v.toGregorianCalendar();
         
        return dateFormat.format(calendar.getTime());
    }
 
    @Override
    public XMLGregorianCalendar unmarshal(String v) throws Exception {
         
        GregorianCalendar c = new GregorianCalendar();
        c.setTime(dateFormat.parse(v));
         
        return  DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
    }
}

This example is using a XMLGregorianCalendar object, but this can be done with any date object.

The second step, it is to indicate JAXB that this adapter should be used instead of the default one. We do this with the annotation @XmlJavaTypeAdapter. Something like this:

@XmlSchemaType(name = "date")
@XmlJavaTypeAdapter(DateAdapter.class)
protected XMLGregorianCalendar date;

That´s all. Now, when the marshaling operation is performed, we should obtain the desired date format in our XMLs.

See you.

Customized date format in JAXB

Checksum calculation

Today, we have another little code snipped. Sometimes, we need to transfer files between systems, and in these cases, it is usually interesting to have some kind of system to check the file content integrity. In these cases, it is when a checksum can be very useful. Here we have a little implementation done in Java. Simple to write, simple to use.

package com.wordpress.binarycoders.checksum;
 
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
 
public class CheckSum {
 
    private static final String MD5 = "MD5";
    private static final String SHA1 = "SHA-1";
     
    public static String md5CheckSum(byte[] content) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance(MD5);
         
        return byteArray2Hex(md.digest(content));
    }
     
    public static String sha1CheckSum(byte[] content) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance(SHA1);
         
        return byteArray2Hex(md.digest(content));
    }
     
    private static String byteArray2Hex(final byte[] hash) {
        String result = "";
         
        try (Formatter formatter = new Formatter()) {
            for (byte b : hash) {
                formatter.format("%02x", b);
            }
             
            result = formatter.toString();
        }
         
        return result;
    }
}

See you.

Checksum calculation

Image URL to byte array

Today, I only have a little code snippet to take a URL with an image and transform it in a byte array in Java 8, the image, not the URL. It is something very simple, but sometimes, it is very useful to have this kind of snippets in a place where we can find it easily.

package com.wordpress.binarycoders.image.recovery;
 
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
 
public class ImageRecover {
     
    public byte[] recoverImageFromUrl(String urlText) throws Exception {
        URL url = new URL(urlText);
        ByteArrayOutputStream output = new ByteArrayOutputStream();
         
        try (InputStream inputStream = url.openStream()) {
            int n = 0;
            byte [] buffer = new byte[ 1024 ];
            while (-1 != (n = inputStream.read(buffer))) {
                output.write(buffer, 0, n);
            }
        }
     
        return output.toByteArray();
    }
}

See you.

Image URL to byte array

Spark + Freemarker basic example

Today, we are going to develop a little web page with a form using Spark and Freemarker. The purpose is simply to know how they are used together and how to manage GET and POST request. In addition, I am going to add Bootstrap to learn how to combine Freemarker with CSS.

As its web page describes “Spark – A tiny Sinatra inspired framework for creating web applications in Java 8 with minimal effort“. You can see a previous example I implemented in this blog called: Quick REST demo with Spark.

In the same way, as its web page describes “FreeMarker is a “template engine”; a generic tool to generate text output (anything from HTML to autogenerated source code) based on templates

The project has these requirements:

  • JDK 8
  • Maven
  • IDE. I have used IntelliJ IDEA CE, but you can use NetBeans, Eclipse or your favorite one.

The final structure for our project will be:

./pom.xml
./src/main/java/com/wordpress/binarycoders/SayMyName.java
./src/main/resources/css/bootstrap.css
./src/main/resources/templates/form.ftl
./src/main/resources/templates/result.ftl

The first step is to create a simple maven java project, obtaining in this way a pom.xml and a basic project structure. We should assign groupId, artifactId and version.

After that, we should edit our pom.xml file to add the dependencies that we are going to use to implement our example:

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-core</artifactId>
    <version>2.1</version>
</dependency>
 
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.22</version>
</dependency>

As I have said at the beginning of this post, Freemarker is a template engine, then, the next step is to write the templates. We are going to write two templates:

  • form.ftl: This is going to be the first page of our application and it is going to show us a form to introduce “user” and “email“.
  • result.ftl: This page is going to show us the information introduced in the form.

The first template: form.ftl

<html>
    <head>
        <title>Welcome</title>
 
        <link href="css/bootstrap.css" rel="stylesheet" />
    </head>
    <body>
        <form class="form-inline" method="POST" action="/sait">
            <div class="form-group">
                <label for="name">Name</label>
                <input type="text"
                       class="form-control"
                       id="name"
                       name="name"
                       placeholder="John Doe">
            </div>
            <div class="form-group">
                <label for="email">Email</label>
                <input type="email"
                       class="form-control"
                       id="email"
                       name="email"
                       placeholder="john.doe@example.org">
            </div>
            <button type="submit" class="btn btn-default">Send invitation</button>
        </form>
    <body>
</html>

The second template: result.ftl

<html>
    <head>
        <title>Said</title>
    </head>
    <body>
        <h1> Your name is ${name}</h1>
        <br>
        <h1> Your email is ${email}</h1>
    </body>
</html>

It is very important to remember in this point that to be allowed to recover our form parameters in the Java code we need to add the name attribute to our inputs. It is not enough with the id attribute.

In this point, we should add Bootstrap CSS file to our project.

And finally, we need to implement our main class that it is going to process the GET and the POST requests.

package com.wordpress.binarycoders;
 
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;
import spark.Spark;
 
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
 
public class SayMyName {
 
    public static void main(String[] args) {
        final Configuration configuration = new Configuration(new Version(2, 3, 0));
        configuration.setClassForTemplateLoading(SayMyName.class, "/");
 
        Spark.get("/", (request, response) -> {
 
            StringWriter writer = new StringWriter();
 
            try {
                Template formTemplate = configuration.getTemplate("templates/form.ftl");
 
                formTemplate.process(null, writer);
            } catch (Exception e) {
                Spark.halt(500);
            }
 
            return writer;
        });
 
        Spark.post("/sait", (request, response) -> {
            StringWriter writer = new StringWriter();
 
            try {
                String name = request.queryParams("name") != null ? request.queryParams("name") : "anonymous";
                String email = request.queryParams("email") != null ? request.queryParams("email") : "unknown";
 
                Template resultTemplate = configuration.getTemplate("templates/result.ftl");
 
                Map<String, Object> map = new HashMap<>();
                map.put("name", name);
                map.put("email", email);
 
                resultTemplate.process(map, writer);
            } catch (Exception e) {
                Spark.halt(500);
            }
 
            return writer;
        });
    }
}

Now, we only need to run this main class and… that’s all. We can go to our browser and introduce the URL:

http://localhost:4567

We should see our form with our Bootstrap style. If we introduce a username and an email, and we submit the form, we will see in the next page two messages with our form data.

Probably, as you have notice, we have not needed a server and this is because the Spark framework have an embedded Jetty server.

See you.

Spark + Freemarker basic example

Customizing our connections with proxies

Nowadays, it is clear that Java / Java EE are mainly back end technologies. In this role, it is quite common for a Java / Java EE application to connect to different systems to collect data or perform different operations, using REST web services, SOAP web services, sockets or other technologies that allow different systems to exchange information without a human being interference.

In complex systems, in addition to the big number of external and internal connections the system performs, we need to consider that sometimes we need to use one or more different proxies to reach the destiny.

Sometime the objects we are using to create and manage connections allow us to add this proxy information inside, but not always, and this creates always a big headache. We usually end, wrapping our object inside others that support a proxy addition.

Today, I have another suggestion that, in some cases, can do our lives easier. This option is to extend the ProxySelector class. This class has been around for a long time, you can find the API page for different Java version:

The idea is to extend this class and implement its abstract methods and assign this extended class as the default class for our system. Each time that a connection is going to be performed, the method List<Proxy> select(URI uri) is going to be called. In this method, we can decide if we need to add a proxy or not to this connection.

The resultant code should be something like that:

package com.wordpress.binarycoders.proxy;
 
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
 
public class CustomProxySelector extends ProxySelector {
 
    private static final int DEFAULT_PORT = 80;
 
    private final ProxySelector defaultProxySelector;
 
    private Proxy proxy;
 
    private List<Proxy> proxyList = new ArrayList<Proxy>();
 
    public CustomProxySelector(String proxyHost, Integer proxyPort) {
 
        defaultProxySelector = ProxySelector.getDefault();
 
        proxy = new Proxy(Proxy.Type.HTTP,
                          new InetSocketAddress(proxyHost,
                                                (proxyPort == null) ?
                                                 DEFAULT_PORT :
                                                 proxyPort));
        proxyList.add(proxy);
    }
 
    @Override
    public List<Proxy> select(URI uri) {
 
        if (uri == null) {
            throw new IllegalArgumentException("URI cannot be null.");
        }
 
        if (needsProxy(uri)) {
            return proxyList;
        }
 
        return def.select(uri);
    }
 
    @Override
    public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
 
        if ((uri == null) || (sa == null) || (ioe == null)) {
            throw new IllegalArgumentException("Arguments cannot be null.");
        }
 
        defaultProxySelector.connectFailed(uri, sa, ioe);
    }
 
    private boolean needsProxy(URI uri) {
        return uri.getHost().contains("urlNeedsProxy");
    }
}

As you can see, we only need a few lines to make it works. Obviously, we can make as complex as you want the method to determinate if a connection needs a proxy or not.

To use this class, we only need to add a simple line to the code in the start point of our application:

ProxySelector.setDefault(new CustomProxySelector(proxyHost, proxyPort));

And that’s all. Now with a few tests we can check if our solution works fine or not.

See you.

Note: Take care if your application share the server with other applications. Remember to test all of them just in case.

Customizing our connections with proxies

Adding a library to our maven repository

Sometimes the maven repositories don’t have all the libraries we need and, we need to add a concrete library to our repository. Usually, this is because there is a problem with its license, something similar or only because it is a library that we have built for our own projects. In both cases, the steps to add the library to our own repository are quite simple.

For this example, we are going to use the library example-1.0-jar and the information about this library is going to be:

  • groupId: org.example
  • artifactId: example
  • version: 1.0

To add this library to our repository, we only need to execute a simple command:

mvn install:install-file -Dfile=<libraryName> -DgroupId=<groupId> -DartifactId=<artifactId> -Dversion=<version> -Dpackaging=jar

With our example data, the command should look like this:

mvn install:install-file -Dfile=example-1.0.jar -DgroupId=org.example -DartifactId=example -Dversion=1.0 -Dpackaging=jar

Finally, we only need to add our new dependency in our maven file, and that’s all.

<dependency>
    <groupId>org.example</groupId>
    <artifactId>example</artifactId>
    <version>1.0</version>
</dependency>

See you.

Adding a library to our maven repository