Fork me on GitHub

Programming, Internet & more

Java 9 Private Interface Methods

This is another post about a new feature in Java 9. Today, we will talk about interfaces.

Private Interface Methods

Since Java 8 it is possible to use default methods in interfaces. These methods allowed us to implement functionality directly into an interface method. However, interface methods neededed to use one of the following visibility modifiers:

  • public
  • abstract
  • default
  • static

Please notice the absence of the private modifier. Since Java 9 it is now allowed to also use private methods in interfaces. Let’s take a look at this example:

public interface NumberCheck {

    public default boolean is42(int number) {
        if (isGreaterThan42(number) || isLessThan42(number)) {
            return false;
        }

        return true;
    }

    private boolean isGreaterThan42(int number) {
        return number > 42;
    }

    private boolean isLessThan42(int number) {
        return number < 42;
    }
}

The default method is42() makes use of the private helper methods to reduce the complexity of itself.

Why do we need private methods in interfaces?

Private interface methods become interesting while using them along with default methods. Before Java 9 it was possible to use default methods but eventually they become longer and longer and it was impossible to structure them properly. With Java 9 we can mainly see private methods as helper methods to split up default methods into several smaller ones like we would do with normal methods in classes.

What about static methods?

The rules of private methods also apply to private static methods. This means we can also use private static methods in interfaces:

public interface NumberCheck {

    public static boolean is42(int number) {
        if (isGreaterThan42(number) || isLessThan42(number)) {
            return false;
        }

        return true;
    }

    private static boolean isGreaterThan42(int number) {
        return number > 42;
    }

    private static boolean isLessThan42(int number) {
        return number < 42;
    }
}

Conclusion

Private interface methods are a great addition to the default methods introduced in Java 8. They play very well together and help to make code more structured and clean.

Posted in java9 | Leave a comment

Java 9 Diamond Operator and anonymous classes

This is another post about a new feature in Java 9. Today, I will show you that you can use the diamond operator along with anonymous classes.

Diamond Operator

We all know about the Diamond Operator since Java 7. It allows us to leave out the generic type on the right side of an expression. For example, let’s declare a simple list:

// before Java 7, explicit generic type declaration required
List<String> myList = new ArrayList<String>();

// since Java 7, diamond operator can be used
List<String> myList = new ArrayList<>();

Unfortunately, the use of the Diamond Operator was not possible for anonymous inner classes. The situation was not very consistent because the generic type of an anonymous inner class can be deduced just as from a normal class.

Since Java 9 the situation has improved and it is now possible to use the Diamond Operator also in anonymous inner classes. Let’s take a look at this example:

// possible since Java 9, diamond operator can be used
Predicate<Integer> predicate = new Predicate<>() {
    @Override
    public boolean test(Integer input) {
        return input == 42;
    }
};

Conclusion

With the introduction of lambda expressions in Java 8, anonymous inner classes have become less important. However, sometimes they are still useful and even can improve readability. Therefore, it is very good that the inconsistency with the Diamond Operator has been removed and it is now possible to use it also on anonymous inner classes.

Posted in java9 | Leave a comment

Java 9 Collection Initializer

Finally, after 3 years of waiting Java 9 has reached the world. This major release was delayed several times due to the integration of its famous modularization feature called “Project Jigsaw”. But besides that major feature, Java 9 contains several other minor improvements which make the life of a programmer easier but are not that popular.

Today, I would like to introduce the collection initializer feature.

Collection initializer

From time to time everyone has to initialize a collection of something. The typical Java way to do this was not very elegant compared to other programming languages. The most common way was to create a new collection and afterwards adding all the elements to it.

List<String> oldList = new ArrayList<>();
oldList.add("list");
oldList.add("initializer");
oldList.add("classic");
oldList.add("style");

There were a few other ways to initialize collections but none was as elegant as the new collection initializer feature. With Java 9 it is possible to do the initialization in one line as we know it from other languages.

List<String> newList = List.of("list", "initializer", "java 9", "style");

One important thing to notice is that the new “of” method does not return one of the common list implementations like ArrayList. Instead, a new immutable list implementation is used, which is not available in the public API. This means you cannot add or remove an item in the list. Doing this will result in an UnsupportedOperationException.

newList.add("boom"); // UnsupportedOperationException
newList.remove(0); // UnsupportedOperationException
newList.clear(); // UnsupportedOperationException

The “of” method can also be applied to the collection types Map and Set.

Set<String> set = Set.of("set", "initializer", "java 9", "style");
Map<Integer, String> map = Map.of(1, "map", 2, "initializer");

Conclusion

After so many years of waiting it was about time that we also got a simple way to initialize collections. There are some drawbacks, like immutability, but I think it was a reasonable decision to design it like that in regard to performance aspects.

Posted in java9 | Leave a comment

Authentication with Spring Boot, Angular 2 and Keycloak

Posted in spring | 1 Comment

CORS with Keycloak and Spring Boot

A quick tip regarding Keycloak, Spring Boot and some kind of JavaScript UI technology. When you’re trying to connect a JavaScript UI like Angular to a backend which is secured by Keycloak you have to be aware of CORS. I’m pretty sure you already know this.

However, there is a common pitfall, you have to enable CORS 2 times. First you have to enable CORS on Spring Boot level to make sure your origin is allowed to make calls to the REST api.

This can be done with a WebMvcConfigurerAdapter like this:

@Configuration
public class FilterProvider {

    @Bean
    public WebMvcConfigurer corsConfiguration() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**")
                        .allowedMethods(HttpMethod.GET.toString(), HttpMethod.POST.toString(),
                                HttpMethod.PUT.toString(), HttpMethod.DELETE.toString(), HttpMethod.OPTIONS.toString())
                        .allowedOrigins("*");
            }
        };
    }
}

The second time you have to enable CORS is explicitly for Keycloak. If you forget this, your UI won’t be able to connect to your REST api. To enable CORS for Keycloak you can simply add the following to your application.properties file:

# Keycloak Enable CORS
keycloak.cors = true

The configuration is simple but trust me this could easily drive you crazy if you forget it. The browser will constantly complain about missing CORS headers. Additionally this error message could be misleading because you already enabled CORS for Spring Boot, right?

So, hopefully this tip will help you the next time when you’re running into this problem with Keycloak.

Posted in programming | 3 Comments

Openkeepass: Android Support

Finally, openkeepass version 0.6.0 is out and its major feature in this version is the Android support.

The whole Xml serialization core was rewritten and now uses the Android friendly Simple XML Api.

Release Notes of openkeepass v0.6.0

Fixed

  • Fixed an issue that could bring the password of an entry into illegal state.
  • Fixed circular reference that occured when moving an entry multiple times to history.
  • Fixed incorrect data check in HashedBlockInputStream.
  • Fixed invalid placeholder in CrsAlgorithm.
  • Fixed leak of resources.
  • Changed

  • Changed XML library from JAXB to SimpleXML (Android support)
  • Changed crypto library from BouncyCastle to SpongyCastle (Android support)
  • Added

  • Contracts between builders and domain objects to support loose coupling
  • KeePass files can now be cloned by using cloneKeePassFile() in GroupZipper
  • GroupBuilder can now add and remove a list of entries
  • Times support in EntryBuilder
  • A lot of refactoring under the hood
  • Removed

  • getZippper() from KeePassFileBuilder
  • Where can I get it

    You can download it with maven or directly from GitHub.

    <dependency>
        <groupId>de.slackspace</groupId>
        <artifactId>openkeepass</artifactId>
        <version>0.6.0</version>
    </dependency>
    Posted in open-source | Leave a comment

    Authentication with Spring Boot, AngularJS and Keycloak

    Update

    There is a new version of this tutorial available for Angular 2 and Keycloak.

    Intro

    In this tutorial, I want to show you how to combine Keycloak with AngularJS and Spring Boot.

    The result will be a small application where you will get a frontend written in AngularJS and the big topics regarding authentication like user-registration, password reset, login page etc. are already solved.

    The backend is implemented with Spring Boot and will provide a REST API with business services exposed. Authentication in the backend is also solved by using Keycloak which means that all REST endpoints will be secured and that you will get all the user information in the backend as well as in the frontend.

    Requirements

    We will use the following tools and frameworks to build the application:

    Maven (Version 3.3.9)
    Spring Boot (Version 1.3.3.RELEASE)
    Keycloak (Version 1.9.1.Final)
    AngularJS (Version 1.5.0)

    Create a realm in Keycloak

    Start up Keycloak by using one of the Standalone executeables in the /bin directory of Keycloak which will start Keycloak immediately by using the bundled WildFly application server.

    After the startup, open up a browser and navigate to http://localhost:8080.

    If this is the first time you start Keycloak it is required to create an admin user.

    After you have created the admin user, use this user to login into the Administration Console. By default Keycloak uses the Master realm to manage its own users. You should never use this realm to authenticate your own application. Instead create your own realm for the authentication of your application.

    Create a new realm by hovering over the Master realm and click on the “Add realm” button. Enter a name, we will use Demo-Realm, and click on “Create”. After that you will be navigated to the configuration page of the realm.

    Open the “Login” tab and enable the features “User registration” and “Forgot password”. By enabling, these features will be added to the login page automatically and will cover the common use-cases that appear in nearly every web application.

    Create roles in Keycloak

    Now, lets add some roles that can be assigned to users later on to handle authorization. We need two roles that will come into play later on. One is the admin role and the other one is the manager role.

    Click on the “Roles” link in the navigation and after that, click on the button “Add Role” at the right side of the screen. This will navigate you to the “Add Role” screen. Enter admin as role name and click on “Save”. Create another role named manager.

    Create clients in Keycloak

    After we have created our roles we can create the clients for our application. We will need two clients. One for the frontend application and one for the REST backend.

    Let’s start by creating the frontend client. Click on the “Clients” link in the navigation and then use the “Create” button to create a new client.

    Use tutorial-frontend as client id and click on “Save”.

    You will be navigated to the client settings. Use the access type public and the following URLs and save the client:

    • Valid Redirect URIs: http://localhost:8000/*
    • Base URL: http://localhost:8000/index.html
    • Web Origins: http://localhost:8000

    Now the frontend client is completely configured and can be used.

    Lets create another client for the backend and name it tutorial-backend. This time configure the access type as bearer-only because the REST backend should only be called when a user has already logged in.

    Now the basic configuration in Keycloak is done and we can start building the applications.

    Frontend application with AngularJS

    We want to build a small Angular application that is secured by a login page and where access is restricted to registered users only. Therefore every request which goes to the Angular application should be checked if it comes from a registered user or not. If a request does not come from a registered user, the request will be redirected to the login page where a user can register.

    To interact with Keycloak from our AngularJS application, Keycloak is providing a JavaScript-Adapter directly on the Keycloak server. This adapter will be used to check if a request is authenticated and can be integrated in our application by including the JavaScript file into our html page:

    <script src="//localhost:8080/auth/js/keycloak.js"></script>

    Futhermore we have to configure the KeyCloak adapter to ensure it knows who our application is and where to find the Keycloak server. We can provide this information as a json file which can be downloaded directly from the Keycloak server.

    To get the json file, open the Keycloak administration console and navigate to the frontend client page. Then open the “Installation” tab and choose “Keycloak OIDC JSON” as format. Then download the JSON file and store it in the angular application as /keycloak/keycloak.json.

    One important thing to know is because we are only allowing registered users to have access to the application we have to manually bootstrap AngularJS and we cannot rely on the automatic bootstrapping with the ng-app directive.

    The following code demonstrates how to authenticate a request and bootstrap angular only if the request comes from a registered user:

    // on every request, authenticate user first
    angular.element(document).ready(() => {
        window._keycloak = Keycloak('keycloak/keycloak.json');

        window._keycloak.init({
            onLoad: 'login-required'
        })
        .success((authenticated) => {
            if(authenticated) {
                window._keycloak.loadUserProfile().success(function(profile){
                    angular.bootstrap(document, ['keycloak-tutorial']); // manually bootstrap Angular
                });
            }
            else {
                window.location.reload();
            }
        })
        .error(function () {
            window.location.reload();
        });
    });

    If an unregistered user opens the application he will be automatically redirected to the Keycloak login page. In the application we can access user information like login name by getting the user profile with loadUserProfile().

    That is basically all what is needed to secure our Angular application. To ensure the user information is transmitted to the backend we also have to add the users access token to the request header while calling a backend REST service. This can be done like this application wide:

    // use bearer token when calling backend
    app.config(['$httpProvider', function($httpProvider) {
        var token = window._keycloak.token;    
        $httpProvider.defaults.headers.common['Authorization'] = 'BEARER ' + token;
    }]);

    Backend application with Spring Boot

    The backend application should be secured against unauthorized access. Therefore, like in the frontend, only requests coming from registered users should be accepted.

    First, it is important to add the maven Keycloak dependencies for Tomcat and Spring Boot:

    <dependency>
                <groupId>org.keycloak</groupId>
                <artifactId>keycloak-tomcat8-adapter</artifactId>
                <version>${keycloak.version}</version>
            </dependency>
            <dependency>
                <groupId>org.keycloak</groupId>
                <artifactId>keycloak-spring-boot-adapter</artifactId>
                <version>${keycloak.version}</version>
            </dependency>

    Then we have to configure keycloak just like we did in the frontend application. This time the configuration is done the Spring Boot way in the application.properties file:

    keycloak.realm = Demo-Realm
    keycloak.realmKey = MI...
    keycloak.auth-server-url = http://localhost:8080/auth
    keycloak.ssl-required = external
    keycloak.resource = tutorial-backend
    keycloak.bearer-only = true
    keycloak.credentials.secret = e12cdacf-0d79-4945-a57a-573a833c1acc

    The values can be retrieved from the “Installation” tab in the administration console of Keycloak for the backend client. One important thing here is to not forget the secret. The secret can be retrieved from the “Credentials” tab of the backend client.

    To secure the REST API endpoints a few other entries in the application.properties file are important:

    keycloak.securityConstraints[0].securityCollections[0].name = spring secured api
    keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = admin
    keycloak.securityConstraints[0].securityCollections[0].authRoles[1] = manager
    keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /api/*

    The patterns property defines the pattern of the API endpoints with * acting as wildcard. That means every endpoint under api like /api/contracts or /api/users is protected by Keycloak. Every other endpoint that is not explicitly listed is NOT secured by Keycloak and is publicly available.

    The authRoles property defines which Keycloak roles are allowed to access the defined endpoints.

    If everything is configured correctly the Keycloak adapter for Spring Boot should intercept incoming request automatically and reject unauthorized requests.

    To access detailed user information in the backend we can use the KeycloakPrincipal class from the Keycloak-SpringBoot adapter. The KeycloakPrincipal will automatically be injected by Spring if used in a REST controller class as method parameter. Detailed user information can then be retrieved by using the AccessToken like this example in a REST controller:

        @RequestMapping(method = RequestMethod.GET)
        @ResponseBody
        public void getUserInformation(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
            AccessToken token = principal.getKeycloakSecurityContext().getToken();
           
            String id = token.getId();
            String firstName = token.getGivenName();
            String lastName = token.getFamilyName();

            // ...
        }

    In the full example you will see that I have build a MethodArgument Resolver to avoid having to deal with the Principal in the REST controllers but that is absolutely not necessary and just for convenience.

    Demo

    The simplest way to start up a demo is to clone the application source with:

    git clone https://github.com/cternes/slackspace-angular-spring-keycloak

    Then you can either configure the frontend and backend application with the correct settings from Keycloak as described above OR use the existing KeyCloak configuration in keycloak/demo-realm.json to import the realm in Keycloak and avoid having to manually configure the applications.

    After that use maven to start both applications with the following command:

    mvn spring-boot:run

    Then navigate to http://localhost:8000 and you should find yourself landing on the Keycloak login page. Register yourself as a new user. After registering you will be redirected back to the Angular application and should see some details about your user.

    Please note that currently your user is not associated to any role defined earlier. That means accessing the backend is impossible because we have only allowed managers and admins to access the backend. To give your user access to the backend we have to map your user to a role.

    To do this, open the Keycloak admin console and navigate to “Users”. Then click on the button “View all users” and click on your username. After that navigate to the “Role Mappings” tab and assign the role “manager” to your user.

    Now open up the Angular app again and you should see a “Call backend service” button that only managers can see. Click on it and some contracts from the backend should be returned together with your user information which comes also from the backend.

    This proves that the frontend and the backend is correctly secured by Keycloak.

    Source-Code

    As always, you can find a full working example at GitHub.

    Posted in spring | 18 Comments

    Openkeepass: Feature release with write support

    Openkeepass is around for a while now and has proved to be a major player when it comes to reading of KeePass files (especially KeePass 2.x).

    However, since its initial release I’ve received a lot of requests regarding write support of KeePass files. After a lot of work this is finally done and has found its way into a new feature release of openkeepass.

    Writing KeePass files

    The major feature of version 0.5.0 is to support writing of KeePass files. To simply create a new KeePass file from scratch you can use the fluent API of the builders. A very simple example to write a KeePass file with only one single entry would be this:

    // Create an entry
    Entry entryOne = new EntryBuilder("First entry")
    .username("Carl")
    .password("Carls secret")
    .build();

    // Create the database file
    KeePassFile keePassFile = new KeePassFileBuilder("myNewKeePassFile")
    .addTopEntries(entryOne)
    .build();

    // Write database file to disk
    KeePassDatabase.write(keePassFile, "masterPassword", "myNewKeePassFile.kdbx");

    By nesting the available builders it is also possible to create much more complex structures in the KeePass file.

    The code to create this structure looks like this:

    // Create the more complex tree structure
    Group root = new GroupBuilder("TestDb")
                .addEntry(new EntryBuilder("First entry").build())
                .addGroup(new GroupBuilder("Banking").build())
                .addGroup(new GroupBuilder("Internet")
                        .addGroup(new GroupBuilder("Shopping")
                                .addEntry(new EntryBuilder("Second entry").build())
                                .build())
                        .build())
                .build();

    // Create the database file    
    KeePassFile keePassFile = new KeePassFileBuilder("TestDb")
            .addTopGroups(root)
            .build();

    // Write database file to disk     
    KeePassDatabase.write(keePassFile, "masterPassword", "myNewKeePassFile.kdbx");

    Modify existing KeePass files

    There is also a new concept called zipper which comes into play when a KeePass structure should be modified instead of creating a new one from scratch. The zipper can be used to easily navigate through the tree structure of a KeePass file and can be compared with the concept of an iterator. There is always a pointer to an element in the tree and by navigating through the tree, the pointer to the current element will be shifted around.

    This is very helpful if you want to replace some nodes in the tree. Please note that entries cannot be replaced directly in the tree, you have to modify the parent group of an entry if you want to modify or replace an entry.

    The following example shows how to rename an existing group by using the zipper:

    // Open keepass file
    KeePassFile database = KeePassDatabase.getInstance("database.kdbx").openDatabase("password");
           
    // Navigate through tree to group
    GroupZipper zipper = new KeePassFileBuilder(database).getZipper()
                .down()
                .right();
           
    // Rename group
    Group group = zipper.getNode();
    Group modifiedGroup = new GroupBuilder(group).name("test2").build();
           
    // Replace old group with new one
    KeePassFile modifiedDatabase = zipper.replace(modifiedGroup).close();

    // Write database file to disk
    KeePassDatabase.write(modifiedDatabase, "password", "modifiedDatabase.kdbx");

    Where can I get it

    You can download it with maven or directly from GitHub.

    <dependency>
        <groupId>de.slackspace</groupId>
        <artifactId>openkeepass</artifactId>
        <version>0.5.0</version>
    </dependency>
    Posted in open-source | 2 Comments

    How to check for updated dependencies with maven

    Regularly updating your dependencies in a project is important because it ensures that you will get all the nice bugfixes that were done in the meantime in some of the libraries you use. However this can be a time-consuming and annoying task.

    Good news if you’re using maven because there is a nice command which exactly does this for you, checking if a new version is available for one of your project dependencies. The following maven command can be used:

    mvn versions:display-dependency-updates

    And the output looks like this:

    [INFO] --- versions-maven-plugin:2.2:display-dependency-updates (default-cli) @ openkeepass ---
    [INFO] The following dependencies in Dependencies have newer versions:
    [INFO]   org.bouncycastle:bcprov-jdk15on ......................... 1.53 -> 1.54

    Just be careful while updating because of eventually breaking changes.

    Posted in programming | Leave a comment

    Continuous Delivery with Jenkins and Docker

    If you’ve ever wondered how to actually build a continuous delivery pipeline for your project this is going to be the ultimative guide. I will tell you how you can build a continuous delivery pipeline from ground up.

    The pipeline will make heavy use of Jenkins together with Docker to provide a stable platform to build on.

    The overall goal is to setup a build process which runs on every commit, compiles all the classes, runs all the unit tests and automatically deploys the application to provide a running instance which could be used by testers.

    Requirements

    To follow this guide you will need a few applications installed. I will use Vagrant to create a virtual machine (vagrant box) which will make it really easy for you to follow and avoid installing a bunch of software on your machine.

    Applications on your machine (host):

    Applications on vagrant box (guest):

    Setting up vagrant

    The first thing you have to do is install VirtualBox and Vagrant. It’s pretty easy just follow the instructions of the installers.

    If you have done that you can clone the repository from github that I’ve prepared. In the repository there is a Vagrantfile which will setup your virtual machine with all the necessary stuff.

    After you’ve cloned the repository open a command shell in the cloned directory and start the virtual machine.

    vagrant up

    Depending on your internet connection it may take a while until that command has finished. This command will do a lot of work by downloading and installing all the applications on the virtual machine that we’ll need in a minute.

    Once the command has finished you can log into the vagrant box.

    vagrant ssh

    This command will ssh into the virtual machine and should look like this:

    Vagrant ssh

    Preparing jenkins

    When you startup your vagrant box jenkins will be automatically started in the background.
    As soon as jenkins is up and running you can open a browser on your host machine and navigate to jenkins http://localhost:9080.

    Now lets install some plugins for jenkins:

    • Git plugin to be able to fetch git projects from github
    • Copy Artifact plugin to be able to copy artifacts from one project to another

    The easiest way is by navigating to Manage Jenkins -> Manage Plugins -> Available and filter for the plugin names

    Jenkins install plugins

    As soon as the plugins are installed you have to install maven to be able to build maven projects. This can be done in Manage Jenkins -> Configure System -> Maven .

    Jenkins install maven

    Configuring the build job in jenkins

    You can now create your first build job which will compile your application and run some basic unit tests. We’ll be using slackspace-javaee-classpath-properties as an example application. The project is a Java EE application hosted on GitHub so it’s pretty easy to include the project into our pipeline. As the project uses maven we can easily compile it without having to worry about dependencies.

    Create a new maven project in your jenkins with name “javaee-classpath-properties-build”.
    Now you have to choose Git as Source Code Management system and use the correct url to the repository: https://github.com/cternes/slackspace-javaee-classpath-properties.git.

    Jenkins maven project
    Jenkins configure source code management

    As build goal use package as we want to compile the project and package all the classes into a *.war file.

    Jenkins configure maven goals in project

    The last step is to define a post-build action called Archive the artifacts. The files to archive should be set to target/*.war. This will ensure that it is possible to access the packaged war-file in another project later on.

    You can now test if the job works by clicking on the Build Now button. If everything works the job should be displayed with a blue circle after a while.

    Configuring the staging job in jenkins

    Now it is time to configure another job that will make use of docker containers to provide a running instance of the application for testing.

    First of all create another jenkins job named javaee-classpath-properties-staging. The type should be Freestyle project.

    Jenkins free-style project

    Leave the Source Code Management untouched. Instead check the build trigger Build after other projects are built and enter the name of our build project (javaee-classpath-properties-build).

    Add a build step of type Copy artifacts from another project and enter the following properties:

    • Project name: javaee-classpath-properties-build
    • Which build: Latest successful build
    • Check Stable build only
    • Artifacts to copy: target/*.war

    Add another build step Execute shell and insert the command:

    docker ps -a | grep 'javaee-classpath-properties-staging:latest' | awk '{print $1}' | xargs --no-run-if-empty docker kill

    echo "FROM glassfish:4.1\nMAINTAINER cternes <github@slackspace.de>\n# Deploy application\nADD target/javaee-classpath-properties.war /usr/local/glassfish4/glassfish/domains/domain1/autodeploy/" > $WORKSPACE/Dockerfile

    service=$JOB_NAME
    service_port=8080
    docker build -t $service $WORKSPACE
    container_id=$(docker run -d -p $service_port:$service_port $service)

    echo "App running on http://localhost:$service_port/javaee-classpath-properties/"

    Jenkins Docker Build Step

    Ok, let me explain what we’ve just did. We have configured another job which will be started automatically after our build job. The job will only be triggered if the build job was successful. We’ve also configured that the generated war-file from our build job will be copied to the staging job and therefore will be reused. This ensures that we’re using exactly the same file that was compiled and tested during the build job. This is an extremely important concept because we’re now indepent from other commits which have been done during the time the build job was running and eventually are breaking the build.

    The main work which is done in this job is a little bit cryptic, hidden in the Execute shell build step. What it basically does is creating a Dockerfile and then building a new docker image with that Dockerfile.

    While building the docker image it is downloading a glassfish docker container and injects our generated war-file into it. After that the docker container will be started, which means the Glassfish Java EE Application Server will be started and our application will be automatically deployed into the Glassfish. As soon as the docker container is running we can access our application through the browser by opening http://localhost:8080/javaee-classpath-properties/.

    You can now test if everything works by “building” the staging job.

    Putting it all together

    The hard work is done. You can see the results by building the job “javaee-classpath-properties-build” in your jenkins. This will compile the application, run the tests and package the application. When the first job has finished successfully, the second job will be triggered automatically and will fire up a docker container with your application inside.

    After a short time you should have access to your application and can test it in the browser. Note how fast the docker container starts up. On my machine the second job runs at most times under a second. That’s amazingly fast to startup a whole testing environment from the ground.

    Next Steps

    You’ve learned the basics how to build a continuous delivery pipeline with Jenkins and Docker. There is a lot more what can be done from here like configuration management, acceptance tests, service discovery, monitoring and so on.

    But this article should be only a kickstart to develop your own ideas. Any comments or feedback is appreciated.

    Posted in javaee, programming, tutorials | 1 Comment