Autor: Christoph Moser

  • Ansible in a Nutshell

    With Ansible you can configure (aka provision) remote machines by using a simple text file. It uses so-called Playbooks to execute a set of commands on the remote machine. So instead of having a dedicated person executing a set of commands on each machine, with Ansible, this configuration can be collaboratively worked-on, reviewed, versioned and reused. You do not need to update a documentation for setting up your environment elsewhere, as the Playbook is the documentation.

    There are other configuration-tools than Ansible, such as Chef or Puppet. Ansible does not require an agent running on the machines it configures. It only needs an ssh-access to the remote machines. In addition, the remote-machines need to have Python running.

    Prerequisites

    In this tutorial, we will configure one of the two machines, we set-up in the previous tutorial. In the tutorial, we copied the public keys of our local machine to the authorized_keys of the remote machines. Hence our local machine is allowed to access the remote machines using ssh – in my case

    ssh vagrant@127.0.0.1 -p2200

    ssh vagrant@127.0.0.1 -p2222

    (or any other user-name and IP-address and port to establish an ssh-connection to your machines)

    Next, install Ansible on your machine (please consult the Installation Guide). I installed Ansible globally using

    sudo python get-pip.py
    sudo pip install ansible
    
    As a prerequisite, you need to install python before. I used brew
    brew install python

    Subsequently, introduce the remote machines to ansible to adding them to /etc/ansible/hosts (aka Inventory in Ansible terminology). If you can’t find your inventory, please have a look here.

    web1 ansible_host=127.0.0.1 ansible_user=vagrant ansible_port=2200
    web2 ansible_host=127.0.0.1 ansible_user=vagrant ansible_port=2222

    You can also use the YAML-notation:

    all:
      hosts:
        web1:
          ansible_host: 127.0.0.1
          ansible_port: 2200
          ansible_user: vagrant
        web2:
          ansible_host: 127.0.0.1
          ansible_port: 2222
          ansible_user: vagrant
    
    

    I had some problems when tabs and spaces for indention are mixed in the configuration. I used spaces instead and it works fine.  Please refer to the Ansible Documentation for more details on the Inventory.

    To see if everything works correctly let us ping the remote machines using Ansible

    ansible all -m ping or ansible all -m ping -u [user-name]

    If everything runs correctly, you should see something like

    web2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
    }
    web1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
    }

    You can now execute commands on the remote machine, e.g.

    ansible all -a "/bin/echo hello”

    As a result, you should see something like

    web2 | SUCCESS | rc=0 >>
    hello
    
    web1 | SUCCESS | rc=0 >>
    hello

    Playbooks

    As mentioned above, Ansible Playbooks are simple text-files in a YAML-syntax. A Playbook contains how a remote-machine should be configured (provisioned).

    • A Playbook consists of one or more Plays.
    • Each Play contains a set of Tasks that are executed on the remote machine.
    • Each task calls an Ansible Module (command). There are simple modules (tasks) to copy files from one location to another or to install software on the remote machine etc. I will focus on a simple set of commands to configure a Jenkins on one remote machine and … on the others. For more on tasks (modules) please refer to the Ansible documentation.

    You can easily set-up Jenkins using predefined Ansible Roles. I will come to this later. Here, I want to explain the basic structure of a Playbook (jenkins.yml). I will go to the different parts of the example in the next chapters.

    - name: Install Jenkins
      hosts: web1, web2
      gather_facts: true
      become: yes
      become_method: sudo
      vars:
        jenkins_port: 8080
    
      tasks:
    
        - name: Populate Service facts
          service_facts:
    
        - debug:
          # var: ansible_facts.services
    
        - name: Stop Jenkins Service
          service:
            name: jenkins
            state: stopped
          when: "'jenkins' in ansible_facts.services"
    
        - name: Clean-Up previous installation
          package:
            name: '{{ item }}'
            state: absent
          loop:
            - jenkins
            - openjdk-8-jdk
            - git
            - wget
    
        - name: Install dependencies
          package:
            name: '{{ item }}'
            state: latest
          loop:
            - openjdk-8-jdk
            - git
            - wget
    
        - name: Download jenkins repo
          apt_repository:
            repo: deb https://pkg.jenkins.io/debian-stable binary/
            state: present
    
        - name: Import Jenkins CI key
          apt_key:
            url: https://pkg.jenkins.io/debian/jenkins-ci.org.key
    
        - name: Update apt packages
          apt:
            upgrade: yes
            update_cache: yes
    
        - name: Install Jenkins
          apt:
            name: jenkins
            state: present
            allow_unauthenticated: yes
    
        - name: Allow port {{jenkins_port}}
          shell: iptables -I INPUT -p tcp --dport {{jenkins_port}} -m state --state NEW,ESTABLISHED -j ACCEPT
    
        - name: Start the server
          service:
            name: jenkins
            state: started
    
        - name: Waiting for Service to start
          wait_for:
            port: 8080
    
    

    Basic Configuration

    - name: Install Jenkins software
      hosts: web1, web2

    All Plays in Ansible can start with a minus (), often followed by a name-parameter (optional) or an Ansible Module (command). The name-parameter shows in the log which play is currently executed. So I recommend it for debugging, but also for documentation.

    The hosts-parameter defines on which hosts in Inventory the Playbook should be executed (in this case web1). You can also add the remote-user that runs the modules in the playbook be specifying the remote_user-parameter (e.g. remote_user: root).

    You can execute the whole playbook or specific commands (like the ones below) as a specific user. In this case use become_method or become_user. In this example, we will install Jenkins as superuser.

    become: yes
    become_method: sudo

    The next part of the Playbook are the tasks that will be executed on the remote machines.

    Installation of prerequisite packages

    To run Jenkins with the desired configuration, we need Java 8 and git on the machine, as well as wget to load the Jenkins packages. We will use the Ansible module Package as a generic package manager. In addition, I will introduce the concept of standard loops.

    - name: Install dependencies
          package:
            name: '{{ item }}'
            state: latest
          loop:
            - openjdk-8-jdk
            - git
            - wget

    The Package module uses two mandatory parameters

    • the name defines the name or the name and version of the package
    • the state defines if the packages should be installed or removed or the state of the underlying package module (here apt)

    The parameter name gets the value '{{ item }}'. The curly braces tell Ansible that is get the values from the next loop block.  Here we will put the names of the packages to install. For more on loops, please consult the documentation.

    Installation of Jenkins

    The basic package manager we used above, won’t offer enough flexibility. Hence, as we will be installing Jenkins on a Debian environment, we will use the Module for the Debian package manager APT (Advanced Package Tool).

    The package information for Jenkins can be found in the corresponding Debian Repository for Jenkins.

    - name: Download jenkins repo
      apt_repository: 
         repo: deb https://pkg.jenkins.io/debian-stable binary/
         state: present

    The Ansible Module apt_repository adds an APT repository in Debian. We add the latest stable Debian Repository for Jenkins.

    - name: Import Jenkins CI key 
      apt_key:
         url: https://pkg.jenkins.io/debian/jenkins-ci.org.key

    To be able to use the repository, we need to add the corresponding key. We use the Ansible Module apt_key.

    - name: Update apt packages
      apt:
        upgrade: yes
        update_cache: yes

    Before you install Jenkins, you might want to update the package lists (for upgrades or new packages).

    - name: Install Jenkins
      apt:
         name: jenkins
         state: present

    Now we can finally download and install the Debian Jenkins package using the Ansible Module apt.

    Configuration the Network

    By default, the Jenkins web interface listens on port 8080. This port has to be accessible from outside the Virtual Machine. Hence, we add a new rule to our iptables by executing a simple shell command.

    - name: Allow port 8080
      shell: iptables -I INPUT -p tcp --dport 8080 -m state --state NEW,ESTABLISHED -j ACCEPT

    Starting the Service

    Finally, we need to start the Jenkins service. Here we can simply use the generic Ansible Module service.

    - name: Start the Service 
      service:
         name: jenkins
         state: started

    Waiting for the Service to run

    The Ansible Module wait_for waits for a condition to continue with the Playbook. In this simple case, we wait for the port to become available.

    - name: Waiting for Jenkins to become available
      wait_for:
         port: 8080

    Idempotency

    Playbooks should be idempotent, i.e. each execution of a Playbook should have the same effect, no matter how often it is executed. Ansible (of course) if not able to verify idempotency, hence you are responsible, e.g. for checking if a task has already been executed. I this example, I will clean-up the packages I want to install first.

    I make use of the ansible_facts.services that contains state information of services on the remote machine. However, I have to populate this variable first by calling the Ansible Module service_facts.

    - name: Populate Service facts
       service_facts:

    To see the contents of services in service_facts use

    - debug:
       var: ansible_facts.services

    Conditionals

    I will shortly introduce conditionals in Ansible, using the when-statement.

    - name: Stop Jenkins Service
      service:
        name: jenkins
        state: stopped
      when: "'jenkins' in ansible_facts.services"

    Basically, I only execute a command (Ansible module) if the when-condition is true.

    In this case, I only stop the service called jenkins, when I can find the service named jenkins in the ansible_facts.services variable (so the service is up and running). Of course, there are different ways to do this – I found this the most elegant.

    Removing previously installed packages

    I clean-up I will further un-install previously installed packages, as I will cleanly install them again below. I use this with caution, as it might not necessarily work, as the Linux distribution might have installed some of the packages using different package managers.

    - name: Clean-Up previous installation
       package:
         name: '{{ item }}'
         state: absent
       loop:
         - jenkins
         - openjdk-8-jdk
         - git
         - wget

    Remarks about Idempotency

    The example above can lead to problems if you use other Ansible Playbooks (or other configuration management tools) on the same machine, or configure the machine manually. Hence, I recommend, only using a single source of truth (way) to configure your remote machine.

    Variables

    As mentioned above, you make use of conditions in your Playbook. These conditions are often based on the state of variables in Ansible. The following command will list the system variables you can use, such as the Unix distribution and version, network configurations, public keys etc.)

    ansible [server-name] -m setup, e.g. ansible web1 -m setup

    You can also define your own variables in a Playbook

    vars:
        jenkins_port: 8080

    and access them using the {{}} notation, I mentioned above (for loops)

    - name: Allow port {{jenkins_port}}
      shell: iptables -I INPUT -p tcp --dport {{jenkins_port}} -m state --state NEW,ESTABLISHED -j ACCEPT

    For more on variables, please consult the Ansible documentation.

    Running the Playbook

    Once you created the Playbook, you can check it with

    ansible-playbook --syntax-check jenkins.yml

    To find out which servers are affected by the Playbook use

    To find out, which hosts are affected by a Playbook, use

    ansible-playbook jenkins.yml --list-hosts

    If everything is correct, you can run the Playbook with

    ansible-playbook jenkins.yml

    For a more detailed output, use

    ansible-playbook jenkins.yml --verbose

    If you want to run several threads use (10 Threads). This is useful to simultaneously run configurations on many different machines, without having to wait for commands to finish on one machine.

    ansible-playbook playbook.yml -f 10

    You can also limit the subset of servers, on which the Playbook should be executed (the name of the servers have to be included in the hosts-parameter of the Playbook.

    ansible-playbook -l web2 jenkins.yml

    Please consult the Ansible documentation for more information on how to use ansible-playbook.

    Execution Order

    Each Task has a name, e.g. “Install Jenkins software”, “Update Software Package Repository” etc. The names are shown when you run a Playbook (especially for debugging purposes).

    The tasks in a Playbook are executed in the following order:

    • Task 1 on Machine 1
    • Task 1 on Machine 2

    If one task can’t be executed on a remote machine, the whole Playbook will be excluded from further execution on this machine. This will not affect the other machines.

    Calling Jenkins

    So now you should be able to call Jenkins in your web browser, using the IP address of the remote machine. You will find the address if you open a secure shell to your machine (in my case ssh vagrant@127.0.0.1 -p2200). You can obtain the IP address by executing ifconfig. In my case, I can access Jenkins calling http://172.28.128.9:8080/ in a web-browser. The rest should be straight-forward.

    You can retrieve the initial admin password for Jenkins by logging into the Jenkins server

    sudo cat /var/lib/jenkins/secrets/initialAdminPassword

    On a side-note – if you don’t always want to type in your ssh password with every login you can store it in the SSH authentication agent.

    ssh-add ~/.ssh/id_rsa

    Configuring Jenkins

    When you search for Jenkins in the Ansible documentation you will find some Ansible Modules that can be used to configure Jenkins. The modules use the Jenkins Remote Access API), so you will configure Jenkins after it is up and running.

    Miscellaneous

    Ansible Roles

    One strength that will become useful is the use of so-called Ansible Roles. I would define a Role as a reusable set of Playbooks. For example, people already wrote re-usable Ansible Roles to install and configure Jenkins on a host (in a more extensible way I used in this example). I will use Ansibles Roles in a blog-post to follow.

    Handlers

    Another interesting concept are Ansible Handlers, i.e. if a state changes, a set of tasks can be performed, e.g. if a configuration has changed within an Ansible Playbook, a service is being restarted. Using handlers is a good practice to ensure idempotency.

    Tags

    Tags are markers on Plays or Tasks that can be explicity executed or omitted when running an Ansible Playbook. I can tag the parts of our Playbook that do the clean-up:

    - name: Populate Service facts
         service_facts:
         tags:
           cleanup
    
    - name: Stop Jenkins Service
         service:
           name: jenkins
           state: stopped
         when: "'jenkins' in ansible_facts.services"
         tags: 
           cleanup
    
    - name: Clean-Up previous installation
         package:
           name: '{{ item }}'
           state: absent
         loop:
           - jenkins
           - openjdk-8-jdk
           - git
           - wget
         tags: 
           cleanup
    

    If I only want to call the Ansible Plays tagged with cleanup, I run the Playbook with

    ansible-playbook jenkins.yml --tags cleanup
    

    In contrast, if I want to skip the Ansible Plays tagged with cleanup, I run the Playbook with

    ansible-playbook jenkins.yml --skip-tags cleanup

    Further Remarks

    If you have configured systems by executing a set of commands by hand you might have noticed that it can be a tedious work. Especially if you are not familiar with the command shell or Unix In general, you might run into a lot of trial-and-error that leave the system in an inconsistent and possibly insecure state.

    Of course, editing and testing a configuration in an Ansible Playbook can also be time-consuming and frustrating. However, by using a Playbook, you have a documented way of how you configured your system. An Ansible Playbook can be written in collaboration with others, it can be reviewed by others and serves as a documentation. In addition, Ansible Playbooks are re-usable. This means I can use a Playbook to configure several environments.

    Hence, I highly recommend Ansible or similar tools for configuration (provisioning), such as Chef, SaltStack, Puppet or other configuration management tools.

  • Vagrant in a Nutshell

    Vagrant is a command-line tool to create virtual environments using a scripting language, i.e. with Vagrant you can create and configure virtual machines by using a text editor. The use of a text-file for configuration makes it easy to document the configuration, to work in collaboration and to store the configuration in a version control system. Vagrant makes it easy for developers to simulate a production environment on their local development machines.

    Vagrant supports different providers out-of-the-box, such as VirtualBox and Hyper-V, others, such as VMWare, Docker, Google Cloud Platform or Amazon Webservices via plugins.

    In this short tutorial, we will create a script to set-up two virtual machines, each with a different configuration to run them in a Virtual Box. We will later configure these two machines using Ansible to set-up a Jenkins server and an Integration environment.

    Prerequisites

    Before we start, please install VirtualBox on your local machine. If you encounter any problems during installation on a Mac you might consult this article. Subsequently, create a folder for the Vagrant configuration (I created a folder in/vagrant my home directory). Install Vagrant (on my Mac I use brew cask install vagrant).

    Setting Up a simple Virtual Machine

    The file that contains the configuration is named Vagrantfile. Use a text editor to create a Vagrantfile with the following content:

    Vagrant.configure("2") do |config|
        config.vm.define "server1" do |web|
            web.vm.box = "ubuntu/xenial64"
        end
    end
    

    The (“2”) is the Vagrant version (the current version number is 2). The name encapsulated by the vertical lines is the name of the configuration (here “config”).

    web.vm.box = "ubuntu/xenial64" defines the so-called box that we want to install on our Virtual Machine (VirtualBox), in our case a basic Ubuntu Linux. A box is basically a package format for the different environments (from different Linux distributions to fully provisioned environments, e.g. Jenkins or ELK stack). You will find these boxes in the Vagrant Cloud.

    To install and run the VirtualBox, use

    vagrant up

    in the command line in the directory that contains the Vagrantfile. Usually, when you run a vagrant-command, Vagrant will climb up the directory tree and runs the first Vagrantfile it finds.

    It can take a couple of minutes for the box (ubuntu/xenial64) to be downloaded, set-up and run. Voilà, now you should have an Ubuntu Linux in VirtualBox up and running. The virtual machine configuration is located in .vagrant in your /vagrant.

    Vagrant Virtual Box
    Vagrant VirtualBox

    To see if your Virtual Box was created either open VirtualBox or by using

    vagrant status
    Current machine states:
    
    server1                   running (virtualbox)
    
    The VM is running. To stop this VM, you can run `vagrant halt` to
    shut it down forcefully, or you can run `vagrant suspend` to simply
    suspend the virtual machine. In either case, to restart it again,
    simply run `vagrant up`.

    To access the Virtual Machine use

    vagrant ssh

    To stop your VirtualBox, use

    vagrant halt

    Other command line instructions you will use are

    • vagrant destroy – to stop and delete the Virtual Machine
    • vagrant reload – to restart the environment and applying the settings in the Vagrantfile again, without destroying the Virtual Machine.
    • vagrant provision – executes the provision part in the Vagrantfile (to re-configure the environment)
    Vagrant State Diagram
    Vagrant State Diagram

    For more on Vagrant commands use vagrant --help or consult the documentation.

    The Vagrantfile

    Now we will use a Vagrantfile to create two Virtual Machines that we will later use to install Jenkins and SonarQube. I will first provide the Vagrantfile and go into more detail below.

    Vagrant.configure("2") do |config|
        config.vm.define "server1" do |web|
            web.vm.provider "virtualbox" do |vb|
               vb.memory = "2048"
               vb.cpus = "1"
            end
            web.vm.box = "ubuntu/xenial64"
            web.vm.hostname = "server1"
    
            web.vm.network "private_network", type: "dhcp"
    
            web.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "~/.ssh/authorized_keys"
            web.vm.provision "shell", inline: "which python || sudo apt -y install python"
    
        end
    
        config.vm.define "server2" do |web|
            web.vm.provider "virtualbox" do |vb|
               vb.memory = "2048"
               vb.cpus = "2"
            end
            web.vm.box = "ubuntu/xenial64"
            web.vm.hostname = "server2"
    
            web.vm.network "private_network", type: "dhcp"
    
            web.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "~/.ssh/authorized_keys"
            web.vm.provision "shell", inline: "which python || sudo apt -y install python"
    
        end
    
    end
    

    To install and run the two Virtual Machines, use

    vagrant up

    Using vagrant status you should now see something like this

    Current machine states:
    
    server1                   running (virtualbox)
    server2                   running (virtualbox)
    
    This environment represents multiple VMs. The VMs are all listed
    above with their current state. For more information about a specific
    VM, run `vagrant status NAME`.

    Instead of using vagrant ssh you should now be able to log into your newly created Virtual Machines using their IP-address and ports (vagrant is the default-user). I configured the Virtual Machines to retrieve the IP addresses via DHCP. You can obtain the ssh-information with

    vagrant ssh-config [server-name], e.g. vagrant ssh-config server1

    You should retrieve an output such as

    Host server1
      HostName 127.0.0.1
      User vagrant
      Port 2222
      UserKnownHostsFile /dev/null
      StrictHostKeyChecking no
      PasswordAuthentication no
      IdentityFile /Users/vividbreeze/vagrant/.vagrant/machines/server1/virtualbox/private_key
      IdentitiesOnly yes
      LogLevel FATAL

    Now you can log into server1 using (server2 respectively)

    ssh vagrant@127.0.0.1 -p2222

    The vagrant-user has sudo privileges by default. If you want to switch to the root user, simply use

    sudo su

    You can set/change the root-user password with

    sudo passwd root

    Provider Configuration

    We can configure our provider (VirtualBox) with specific parameters, in this case, the memory and the number of CPUs. More on the configuration of the different providers can be found in the Vagrant documentation.

    web.vm.provider "virtualbox" do |vb|
       vb.memory = "1024"
       vb.cpus = "1"
    end

    Network Settings

    In the example, I let the DCHP server assign an IP in the private network (not accessible from the Internet) to the Virtual Machine:

    config.vm.network "private_network", type: "dhcp"

    You can also assign static IP to the Virtual Machine using

    web.vm.network "private_network", ip: "192.168.33.11"
    

    In addition, you can define a public network, so your machine will be accessible from outside the host machine

    web.vm.network "public_network"

    If you have more than one network (which is often the case), you will be prompted to select a network after running vagrant up. You specify the network using (you need to provide the full name

    web.vm.network "public_network", bridge: "en0: Wi-Fi (AirPort)"

    Some providers, such as VirtualBox, can be run in a closed environment that is not accessible from the machine it is running on. Port Forwarding enables you to create rules to forward traffic from the host machine to the VirtualMachine.

    web.vm.network "forwarded_port", guest: 80, host: 8080

    For more about Network configuration, please consult the Vagrant documentation.

    Provisioning

    Provisioning means to configure the environments via shell scripts or configuration management tools such as Chef or Ansible. We will only do a basic configuration here. As I will use Ansible for provisioning the machine, Python has to be installed.

    web.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "~/.ssh/authorized_keys"
    web.vm.provision "shell", inline: "which python || sudo apt -y install python"
    

    You can also call other provisioning tools, such as Ansible Playbooks directly from the Vagrantfile.

    web.vm.provision "ansible" do |ansible|
       ansible.playbook = "playbook.yml"
    end

    SSH

    Most of the Vagrant boxes come with two users – root and vagrant (password: vagrant). You can log into a box by using vagrant ssh [machine-name]. You can omit this when overwriting the ~/.ssh/authorized_keys file with a new file that includes the public key of your host machine. You then can log into the machine with ssh vagrant@[machine-url] -p [port].

    web.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "~/.ssh/authorized_keys"
    

    Shared Folders

    Although not used in the example, you are able to share files between your Virtual Machine and your local environment.

    web.vm.synced_folder "./sync_folder", "/vagrant", create: true

    This allows you e.g. to store the configuration on your local machine to easily and quickly reconfigure the software running on your remote machines without connection the server via ssh.

    Further Remarks

    Vagrant is an easy way to design simple infrastructure as code, mainly used in development environments, e.g. you cannot design a large infrastructure with several components spanning different networks. In the latter case, I recommend using Terraform or Apache Mesos.

    I use Vagrant mainly for testing changes of a configuration before I roll it out in production, e.g. I use a local Jenkins VM, running with the same (virtual) hardware configuration as in production on my local machine. Hence, I test changes of the build pipeline or the configuration of plugins locally before rolling them out on the production system. I also use it for testing new software before I role it out in production.

    Tools that are in a way similar to Vagrant (for setting up infrastructure as code for a development environment) are Nanobox or Docker.

    Of course, this was only a short tutorial that should provide you with the basics to set-up a virtual machine in Vagrant. For further reading, I recommend the Vagrant Documentation.

    Links

  • Inversion of Control – Part III – Dependency Injection in Java Spring II (Example)

    I will continue with using the AlertService from part 2 of the series, to show how to utilise Dependency Injection in Spring with a more common situation. Let us start with the MessageServices and bring them under control of the BeanFactory in Spring by annotating them as a Component.

    @Component
    public class EmailMessageService implements MessageService {
        ...
    }
    
    @Component
    public class SlackMessageService implements MessageService {
        ...
    }
    

    One of these Components is the DiscFullAlertService bean. We will inject the dependency to a MessageService Bean via constructor injection.

    package com.vividbreeze.designpattern.spring.di;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Component;
    
    @Component
    public class DiscFullAlertService extends AlertService {
    
        public static final String ALERT_TOPIC = "Alert on disk /gdalogs1 almost full.";
        public static final String ALERT_MESSAGE = "disk /gdalogs1 has reached 90% of its capacity.";
    
        @Autowired
        public DiscFullAlertService(MessageService messageService) {
            super (messageService);
        }
    
        @Override
        public void processAlert(String receiver) {
            messageService.sendMessage(ALERT_TOPIC, ALERT_MESSAGE, receiver);
        }
    }
    

    Let us now run the application

    @ComponentScan
    public class FireAlert {
    
        public static void main (String args[]) {
    
            String receiver = "ops@vividbreeze.com";
    
            ApplicationContext context =
                    new AnnotationConfigApplicationContext(FireAlert.class);
    
            AlertService alertService = context.getBean(DiscFullAlertService.class);
            alertService.processAlert(receiver);
        }
    }
    

    It looks like we might run into problems here, as we want to inject a MessageService (the abstract super-class), but there are two beans that implement the MessageService: EmailMessageService and SlackMessageService. You might find the following message in the console:

    ... nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.vividbreeze.designpattern.spring.di.MessageService' available: expected single matching bean but found 2: emailMessageService,slackMessageService
    

     

    Configurations

    So the BeanFactory is confused which implementation to inject into the DiscFullAlertService. One solution would be to configure the BeanFactory so that it knows which implementation to choose. In this configuration, you are able to instantiate and register a Bean with the BeanFactory, so it later can be injected.

    package com.vividbreeze.designpattern.spring.di;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan
    public class AlertConfiguration {
    
        @Bean
        public MessageService messageService() {
            return new EmailMessageService();
        }
    }
    

    The class is annotated as a class that contains the configuration (@Configuration). The configuration is implemented in form of beans (or optionally an XML-file). The bean-name is the name of the method that is annotated with @Bean (messageService, not getMessageService). This method returns the instance of the bean that is then registered with the BeanFactory. After the initialisation, a ComponentScan is performed. So when it reaches

    @Autowired
    public DiscFullAlertService(MessageService messageService) {
        super (messageService);
    }
    

    it the BeanFactory already has a registered Bean „messageService“ and injects it in the messageService attribute of DiscFullAlertService. Notice that in our main-method, we pass the Configuration class when we initialise the ApplicationContext and we don’t perform a ComponentScan here.

    public class FireAlert {
    
        public static void main (String args[]) {
    
            String receiver = "ops@vividbreeze.com";
    
            ApplicationContext context =
                    new AnnotationConfigApplicationContext(AlertConfiguration.class);
    
            AlertService alertService = context.getBean(DiscFullAlertService.class);
            alertService.processAlert(receiver);
        }
    }

    The reason why I included the ComponentScan in the Configuration class will become more obvious when we work with a different Configuration for unit-tests. As mentioned in the previous blog-post where we might not be able to send e-mails or Slack-messages from our local computers. Thus we can use a MockMessageService that just logs the message to the console.

    @Component
    public class MockMessageService implements MessageService {
    
        private static final Logger LOG = LoggerFactory.getLogger(MockMessageService.class);
    
        @Override
        public void sendMessage(String subject, String message, String receiver) {
            LOG.debug("MockMessageService - subject: " + subject + ", receiver: " + receiver + ", message: " + message);
        }
    }
    

    The instance of this class will also be annotated as a component so we can access it later via context.getBean(). The configuration will then look like this

    @Configuration
    @ComponentScan
    public class AlertTestConfiguration {
    
        //@Bean
        public MessageService messageService() {
            return new MockMessageService();
        }
    }
    

    The unit test can now look like this

    public class FireAlertTest {
    
        private static final Logger LOG = LoggerFactory.getLogger(FireAlertTest.class);
    
        ApplicationContext context = new AnnotationConfigApplicationContext(AlertTestConfiguration.class);
    
        @Test
        public void sendAlertMessage() {
    
            AlertService alertService = context.getBean(DiscFullAlertService.class);
            alertService.processAlert("vividbreeze");
        }
    }
    

    Debugging

    The dependencies are resolved during run-time. If you have many beans with lots of dependencies your application might become more prone to errors. You can see which beans are initialised under which name during start-up (when the ApplicationContext is instantiated and initialised). This log message might be a bit confusing. You can also list all beans that are registered with the BeanFactory using the following snippet

    ApplicationContext context =
            new AnnotationConfigApplicationContext(FireAlert.class);
    
    String[] beanNames = context.getBeanDefinitionNames();
    for (String beanname: beanNames) {
        LOG.debug(">>> " + beanname + " - " + context.getBean(beanname).toString());
    }

    Remarks

    This example should give an overview of how to use the Spring Framework in a simple real-life situation. I highly recommend to consult other tutorials and to experiment with small sample applications to gain a better understanding of Dependency Injection in Spring.

     

     

  • Inversion of Control – Part III – Dependency Injection in Java Spring I

    As I explained in the blog post about Inversion of Control, your code can be controlled not only by implementing an IoC Design Pattern within your code, by a framework that controls (part of) your code, but also by an entity, that you don’t have direct control over, such as a Servlet Container that controls your code in a certain behaviour. Java Spring is a framework that takes control over part of your code. One of the key features of Spring is an extensive use of Dependency Injection.

    Components in Spring

    Firstly, Spring manages your beans; in this case, instances of Java classes. You can tell Spring which instances of classes should be controlled by Spring by either using annotations or XML-configuration files. In this introduction, I will solely focus on annotations, to not cause too much confusion. I will focus on XML-configuration in a later blog post.

    Alle components that Spring should take control of, have to be annotated. The most basic annotation is @Component on a class level.

    package com.vividbreeze.spring;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class FormalGreeting {
        public void sayHello() {
            System.out.println("Good day, Madam or Sir. How may I assist you?");
        }
    }
    

    Spring now needs to know that it should take control of this bean. Spring does this by a so-called ComponentScan

    package com.vividbreeze.spring;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.ComponentScan;
    
    @ComponentScan
    public class GreetingExample {
    
        public static void main (String args[]) {
    
            ApplicationContext context =
                    new AnnotationConfigApplicationContext(GreetingExample.class);
    
            context.getBean(FormalGreeting.class).sayHello();
        }
    }
    

    Spring scans all classes in the package com.vividbreeze.spring (and its sub-packages by default) that are annotated with (@Component). These classes (beans) are then instantiated and controlled by the BeanFactory. This BeanFactory can be accessed via the ApplicationContext. The ApplicationContext is bound to the class that is annotated with @ComponentScan. Notice, that the component scan is performed, not until the ApplicationContext is created (new ApplicationConfigApplicationContext(…)).

    You can access a bean under Spring with context.getBean (bean-name). By default, beans are singletons, i.e. only one shared instance of a bean will be managed by Spring. The other option would be non-singleton, i.e. everytime you access a bean with getBean (...) a new instance will be created. The BeanFactory stores beans either by the class-name or a separate bean-name, that you pass as an attribute to the Component annotation.

    @Component ("commonGreeting")
    public class FormalGreeting implements Greeting {
        public void sayHello() {
            System.out.println("Good day, Madam or Sir. How may I assist you?");
        }
    }
    
    @ComponentScan
    public class GreetingExample {
    
        public static void main (String args[]) {
    
            ApplicationContext context =
                    new AnnotationConfigApplicationContext(GreetingExample.class);
    
            ((FormalGreeting)context.getBean("commonGreeting")).sayHello();
        }
    }
    

     

    Dependency Injection in Spring (autowiring)

    This might only seem of a minor benefit so far. The real advantage of Spring is the so-called auto-wiring, where instances of beans are injected into other beans. You can either inject dependencies on an attribute level (as shown above) or on a setter or on the constructor.

    Attribute Level Dependency Injection

    package com.vividbreeze.spring;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class GreetingProcessor {
    
        @Autowired
        private FormalGreeting greeting;
    
        public void process() {
            greeting.sayHello();
        }
    }
    

    When Spring scans the classes annotated with @Component, the BeanFactory will instantiate GreetingProcessor and FormalGreeting. It will then see that GreetingProcessor contains an @Autowired attribute of type FormalGreeting. The BeanFactory finds a bean with the name „FormalGreeting“ and wires it to greeting in the GreetingProcessor Bean.

    So far this is an advantage, as you don’t have to worry about instantiating (and managing) dependencies anymore.

    Setter Dependency Injection

    When you use setter injection during runtime you might notice that the bean was not injected and is null. You can avoid this by annotating the setter with @Required.

    package com.vividbreeze.spring;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class GreetingProcessor {
    
        private FormalGreeting greeting;
    
        @Autowired
        public void setFormalGreeting(FormalGreeting greeting) {
            this.greeting = greeting;
        }
    
        public void process() {
            greeting.sayHello();
        }
    }

    Class Dependency Injection

    package com.vividbreeze.spring;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class GreetingProcessor {
    
        private FormalGreeting greeting;
    
        @Autowired
        public GreetingProcessor (FormalGreeting greeting) {
            this.greeting = greeting;
        }
    
        public void process() {
            greeting.sayHello();
        }
    }

    Circular Dependencies

    We might have dependencies like this: Bean A is instantiated with Bean B, which in turn is instantiated with Bean C. In this case, Spring creates bean C first, then Bean B and injects Bean C into it, then it will create bean A and injects bean B into it.

    There might be some situations where the dependencies are circular, i.e. bean A is instantiated with bean B that, in turn, instantiate with bean A.

    @Component
    public class ComponentA {
    
        private ComponentB componentB;
    
        @Autowired
        private ComponentA (ComponentB componentB) {
            this.componentB = componentB;
        }
    }
    
    @Component
    public class ComponentB {
    
        private ComponentA componentA;
    
        @Autowired
        private ComponentB(ComponentA componentA) {
            this.componentA = componentA;
        }
    }
    
    @ComponentScan
    public class CircularComponentExample {
        public static void main (String args[]) {
    
            ApplicationContext context =
                    new AnnotationConfigApplicationContext(CircularComponentExample.class);
    
            context.getBean(ComponentA.class);
        }
    }
    

    In the console, you will see something like this

    Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'componentA': Requested bean is currently in creation: Is there an unresolvable circular reference?
    

    It might seem like a far-fetched example, however, in reality, this happens once in a while especially if you have complex nested dependencies between objects. How can you solve the problem? Simply, try to solve circular dependencies by breaking them up or use attribute or setter-injection, as here the injections are fully resolved when the attribute is used the first time. In the next example, the componentA bean is created upon request when calling context.getBean (ComponentA.class). Alternatively, you can use setter-injection.

    @Component
    public class ComponentA {
    
        @Autowired
        private ComponentB componentB;
    
        private ComponentA () {
            //
        }
    }
    @Component
    public class ComponentB {
    
        @Autowired
        private ComponentA componentA;
    
        private ComponentB() {
        }
    }

    In the console, you can see how Spring is now handling the situation

    08:10:32.536 [main] DEBUG ...DefaultListableBeanFactory - Eagerly caching bean 'org.springframework.context.event.internalEventListenerFactory' to allow for resolving potential circular references
    08:10:32.539 [main] DEBUG ...DefaultListableBeanFactory - Finished creating instance of bean 'org.springframework.context.event.internalEventListenerFactory'
    08:10:32.539 [main] DEBUG ...DefaultListableBeanFactory - Creating shared instance of singleton bean 'circularComponentExample'
    08:10:32.539 [main] DEBUG ...DefaultListableBeanFactory - Creating instance of bean 'circularComponentExample'
    08:10:32.539 [main] DEBUG ...DefaultListableBeanFactory - Eagerly caching bean 'circularComponentExample' to allow for resolving potential circular references
    08:10:32.541 [main] DEBUG ...DefaultListableBeanFactory - Finished creating instance of bean 'circularComponentExample'
    08:10:32.541 [main] DEBUG ...DefaultListableBeanFactory - Creating shared instance of singleton bean 'componentA'
    08:10:32.541 [main] DEBUG ...DefaultListableBeanFactory - Creating instance of bean 'componentA'
    08:10:32.545 [main] DEBUG ...InjectionMetadata - Registered injected element on class [com.vividbreeze.spring.ComponentA]: AutowiredFieldElement for private com.vividbreeze.spring.ComponentB com.vividbreeze.spring.ComponentA.componentB
    08:10:32.545 [main] DEBUG ...DefaultListableBeanFactory - Eagerly caching bean 'componentA' to allow for resolving potential circular references
    08:10:32.547 [main] DEBUG ...InjectionMetadata - Processing injected element of bean 'componentA': AutowiredFieldElement for private com.vividbreeze.spring.ComponentB com.vividbreeze.spring.ComponentA.componentB
    08:10:32.548 [main] DEBUG org.springframework.core.annotation.AnnotationUtils - Failed to meta-introspect annotation interface ...Autowired: java.lang.NullPointerException
    08:10:32.552 [main] DEBUG ...DefaultListableBeanFactory - Creating shared instance of singleton bean 'componentB'
    08:10:32.552 [main] DEBUG ...DefaultListableBeanFactory - Creating instance of bean 'componentB'
    08:10:32.553 [main] DEBUG ...InjectionMetadata - Registered injected element on class [com.vividbreeze.spring.ComponentB]: AutowiredFieldElement for private com.vividbreeze.spring.ComponentA com.vividbreeze.spring.ComponentB.componentA
    08:10:32.553 [main] DEBUG ...DefaultListableBeanFactory - Eagerly caching bean 'componentB' to allow for resolving potential circular references
    08:10:32.554 [main] DEBUG ...InjectionMetadata - Processing injected element of bean 'componentB': AutowiredFieldElement for private com.vividbreeze.spring.ComponentA com.vividbreeze.spring.ComponentB.componentA
    08:10:32.554 [main] DEBUG org.springframework.core.annotation.AnnotationUtils - Failed to meta-introspect annotation interface ...Autowired: java.lang.NullPointerException
    08:10:32.554 [main] DEBUG ...DefaultListableBeanFactory - Returning eagerly cached instance of singleton bean 'componentA' that is not fully initialized yet - a consequence of a circular reference
    08:10:32.555 [main] DEBUG ...AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 'componentB' to bean named 'componentA'
    08:10:32.556 [main] DEBUG ...DefaultListableBeanFactory - Finished creating instance of bean 'componentB'
    08:10:32.556 [main] DEBUG ...AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 'componentA' to bean named 'componentB'
    08:10:32.556 [main] DEBUG ...DefaultListableBeanFactory - Finished creating instance of bean 'componentA'
    08:10:32.556 [main] DEBUG ...DefaultListableBeanFactory - Returning cached instance of singleton bean 'componentB'
    

    There are other ways to deal with circular dependencies in Spring, such as the @Lazy annotation, where the injected bean creation will be completed when first used (and before as a proxy bean), the @PostConstruct and other.  I recommend, whenever possible, to try to avoid circular dependencies.

     

    Remarks

    You will find many discussion about which form of Dependency Injection to use. Personally, I find that dependencies should be made visible to others that use the class. Hence I avoid attribute injection, although it seems more elegant, especially if you want to inject many dependencies. However, if you have many dependencies in one class, it can be an indication of bad design and concerns might be not separated well enough. Fewer dependencies make a class easier to test and easier to understand. Constructor injection avoids that dependencies are set after the instantiation of a class and hence can be controlled from the outside. If this is changing the dependency during runtime, a setter to inject a dependency makes this clearly visible to others.

    The benefit of using Dependency Injection in Spring is that the IoC container of Spring dissolves, especially complex and nested injection chains. Hence it does a great deal of work from developers.

    This short introduction should give you a good base to learn more about Dependency Injection in Spring. Of course, there is more to DI in Spring. In the next blog post, I will use the Spring Framework with the example from the previous blog post.

  • JVM Classloading

    Java Byte-Code

    When you compile java-code (.java files and resources), the compiler will generate so-called byte-code (.class files, or packaged .jar files). This byte-code can’t be executed by the local operating system, but only by the Java Runtime Environment (JRE). The JRE is the environment where a Java Virtual Machine (JVM) runs. The benefits are that the byte-code can run on any machine where a JRE is present (providing you haven’t used any operating-system specific code). In addition, the Java application runs in a safe space (sandbox) without having much chance to attack the underlying OS. Another advantage can be that the byte-code is executed by a just-in-time compiler (JIT compiler). A JIT compiler compiles byte-code into machine-code that can be read and executed by the underlying OS on-the-fly, often with using profiling information to optimise the machine-code.

    public class HelloWorld {
        public static void main(String[] args) {
            System.out.println("Hello World.");
        }
    }
    

    You can see the byte by using

    javap -c HelloWorld.class

    Hierarchy of Classloaders

    Classloader Hierarchy
    Classloader Hierarchy

    A Java program usually consists of many classes that are linked to each other. These classes are loaded and initialised when they are needed during runtime. Java provides a hierarchy of different ClassLoaders that are responsible for this job

    • The Bootstrap Classloader (aka Primordial Classloader) loads the classes of the JRE, classes that can be found in $JAVAHOME/jre/lib/rt.jar. The Bootstrap Classloader is the root of all other the other Classloaders. Most of the classes are implemented in C.
    • The Extension Classloader loads classes from Extension API under $JAVAHOME/jre/lib/ext (or in the directories defined in the System-Property java.ext.dirs). The Extension Classloader is a sub-class of the Bootstrap Classloader. It is implemented in Java.
    • The Application Classloader (aka System Classloader) is the default Classloader and loads classes from the classpath (java -cp or java -classpath) or Class-Path attribute of a META-INF/MANIFEST.MF file inside of a jar-file. The System Classloader is also implemented in Java.
    • In addition, Custom Classloader can be written that can load classes from any location. These User-Defined Classloaders are derived from java.lang.ClassLoader. Custom Classloader are organised as a tree, each Custom Classloader has a parent, the System Classloader is the root Classloader for all Custom Classloaders

    Finding and Loading a Class

    Class Loading Process
    Class Loading Process

    The loading of classes happens hierarchically. To load a class, the loadClass() method of the Application Classloader is called (1).

    1.  If the Application ClassLoader has already loaded the class it simply returns it. Otherwise, the Application Classloader calls loadClass() on the Extension Classloader (2).
    2. If the Extension Classloader has loaded the class already it returns it. Otherwise, the Extension Classloader calls loadClass() on the Bootstrap Classloader (3).
    3. If the Bootstrap Classloader has loaded the class already it returns it. Otherwise, the Bootstrap Classloader calls loadClass() (4) which calls findClass() (5), which then tries to find the class in $JAVAHOME/jre/lib/rt.jar, caches (stores) and returns it (6). If the Bootstrap Classloader cannot find the class, it delegates it back to the Extension Classloader (6).
    4. The loadClass() method  (7) of the Extension Classloader then calls findClass() (8), which in turn tries to find the class in $JAVAHOME/jre/lib/ext (or in the directories defined in the System-Property java.ext.dirs), caches (stores) and returns it (9). If the Extension Classloader cannot find the class, it delegates it back to the Application Classloader (9).
    5. The loadClass() method (10) of the Application Classloader then calls findClass() (11), which in turn tries to find the class in the application classpath (java -cp or java -classpath), caches (stores) and returns it (12). If the Application Classloader cannot find the class, it throws a java.lang.ClassNotFoundException to the caller (12).

    This principle is also called delegation principle. A child Classloader can see all classes loaded by the parent Classloader (not vice-versa). The parent Classloader cannot see the classes loaded by the child Classloader (visibility principle). Each Classloader contains (loads, caches, stores) the classes it is responsible for (uniqueness principle).

    This is a recursive process. To sum it up

    1. if the Classloader has already loaded the class and returns the class from its cache,
    2. if not it asks their Parent ClassLoader
    3. if the Parent ClassLoader doesn’t have the class, the ClassLoader loads it from the associated location

    You can see how the Classloading mechanism works when you start an application with

    java -verbose:class HelloWorld

    Class Loading

    A class is loaded as soon as it is referenced by another class or until the class is initialised (lazy loading). The loading occurs by the following sequence:

    1. The JRE doesn’t know the source of the byte-code. Hence, a couple of checks are performed on the byte-code to ensure it won’t cause any harm when executed (Verification of class Files in the JVM Specification) (verify)
    2. If the byte-code passes the test, the data structures are prepared that represents attributes, methods and interfaces (prepare)
    3. Subsequently, the references are resolved (interfaces, super-classes, field-references, references in method-signatures, and local variables in methods) (resolve)

    Class Initialisation

    A class, or more precise, the static members of this class, are initialised when

    • an instance of the class is created
    • a static method of the class is invoked
    • a static field of the class is assigned
    • a static field of a class is used (and not a constant)
    • a class is accessed via reflection

    Classes are initialised in the following order

    1. a field declared in a super-class is initialised before a field in a derived class
    2. a super-class is initialised before a derived class, with the exception of super interfaces
    3. if a class initialisation is triggered by access to a static field, the corresponding class is initialised (without initialising the super-class)
    4. static fields are initialised before instance attributes
    5. instance attributes are initialised when the constructor is called. A constructor of a sub-class calls the identical constructor in the super-class first.

    You can experiment this behaviour with some classes like this

    public class SuperClass {
    
        public static int A = 200;
    
        static {
            System.out.println ("Static part of SuperClass.");
        }
    
        {
            System.out.println("Non-Static part of SuperClass is initialized");
        }
    }
    
    public class SubClass extends SuperClass {
    
        public static int A = 100;
    
        static {
            System.out.println ("Static part of SubClass.");
        }
        
        {
            System.out.println("Non-Static part of SubClass is initialized");
        }
    }
    public class ClassHierarchyDemo {
    
        public static void main (String[] args) {
            System.out.println (SubClass.A);
            SubClass subClass = new SubClass();
        }
    }

    You can have a further look at when the classes are loaded with

    java -verbose:class ClassHierarchyDemo

    Remarks

    You might not need to know how classes are loaded into the JVM when you are writing simple Java programs. However, this knowledge will become useful, when writing large applications that use different libraries, and you e.g. experience version conflicts or wondering why classes and especially members are not initialised in the way you would expect. I recommend experimenting a bit with the examples above. More information can be found in the Java Language and Virtual Machine Specifications.

     

  • Inversion of Control – Part II – Dependency Injection

    In the first part, I described what Inversion of Control (IoC) is and how it can be implemented using the classical GoF design patterns. In this post, I will explain another implementation of IoC: Dependency Injection.

    I assume that you are familiar with programming to an interface (or abstract class) rather than classes, as you can easily switch the implementation (aka polymorphism, programming by contract).

    I will start right way with an example: Let us assume we want to send an alert via different mechanisms, such as an E-Mail and a Slack message. The Services that send a message, have a common interface: MessageService; the implementations are EmailMessageService and SlackMessageService. I won’t include that code for sending actual messages, as this would become too complicated. Instead, I will simply log the result to the console.

    package com.vividbreeze.designpattern.di;
    
    public interface MessageService {
        void sendMessage (String subject, String message, String receiver);
    }
    
    package com.vividbreeze.designpattern.di;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class EmailMessageService implements MessageService {
    
        private static final Logger LOG = LoggerFactory.getLogger(EmailMessageService.class);
    
        @Override
        public void sendMessage(String receiver, String subject, String message) {
    
            // Code to send an E-Mail message
    
            LOG.debug("E-Mail successfully sent.");
            LOG.debug("Subject: '" + subject + "'");
            LOG.debug("Receiver: '" + receiver + "'");
            LOG.debug("Message:");
            LOG.debug(message);
        }
    }
    
    package com.vividbreeze.designpattern.di;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class SlackMessageService implements MessageService {
        private static final Logger LOG = LoggerFactory.getLogger(SlackMessageService.class);
    
        @Override
        public void sendMessage(String receiver, String subject, String message) {
    
            // Code to send message to a Slack Channel
    
            LOG.debug("Slack Message successfully sent.");
            LOG.debug("Topic: '" + subject + "'");
            LOG.debug("Receiver or Channel: '" + receiver + "'");
            LOG.debug("Message:");
            LOG.debug(message);
        }
    }

    I further have an abstract class for any kind of service that is responsible for processing the alert, such as sending a message to the correct receiver, e.g. when the disk is full an admin is notified via e-mail; when an exception in the code occurs during working hours, the developers are informed via Slack.

    package com.vividbreeze.designpattern.di;
    
    public abstract class AlertService {
    
        protected MessageService messageService;
    
        public AlertService(MessageService messageService) {
            this.messageService = messageService;
        }
    
        public abstract void processAlert(String receiver);
    }
    

     

    Constructor-Based Dependency Injection

    We can inject the dependency to the MessageService in the constructor. I will continue the example above and subclass the AlertService.

    package com.vividbreeze.designpattern.di;
    
    public class DiscFullAlertService extends AlertService {
    
        public static final String ALERT_TOPIC = "Alert on disk /gdalogs1 almost full.";
        public static final String ALERT_MESSAGE = "disk /gdalogs1 has reached 90% of its capacity.";
    
    
        public DiscFullAlertService(MessageService messageService) {
            super (messageService);
        }
    
        @Override
        public void processAlert(String receiver) {
           messageService.sendMessage(ALERT_TOPIC, ALERT_MESSAGE, receiver);
        }
    }

    The following code shows how to put the pieces together and run the application.

    package com.vividbreeze.designpattern.di;
    
    public class FireAlert {
    
        public static void main (String args[]) {
    
            String receiver = "ops@vividbreeze.com";
    
            new DiscFullAlertService(new EmailMessageService()).processAlert(receiver);
        }
    }
    

    In the example above, the special AlertService or it subclasses do not know which MessageService will send the message (EmailMessageService or SlackMessageService) at runtime. So I will inject an instance of the appropriate Service when instantiating the DiscFullAlertService (in the constructor).

    When I write a test for the DiscFullAlertService, the system running the test, might not be capable of sending Emails or Slack messages (e.g. the development environment). In this case, we have to mock these services without having to change existing code. As we are using Dependency Injection, this has become fairly easy. I can initialise the DiscFullAlertService with a MockMessageService, that does not actually send a message, but only logs it on the console.

    package com.vividbreeze.designpattern.di;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    @Component
    public class MockMessageService implements MessageService {
    
        private static final Logger LOG = LoggerFactory.getLogger(MockMessageService.class);
    
        @Override
        public void sendMessage(String subject, String message, String receiver) {
            LOG.debug("MockMessageService - subject: " + subject + ", receiver: " + receiver + ", message: " + message);
        }
    }
    

    The test will then look like this

    package com.vividbreeze.designpattern.di;
    
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class FireAlertTest {
    
        private static final Logger LOG = LoggerFactory.getLogger(FireAlertTest.class);
        private MessageService mockMessageService;
    
        @BeforeEach
        public void setUp() {
            mockMessageService = new MockMessageService();
        }
    
        @Test
        public void sendAlertMessage() {
            new DiscFullAlertService(mockMessageService).processAlert("test-ops@vividbreeze.com");
        }
    }
    

     

    Setter-Based Dependency Injection

    We can also inject the dependency to the MessageService via a setter, instead of a constructor.

    package com.vividbreeze.designpattern.di;
    
    public abstract class AlertService {
    
        protected MessageService messageService;
    
        public void setMessageService(MessageService messageService) {
            this.messageService = messageService;
        }
    
        public abstract void processAlert(String receiver);
    }
    
    package com.vividbreeze.designpattern.di;
    
    public class DiscFullAlertService extends AlertService {
    
        public static final String ALERT_TOPIC = "Alert on disk /gdalogs1 almost full.";
        public static final String ALERT_MESSAGE = "disk /gdalogs1 has reached 90% of its capacity.";
    
        @Override
        public void processAlert(String receiver) {
           messageService.sendMessage(ALERT_TOPIC, ALERT_MESSAGE, receiver);
        }
    }
    package com.vividbreeze.designpattern.di;
    
    public class FireAlert {
    
        public static void main (String args[]) {
    
            String receiver = "ops@vividbreeze.com";
    
            AlertService alertService = new DiscFullAlertService();
            alertService.setMessageService(new EmailMessageService());
            alertService.processAlert(receiver);
        }
    }
    package com.vividbreeze.designpattern.di;
    
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class FireAlertTest {
    
        private static final Logger LOG = LoggerFactory.getLogger(FireAlertTest.class);
        private MessageService mockMessageService;
    
        @BeforeEach
        public void setUp() {
    
            mockMessageService = new MockMessageService();
        }
    
        @Test
        public void sendAlertMessage() {
    
            AlertService alertService = new DiscFullAlertService();
            alertService.setMessageService(new EmailMessageService());
            alertService.processAlert("test-ops@vividbreeze.com");
        }
    }
    

    Remarks

    So we have seen that dependencies can be easily set by other objects at runtime. You might run into some interesting discussions about Dependency Injection. The arguments I have heard so far is that Dependency Injection increases the number of classes and hence make the code more difficult to understand, especially if you have many dependencies. I concur, as I rather deal with many simple classes that are easier to understand, than a few complex classes. In addition, you have the flexibility of changing implementation, which becomes especially useful when testing implementations. Dependency Injection might have an effect on performance, but I consider it negligible.

    In the subsequent blog post, I will explain how the Java Spring Framework can support you in using Dependency Injection.

  • Inversion of Control – Part I

    Why am I talking about Inversion of Control? I will use Spring (Boot) later on to build services. Spring is based on Dependency Injection. Dependency Injection is one possible implementation of Inversion of Control. Hence, it is reasonable to understand the basics of Inversion of Control (IoC) and how it can be implemented. Before I get to the Sprint implementation, I will explain the concept, the Design Patterns that use IoC and will write about Dependency Injection in Spring in a subsequent blog post.

    What is Inversion of Control?

    When you write an application (code) you are fully in control of the flow.

    public static void main(String args[]) {
    
        while (true) {
            Scanner scan = new Scanner(System.in);
            String text = scan.nextLine();
            System.out.println(text);
        }
    }
    

    However, quite often the control is handed over to a framework that is in control of your code.

    Take for example Java Servlets, that I explained in an earlier blog post. In your implementation of the HttpServlet class, you implement a method such as doGet() which handles HTTP GET requests. This method is called whenever a request is made to an URL you specify in your web.xml. Here the servlet container takes control of your class. This allows the elegant implementation of different Servlets that are all controlled the same way.

    public class HelloServlet extends HttpServlet {
      private static final long serialVersionUID = 1L;
    
      public void init() throws ServletException {
        System.out.println("init()");
        super.init();
      }
    
      protected void doGet(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {
        System.out.println("doGet()");
      }
    }

    Another example is Event Handling, e.g. in JavaScript. You can bind JavaScript code to an event on an element, e.g. object.addEventListener("click", myScript); Once you click on the element, the JavaScript Engine of your Browser will call myScript.

    document.getElementById("submitButton").addEventListener("click", submitForm);
    
    function submitForm() {
       var name = document.getElementById("name");
       // read elements and call service()-method
    }

    Basically, IoC separates what code is executed from when it is executed. Both parts know as little as possible about each other – there only connection is an interface or abstract class provided by the controlling code. Furthermore, IoC reduces code duplication and encourages the use of Interfaces instead of implementations.

    Implementations of Inversion of Control

    Some of the well-known Design Patterns by the GoF (Gang of Four –  E. Gamma, R. Helm, R. Johnson and J. Vlissides) implement the Inversion of Control, such as the Observer, Strategy, Factory or the Template design pattern. Other examples are the Service Locator or Dependency Injection. In the next part, we will take a further look at Dependency Injection. In the last part, we will see how Dependency Injection is used with the Spring Framework.

     

     

     

  • What is a Servlet?

    Introduction

    Java uses so-called Servlets as the component that handles a request from a user (or other systems) and generates a response based on the request. Although with frameworks like Spring MVC you might not deal with Servlets directly. However, it is useful to understand the underlying principles of a Servlet, as you will come in touch with the terminology many times in your code.
    Java Servlets are Java Classes that conform to the Java Servlet API and run inside of a so-called Servlet Container. A Servlet Container is part of an Application Server (such as Apache Tomcat). The Servlet Container manages
    • the lifecycle of a Servlet,
    • access control to the Servlet, and
    • mapping URLs to the appropriate service.
    Servlets can understand any client-server protocol, but most often the HTTP protocol is used. Servlets are part of a web application – packaged in a so-called war-file and deployed on the server.
    Servlet Container and Servlet Lifecycle
    Servlet Container and Servlet Lifecycle

    Instantiation and Initialisation

    Basically, a Java Servlet is an instance of javax.servlet.http.HttpServlet. To be correct here, as HttpServlet is an abstract class, a specific Servlet is an instance of a class that extends HttpServlet and implements one of its methods. In an application, you might have several servlets, each one responsible for a different group of requests (e.g. a servlet to handle a shopping basket, one to handle the payment-process).

    A Servlet is generally instantiated when the Server starts-up. A Servlet is initialised (the init()-method is called) the first time it is requested (although it can be configured that it is initialised at startup in the configuration of the Servlet-Container).

    In general, only one instance of a specific Servlet is instantiated by the Servlet Container. This Servlet object is then shared by all requests. For each request, the Servlet Container creates a thread (or takes a thread from a pool of threads) to handle the request. In addition, for each request, a new pair of HttpRequest and HttpResponse instances is created. This thread then calls the service()-method of the Servlet instance. So multiple threads can access the service()-method (which calls one of the do...()-methods) of the Servlet instance simultaneously.

    Servlet Handling Multiple Requests
    Servlet Handling Multiple Requests (one instance of each Servlet, multiple threads to handle the requests)

    The configuration of the Servlet is described in the web.xml (which is part of the web application). The configuration and state of the Servlet-Container is held in thejavax.servlet.http.ServletContext, e.g. you can set attributes are stored during the lifetime of the Container.

    package com.vividbreeze.servletdemo;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class HelloServlet extends HttpServlet {
      private static final long serialVersionUID = 1L;
    
      public void init() throws ServletException {
        System.out.println("init()");
        super.init();
      }
    
      protected void doGet(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {
        System.out.println("doGet()");
      }
    }

    Request Handling

    When a request is made to the Server, an instance of java.servlet.http.HttpServletRequest is created and filled with the HTTP-Request data, similar for a response a HttpServletResponse instance is created.

    In the image above, I also depicted Listeners and Filters. Filters can be used to monitor or modify requests and responses, a Listener listen to events in a Web Container, e.g. Session-creation and more.

    The Servlet that handles the request is defined in the web.xml

    ...
    <servlet>
        <description></description>
        <display-name>HelloServlet</display-name>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.vividbreeze.servletdemo.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/HelloServlet</url-pattern>
    </servlet-mapping>
    ...

    You call the servlet by a URL of the form http://[hostname]:[port]/[servlet-name]. If we assume the application above runs on your localhost on port 8080, the URL would be http://localhost:8080/HelloServlet. Parameters can be transferred via get-request (Parameters are in the URL) or post-request (Parameters are inside the message body).

    The WebContainer passes the HttpServletRequest-Object to the service()-method, which then, depending on the request-method calls the corresponding doGet(), doPost(), … methods. These methods interpret the request data, calls some business-logic and fill the HttpServletResponse-Object, which is passed the same way back to the client.

    Server Shutdown

    The destroy()-method of the Servlet is called when the server shuts down. This method is usually used to release resources used by the Servlet.

    Remarks

    Of course, there is more to Servlets than described here briefly. When you work with technologies that build on Servlets, such as Java Server Pages (JSP), Java Server Faces (JSF), Apache Struts, Spring MVC and others, you might not come directly in touch with the underlying concepts. However, often things don’t run smoothly it helps to understand the basic technologies.

    Further Readings

    Java Servlet Programming (J. Hunter & W. Crawford, 1998) – Chapter 3. The Servlet Life Cycle (this reference seems old (and some parts are outdated), but I have found no other documentation online that so thoroughly explains the lifecycle of a Servlet)

     

  • Maven Overview

    Introduction

    Maven is a build tool. A build tool automates processes related to building software. This can include
    • compilation of the source-code
    • (triggering) auto-generating (parts of) the code, e.g.with css
    • generation of documentation
    • packaging of the compiled-code
    • generation of containers (e.g. a docker-container)
    • deploying packages or containers on a remote server

    Installing Maven is straight-forward, as describe on the Maven project webpage. If you run into problems, remember that stack overflow is your friend.

    This overview doesn’t replace a Maven tutorial or the Maven documentation. The aim is to equip you with the basics, so you gain a better understanding of what you are doing when you are working hands-on with Maven (like in the next blog posts).

    The Basics

    Maven uses so-called POMs (Project Object Model) for its configuration. These POMs tell Maven how to build the software. A POM is often written in XML, but also other dialects can be used, such as YAML. I recently use YAML for POMs as they are easier to read. However, as XML is still more common, I will use XML in this introduction.

    <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>...</groupId>
        <artifactId>...</artifactId>
        <version>...</version>
        <packaging>...</packaging>
        <dependencies>...</dependencies>
        <parent>...</parent>
        <dependencyManagement>...</dependencyManagement>
        <modules>...</modules>
        <properties>...</properties>
    
        <build>...</build>
        <reporting>...</reporting>
    
        <repositories>...</repositories>
        <pluginRepositories>...</pluginRepositories>
        <profiles>...</profiles>
    </project>

    Maven reads and executes the POM in the following sequence

    • Download the dependencies into a local repository (if not present)
    • Execute the build lifecycles, phases and/or goals (in relation to the desired profile)
    • Execute plugins

    You start the build process with Maven using

    mvn [build-lifecyle||build-phase||build-goal]

    The build lifecycle consists of build phases; the build phases consist of build goals. These are always executed in sequential order. If a build phase is executed, all previous build phases are executed, too.

    Before Maven executes the command it resolves the dependencies of the used libraries (jar-files in Java) recursively, i.e. you specify lib11.jar in the POM, which references,lib22.jar which in turn references lib33.jar. This is a significant advantage of Maven, as it resolves these dependencies fully automatically. However, in large projects, this process can take a quite long time. Hence Maven maintains a local repository (which is stored on your computer), where it stores the jars once downloaded.

    If you work with different environments with different configurations (e.g. local, integration, pre-production, production), you can use different build profiles.

    You can have more than one POM. POMs are organised in a tree structure. All Maven POMs inherit from a Super-POM. The child POMs get to override the configuration of the parent-POM.

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    

    If you have done builds with shell-scripts or ant, you were able to use low-level commands (copy or rename files, …). You have described how to build something. In Maven you define what to build (using the above build lifecycles, phases and goals).

    Maven Directory Structure

    Out-of-the-box Maven uses the following standard directory-structure for a Java-project (generated with mvn install)

    [project-name]
        ├───pom.xml
        ├───README.txt
        ├───NOTICE.txt
        ├───LICENSE.txt
        └───src
            ├───main
            │   ├───java
            │   ├───resources
            │   ├───filters
            │   └───webapp
            ├───test
            │   ├───java
            │   ├───resources
            │   └───filters
            ├───it
            ├───site
            └───assembly
    

    Maven Dependencies

    One of the key features of Maven is dependency management of libraries you use in your project. Before Maven you had to care about what jar-files in which version you had to include. Maven does a large part of the work here and resolves the dependencies between the jar-files automatically.

    You define your dependencies in the <dependency>-element of the POM. I recommend copying the definitions directly from the Maven Central Repository, which include groupId, artifactId and version. Those three parameters also define the directory structure of your local repository~/.m2/repository, in the example below: ~/.m2/repository/junit/junit/4.12

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.1.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    

    The jar-file of your project will also be a part of the local repository. Hence, on top of your pom.xml you will also define groupId, artifactId and a version amongst other parameters.

    <?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">
    
        <groupId>com.vividbreeze.grammardrill</groupId>
        <artifactId>grammardrill</artifactId>
        <version>0.1</version>
        <packaging>jar</packaging>
    
        <name>grammardrill</name>
        <description>Grammar Drill Application</description>
    
        <parent>
            ...
    

    Maven Repositories

    Maven repositories are jar-files that contain meta-data in the form of a POM. This POM-files often include their dependencies, amongst other information. So quite often, dependencies are downloaded recursively into your local repository by Maven.

    Maven Repository Structure
    Maven Repository Structure

    Maven knows the following repositories, which are scanned through in this sequence

    • Local Repository, a directory on the computer Maven runs. It functions as a cache for all dependencies Maven downloads from the Central or Remote Repository. The Local repository is shared among different projects. Also, your project-jar can be stored in the Local Repository, so other projects can access it. The default location of your local repository is ~/.m2/repository (it can be changed in ~/.m2/settings.xml).
    • (Maven) Central Repository is used when Maven can’t find a dependency in your local repository. The Central Repository is provided by the Maven Community. You can go to their webpage and copy and paste the artefacts for standard build tools, including Maven (e.g. the Apache Commons Collection).
    • Remote Repository is an external server that contains dependencies. A remote repository is often used to share organisation-wide dependencies that are used by other projects within the organisation. You can specify external repositories either in the repositories section or in your profile-section in the POM or for all projects in ~/.m2/settings.xmlArtifactory is an example for a remote repository.
     <repositories>
        <repository>
            <id>spring-snapshots</id>
            <url>http://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
            </repository>
            <repository>
                <id>spring-milestones</id>
            <url>http://repo.spring.io/milestone</url>
        </repository>
    </repositories>

    Maven Build Life Cycles, Phases and Goals

    Maven - Relationship between Lifecycle, Phases and Goals
    Maven – Relationship between Lifecycle, Phases and Goals (example)

    Build Life Cycles

    Maven provides three build-in build life cycles
    • default – project deployment (mvn)
    • clean – project cleaning (mvn clean)
    • site – site documentation (mvn site)

    Build Phases

    As mentioned above, a build lifecycle is made up of different build phases. The default-lifecycle executes the following build phases (amongst others) in sequential order:

    1. validate – validates the consistency of the project
    2. compile – compiles the source code
    3. test – runs the (local) tests
    4. package – packages the compiled and tested code
    5. verify – runs integration tests on the packaged software
    6. install – pushes the package to the local Maven repository
    7. deploy – deploys the final package to the remote repository
    If you call mvn in the project directory (that contains the pom.xml) all the above steps will be executed in sequential order.  You can also tell Maven to execute a build phase (mvn [phase-name]). As mentioned above, in this case, Maven will also execute the phases before the given phase, e.g. when you call mvn test – validate and compile are executed before a test.

    You can trigger two lifecycles, e.g.,mvn clean install which cleans the project first and then calls all the phases up to install.

    (Build) Plugin Goals

    Each of the phases above is carried out different steps, called (build) plugin goals. I plugin goal is a specific task in the build process. One plugin goal can be bound to none, one or more than one phase. You can call a goal that is not linked to a build phase by mvn dependency:copy-dependencies.

    Maven Plugins

    As mentioned in the previous chapter, goals are implemented via plugins. There are basically

    • build plugins are responsible for the build process (configurable in the <build>-element of the POM)
    • reporting plugins are responsible for the site generation (configurable in the <reporting>-element of the POM)

    Each plugin (aka Mojo) has a groupId, artifactId and version and can contain its own configurations and dependencies. You can find a list of all available plugins supported by the Maven Project on their webpage. Of course, you can use plugins developed by third-parties or develop your own plugins. You can configure each plugin inside of the <configuration>-element of the <plugin>-element. You can connect plugin goals with a phase using the <phase>-element. The Plugin will be executed after the deploy goal has run. Since Maven 3.0.3 the plugins will be executed in the same order as they are listed in the POM.

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-checkstyle-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
            <execution>
                <configuration>
                    <configLocation>config/checkstyle/checkstyle.xml</configLocation>
                </configuration>
                <goals>
                    <goal>check</goal>
                </goals>
                <phase>validate</phase>
            </execution>
        </executions>
    </plugin>
    

    Maven Build Profiles

    As mentioned above, Maven supports different profiles (build configurations). It is often used to build your software on different environments, e.g. local, integration, production or similar. You don’t need to repeat every single build-step in a profile, but instead override the elements that are different. You can also have global profiles or profiles per user (defined in~/.m2/settings.xml).

    <profiles>
        <profile>
            <id>test</id>
            <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <version>1.1</version>
                    <executions>
                        <execution>
                        <phase>test</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <tasks>
                                ...
                            </tasks>
                        </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
            </build>
        </profile>
    </profiles>

    Inside the POM, profiles they are located in the profiles element and are referenced by their profile-name, e.g. mvn -P [profile-name] install You can also set the active profile in the settings.xml or you can set triggers inside the profile-element inside the activation-element.

    Running Maven

    Maven expects a list of Build Lifecycles, Phases and Goals that are executed in the specified order, such as

    mvn clean dependency:copy-dependencies package

    which first calls the build lifecycle clean, than the goal copy-dependencies and than the build-phase package.

    Miscellaneous

    Properties

    Properties can be defined or set in the POM in XML with <[property-name]>[property value]</[property-name]>.

    Custom properties can be defined at the beginning of the POM and are accessible inside the POM by using ${property-name}. You can also set global values that are valid inside the POM like in the example below. Properties can be also used to configure plugins.

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    

    Remarks

    This short introduction should have provided the basics of Maven, so you are able to read and maintain a POM and build your project. Maven is a strong build tool and hence there is much more to it. I will show hands-on examples throughout the next tutorials.

  • Git Branches – Working with Branches – Part III – Merging versus Rebasing

    You have learned how to merge two branches and how to deal with merge-conflicts. When you develop new features it makes sense to develop them on a branch that is based on the latest version of your Master branch. If the feature branches are based on the non-current version of the Master branch than

    • you might run into merge conflicts when merging your feature branch into your Master or
    • you will discover that your application might not behave as you expected, i.e. different than when you tested it on your feature branch.

    So when the Master branch changes (e.g. because another feature branch or bugfix was merged into the Master) it makes sense to update the feature branch you are currently working on. There are two ways of doing this.

    The next chapters are based on the following example:

    • Feature Branch A based on the 3. commit of the Master Branch (git checkout -b A)
    • Debug Branch based on the 3. commit on the Master Branch (git checkout -b debug)
    • Alter file in the Debug branch
    • Merge Debug Branch into Master branch (git checkout master, git merge debug)
    Git Basic Branching Commit View (2 Commits)
    Git Basic Branching Commit View (2 Commits)

    Merging the latest Master Branch into your Feature Branch (Merging)

    We will assume that the files that were changed in the Bugfix branch and branch A are different, so that we won’t run into merge-conflicts. You can now checkout your feature branch and merge your new Master into your feature branch.

    git checkout A
    
    git merge master
    Git Commit View - Merge Master Back Into Feature Branch
    Git Commit View – Merge Master Back Into Feature Branch

    In this case the editor will open with a default commit message („Merge branch ‚master‘ into A“). You can alter this message in the editor, save and quit (in the case of vi use: iinsert, esccommand mode, then enter „:wq“ for write and quit).

    You could also merge the Bugfix branch into your feature branch (git checkout A, git merge bugfix). But when working with others (as we will see later), you might not have the latest version of the Master branch.

    If you have a look at the commit history (git log) you will see something like the above, which can be pretty exhausting to look through. It will look even more confusing, if you work with other developers on the same Master (which we will explore later). But basically, confusing or not, the history reflects exactly what happened.

    Merge Conflicts

    Let’s imaging you change a file in your Debug branch that you changed before in your feature branch A (say styles.css).

    > git merge master
    Auto-merging styles.css
    CONFLICT (content): Merge conflict in styles.css
    Automatic merge failed; fix conflicts and then commit the result.
    >

    The styles.css might look something like this

    body {background-color: powderblue;}
    <<<<<<< HEAD
    h1   {color: blue;}
    =======
    h1   {color: red;}
    >>>>>>> master
    

    Then alter styles.css to the preferred state, and add and commit the changes:

    git commit -a -m "resolved merge conflict in styles.css"

    Using the latest Master Branch as a new Base for your Feature Branch (Rebasing)

    Rebase means, that you change the base of the branch to the latest state of the branch it derived from. In the example above, branch A originally derives from the 3rd commit of the Master branch. Now the Master branch is altered by the bugfix. If you subsequently checkout branch A, you set the base to the current version of the Master branch:

    git rebase master
    Git Rebase Sequential View
    Git Rebase Sequential View

    In this case the commit-history will be changed and won’t reflect what has really happened. However, it is much easier to read (compared to the merge in the previous chapter).

    Git Rebase Clean View
    Git Rebase Clean View

    Merge Conflicts

    Again, let us use the same example as above, style.css was changed in branch A (git checkout A, vi style.css, git commit -a -m "...") and in the debug branch (git checkout debug, vi style.css, git commit -a -m "..."). Then the debug branch was merged into the master (git checkout master, git merge debug). When we switched to branch A to subsequently rebase it (git checkout A, git rebase master), we get an error message like this

    First, rewinding head to replay your work on top of it...
    Applying: new feature implemented
    Using index info to reconstruct a base tree...
    M	styles.css
    Falling back to patching base and 3-way merge...
    Auto-merging styles.css
    CONFLICT (content): Merge conflict in styles.css
    error: Failed to merge in the changes.
    Patch failed at 0001 new feature implemented
    The copy of the patch that failed is found in: .git/rebase-apply/patch
    
    When you have resolved this problem, run "git rebase --continue".
    If you prefer to skip this patch, run "git rebase --skip" instead.
    To check out the original branch and stop rebasing, run "git rebase --abort".

    So Git tells you how to continue. You can either

    • resolve the merge-conflict in styles.css and use git rebase --continue.
    • abort the rebase operation by using git rebase --abort as if nothing has happened (like an undo operation)
    • skip the patch by using git rebase --skip. This basically means, that the rebase is done, and the file where is merge-conflict occurred will be overwritten with the version from the master. I rarely use this command and just tested it for the first time, with the result just mentioned.

    Remarks

    So which one should you use: merge or rebase? There has been lot of debate on this one. I explained the advantages and disadvantages of both. In the Atlassian Git Tutorial you will find some suggestions. Personally, I prefer merge over rebase, to merge the current version of the branch my feature branch derived from into my feature branch. I occasionally use a merge when I know that lots of changes have been made by other developers that affect the functioning of the feature I am implementing. Otherwise I use a merge just before testing my feature and merging it into the branch it derived from (the master branch or similar). I use graphical tools when I work with Git so the commit history becomes readable.

    As I mentioned before, this short tutorial covers the basics. It gives you the tools to understand how to use Git in the most common way. Again, I suggest that you play with Git to become more familiar with merging and rebasing. You just need to branches and two or more files, nothing more.

    Further Reading

    GIT Tutorial – Basics

    GIT Tutorial – Working with Branches – Part I

    Git Branches – Working with Branches – Part II (Merge Conflicts)

    Git Branches – Working with Branches – Part III (Merging versus Rebasing)

    GIT Tutorial – Remote Repositories