1 February 2016

Infinispan 8 Tour

Last Wednesday, the 27th of January, C2B2 Consulting, together with Skills Matter CodeNode, once again hosted a London JBoss User Group event.

This time, we explored Infinispan 8, guided by Gustavo Fernandes from Red Hat's Infinispan team.

Infinispan 8 is the first version based on Java 8, and it brings many major features that take full advantage of the novelties introduced by the language, such as Lambdas, Streams and Completable Futures. It also introduces a brand new administration console, along with many query advanced capabilities and integration with the latest data processing tools.
Gustavo's talk showcased Infinispan 8 exciting new features with code samples and demos.

Click the image to see 'Infinispan 8 Tour' video presentation

Join London JBoss User Group on Meetup to make sure you won't miss any of our future events!

29 January 2016

Spring Boot as a Microservice Platform



We are starting to see quite a few customers using or evaluating Spring Boot as a platform for their microservice applications, and as it is a platform we haven't discussed in any detail on this blog, I felt it was about time.

What is Spring Boot?

Spring Boot is a framework that pulls together a number of common application frameworks (mostly the various spring frameworks) for writing enterprise Java code, providing a quick way to write an enterprise application and deploy it as a single executable jar. Key to this single jar deployment is the fact that it can contain an embedded Tomcat (or Jetty) web container so that your jar doesn't need to be deployed into an external container.

Inverted containers

There has  been some talk about how platforms like Spring Boot make application servers or traditional containers irrelevant, and this is very much not the case. What Spring Boot does is take a Java EE 6 Web profile container and package it inside your application jar file, together with code to bootstrap the container, and servlets to call your code when the URL's you specified are requested. The only real change is that you package your container inside your application, rather than deploying your application to the container. Containers are not defined by how applications are deployed to them, but by the services that they provide, such as HTTP request handling, thread management, and component lifecycle management. There is very much still a need for containers to exist and continue to provide these services, although we may see them adapt to be more embeddable frameworks than deployment containers.

The relevance of Spring Boot to microservice architectures.

Spring Boot is an attractive platform for a project based on a microservice architecture for a number of reasons.
  • It includes all the frameworks necessary to rapidly develop RESTful and REST-like services
  • Its simple deployment (just run the jar file) makes it perfect for an architecture where rapid scaling up or down of a service may be required.
  • Being based on the Spring framework, it will already be familiar to many developers.
  • It's lightweight approach is well suited to building small lightweight services that individually have few dependencies.
  • It has good integration with Docker.
These all add up to make it an attractive choice when looking to build a lightweight and tight-scoped service that implements a part of your microservice architecture. There are situations when it is not quite as suitable as using a container with more features, but one of the advantages of a microservice architecture is that not all of your services need to be implemented using the same technologies.

A simple Spring Boot microservice example.

To demonstrate how simple it is to write a microservice with Spring Boot, lets create a complete example. We will build the following structure:


springboot-microservice
                      |
                      |-pom.xml
                      |
                      |-src/main/java
                                    |
                                    |-hello
                                          |
                                          |-Application.java
                                          |-HelloController.java
                                          |-HelloResponse.java




We start with a Maven POM, derived from the example in the Spring Boot get started example.

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>



    <groupId>com.c2b2</groupId>

    <artifactId>springboot-microservice</artifactId>

    <version>0.1.0</version>



    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>1.3.2.RELEASE</version>

    </parent>



    <dependencies>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

<!--        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-jetty</artifactId>

        </dependency> -->

    </dependencies>



    <properties>

        <java.version>1.8</java.version>

    </properties>





    <build>

        <plugins>

            <plugin>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-maven-plugin</artifactId>

            </plugin>

        </plugins>

    </build>



</project>

Our POM defines a single dependency, on the spring-boot-starter-web artifact. Note the commented out dependency on Jetty, uncommenting this will cause Spring Boot to package Jetty as an embedded container within our application, rather than Tomcat (the default). I left this in just to demonstrate how easy it is to switch between the two containers, it is not directly relevant for our example.

Next we need an application class, this class should have a main method, and Spring Boot will detect this and make it the entry point to our application. This class will be configured as the entry point when we execute our packaged jar file.

package hello;



import java.util.Arrays;



import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.ApplicationContext;



@SpringBootApplication

public class Application {

    

    public static void main(String[] args) {

        ApplicationContext ctx = SpringApplication.run(Application.class, args);

    }



}

This class only does one thing, which is bootstrap itself as a Spring application. This will cause the spring bootstrap framework to find our other classes annoted with relevant applications, and make them available.

We also need an HTTP endpoint, we could have this in the main application class, but this makes the example a little contrived, so instead we will have our endpoint in a separate class.

package hello;



import org.springframework.web.bind.annotation.ResponseBody;

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.bind.annotation.RequestMapping;



@RestController

public class HelloController {

    

    @RequestMapping("/")

    @ResponseBody

    public HelloResponse index() {

        HelloResponse response = new HelloResponse();

        response.setWho("Matt");

        response.setWhat("Hello");

        response.setWhere("World");

        return response;

    }





    

}

This class uses the @RestController annotation to define itself as a restful endpoint handler, and the @RequestMapping and @ResponseBody specify that the index() method should handle requests that come to the URL /, and that the return value of the method should be bound as the response body.

Our class constructs a simple POJO as the response, and that pojo is defined below:

package hello;



/**

 * Created by matt on 29/01/16.

 */

public class HelloResponse {

    public String who;

    public String what;

    public String where;



    public String getWhere() {

        return where;

    }



    public void setWhere(String where) {

        this.where = where;

    }



    public String getWho() {

        return who;

    }



    public void setWho(String who) {

        this.who = who;

    }



    public String getWhat() {

        return what;

    }



    public void setWhat(String what) {

        this.what = what;

    }





}

Note that there is nothing in this class except three variables and their getters and setters. We are leaving it completely up to Spring Boot to map that to the response.

We can build this application using the command
$mvn package

This will build a jar file called springboot-microservice-0.1.0.jar in target, which we can execute with:
$java -jar target/springboot-microservice-0.1.0.jar

You will see Spring Boot start up
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.3.2.RELEASE)

2016-01-29 11:11:30.591  INFO 4648 --- [           main] hello.Application                        : Starting Application v0.1.0 on matt-virtual-machine with PID 4648 (/home/matt/springboot/gs-spring-boot/initial/target/springboot-microservice-0.1.0.jar started by matt in /home/matt/springboot/gs-spring-boot/initial)
2016-01-29 11:11:30.595  INFO 4648 --- [           main] hello.Application                        : No active profile set, falling back to default profiles: default
2016-01-29 11:11:30.674  INFO 4648 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@655deae9: startup date [Fri Jan 29 11:11:30 GMT 2016]; root of context hierarchy
.
.
.


You can then open a second command prompt, and send a request to http://localhost:8080/ to see the response come back.

$curl http://localhost:8080/
{"who":"Matt","what":"Hello","where":"World"}

Note that the response comes back as JSON, Spring Boot will automatically determine how to map your response object based on the accepted content types specified in the request.

What about Configuring the container.

One of the key issues with embedding your container inside your application, is that it becomes a bit harder to make configuration changes to the container. The normal way you would configure Tomcat, via editing the server.xml file, is no longer available to you. Some of the properties, such as JVM memory pool sizes and garbage collector settings, you just set on the command line that you use to execute your jar file as you would for any JVM property. Other settings such as the port and address that Tomcat listens on are slightly more complex, but for most of the common properties, Spring Boot gives us a number of approaches. The easiest approach is to include an application.properties file within your application jar file. Spring Boot will find this, and it can be used to configure a large number of commonly used settings in the various frameworks and containers that make up Spring Boot. For example to set the IP address that we want our embedded Tomcat to listen on, we would create an application.properties file, and include the following properties:

server.port=8081

server.address=127.0.0.1

which properties are available in application.properties depends on which frameworks and containers you are using in your Spring Boot application, but a good reference of many of the common ones can be found here:


Conclusion

Hopefully this blog has given you an overview of why people are choosing Spring Boot as a platform for their microservice application, and shown you how simple it is to get started. Despite the simplicity of getting started with Spring Boot, it still needs just as much tuning and configuration as running any other web container or framework. In the next blog in this series, we will look at some of those tuning and configuration options in more detail.



6 January 2016

Chef - Test Kitchen and Docker


In today’s blog I’m going to show you how to create a local Chef development environment that can be used to provision a simple cookbook to a Docker Centos 7 instance based. This environment is based on a VMWare Workstation vm created from a Centos 7 ISO image. 


To install Docker, logon to the newly created vm as root and run the following commands: 

$ sudo yum update

$ cat >/etc/yum.repos.d/docker.repo <<-EOF
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF

$ yum install docker-engine

$ chkconfig docker on

$ service docker start


Create a linux group named docker and add your user to it, this will enable you to run Docker commands without using sudo

$ usermod -aG docker afryer

Install wget and curl packages

$ yum install wget
$ yum install curl-devel

Download the latest ChefDK and install


$ rpm -Uvh chefdk-0.10.0-1.el7.x86_64.rpm

Install the kitchen-docker ruby gem, switch to the user you will use for developing the Chef Cookbook and execute the following:

$ chef gem install kitchen-docker 


 Creating the Application Cookbook

Let’s create a simple application cookbook for a simple webserver configuration that uses the Apache2 cookbook from the Chef Supermarket to install Apache.

Switch to the user that you will use for creating the application cookbook and create the folder ~/chef-repo, this will be used as the local Chef repository for the source files for the application cookbook.
~$ mkdir -p ~/chef-repo

The chef executable is a command-line utility that comes as part of the ChefDk we will use this to generate the Chef Source code for the Application Cookbook.  

Create the c2b2_website application cookbook by executing the following commands:

$ cd ~/chef-repo
$ chef generate app c2b2_website

This generates the following folder structure which includes a top level Test Kitchen instance for testing the cookbook.

/c2b2_website
   /.git   
   /cookbooks      
      /c2b2_website         
         /recipes            
            default.rb         
         /spec            
            /unit               
               /recipes                  
                  default_spec.rb            
            spec_helper.rb         
         Berksfile         
         chefignore         
         metadata.rb   
   /test      
      /integration         
         /default            
            /server_spec               
               default_spec.rb         
            /helpers            
               /server_spec               
                  spec_helper.rb   
   .gitignore   
    README.md   
   .kitchen.yml

Let’s create a new recipe for the application cookbook named intsallapache, this will reference the appropriate recipes in the Apache2 cookbook to install Apache.  

First we need to set up the dependency to this cookbook in the metadata.rb file for the c2b2_website cookbook, add the following to the file ~/chef-repo/c2b2_website/cookbook/c2b2_website/metadata.rb:

depends 'apache2'

Test Kitchen uses Berkshelf for cookbook dependency management, so to run the integration tests we need to create the configuration file in the folder ~/chef-repo/c2b2_website/Berksfile and reference the Apache2 cookbook and the c2b2_website cookbook.  

Create the file ~/chef-repo/c2b2_website/Berksfile and add the following content:

source 'https://supermarket.chef.io'

cookbook 'apache2', '~> 3.1.0'

Dir['/home/username/chef-repo/c2b2_website/cookbooks/**'].each do |path|
  cookbook File.basename(path), path: path
end

The Apache2 cookbook installs Apache as a Linux service, as Docker by default does not run services we need to disable the creation of the service and create a recipe to start Apache.

Fortunately, the default recipe will only create the service if the only_if condition defined in the service resource block succeeds. The only_if condition runs the httpd binary with the -t switch which performs a syntax check on the Apache configuration, where the binary name is defined in the node attribute node[‘apache’][‘binary’].  

We can use this to our advantage by creating an attribute in our cookbook to override the default value set in the Apache2 cookbook, and set the value to ‘httpd -‘.  This will cause the condition to fail, hence preventing Apache from being installed as a service.

Create an attribute file named default using the ‘chef generate attribute’ command:

$ cd ~/chef-repo/c2b2_website
$ chef generate attribute cookbooks/c2b2_website default

add the following content to the file

default['apache']['binary'] = '/usr/sbin/httpd - '

Create a recipe named startapache using the ‘chef generate recipe’ command:

$ cd ~/chef-repo/c2b2_website
$ chef generate recipe cookbooks/c2b2_website startapache

Add the following content to start Apache

execute 'start_apache' do
  command 'httpd -k start'
  user 'root'
  group 'root'
  action :run
end

Create the recipe installapache:

$ cd ~/chef-repo/c2b2_website
$ chef generate recipe cookbooks/c2b2_website installapache

add the following content to include the default recipe from the Apache2 cookbook which installs a basic Apache configuration and the recipe from this cookbook to start Apache: 

include_recipe 'apache2::default'
include_recipe 'c2b2_website::startapache'

Configure Test Kitchen (Docker)

Now let’s configure Test Kitchen to use provision a Docker image based on Centos 7, update the file .kitchen.yml file with the contents below, see for more information https://github.com/spheromak/kitchen-docker/blob/master/README.md:

---
driver:
  name: docker
  binary: docker
  use_sudo: false

provisioner:
  name: chef_solo
  environments_path: environments
  coobooks_path:
    - cookbooks

  ohai:
    disabled_plugins: ["passwd"]

platforms:
  - name: centos-7
    driver_config:
      privileged: true
      memory: 1512m
      volume:
        - /sys/fs/cgroup:/sys/fs/cgroup:ro
      provision_command:
        - echo "root:password" | chpasswd
        - sed -i 's/Defaults    requiretty/#Defaults    requiretty/g' /etc/sudoers
suites:
  - name: default
    run_list:
      - recipe[c2b2_website::installapache]

Test Kitchen


Test Kitchen can be run in different modes of operation are:

Command Description
kitchen create Creates one or more instances configured in the .kitchen.yml file
kitchen converge Converging the vm(s) with the configured Chef policy (cookbooks, roles, environment and data bags)
kitchen destroy Destroys the instance and deletes all information for the instance
kitchen list
List on or more instances and their state (Created, converged, Verified)
kitchen login

kitchen verify
Run the test suite(s) configured in the.kitchen.yml file on one or more instances
kitchen test
Test (destroys, creates, converges, verifies and destroys) one or more instances


If we now run ‘kitchen converge’, a Centos 7 Docker instance is created and Chef Solo used to converge the instance, running the c2b2_website cookbook, installing and starting Apache.  


We can check that Apache is installed and running by logging to the Docker instance and executing ps -ef | grep httpd to check that the process is running:


$ kitchen login
$$$$$$ Running legacy login for 'Docker' Driver
[kitchen@6c610c7ab9ce ~]$ ps -ef | grep httpd
root       512     1  0 17:32 ?        00:00:00 httpd -k start
apache     513   512  0 17:32 ?        00:00:00 httpd -k start
apache     514   512  0 17:32 ?        00:00:00 httpd -k start
apache     515   512  0 17:32 ?        00:00:00 httpd -k start
apache     516   512  0 17:32 ?        00:00:00 httpd -k start
apache     517   512  0 17:32 ?        00:00:00 httpd -k start
apache     518   512  0 17:32 ?        00:00:00 httpd -k start
apache     519   512  0 17:32 ?        00:00:00 httpd -k start
apache     520   512  0 17:32 ?        00:00:00 httpd -k start
apache     521   512  0 17:32 ?        00:00:00 httpd -k start
apache     522   512  0 17:32 ?        00:00:00 httpd -k start
apache     523   512  0 17:32 ?        00:00:00 httpd -k start
apache     524   512  0 17:32 ?        00:00:00 httpd -k start
apache     525   512  0 17:32 ?        00:00:00 httpd -k start
apache     526   512  0 17:32 ?        00:00:00 httpd -k start
apache     527   512  0 17:32 ?        00:00:00 httpd -k start
apache     528   512  0 17:32 ?        00:00:00 httpd -k start
kitchen    559   536  0 17:41 pts/0    00:00:00 grep --color=auto httpd
[kitchen@6c610c7ab9ce ~]$


There you have it, a way to develop and provision Chef cookbooks to Docker instance running in this case Centos 7.  In the next blog I’ll take this a step further and add integration tests to Test Kitchen to validate the Apache installation.