<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog4Java &#187; Architecture</title>
	<atom:link href="http://malsolo.com/blog4java/?cat=10&#038;feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://malsolo.com/blog4java</link>
	<description>A personal and Java blog, likely only for me</description>
	<lastBuildDate>Tue, 31 Mar 2015 15:52:42 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1.1</generator>
	<item>
		<title>Getting started with Docker</title>
		<link>http://malsolo.com/blog4java/?p=794</link>
		<comments>http://malsolo.com/blog4java/?p=794#comments</comments>
		<pubDate>Tue, 31 Mar 2015 15:51:23 +0000</pubDate>
		<dc:creator><![CDATA[Javier (@jbbarquero)]]></dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Docker]]></category>

		<guid isPermaLink="false">http://malsolo.com/blog4java/?p=794</guid>
		<description><![CDATA[What is Docker? Docker is a platform. Docker runs natively on Linux or on OS X and Windows through a helper application called boot2docker that creates a Linux Virtual Machine, by using only RAM, to run Docker. Docker&#8216;s main goal &#8230; <a href="http://malsolo.com/blog4java/?p=794">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<h1>What is Docker?</h1>
<p><a href="https://www.docker.com/whatisdocker/" title="What is Docker?" target="_blank">Docker</a> is a platform.</p>
<p><a href="https://docs.docker.com/introduction/understanding-docker/" title="Understanding Docker" target="_blank">Docker</a> runs natively on Linux or on OS X and Windows through a helper application called <a href="https://github.com/boot2docker/boot2docker" title="boot2docker at GitHub" target="_blank">boot2docker</a> that creates a Linux Virtual Machine, by using only RAM, to run Docker.</p>
<p><a href="https://docs.docker.com/" title="About Docker" target="_blank">Docker</a>&#8216;s main goal is to allow you to ship distributed applications, that you&#8217;ve created previously, by running them as isolated process on what is known as a <em>container</em>, thus it avoids the need of Virtual Machines that implies a resources saving in the involved machines. The isolation also allows to run several containers simultaneously.</p>
<p>So, <em><strong>Docker</strong> is an open platform for developing, shipping, and running applications</em>.</p>
<p>The key point is that you can separate your application from the infrastructure and also treats the infrastructure as an application. Everything can be packaged, distributed and deployed anywhere and quickly. It&#8217;s said that Docker eliminates the friction between development, QA, and production environments.</p>
<p>Docker has two major <strong>components</strong>:</p>
<ul>
<li><a href="https://github.com/docker/docker" title="Docker at GitHub" target="_blank">Docker</a>, the container virtualization platform, that has a <em>daemon</em> running on a host server and a client (the <em>docker</em> binary) to talk to the Docker <em>daemon</em>.</li>
<li><a href="https://hub.docker.com/" title="Docker Hub" target="_blank">Docker Hub</a>, the <a href="http://en.wikipedia.org/wiki/Software_as_a_service" title="Software as a service at Wikipedia" target="_blank">SaaS</a> platform for sharing and managing Docker containers.</li>
</ul>
<h2>Docker concepts</h2>
<ul>
<li><strong>Image</strong> (<em>build</em> component of Docker): a Docker environment template, it consists in files (a copy of what is expected to contain) and metadata (information such as environment variables, port mappings and so on) and it has a name (<em>&#8220;ubuntu&#8221;</em>, for instance)</li>
<li><strong>Registry</strong> (<em>distribution</em> component of Docker): a public or private store that holds images. The public Docker registry is called <a href="http://hub.docker.com/" title="Docker Hub" target="_blank">Docker Hub</a>.</li>
<li><strong>Container</strong> (<em>run</em> component of Docker):  a running instance of a Docker image. It&#8217;s created from a Docker image, and it can be run, started, stopped, moved, and deleted. Each container is an isolated and secure application platform.</li>
</ul>
<h2>How Does Docker work?</h2>
<p>An image is a serie of layers that are combined into a single image by Docker using <em><strong>union file systems</strong></em> (<a href="http://en.wikipedia.org/wiki/UnionFS" title="UnionFS at Wikipedia" target="_blank">UnionFS</a>, <em>a file system service that allows files and directories of separate file systems, known as branches, to be transparently overlaid, forming a single coherent file system</em>)</p>
<p>From a base image, you can add and modify additional layers and there&#8217;s no need of rebuilding the entire image if there is a change, you only need replace the added or updated layer.  </p>
<p>A container is built from an image, that is read-only. For running the container, Docker adds a read-write layer on top of the image (using UnionFS) and then allocates a network/bridge interface, an IP address, and finally, executes the specified process and captures input and provides output.</p>
<p>The container is isolated thanks to a technology called <em><strong>namespaces</strong></em> (<a href="http://en.wikipedia.org/wiki/Cgroups#NAMESPACE-ISOLATION" title="Namespaces at Wikipedia" target="_blank">Namespace isolation</a>, <em>where groups of processes are separated such that they cannot &#8220;see&#8221; resources in other groups</em>)</p>
<p>Docker use these namespaces:</p>
<ul>
<li>The <strong>pid</strong> namespace, for process isolation.</li>
<li>The <strong>net</strong> namespace, for managing network interfaces.</li>
<li>The <strong>ipc</strong> namespace, for Inter-Process Communication.</li>
<li>The <strong>mnt</strong> namespace, for managing mount-points.</li>
<li>The <strong>uts</strong> namespace, for changing the hostname.</li>
</ul>
<p>In order to achieve isolation on running application, Docker uses another technology called <em><strong>control groups</strong></em> (<a href="http://en.wikipedia.org/wiki/Cgroups" title="cgroups at Wikipedia" target="_blank">cgroups</a>, <em>it limits, accounts for, and isolates the resource usage (CPU, memory, disk I/O, network, etc.) of a collection of processes</em>)</p>
<h1>Installing Docker</h1>
<p>I&#8217;m going to use <a href="http://www.ubuntu.com/" title="Ubuntu: The leading OS for PC, tablet, phone and cloud" target="_blank">Ubuntu</a> (as <a href="http://en.wikipedia.org/wiki/Sheldon_Cooper" title="Sheldon Cooper at Wikipedia" target="_blank">Sheldon Cooper</a> said, <a href="http://www.imdb.com/title/tt1648756/quotes?item=qt1224150" title="Sheldon Cooper and Ubuntu" target="_blank">my favorite Linux-based operating system</a>)</p>
<p>There are <u>three packages available</u>, two of them from Ubuntu, an older KDE3/GNOME2 called <em>docker</em> (warning, this is the suggested package when you try <em>docker version</em> before having installed: <em>&#8220;The program &#8216;docker&#8217; is currently not installed. You can install it by typing: sudo apt-get install docker&#8221;</em>) and a newer called <em>docker.io</em>, that is not the most recent Docker release. The third one is a PPA (Personal Package Archives for Ubuntu) for <a href="http://www.ubuntuupdates.org/ppa/docker" title="3rd Party Repository: Docker" target="_blank">Docker</a> and it&#8217;s called <a href="http://www.ubuntuupdates.org/package/docker/docker/main/base/lxc-docker" title="Ubuntu Package &quot;lxc-docker&quot;" target="_blank"><em>lxc-docker</em></a>.</p>
<p>If you don&#8217;t want extra repositories and you don&#8217;t want the latest version, just install <em>docker.io</em> (I recommend you to enable tab-completion of Docker commands in BASH if you install it):</p>
<p></p><pre class="crayon-plain-tag">$ sudo apt-get update
$ sudo apt-get install docker.io
$ source /etc/bash_completion.d/docker.io</pre><p></p>
<p>To validate the installation, type:</p><pre class="crayon-plain-tag">$ sudo docker version
Client version: 1.0.1
Client API version: 1.12
Go version (client): go1.2.1
Git commit (client): 990021a
Server version: 1.0.1
Server API version: 1.12
Go version (server): go1.2.1
Git commit (server): 990021a
$</pre><p></p>
<p>You need to use <strong>sudo</strong> because the <em>docker</em> daemon always runs as the <em>root</em> user, that&#8217;s because the <em>docker</em> daemon binds to a Unix socket (instead of a TCP port, as it happened until version 0.5.2). By default that Unix socket is owned by the user <em>root</em>, so you need to use the <em>docker</em> command with <em>sudo</em>. You can solve it by <a href="http://docs.docker.com/v1.4/installation/ubuntulinux/#giving-non-root-access" title="Giving non-root access" target="_blank">giving non-root access to Docker</a> or, even better, you can <a href="https://docs.docker.com/installation/ubuntulinux/#create-a-docker-group" title="Create a docker group" target="_blank">create a docker group and add users to it</a>.</p>
<p>Otherwise, if you run docker without sudo you will obtain this error message:</p><pre class="crayon-plain-tag">$ docker version
Client version: 1.0.1
Client API version: 1.12
Go version (client): go1.2.1
Git commit (client): 990021a
2015/03/20 11:40:30 Get http:///var/run/docker.sock/v1.12/version: dial unix /var/run/docker.sock: permission denied
$</pre><p></p>
<p>In order to have the latest version, use the <em>lxc-docker</em> package, that is the one maintained by Docker itself.</p>
<p>There is a <a href="https://get.docker.com/ubuntu/" title="Get Docker on Ubuntu" target="_blank">script to install the Docker package on Ubuntu</a>, but I&#8217;d rather to do it manually. But you can try with:</p>
<p></p><pre class="crayon-plain-tag">$ curl -sSL https://get.docker.com/ubuntu/ | sudo sh</pre><p></p>
<p>To install lxc-docker, your APT system have to deal with https (you can if the file <em>/usr/lib/apt/methods/https</em> exists, it you don&#8217;t have it, install the <em><strong>apt-transport-https</strong></em> package)</p>
<p>Then, just add the Docker repository key to the local keychain, and to the apt sources list. Finally, update and install the <em><strong>lxc-docker</strong></em> package:</p>
<p></p><pre class="crayon-plain-tag">$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
$ sudo sh -c "echo deb https://get.docker.com/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
$ sudo apt-get update
$ sudo apt-get install lxc-docker</pre><p></p>
<p>Now we have the last version:</p>
<p></p><pre class="crayon-plain-tag">$ sudo docker version
Client version: 1.5.0
Client API version: 1.17
Go version (client): go1.4.1
Git commit (client): a8a31ef
OS/Arch (client): linux/amd64
Server version: 1.5.0
Server API version: 1.17
Go version (server): go1.4.1
Git commit (server): a8a31ef
$</pre><p></p>
<p>And we can run the basic example, that downloads the <em>ubuntu</em> image, and then start <em>bash</em> in a container. When you&#8217;re done, type <em>exit</em>.</p>
<p></p><pre class="crayon-plain-tag">$ sudo docker run -i -t ubuntu /bin/bash
Unable to find image 'ubuntu:latest' locally
511136ea3c5a: Pull complete 
f3c84ac3a053: Pull complete 
511136ea3c5a: Download complete 
f3c84ac3a053: Download complete 
a1a958a24818: Download complete 
9fec74352904: Download complete 
d0955f21bf24: Download complete 
Status: Downloaded newer image for ubuntu:latest
root@0f5e5a64c583:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr
root@0f5e5a64c583:/# exit
exit
$</pre><p></p>
<p>Having said that, Docker has changed the instructions for <a href="https://docs.docker.com/installation/ubuntulinux/#installing-docker-on-ubuntu" title="Installing Docker on Ubuntu" target="_blank">Installing Docker on Ubuntu</a>&#8230; today! <img src="http://malsolo.com/blog4java/wp-includes/images/smilies/icon_neutral.gif" alt=":|" class="wp-smiley" /></p>
<p>It seems easier, but I don’t like it very much. If you have wget installed, you can get the latest Docker package with:</p>
<p></p><pre class="crayon-plain-tag">$ wget -qO- https://get.docker.com/ | sh</pre><p></p>
<p>It prompts for the password and then it downloads and installs&#8230; the <em>lxc-docker</em> package. </p>
<p>And then, verify the installation with:</p>
<p></p><pre class="crayon-plain-tag">$ sudo docker run hello-world
[sudo] password for Javier: 
Unable to find image 'hello-world:latest' locally
31cbccb51277: Pull complete 
e45a5af57b00: Pull complete 
511136ea3c5a: Already exists 
hello-world:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Status: Downloaded newer image for hello-world:latest
Hello from Docker.
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (Assuming it was not already locally available.)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

For more examples and ideas, visit:
 http://docs.docker.com/userguide/
$</pre><p></p>
<h1>Using Docker</h1>
<h2>Running applications inside containers</h2>
<p>Docker allows you to run applications inside containers with the command <strong><em>docker run</em></strong>.</p>
<p>The command <em>docker run</em> creates a new container from the image name that you specify (the mandatory parameter for <em>run</em>) and then runs the command in it by performing these steps: Docker looks for the image in this computer, if it isn&#8217;t installed yet, Docker searches the image at Docker Hub to download it and install it. Once the image is installed, Docker creates a new container and starts the program.</p>
<p>We&#8217;ve seen above one example:</p>
<p></p><pre class="crayon-plain-tag">$ sudo docker run -t -i ubuntu:14.04.2 /bin/bash</pre><p></p>
<p>It creates a container from the <a href="https://registry.hub.docker.com/_/ubuntu/" title="Docker Hub: Official Ubuntu base image" target="_blank">Official Ubuntu base image</a> (tag 14.04.2) and then it runs a Bash shell command, with a terminal assigned (flag <strong>-t</strong>), and grabs the standard in of the container(flag <strong>-i</strong>)</p>
<p>For executing in the background (or daemonized), use the <strong>-d</strong> flag:</p>
<p></p><pre class="crayon-plain-tag">$ sudo docker run -d --name="Javier" ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
e84ae64138881b9eaf6ac743c6f0076cfc414f017daef9e59c3d2e1d591eb7b9</pre><p></p>
<p>Here, the command will run forever. Besides, I have assigned a name to the container (OK, my very name, some egocentricity here) to easily discover it later (Docker automatically names any containers that you start, but I&#8217;d rather to specify the name by myself). Furthermore, Docker returns the container ID (<em>e84ae6413888&#8230;</em>).</p>
<p>You can find both the ID and the name when listing containers with the command <em><strong>docker ps</strong></em> (flag <strong>-a</strong> to show all regardless they are running or not)</p>
<p></p><pre class="crayon-plain-tag">$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
e84ae6413888        ubuntu:14.04        "/bin/sh -c 'while t   5 days ago          Up 2 minutes                            Javier              
$</pre><p></p>
<p>The <strong>ports</strong> in the container can be exposed randomly with the <strong>-P</strong> flag or manually with <strong>-p</strong>. In any case, you can see in the column <em>PORTS</em> of the <em>docker ps</em> command or with the <em>docker port</em> command. Let&#8217;s see an example with a <a href="https://registry.hub.docker.com/u/training/webapp/" title="The Docker Fundamentals repository contains the example Hello World Python WebApp" target="_blank">sample web application image</a>.</p>
<p></p><pre class="crayon-plain-tag">$ sudo docker run -d -P training/webapp python app.py
Unable to find image 'training/webapp:latest' locally
Pulling repository training/webapp
31fa814ba25a: Download complete 
511136ea3c5a: Download complete 
f10ebce2c0e1: Download complete 
82cdea7ab5b5: Download complete 
5dbd9cb5a02f: Download complete 
74fe38d11401: Download complete 
64523f641a05: Download complete 
0e2afc9aad6e: Download complete 
e8fc7643ceb1: Download complete 
733b0e3dbcee: Download complete 
a1feb043c441: Download complete 
e12923494f6a: Download complete 
a15f98c46748: Download complete 
Status: Downloaded newer image for training/webapp:latest
a03ec94ea8087789d605ca91d6689d8026e7806e9138b8b9b7ed7f5a1295db85
$ sudo docker ps
CONTAINER ID        IMAGE                    COMMAND             CREATED             STATUS              PORTS                     NAMES
a03ec94ea808        training/webapp:latest   "python app.py"     25 seconds ago      Up 24 seconds       0.0.0.0:49153->5000/tcp   happy_pare          
$ sudo docker port happy_pare
5000/tcp -> 0.0.0.0:49153
$ curl http://localhost:49153
Hello world!
$</pre><p></p>
<p>This means that you can access the application running in the container by using the port 49153 locally.</p>
<p>To manage the container, you can use the next commands:</p>
<ul>
<li><em><strong>docker logs</strong></em> to see the standard output of a container (<strong>-f</strong> to view the new additions, press Ctrl+C to exit)</li>
<li><em><strong>docker top</strong></em> to see the process in the container.</li>
<li><em><strong>docker inspect</strong></em> to see configuration and status information about a container.</li>
<li><em><strong>docker stop/kill</strong></em> to stop or kills (respectively) a running container.</li>
<li><em><strong>docker start</strong></em> to restart a stopped container (remember the command <em>docker ps -a</em>).</li>
<li><em><strong>docker rm</strong></em> to remove a container.</li>
<li><em><strong>docker version</strong></em> to see the current version of the program, its programming language (<a href="https://golang.org/" title="The Go Programming Language" target="_blank">Go</a>) and so on.</li>
</ul>
<p></p><pre class="crayon-plain-tag">$ sudo docker logs happy_pare
 * Running on http://0.0.0.0:5000/
172.17.42.1 - - [31/Mar/2015 09:51:38] "GET / HTTP/1.1" 200 -
$ sudo docker stop happy_pare
happy_pare
$ sudo docker start happy_pare
happy_pare
$ sudo docker kill happy_pare
happy_pare
$ sudo docker rm happy_pare
happy_pare
$ sudo docker top happy_pare
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                8580                1372                0                   12:00               ?                   00:00:00            python app.py
$ sudo docker inspect hungry_kirch
[{
    "AppArmorProfile": "",
    "Args": [
        "app.py"
    ],
    "Config": {
        "AttachStderr": false,
        "AttachStdin": false,
        "AttachStdout": false,
        "Cmd": [
            "python",
            "app.py"
        ],
        "CpuShares": 0,
        "Cpuset": "",
        "Domainname": "",
        "Entrypoint": null,
        "Env": [
            "HOME=/",
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
        ],
        "ExposedPorts": {
            "5000/tcp": {}
        },
        "Hostname": "468cd593eada",
        "Image": "training/webapp",
        "MacAddress": "",
        "Memory": 0,
        "MemorySwap": 0,
        "NetworkDisabled": false,
        "OnBuild": null,
        "OpenStdin": false,
        "PortSpecs": null,
        "StdinOnce": false,
        "Tty": false,
        "User": "",
        "Volumes": null,
        "WorkingDir": "/opt/webapp"
    },
    "Created": "2015-03-31T10:00:32.697111567Z",
    "Driver": "aufs",
    "ExecDriver": "native-0.2",
    "ExecIDs": null,
    "HostConfig": {
        "Binds": null,
        "CapAdd": null,
        "CapDrop": null,
        "ContainerIDFile": "",
        "Devices": [],
        "Dns": null,
        "DnsSearch": null,
        "ExtraHosts": null,
        "IpcMode": "",
        "Links": null,
        "LxcConf": [],
        "NetworkMode": "bridge",
        "PidMode": "",
        "PortBindings": {},
        "Privileged": false,
        "PublishAllPorts": true,
        "ReadonlyRootfs": false,
        "RestartPolicy": {
            "MaximumRetryCount": 0,
            "Name": ""
        },
        "SecurityOpt": null,
        "VolumesFrom": null
    },
    "HostnamePath": "/var/lib/docker/containers/468cd593eadaea6d18441a33ca6c1ea42f1b398d6fd028fa5b557181a5cf36f3/hostname",
    "HostsPath": "/var/lib/docker/containers/468cd593eadaea6d18441a33ca6c1ea42f1b398d6fd028fa5b557181a5cf36f3/hosts",
    "Id": "468cd593eadaea6d18441a33ca6c1ea42f1b398d6fd028fa5b557181a5cf36f3",
    "Image": "31fa814ba25ae3426f8710df7a48d567d4022527ef2c14964bb8bc45e653417c",
    "MountLabel": "",
    "Name": "/hungry_kirch",
    "NetworkSettings": {
        "Bridge": "docker0",
        "Gateway": "172.17.42.1",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAddress": "172.17.0.10",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "LinkLocalIPv6Address": "fe80::42:acff:fe11:a",
        "LinkLocalIPv6PrefixLen": 64,
        "MacAddress": "02:42:ac:11:00:0a",
        "PortMapping": null,
        "Ports": {
            "5000/tcp": [
                {
                    "HostIp": "0.0.0.0",
                    "HostPort": "49155"
                }
            ]
        }
    },
    "Path": "python",
    "ProcessLabel": "",
    "ResolvConfPath": "/var/lib/docker/containers/468cd593eadaea6d18441a33ca6c1ea42f1b398d6fd028fa5b557181a5cf36f3/resolv.conf",
    "RestartCount": 0,
    "State": {
        "Error": "",
        "ExitCode": 0,
        "FinishedAt": "0001-01-01T00:00:00Z",
        "OOMKilled": false,
        "Paused": false,
        "Pid": 8580,
        "Restarting": false,
        "Running": true,
        "StartedAt": "2015-03-31T10:00:32.898205331Z"
    },
    "Volumes": {},
    "VolumesRW": {}
}
]
$</pre><p></p>
<h2>Working with Docker Images</h2>
<p>As we have explained, Docker runs container by using images that are either installed in your system or exists at <a href="https://hub.docker.com/" title="Docker Hub" target="_blank">Docker Hub</a> (in order to download it and install in your system)</p>
<p>You can see what images are already installed with the <strong><em>docker images</em></strong> command.  </p>
<p></p><pre class="crayon-plain-tag">$ sudo docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu                  trusty-20150320     d0955f21bf24        11 days ago         188.3 MB
ubuntu                  14.04               d0955f21bf24        11 days ago         188.3 MB
ubuntu                  14.04.2             d0955f21bf24        11 days ago         188.3 MB
ubuntu                  latest              d0955f21bf24        11 days ago         188.3 MB
ubuntu                  trusty              d0955f21bf24        11 days ago         188.3 MB
training/webapp         latest              31fa814ba25a        10 months ago       278.8 MB
$</pre><p></p>
<p>If you want to manually install an image before running it, you can use the <strong><em>docker pull</em></strong> command for images that you can find at <a href="https://hub.docker.com/" title="Docker Hub" target="_blank">Docker Hub</a> or with the command <strong><em>docker search</em></strong>. </p>
<p>As a curiosity, if you look for images at Docker Hub, you can find Official repos, for instance, the <a href="Java OFFICIAL REPO" title="https://registry.hub.docker.com/_/java/" target="_blank">Java OFFICIAL REPO</a>.</p>
<p>You can add a new name to the image with the <strong><em>docker tag</em></strong>.</p>
<p>If you want to remove an image, you can do so with the <strong><em>docker rmi</em></strong> command.</p>
<h3>A note about the official images</h3>
<p>The images and relevant files are maintained at GitHub by an organization called <a href="https://github.com/docker-library" title="docker-library" target="_blank">docker-library</a> (Docker is open source, and it&#8217;s maintained at GitHub by an organization called <a href="https://github.com/docker" title="Docker" target="_blank">Docker</a>, that has several repositories, including the one for <a href="https://github.com/docker/docker" title="Docker - the open-source application container engine" target="_blank">docker</a>).</p>
<p>The official images exist in a repository, <a href="https://github.com/docker-library/official-images" title="Docker Official Images" target="_blank">Docker Official Images</a>, that contains a folder for the <a href="https://github.com/docker-library/official-images/tree/master/library" title="official-images/library" target="_blank">library definitions</a>, for instance, the one for <a href="https://github.com/docker-library/official-images/blob/master/library/java" title="official-images/library/java" target="_blank">java</a>.</p>
<p>The image packages are also maintained by docker-library in each corresponding repository, for instance, the <a href="https://github.com/docker-library/java" title="Docker Official Image packaging for Java (openJDK)" target="_blank">Docker Official Image packaging for Java</a> (<a href="http://openjdk.java.net/" title="OpenJDK" target="_blank">openJDK</a>)</p>
<p>It&#8217;s worth to mention it because there is another organization at GitHub called <a href="https://github.com/dockerfile" title="Dockerfile Project" target="_blank"></a> (<em>Trusted Automated Docker Builds</em>) that has repositories for several Docker builds, for instance, the one for <a href="https://github.com/dockerfile/java" title="Java Dockerfile for trusted automated Docker builds" target="_blank">Java</a>, that includes an image for <a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html" title="Java SE Development Kit 8 Downloads" target="_blank">Oracle Java 8 JDK</a> (that I was looking for) </p>
<h3>Creating your own images</h3>
<p>There are two ways for updating and creating images.</p>
<ol>
<li>Run a container from an image (<em>docker run</em>), then update it, and finally commit the results to an image, with the <em><strong>docker commit</strong></em> command.</li>
<li>Use a <em><strong>Dockerfile</strong></em> to create an image.</li>
</ol>
<p>When you&#8217;re done, you can push the created image to Docker Hub with the <strong><em>docker push</em></strong> command.</p>
<p>Finally, you can remove images with the <strong><em>docker rmi</em></strong> command.</p>
<p></p><pre class="crayon-plain-tag">$ sudo docker run -t -i ubuntu:latest /bin/bash
root@98bec5327540:/# sudo apt-get install --reinstall software-properties-common
root@98bec5327540:/# sudo add-apt-repository ppa:webupd8team/java
root@98bec5327540:/# sudo apt-get update
root@98bec5327540:/# sudo apt-get install oracle-java8-installer
root@98bec5327540:/# sudo apt-get install nano
root@98bec5327540:/# wget http://apache.rediris.es/maven/maven-3/3.3.1/binaries/apache-maven-3.3.1-bin.tar.gz
root@98bec5327540:/# tar -xvf apache-maven-3.3.1-bin.tar.gz 
root@98bec5327540:/# cp -r apache-maven-3.3.1 /usr/local/apache-maven
root@98bec5327540:/# sudo nano /etc/environment
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/apache-maven/bin"
JAVA_HOME="/usr/lib/jvm/java-8-oracle"
MAVEN_OPTS="-Xms256m -Xmx512m"
root@98bec5327540:/# source /etc/environment 
root@98bec5327540:/# echo $JAVA_HOME
/usr/lib/jvm/java-8-oracle
root@98bec5327540:/# java -version
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b25)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)
root@98bec5327540:/# mvn -version
Apache Maven 3.3.1 (cab6659f9874fa96462afef40fcf6bc033d58c1c; 2015-03-13T20:10:27+00:00)
Maven home: /usr/local/apache-maven
Java version: 1.8.0_40, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-8-oracle/jre
Default locale: en_US, platform encoding: ANSI_X3.4-1968
OS name: "linux", version: "3.13.0-48-generic", arch: "amd64", family: "unix"
root@98bec5327540:/# exit
$ sudo docker ps -a
CONTAINER ID        IMAGE                    COMMAND                CREATED             STATUS                        PORTS               NAMES
98bec5327540        ubuntu:14.04             "/bin/bash"            47 minutes ago      Exited (0) 4 minutes ago                          determined_carson   
468cd593eada        training/webapp:latest   "python app.py"        2 hours ago         Exited (137) 2 minutes ago                        hungry_kirch        
e84ae6413888        ubuntu:14.04             "/bin/sh -c 'while t   5 days ago          Exited (137) 3 hours ago                          Javier              
0f5e5a64c583        ubuntu:14.04             "/bin/bash"            11 days ago         Exited (0) 11 days ago                            dreamy_hopper     

$ sudo docker commit -m "Ubuntu latest (14.04) with  Oracle Java 8 JDK and Apache Maven 3.3.1 (and nano editor)" -a "Javier Beneito Barquero" 98bec5327540 jbbarquero/ubuntu-java8_oracle-maven
e262639379c46afa53eca74de9df9bd2f81e0ab7839a3472cafb67d7e199d85e
$

$ sudo docker images
REPOSITORY                             TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
jbbarquero/ubuntu-java8_oracle-maven   latest              e262639379c4        56 seconds ago      828 MB
ubuntu                                 14.04               d0955f21bf24        11 days ago         188.3 MB
ubuntu                                 14.04.2             d0955f21bf24        11 days ago         188.3 MB
ubuntu                                 latest              d0955f21bf24        11 days ago         188.3 MB
ubuntu                                 trusty              d0955f21bf24        11 days ago         188.3 MB
ubuntu                                 trusty-20150320     d0955f21bf24        11 days ago         188.3 MB
centos                                 latest              88f9454e60dd        3 weeks ago         210 MB
hello-world                            latest              e45a5af57b00        12 weeks ago        910 B
training/webapp                        latest              31fa814ba25a        10 months ago       278.8 MB
$ sudo docker tag jbbarquero/ubuntu-java8_oracle-maven my-java8
$ sudo docker images
REPOSITORY                             TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
jbbarquero/ubuntu-java8_oracle-maven   latest              e262639379c4        About a minute ago   828 MB
my-java8                               latest              e262639379c4        About a minute ago   828 MB
ubuntu                                 trusty-20150320     d0955f21bf24        11 days ago          188.3 MB
ubuntu                                 14.04               d0955f21bf24        11 days ago          188.3 MB
ubuntu                                 14.04.2             d0955f21bf24        11 days ago          188.3 MB
ubuntu                                 latest              d0955f21bf24        11 days ago          188.3 MB
ubuntu                                 trusty              d0955f21bf24        11 days ago          188.3 MB
centos                                 latest              88f9454e60dd        3 weeks ago          210 MB
hello-world                            latest              e45a5af57b00        12 weeks ago         910 B
training/webapp                        latest              31fa814ba25a        10 months ago        278.8 MB

$ sudo docker run -t -i my-java8 /bin/bash
root@da1045b88138:/# mvn -version
Apache Maven 3.3.1 (cab6659f9874fa96462afef40fcf6bc033d58c1c; 2015-03-13T20:10:27+00:00)
Maven home: /usr/local/apache-maven
Java version: 1.8.0_40, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-8-oracle/jre
Default locale: en_US, platform encoding: ANSI_X3.4-1968
OS name: "linux", version: "3.13.0-48-generic", arch: "amd64", family: "unix"
root@da1045b88138:/# exit
exit
$ 

$ sudo docker push jbbarquero/ubuntu-java8_oracle-maven
The push refers to a repository [jbbarquero/ubuntu-java8_oracle-maven] (len: 1)
Sending image list

Please login prior to push:
Username: jbbarquero
Password: 
Email: jbbarquero@gmail.com
Login Succeeded
The push refers to a repository [jbbarquero/ubuntu-java8_oracle-maven] (len: 1)
Sending image list
Pushing repository jbbarquero/ubuntu-java8_oracle-maven (1 tags)
511136ea3c5a: Image already pushed, skipping 
f3c84ac3a053: Image already pushed, skipping 
a1a958a24818: Image already pushed, skipping 
9fec74352904: Image already pushed, skipping 
d0955f21bf24: Image already pushed, skipping 
e262639379c4: Image successfully pushed 
Pushing tag for rev [e262639379c4] on {https://cdn-registry-1.docker.io/v1/repositories/jbbarquero/ubuntu-java8_oracle-maven/tags/latest}
$</pre><p></p>
<p>You can find this image at <a href="https://registry.hub.docker.com/u/jbbarquero/ubuntu-java8_oracle-maven/" title="jbbarquero / ubuntu-java8_oracle-maven" target="_blank">jbbarquero / ubuntu-java8_oracle-maven</a></p>
<p>How to <a href="https://docs.docker.com/reference/builder/" title="Dockerfile Reference" target="_blank">write a Dockerfile</a> is out of the bounds of this first post, but I can create a very basic one. Just for fun.</p>
<p>Having this Dockerfile:</p>
<p></p><pre class="crayon-plain-tag"># This is a comment
FROM jbbarquero/ubuntu-java8_oracle-maven
MAINTAINER Javier Beneito Barquero &lt;jbbarquero@gmail.com&gt;
RUN apt-get update &amp;&amp; apt-get install -y git</pre><p></p>
<p>Just build it (and then push it)</p>
<p></p><pre class="crayon-plain-tag">$ sudo docker build -t jbbarquero/ubuntu-java8_oracle-maven-git .
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon 
Step 0 : FROM jbbarquero/ubuntu-java8_oracle-maven
 ---> e262639379c4
Step 1 : MAINTAINER Javier Beneito Barquero <jbbarquero@gmail.com>
 ---> Running in d1be5fc2ed6e
 ---> 162fdb8b3a3d
Removing intermediate container d1be5fc2ed6e
Step 2 : RUN apt-get update && apt-get install -y git
 ---> Running in b7c2cf318638

... Lot of installation messages here

 ---> f63b88cf14ab
Removing intermediate container b7c2cf318638
Successfully built f63b88cf14ab
$ sudo docker images
REPOSITORY                                 TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
jbbarquero/ubuntu-java8_oracle-maven-git   latest              f63b88cf14ab        17 seconds ago      876.5 MB
...

$ sudo docker run -t -i jbbarquero/ubuntu-java8_oracle-maven-git /bin/bash
root@bb9caa298372:/# git --version
git version 1.9.1
root@bb9caa298372:/# mvn -version
Apache Maven 3.3.1 (cab6659f9874fa96462afef40fcf6bc033d58c1c; 2015-03-13T20:10:27+00:00)
Maven home: /usr/local/apache-maven
Java version: 1.8.0_40, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-8-oracle/jre
Default locale: en_US, platform encoding: ANSI_X3.4-1968
OS name: "linux", version: "3.13.0-48-generic", arch: "amd64", family: "unix"
root@bb9caa298372:/# exit
exit</pre><p></p>
<p>The new image can be found in Docker Hub, find it at <a href="https://registry.hub.docker.com/u/jbbarquero/ubuntu-java8_oracle-maven-git/http://" title="jbbarquero / ubuntu-java8_oracle-maven-git" target="_blank">jbbarquero / ubuntu-java8_oracle-maven-git</a>.</p>
<h1>Closing words</h1>
<p>That&#8217;s enough for now. There are a couple of interesting topics, but we&#8217;ll leave for another time:</p>
<ul>
<li><a href="https://docs.docker.com/userguide/dockerlinks/" title="Linking Containers Together" target="_blank">Linking Containers</a>, for sending information between containers in Docker.</li>
<li><a href="https://docs.docker.com/userguide/dockervolumes/" title="Managing Data in Containers" target="_blank">Data in containers</a>, for managing data volumes.</li>
</ul>
<h1>Resources</h1>
<ul>
<li><a href="https://docs.docker.com/" title="Docker docs" target="_blank">Docker official documentation</a></li>
<li><a href="https://www.docker.com/tryit/" title="Docker, try it!" target="_blank">Docker 10-minute tutorial</a></li>
<li><a href="https://docs.docker.com/installation/ubuntulinux/" title="Docker installation: Ubuntu" target="_blank">Docker installation: Ubuntu</a></li>
<li><a href="http://www.manning.com/nickoloff/" title="Docker in Action" target="_blank">Docker in Action</a>. By Jeff Nickoloff (Manning)</li>
<li><a href="http://www.manning.com/miell/" title="Docker in Practice" target="_blank">Docker in Practice</a>. By Ian Miell and Aidan Hobson Sayers (Manning)</li>
</li>
<li><a href="http://www.webupd8.org/2012/09/install-oracle-java-8-in-ubuntu-via-ppa.html" title="install oracle java 8 in ubuntu via ppa repository [jdk8]" target="_blank">Install oracle java 8 in ubuntu via ppa repository [jdk8]</a></li>
<li><a href="http://askubuntu.com/questions/38021/how-to-add-a-ppa-on-a-server" title="How to add a PPA on a server?" target="_blank">How to add a PPA on a server?</a></li>
<li><a href="https://help.ubuntu.com/community/Nano" title="Nano" target="_blank">Nano at Ubuntu</a></li>
<li><a href="https://maven.apache.org/download.cgi" title="Download Apache Maven 3.3.1" target="_blank">Download Apache Maven 3.3.1</a></li>
</ul>
<h1>Post scríptum</h1>
<p>When re-starting the container jbbarquero/ubuntu-java8_oracle-maven, <em>source /etc/environment</em> is not called, so the values that I wrote there are not applied. For solving this issue, I edited /etc/bash.bashrc and I put there the environment variables.</p>
<p></p><pre class="crayon-plain-tag">root@98bec5327540:/# sudo nano /etc/bash.bashrc
$ sudo docker start -i 98bec5327540
root@98bec5327540:/# sudo nano /etc/bash.bashrc

JAVA_HOME="/usr/lib/jvm/java-8-oracle"
export JAVA_HOME

M2_HOME=/usr/local/apache-maven
export M2_HOME
M2=$M2_HOME/bin
export M2

PATH=$PATH:$JAVA_HOME
PATH=$PATH:$M2
export PATH

root@98bec5327540:/# exit</pre><p></p>
<p>Maybe a <strong>Dockerfile</strong> is a better idea to create containers with <a href="https://docs.docker.com/reference/builder/#env" title="Dockerfile Reference: ENV instruction" target="_blank">environment variables using ENV</a>.<br />
so the values that I wrote there</p>
]]></content:encoded>
			<wfw:commentRss>http://malsolo.com/blog4java/?feed=rss2&#038;p=794</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction to Spring Batch. Part II: more on running a Job</title>
		<link>http://malsolo.com/blog4java/?p=375</link>
		<comments>http://malsolo.com/blog4java/?p=375#comments</comments>
		<pubDate>Thu, 04 Sep 2014 15:45:23 +0000</pubDate>
		<dc:creator><![CDATA[Javier (@jbbarquero)]]></dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Springsource]]></category>
		<category><![CDATA[JSR-352]]></category>
		<category><![CDATA[Spring Batch]]></category>
		<category><![CDATA[Spring Framework]]></category>

		<guid isPermaLink="false">http://malsolo.com/blog4java/?p=375</guid>
		<description><![CDATA[In the previous blog post entry, we introduced Spring Batch with a simple exposition of its features, main concepts both for configuring and running Batch Jobs. We also saw a sample application and two ways of running it: by invoking &#8230; <a href="http://malsolo.com/blog4java/?p=375">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>In the previous blog post entry, <a href="http://malsolo.com/blog4java/?p=260" title="Introduction to Spring Batch" target="_blank">we introduced Spring Batch</a> with a simple exposition of its features, main concepts both for configuring and running Batch Jobs.</p>
<p>We also saw a sample application and two ways of running it: by invoking a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobLauncher.html" title="Interface JobLauncher" target="_blank">JobLauncher</a> bean or by using <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/support/CommandLineJobRunner.html" title="Class CommandLineJobRunner" target="_blank">CommandLineJobRunner</a> from the command line.</p>
<p>In this blog entry, we&#8217;ll see two additional ways to run a Spring Batch job:</p>
<ol>
<li>Using <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobOperator.html" title="Interface JobOperator" target="_blank">JobOperator</a>, in order to have control of the batch process, from start a job to monitoring tasks such as stopping, restarting, or summarizing a Job. We&#8217;ll only pay attention to the start operation, but once a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobOperator.html" title="Interface JobOperator" target="_blank">JobOperator</a> is configured, you can use for the remaining monitoring tasks.</li>
<li>Using <a href="http://projects.spring.io/spring-boot/" title="Spring Boot" target="_blank">Spring Boot</a>, the new convention-over-configuration centric framework from the Spring team, that allows you to create with a few lines of code applications that &#8220;just run&#8221;, because Spring Boot provides a lot of features based on what you have in your classpath.</li>
</ol>
<p>As usual, all the source code is available at <a href="https://github.com/jbbarquero/spring-batch-sample" title="My Spring Batch sample at GitHub" target="_blank">GitHub</a>.</p>
<h3>Running the sample: JobOperator</h3>
<p><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobOperator.html" title="Interface JobOperator" target="_blank">JobOperator</a> is an interface that provides operations <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#JobOperator" title="JobOperator" target="_blank">for inspecting and controlling jobs</a>, mainly for a command-line client or a remote launcher like a JMX console.</p>
<p>The implementation that Spring Batch provides, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/support/SimpleJobOperator.html" title="Class SimpleJobOperator" target="_blank">SimpleJobOperator</a>, uses <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobLauncher.html" title="Interface JobLauncher" target="_blank">JobLauncher</a>, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/repository/JobRepository.html" title="Interface JobRepository" target="_blank">JobRepository</a>, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/explore/JobExplorer.html" title="Interface JobExplorer" target="_blank">JobExplorer</a>, and <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/JobRegistry.html" title="Interface JobRegistry" target="_blank">JobRegistry</a> for performing its operations. They are created by the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.html" title="Annotation Type EnableBatchProcessing" target="_blank">@EnableBatchProcessing</a> annotation, so we can create an <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/AdditionalBatchConfiguration.java" title="AdditionalBatchConfiguration.java" target="_blank">additional batch configuration</a> file with these dependencies autowired and later import it in the <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/BatchConfiguration.java" title="BatchConfiguration.java" target="_blank">batch configuration</a> file (not without issues, due to the way Spring loads the application context, we&#8217;ll see this shortly):</p>
<p></p><pre class="crayon-plain-tag">@Configuration
public class AdditionalBatchConfiguration {

    @Autowired
    JobRepository jobRepository;
    @Autowired
    JobRegistry jobRegistry;
    @Autowired
    JobLauncher jobLauncher;
    @Autowired
    JobExplorer jobExplorer;

    @Bean
    public JobOperator jobOperator() {
        SimpleJobOperator jobOperator = new SimpleJobOperator();
        jobOperator.setJobExplorer(jobExplorer);
        jobOperator.setJobLauncher(jobLauncher);
        jobOperator.setJobRegistry(jobRegistry);
        jobOperator.setJobRepository(jobRepository);
        return jobOperator;
    }

}</pre><p></p>
<p>And the <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/annotation/Import.html" title="Annotation Type Import" target="_blank">@Import</a>:</p>
<p></p><pre class="crayon-plain-tag">@Configuration
@EnableBatchProcessing
@Import(AdditionalBatchConfiguration.class)
public class BatchConfiguration {

	// Omitted

}</pre><p></p>
<p>Now it seems easy to run the job with a <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/MainJobOperator.java" title="MainJobOperator.java" target="_blank">main class</a>:</p>
<p></p><pre class="crayon-plain-tag">@Component
public class MainJobOperator {

    @Autowired
    JobOperator jobOperator;

    @Autowired
    Job importUserJob;

    public static void main(String... args) throws JobParametersInvalidException, JobInstanceAlreadyExistsException, NoSuchJobException, DuplicateJobException, NoSuchJobExecutionException {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);

        MainJobOperator main = context.getBean(MainJobOperator.class);
        long executionId = main.jobOperator.start(main.importUserJob.getName(), null);

        MainHelper.reportResults(main.jobOperator, executionId);
        MainHelper.reportPeople(context.getBean(JdbcTemplate.class));

        context.close();

        System.out.printf(&quot;\nFIN %s&quot;, main.getClass().getName());

    }
}</pre><p></p>
<p>But there&#8217;s a little problem&#8230; it doesn&#8217;t work:</p>
<p></p><pre class="crayon-plain-tag">Exception in thread "main" org.springframework.batch.core.launch.NoSuchJobException: No job configuration with the name [importUserJob] was registered
	at org.springframework.batch.core.configuration.support.MapJobRegistry.getJob(MapJobRegistry.java:66)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:483)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
	at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
	at com.sun.proxy.$Proxy14.getJob(Unknown Source)
	at org.springframework.batch.core.launch.support.SimpleJobOperator.start(SimpleJobOperator.java:310)
	at com.malsolo.springframework.batch.sample.MainJobOperator.main(MainJobOperator.java:15)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:483)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

Process finished with exit code 1</pre><p></p>
<p>The problem here, <em><font color=red>No job configuration with the name [<strong>importUserJob</strong>] was registered</font></em>, is due to the way that <a href="http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/core/launch/JobOperator.html#start-java.lang.String-java.lang.String-" title="API" target="_blank">JobOperator.start(String jobName, String parameters)</a> works.</p>
<p>The main difference with <a href="http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/core/launch/JobLauncher.html#run-org.springframework.batch.core.Job-org.springframework.batch.core.JobParameters-" title="API" target="_blank">JobLauncher.run(Job job, JobParameters jobParameters)</a> is that the former has String as parameters while the latter uses objects directly.</p>
<p>So <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobOperator.html" title="Interface JobOperator" target="_blank">JobOperator</a>, actually <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/support/SimpleJobOperator.html" title="Class SimpleJobOperator" target="_blank">SimpleJobOperator</a>, has to obtain a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/Job.html" title="Interface Job" target="_blank">Job</a> with the provided name. In order to do so, it uses the <a href="http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/core/configuration/JobLocator.html#getJob-java.lang.String-" title="API" target="_blank">JobRegistry.getJob(String name)</a> method. The available Spring Batch implementation is <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/support/MapJobRegistry.html" title="Class MapJobRegistry" target="_blank">MapJobRegistry</a> that uses a ConcurrentMap to store using the job name as the key, a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/JobFactory.html" title="Interface JobFactory" target="_blank">JobFactory</a> to create the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/Job.html" title="Interface Job" target="_blank">Job</a> when requested.</p>
<p>The problem is that this map has not been populated.</p>
<p>The first solution is easy: the JobRegistry allows you to register at runtime a JobFactory to later obtain the Job as explained above. So, we only need to create this JobFactory&#8230;</p>
<p></p><pre class="crayon-plain-tag">@Configuration
public class AdditionalBatchConfiguration {
//    Rest omitted
    @Autowired
    Job importUserJob;

    @Bean
    public JobFactory jobFactory() {
        return new ReferenceJobFactory(importUserJob);
    }
}</pre><p></p>
<p>&#8230;and register it in the main method:</p>
<p></p><pre class="crayon-plain-tag">@Component
public class MainJobOperator {

    @Autowired
    JobFactory jobFactory;
    @Autowired
    JobRegistry jobRegistry;
    @Autowired
    JobOperator jobOperator;

    @Autowired
    Job importUserJob;

    public static void main(String... args) throws JobParametersInvalidException, JobInstanceAlreadyExistsException, NoSuchJobException, DuplicateJobException, NoSuchJobExecutionException {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);

        MainJobOperator main = context.getBean(MainJobOperator.class);
        main.jobRegistry.register(main.jobFactory);
        long executionId = main.jobOperator.start(main.importUserJob.getName(), null);

        MainHelper.reportResults(main.jobOperator, executionId);
        MainHelper.reportPeople(context.getBean(JdbcTemplate.class));

        context.close();

        System.out.printf(&quot;\nFIN %s&quot;, main.getClass().getName());

    }
}</pre><p></p>
<p>And now it works:</p>
<p></p><pre class="crayon-plain-tag">***********************************************************
JobExecution: id=0, version=2, startTime=2014-09-04 13:03:37.964, endTime=2014-09-04 13:03:38.141, lastUpdated=2014-09-04 13:03:38.141, status=COMPLETED, exitStatus=exitCode=COMPLETED;exitDescription=, job=[JobInstance: id=0, version=0, Job=[importUserJob]], jobParameters=[{}]
* Steps executed:
StepExecution: id=0, version=3, name=step1, status=COMPLETED, exitStatus=COMPLETED, readCount=5, filterCount=0, writeCount=5 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
***********************************************************
***********************************************************
* People found:

* Found firstName: JILL, lastName: DOE in the database

* Found firstName: JOE, lastName: DOE in the database

* Found firstName: JUSTIN, lastName: DOE in the database

* Found firstName: JANE, lastName: DOE in the database

* Found firstName: JOHN, lastName: DOE in the database
***********************************************************</pre><p></p>
<p>But I don&#8217;t like this approach, it&#8217;s too manual.</p>
<p>I&#8217;d rather to populate the JobRegistry automatically, and Spring Batch provides two mechanisms for doing so, <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#d4e1228" title="JobRegistryBeanPostProcessor" target="_blank">a bean post-processor</a>, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.html" title="Class JobRegistryBeanPostProcessor" target="_blank">JobRegistryBeanPostProcessor</a>, and <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#d4e1233" title="AutomaticJobRegistrar" target="_blank"> a component</a> that loads and unloads Jobs by creating child context and registering  jobs from those contexts as they are created, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/support/AutomaticJobRegistrar.html" title="Class AutomaticJobRegistrar" target="_blank">AutomaticJobRegistrar</a>.</p>
<p>We&#8217;ll see the post-processor approach, because it&#8217;s very easy. Just declare the bean in the Batch configuration and run the original main class.</p>
<p></p><pre class="crayon-plain-tag">@Configuration
@EnableBatchProcessing
@Import(AdditionalBatchConfiguration.class)
public class BatchConfiguration {

	// Omitted

    @Bean
    public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) {
        JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor = new JobRegistryBeanPostProcessor();
        jobRegistryBeanPostProcessor.setJobRegistry(jobRegistry);
        return jobRegistryBeanPostProcessor;
    }

}</pre><p></p>
<p>The bean post processor has to be declared in this configuration file for registering the job when it&#8217;s created (this is the issue that I mentioned before, if you declare the post processor in another java file configuration, for instance in the <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/AdditionalBatchConfiguration.java" title="AdditionalBatchConfiguration.java" target="_blank">AdditionalBatchConfiguration</a> it will never receive the job bean). It uses the same <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/JobRegistry.html" title="Interface JobRegistry" target="_blank">JobRegistry</a> that uses the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobOperator.html" title="Interface JobOperator" target="_blank">JobOperator</a> to launch the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/Job.html" title="Interface Job" target="_blank">Job</a>. Actually the only that exists, but it&#8217;s good to know this.</p>
<p>It also works:</p>
<p></p><pre class="crayon-plain-tag">***********************************************************
JobExecution: id=0, version=2, startTime=2014-09-04 13:20:07.343, endTime=2014-09-04 13:20:07.522, lastUpdated=2014-09-04 13:20:07.522, status=COMPLETED, exitStatus=exitCode=COMPLETED;exitDescription=, job=[JobInstance: id=0, version=0, Job=[importUserJob]], jobParameters=[{}]
* Steps executed:
StepExecution: id=0, version=3, name=step1, status=COMPLETED, exitStatus=COMPLETED, readCount=5, filterCount=0, writeCount=5 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
***********************************************************
***********************************************************
* People found:

* Found firstName: JILL, lastName: DOE in the database

* Found firstName: JOE, lastName: DOE in the database

* Found firstName: JUSTIN, lastName: DOE in the database

* Found firstName: JANE, lastName: DOE in the database

* Found firstName: JOHN, lastName: DOE in the database
***********************************************************</pre><p></p>
<h3>Running the sample: Spring Boot</h3>
<p>We&#8217;d like to try how quickly and easy is Spring Boot for launching Spring Batch applications once we already have a functional configuration.</p>
<p>And it seems to be a piece of cake (the problem here is to know what is happening under the hood)</p>
<p></p><pre class="crayon-plain-tag">package com.malsolo.springframework.batch.sample;
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ApplicationConfiguration.class)})
@EnableAutoConfiguration
public class MainBoot {

    public static void main(String... args) {

        ApplicationContext context = SpringApplication.run(MainBoot.class);

        MainHelper.reportPeople(context.getBean(JdbcTemplate.class));

    }
}</pre><p></p>
<p>Actually, Spring Boot is out of the bounds of this topic, it deserves its own entry (even, an entire book) but we can summarize the important code here:</p>
<ul>
<li>Line 3: <a href="http://docs.spring.io/spring-boot/docs/current/api/index.html?org/springframework/boot/autoconfigure/EnableAutoConfiguration.html" title="Annotation Type EnableAutoConfiguration" target="_blank">@EnableAutoConfiguration</a>, with this annotation you want Spring Boot to instantiate the beans that you&#8217;re going to need based on the libraries on your classpath.</li>
<li>Line 8: <a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/SpringApplication.html#run(java.lang.Object[], java.lang.String[])" title="API" target="_blank">the run method</a>, to bootstrap the application by passing the class itself (in our case, <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/MainBoot.java" title="MainBoot.java" target="_blank">MainBoot</a>) that serves as the primary Spring component.
</ul>
<p>It&#8217;s enough to run the Batch application:</p>
<p></p><pre class="crayon-plain-tag">.   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.1.4.RELEASE)

2014-09-04 16:58:55.109  INFO 15646 --- [           main] c.m.s.batch.sample.MainBoot              : Starting MainBoot on jbeneito-Latitude-3540 with PID 15646 (/home/jbeneito/Documents/git/spring-batch-sample/target/classes started by jbeneito in /home/jbeneito/Documents/git/spring-batch-sample)
2014-09-04 16:58:55.237  INFO 15646 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6366ebe0: startup date [Thu Sep 04 16:58:55 CEST 2014]; root of context hierarchy
2014-09-04 16:58:56.039  INFO 15646 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'jdbcTemplate': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=batchConfiguration; factoryMethodName=jdbcTemplate; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/malsolo/springframework/batch/sample/BatchConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=mainForSpringInfo; factoryMethodName=jdbcTemplate; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/malsolo/springframework/batch/sample/MainForSpringInfo.class]]
2014-09-04 16:58:56.691  WARN 15646 --- [           main] o.s.c.a.ConfigurationClassEnhancer       : @Bean method ScopeConfiguration.stepScope is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean Javadoc for complete details
2014-09-04 16:58:56.724  WARN 15646 --- [           main] o.s.c.a.ConfigurationClassEnhancer       : @Bean method ScopeConfiguration.jobScope is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean Javadoc for complete details
2014-09-04 16:58:56.729  INFO 15646 --- [           main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2014-09-04 16:58:56.975  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'batchConfiguration' of type [class com.malsolo.springframework.batch.sample.BatchConfiguration$$EnhancerBySpringCGLIB$$c3ec56ab] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:57.145  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [class org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$5a15b25b] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:57.238  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'transactionAttributeSource' of type [class org.springframework.transaction.annotation.AnnotationTransactionAttributeSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:57.294  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'transactionInterceptor' of type [class org.springframework.transaction.interceptor.TransactionInterceptor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:57.301  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.config.internalTransactionAdvisor' of type [class org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:57.374  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'dataSourceConfiguration' of type [class com.malsolo.springframework.batch.sample.DataSourceConfiguration$$EnhancerBySpringCGLIB$$18a97d02] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:57.455  INFO 15646 --- [           main] o.s.j.d.e.EmbeddedDatabaseFactory        : Creating embedded database 'testdb'
2014-09-04 16:58:58.156  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from class path resource [schema-all.sql]
2014-09-04 16:58:58.178  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from class path resource [schema-all.sql] in 20 ms.
2014-09-04 16:58:58.178  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from class path resource [org/springframework/batch/core/schema-hsqldb.sql]
2014-09-04 16:58:58.189  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from class path resource [org/springframework/batch/core/schema-hsqldb.sql] in 11 ms.
2014-09-04 16:58:58.198  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'dataSource' of type [class org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory$EmbeddedDataSourceProxy] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:58.206  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$DataSourceInitializerConfiguration' of type [class org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$DataSourceInitializerConfiguration$$EnhancerBySpringCGLIB$$c0608242] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:58.257  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'spring.datasource.CONFIGURATION_PROPERTIES' of type [class org.springframework.boot.autoconfigure.jdbc.DataSourceProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:58.260  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from URL [file:/home/jbeneito/Documents/git/spring-batch-sample/target/classes/schema-all.sql]
2014-09-04 16:58:58.262  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from URL [file:/home/jbeneito/Documents/git/spring-batch-sample/target/classes/schema-all.sql] in 2 ms.
2014-09-04 16:58:58.263  WARN 15646 --- [           main] o.s.b.a.jdbc.DataSourceInitializer       : Could not send event to complete DataSource initialization (ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.context.annotation.AnnotationConfigApplicationContext@6366ebe0: startup date [Thu Sep 04 16:58:55 CEST 2014]; root of context hierarchy)
2014-09-04 16:58:58.263  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'dataSourceInitializer' of type [class org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:58.277  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration' of type [class org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$$EnhancerBySpringCGLIB$$85a27e41] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:58.320  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'jobRegistry' of type [class com.sun.proxy.$Proxy25] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:58.795  INFO 15646 --- [           main] o.s.b.c.r.s.JobRepositoryFactoryBean     : No database type set, using meta data indicating: HSQL
2014-09-04 16:58:59.056  INFO 15646 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : No TaskExecutor has been set, defaulting to synchronous executor.
2014-09-04 16:58:59.361  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from class path resource [org/springframework/batch/core/schema-hsqldb.sql]
2014-09-04 16:58:59.381  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from class path resource [org/springframework/batch/core/schema-hsqldb.sql] in 20 ms.
2014-09-04 16:58:59.890  INFO 15646 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2014-09-04 16:58:59.926  INFO 15646 --- [           main] o.s.b.a.b.JobLauncherCommandLineRunner   : Running default command line with: []
2014-09-04 16:59:00.023  INFO 15646 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [FlowJob: [name=importUserJob]] launched with the following parameters: [{run.id=1}]
2014-09-04 16:59:00.060  INFO 15646 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [step1]
Converting (firstName: Jill, lastName: Doe) into (firstName: JILL, lastName: DOE)
Converting (firstName: Joe, lastName: Doe) into (firstName: JOE, lastName: DOE)
Converting (firstName: Justin, lastName: Doe) into (firstName: JUSTIN, lastName: DOE)
Converting (firstName: Jane, lastName: Doe) into (firstName: JANE, lastName: DOE)
Converting (firstName: John, lastName: Doe) into (firstName: JOHN, lastName: DOE)
2014-09-04 16:59:00.162  INFO 15646 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [FlowJob: [name=importUserJob]] completed with the following parameters: [{run.id=1}] and the following status: [COMPLETED]
2014-09-04 16:59:00.164  INFO 15646 --- [           main] c.m.s.batch.sample.MainBoot              : Started MainBoot in 5.963 seconds (JVM running for 8.019)
***********************************************************
* People found:

* Found firstName: JILL, lastName: DOE in the database

* Found firstName: JOE, lastName: DOE in the database

* Found firstName: JUSTIN, lastName: DOE in the database

* Found firstName: JANE, lastName: DOE in the database

* Found firstName: JOHN, lastName: DOE in the database
***********************************************************
2014-09-04 16:59:00.258  INFO 15646 --- [       Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6366ebe0: startup date [Thu Sep 04 16:58:55 CEST 2014]; root of context hierarchy
2014-09-04 16:59:00.262  INFO 15646 --- [       Thread-1] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown

Process finished with exit code 0</pre><p></p>
<p>As a side note, this class already scans for compontents, so we don’t need to make an additional scan for components, so we exclude the <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/ApplicationConfiguration.java" title="ApplicationConfiguration.java" target="_blank">ApplicationConfiguration</a> class with a filter.</p>
<p>Finally, we use the <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/MainHelper.java" title="MainHelper.java" target="_blank">MainHelper</a> class to show a summary of the results.</p>
<p>That&#8217;s all for now, because one more time this entry is growing really fast. Thus, we&#8217;ll see in the next post the last topic of Spring Batch that I want to talk about: <a href="https://jcp.org/en/jsr/detail?id=352" title="JSR 352: Batch Applications for the Java Platform" target="_blank">JSR 352</a>.</p>
<h3>Resources</h3>
<ul>
<li><a href="https://www.youtube.com/watch?v=lHCPppMlylY" title="Youtube" target="_blank">Webinar: Spring Batch 3.0.0</a> by <strong>Michael Minella</strong>. Published on Jun 18, 2014.</li>
<li><a href="https://www.youtube.com/watch?v=yKs4yPs-5yU" title="youtube" target="_blank">JSR-352, Spring Batch and You</a> by <strong>Michael Minella</strong>. Published on Feb 3, 2014.</li>
<li><a href="https://www.youtube.com/watch?v=8tiqeV07XlI" title="youtube" target="_blank">Integrating Spring Batch and Spring Integration</a> by <strong>Gunnar Hillert</strong>, <strong>Michael Minella</strong>. Published on Jul 9, 2014.</li>
<li><a href="http://www.amazon.com/Pro-Spring-Batch-Experts-Voice/dp/1430234520/ref=sr_1_1?ie=UTF8&#038;qid=1409752293&#038;sr=8-1&#038;keywords=pro+spring+batch" title="Amazon" target="_blank">Pro Spring Batch (Expert&#8217;s Voice in Spring)</a> by <strong>Michael Minella</strong>. Published on July 12, 2011 by <a href="http://www.apress.com/9781430234524" title="Apress" target="_blank">Apress</a>.</li>
<li>Spring Batch in Action by <strong>Arnaud Cogoluegnes</strong>, <strong>Thierry Templier</strong>, <strong>Gary Gregory</strong>, <strong>Olivier Bazoud</strong>. Published on October 10, 2011 by <a href="http://www.manning.com/templier/" title="Manning" target="_blank">Manning Publications</a>.</li>
<li>Spring.io GETTING STARTED GUIDE: <a href="http://spring.io/guides/gs/batch-processing/" title="GETTING STARTED: Creating a Batch Service" target="_blank">Creating a Batch Service</a>.
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/html/" title="Spring Batch - Reference Documentation" target="_blank">Spring Batch &#8211; Reference Documentation</a></li>
<li><a href="http://docs.spring.io/spring-batch/apidocs/index.html?overview-summary.html" title="Spring Batch 3.0.1.RELEASE API" target="_blank">Spring Batch &#8211; API specification</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://malsolo.com/blog4java/?feed=rss2&#038;p=375</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction to Spring Batch</title>
		<link>http://malsolo.com/blog4java/?p=260</link>
		<comments>http://malsolo.com/blog4java/?p=260#comments</comments>
		<pubDate>Wed, 03 Sep 2014 10:58:02 +0000</pubDate>
		<dc:creator><![CDATA[Javier (@jbbarquero)]]></dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Springsource]]></category>
		<category><![CDATA[JSR-352]]></category>
		<category><![CDATA[Spring Batch]]></category>
		<category><![CDATA[Spring Framework]]></category>

		<guid isPermaLink="false">http://malsolo.com/blog4java/?p=260</guid>
		<description><![CDATA[Spring Batch is the Spring Project aimed to write Java Batch applications by using the foundations of Spring Framework. Michael T. Minella, project lead of Spring Batch and also a member of the JSR 352 (Batch Applications for the Java &#8230; <a href="http://malsolo.com/blog4java/?p=260">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><a href="http://projects.spring.io/spring-batch/" title="Spring Batch" target="_blank">Spring Batch</a> is the <a href="http://spring.io/projects" title="Spring Projects" target="_blank">Spring Project</a> aimed <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.html" title="Class DefaultBatchConfigurer" target="_blank"></a>to write Java Batch applications by using the foundations of Spring Framework.</p>
<p><a href="http://spring.io/team/mminella" title="Michael Minella" target="_blank">Michael T. Minella</a>, project lead of Spring Batch and also a member of the <a href="https://jcp.org/en/jsr/detail?id=352" title="JSR 352" target="_blank">JSR 352 (Batch Applications for the Java Platform)</a> expert group, wrote in his book <a href="http://www.amazon.com/Pro-Spring-Batch-Experts-Voice/dp/1430234520" title="Pro Spring Batch" target="_blank">Pro Spring Batch</a> the next definition &#8220;<em>Batch processing [&#8230;] is defined as the processing of data without interaction or interruption. Once started, a batch process runs to some form of completion without any intervention</em>&#8220;.</p>
<p>Typically Batch Jobs are long-running, non-interactive and process large volumes of data, more than fits in memory or a single transaction. Thus they usually run outside office hours and include logic for handling errors   and restarting if necessary.</p>
<p>Spring Batch provides, among others, the next features:</p>
<ul>
<li>Transaction management, to allow you to focus on business processing.</li>
<li>Chunk based processing, to process a large value of data by dividing it in small pieces.</li>
<liDeclarative I/O, by providing readers and writers for a lot of scenarios.</li>
<li>Start/Stop/Restart/Skip/Retry capabilities, to handle non-interactive management of the process.</li>
<li>Web based administration interface (Spring Batch Admin), it provides an API for administering tasks.</li>
<li>Based on Spring framework, so it includes all the configuration options, including Dependency Injection.</li>
<li>Compliance with JSR 352: Batch Applications for the Java Platform.</li>
</ul>
<h3>Spring Batch concepts</h3>
<div id="attachment_266" style="width: 310px" class="wp-caption alignnone"><a href="http://malsolo.com/blog4java/wp-content/uploads/2014/08/spring-batch-reference-model.png"><img src="http://malsolo.com/blog4java/wp-content/uploads/2014/08/spring-batch-reference-model-300x119.png" alt="The Domain Language of Batch" width="300" height="119" class="size-medium wp-image-266" /></a><p class="wp-caption-text">Batch Stereotypes</p></div>
<ul>
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#domainJob" title="Job" target="_blank">Job</a>: an entity that encapsulates an entire batch process. It is composed of one or more ordered <strong>Steps</strong> and it has some properties such as restartability.</li>
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#domainStep" title="Step" target="_blank">Step</a>: a domain object that encapsulates an independent, sequential phase of a batch job.</li>
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#readersAndWriters" title="ItemReaders and ItemWriters and  ItemProcessors" target="_blank">Item</a>: the individual piece of data that it&#8217;s been processed.</li>
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#chunkOrientedProcessing" title="Chunk-Oriented Processing" target="_blank">Chunk</a>: the processing style used by Spring Batch: read and process the item and then aggregate until reach a number of items, called &#8220;<em>chunk</em>&#8221; that will be finally written.</li>
<div id="attachment_271" style="width: 310px" class="wp-caption alignnone"><a href="http://malsolo.com/blog4java/wp-content/uploads/2014/08/chunk-oriented-processing.png"><img src="http://malsolo.com/blog4java/wp-content/uploads/2014/08/chunk-oriented-processing-300x165.png" alt="Chunk-Oriented Processing" width="300" height="165" class="size-medium wp-image-271" /></a><p class="wp-caption-text">Chunk-Oriented Processing</p></div>
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#domainJobLauncher" title="JobLauncher" target="_blank">JobLauncher</a>: the entry point to launch Spring Batch jobs with a given set of JobParameters.</li>
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#domainJobRepository" title="JobRepository" target="_blank">JobRepository</a>: maintains all metadata related to job executions and provides CRUD operations for JobLauncher, Job, and Step implementations.</li>
</ul>
<h3>Running a Job</h3>
<p>The <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobLauncher.html" title="JobLauncher API" target="_blank">JobLauncher</a> interface has a basic implementation <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/support/SimpleJobLauncher.html" title="SimpleJobLauncher API" target="_blank">SimpleJobLauncher</a> whose only required dependency is a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/repository/JobRepository.html" title="JobRepository API" target="_blank">JobRepository</a>, in order to obtain an execution, so that you can use it for executing the Job.</p>
<div id="attachment_275" style="width: 310px" class="wp-caption alignnone"><a href="http://malsolo.com/blog4java/wp-content/uploads/2014/08/job-launcher-sequence-sync.png"><img src="http://malsolo.com/blog4java/wp-content/uploads/2014/08/job-launcher-sequence-sync-300x229.png" alt="JobLauncher" width="300" height="229" class="size-medium wp-image-275" /></a><p class="wp-caption-text">JobLauncher</p></div>
<p>You can also launch a Job asynchronously by configuring a <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/core/task/TaskExecutor.html" title="TaskExecutor API" target="_blank">TaskExecutor</a>. You can also this configuration <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#runningJobsFromWebContainer" title="Running Jobs from within a Web Container" target="_blank">for running Jobs from within a Web Container</a>.</p>
<div id="attachment_277" style="width: 310px" class="wp-caption alignnone"><a href="http://malsolo.com/blog4java/wp-content/uploads/2014/08/job-launcher-sequence-async.png"><img src="http://malsolo.com/blog4java/wp-content/uploads/2014/08/job-launcher-sequence-async-300x229.png" alt="Job launcher sequence async" width="300" height="229" class="size-medium wp-image-277" /></a><p class="wp-caption-text">Job launcher sequence async</p></div>
<p>A <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobLauncher.html" title="JobLauncher API" target="_blank">JobLauncher</a> uses the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/repository/JobRepository.html" title="JobRepository API" target="_blank">JobRepository</a> to create new <strong>JobExecution</strong> objects and run them.</p>
<div id="attachment_281" style="width: 310px" class="wp-caption alignnone"><a href="http://malsolo.com/blog4java/wp-content/uploads/2014/08/job-repository.png"><img src="http://malsolo.com/blog4java/wp-content/uploads/2014/08/job-repository-300x265.png" alt="Job Repository" width="300" height="265" class="size-medium wp-image-281" /></a><p class="wp-caption-text">Job Repository</p></div>
<h3>Running Jobs: concepts</h3>
<p>The main concepts related with Job execution are</p>
<div id="attachment_283" style="width: 310px" class="wp-caption alignnone"><a href="http://malsolo.com/blog4java/wp-content/uploads/2014/08/jobHeirarchyWithSteps.png"><img src="http://malsolo.com/blog4java/wp-content/uploads/2014/08/jobHeirarchyWithSteps-300x220.png" alt="Job hierarchy with steps" width="300" height="220" class="size-medium wp-image-283" /></a><p class="wp-caption-text">Job hierarchy with steps</p></div>
<ul>
<li><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/JobInstance.html" title="JobInstance API" target="_blank">JobInstance</a>: a logical run of a Job.</li>
<li><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/JobParameter.html" title="JobParameter API" target="_blank">JobParameters</a>: a set of parameters used to start a batch job. It categorizes each JobInstance.</li>
<li><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/JobExecution.html" title="JobExecution API" target="_blank">JobExecution</a>: physical runs of Jobs, in order to know what happens with the execution.</li>
<li><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/StepExecution.html" title="StepExecution API" target="_blank">StepExecution</a>: a single attempt to execute a Step, that is created each time a Step is run and it also provides information regarding the result of the processing.</li>
<li><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/ExecutionContext.html" title="ExecutionContext API" target="_blank">ExecutionContext</a>: a collection of key/value pairs that are persisted and controlled by the framework in order to allow developers a place to store persistent state that is scoped to a StepExecution or JobExecution.</li>
</ul>
<h3>Sample application</h3>
<p>Now we are going to see a simple sample application that reads a POJO that represents a Person from a file containing People data and after processing each  of them, that is just uppercase its attributes, saving them in a database.</p>
<p>All the code is available at <a href="https://github.com/jbbarquero/spring-batch-sample" title="My Spring Batch sample at GitHub" target="_blank">GitHub</a>. </p>
<p>Let&#8217;s begin with the basic domain class: <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/Person.java" title="Person.java" target="_blank">Person</a>, just a POJO.</p>
<p></p><pre class="crayon-plain-tag">package com.malsolo.springframework.batch.sample;

public class Person {
    private String lastName;
    private String firstName;
    //...
}</pre><p></p>
<p>Then, let&#8217;s see the simple processor, <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/PersonItemProcessor.java" title="PersonItemProcessor.java" target="_blank">PersonItemProcessor</a>. It implements an <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/ItemProcessor.html" title="ItemProcessor API" target="_blank">ItemProcessor</a>, with a Person both as Input and Output.</p>
<p>It provides a method to be overwritten, <strong>process</strong>, that allows you to write the custom transformation.</p>
<p></p><pre class="crayon-plain-tag">package com.malsolo.springframework.batch.sample;

import org.springframework.batch.item.ItemProcessor;

public class PersonItemProcessor implements ItemProcessor&lt;Person, Person&gt; {

    @Override
    public Person process(final Person person) throws Exception {
        final String firstName = person.getFirstName().toUpperCase();
        final String lastName = person.getLastName().toUpperCase();

        final Person transformedPerson = new Person(firstName, lastName);

        System.out.println(&quot;Converting (&quot; + person + &quot;) into (&quot; + transformedPerson + &quot;)&quot;);

        return transformedPerson;
    }

}</pre><p></p>
<p>Once done this, we can proceed to configure the Spring Batch Application, for doing so, we&#8217;ll use Java Annotations in a <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/BatchConfiguration.java" title="BatchConfiguration.java" target="_blank">BatchConfiguration</a> file:</p>
<p></p><pre class="crayon-plain-tag">// Imports and package omitted
@Configuration
@EnableBatchProcessing
@Import(AdditionalBatchConfiguration.class)
public class BatchConfiguration {

	// Input, processor, and output definition
	
	@Bean
    public ItemReader&lt;Person&gt; reader() {
		FlatFileItemReader&lt;Person&gt; reader = new FlatFileItemReader&lt;Person&gt;();
		reader.setResource(new ClassPathResource(&quot;sample-data.csv&quot;));
		reader.setLineMapper(new DefaultLineMapper&lt;Person&gt;() {{
			setLineTokenizer(new DelimitedLineTokenizer() {{
				setNames(new String[] {&quot;firstName&quot;, &quot;lastName&quot;});
			}});
			setFieldSetMapper(new BeanWrapperFieldSetMapper&lt;Person&gt;() {{
				setTargetType(Person.class);
			}});
			
		}});
		return reader;
	}
	
	@Bean
    public ItemProcessor&lt;Person, Person&gt; processor() {
        return new PersonItemProcessor();
    }
	
	@Bean
    public ItemWriter&lt;Person&gt; writer(DataSource dataSource) {
		JdbcBatchItemWriter&lt;Person&gt; writer = new JdbcBatchItemWriter&lt;Person&gt;();
		writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider&lt;Person&gt;());
		writer.setSql(&quot;INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)&quot;);
		writer.setDataSource(dataSource);
		return writer;
	}
	
	//  Actual job configuration
	
	@Bean
    public Job importUserJob(JobBuilderFactory jobs, Step s1) {
		return jobs.get(&quot;importUserJob&quot;)
				.incrementer(new RunIdIncrementer())
				.flow(s1)
				.end()
				.build();
	}
	
	@Bean
    public Step step1(StepBuilderFactory stepBuilderFactory, ItemReader&lt;Person&gt; reader,
            ItemWriter&lt;Person&gt; writer, ItemProcessor&lt;Person, Person&gt; processor) {
		return stepBuilderFactory.get(&quot;step1&quot;)
				.&lt;Person, Person&gt; chunk(10)
				.reader(reader)
				.processor(processor)
				.writer(writer)
				.build();
	}
	
	@Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
	
}</pre><p></p>
<p>Highlights for this class are:</p>
<ul>
<li>Line 2: <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/annotation/Configuration.html" title="Configuration API" target="_blank">@Configuration</a>, this class will be processed by the <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-java-basic-concepts" title="Java-based container configuration, basic concepts." target="_blank">Spring container to generate bean definitions</a>.</li>
<li>Line 3: <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.html" title="EnableBatchProcessing API" target="_blank">@EnableBatchProcessing</a>, provides a base configuration for building batch jobs <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#javaConfig" title="Spring Batch Java Config" target="_blank">by creating the next beans beans available to be autowired</a>:
<ul>
<li>JobRepository &#8211; bean name &#8220;jobRepository&#8221;</li>
<li>JobLauncher &#8211; bean name &#8220;jobLauncher&#8221;</li>
<li>JobRegistry &#8211; bean name &#8220;jobRegistry&#8221;</li>
<li>PlatformTransactionManager &#8211; bean name &#8220;transactionManager&#8221;</li>
<li>JobBuilderFactory &#8211; bean name &#8220;jobBuilders&#8221;</li>
<li>StepBuilderFactory &#8211; bean name &#8220;stepBuilders&#8221;</li>
</ul>
<p>We&#8217;ll see shortly how it works.</li>
<li>Line 10: the <strong>reader bean</strong>, an instance of a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/file/FlatFileItemReader.html" title="Class FlatFileItemReader&lt;T&gt;" target="_blank">FlatFileItemReader</a>, that implements the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/ItemReader.html" title="Interface ItemReader&lt;T&gt;" target="_blank">ItemReader</a> interface to read each <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/Person.java" title="Person.java" target="_blank">Person</a> from the file containing people. Spring Batch provides several implementations for this interface, being this implementation that read lines from one Resource one of them.You know, <u>no need of custom code</u>.</li>
<li>Line 26: the <strong>processor bean</strong>, an instance of the previously defined <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/PersonItemProcessor.java" title="PersonItemProcessor.java" target="_blank">PersonItemProcessor</a>. See above.</li>
<li>Line 31: the <strong>writer bean</strong>, an instance of a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/database/JdbcBatchItemWriter.html" title="Class JdbcBatchItemWriter&lt;T&gt;" target="_blank">JdbcBatchItemWriter</a>, that implements the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/ItemWriter.html" title="Interface ItemWriter&lt;T&gt;" target="_blank">ItemWriter interface</a> to write the People already processed to the database. It&#8217;s also an implementation provided by Spring Batch, so <u>no need of custom code</u> again. In this case, you only have to provide an SQL, and a callback for the parameters. Since we are using named parameters, we&#8217;ve chosen a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/database/BeanPropertyItemSqlParameterSourceProvider.html" title="Class BeanPropertyItemSqlParameterSourceProvider&lt;T&gt;" target="_blank">BeanPropertyItemSqlParameterSourceProvider</a>. This bean also needs a DataSource, so we provided it by passing one as a method parameter in order to Spring inject the instance that it has registered.</li>
<li>Line 42: a <strong><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/Job.html" title="Interface Job" target="_blank">Job</a> bean</strong>, that it&#8217;s built using the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/JobBuilderFactory.html" title="Class JobBuilderFactory" target="_blank">JobBuilderFactory</a> that is autowired by passing it as method parameter for this @Bean method. When you call its get method, Spring Batch will create a <strong>job builder</strong> and will initialize its job repository, the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/job/builder/JobBuilder.html" title="Class JobBuilder" target="_blank">JobBuilder</a> is the convenience class for building jobs of various kinds as you can see in the code above. We also use a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/Step.html" title="Interface Step" target="_blank">Step</a> that is configured as the next Spring bean.</li>
<li>Line 51: a <strong><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/Step.html" title="Interface Step" target="_blank">Step</a> bean</strong>, that it’s built using the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/StepBuilderFactory.html" title="Class StepBuilderFactory" target="_blank">StepBuilderFactory</a> that is autowired by passing it as method parameter for this @Bean method, as well as the other dependencies: the <strong>reader</strong>, the <strong>processor</strong> and the <strong>writer</strong> previously defined. When calling the get method from the StepBuilderFactory, Spring Batch will create a step builder and will initialize its job repository and transaction manager, the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/step/builder/StepBuilder.html" title="Class StepBuilder" target="_blank">StepBuilder</a> is an entry point for building all kinds of steps as you can see in the code above.
</ul>
<p>This configuration is almost everything needed to configure a Batch process as defined in the concepts above.</p>
<p>Actually, only one configuration class needs to have the @EnableBatchProcessing annotation in order to have the base configuration for building batch jobs. Then you can define the job with their steps and the readers/processors/writers that they need.</p>
<p>But an additional data source is needed to be used by the <strong>JobRepository</strong>. For this sample we&#8217;ll use an in-memory one:</p>
<p></p><pre class="crayon-plain-tag">@Configuration
public class DataSourceConfiguration {

    @Bean
    public DataSource dataSource() {
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        return builder
                .setType(HSQL)
                .addScript(&quot;schema-all.sql&quot;)
                .addScript(&quot;org/springframework/batch/core/schema-hsqldb.sql&quot;)
                .build();
    }

}</pre><p></p>
<p>In this case we&#8217;ll use the same in-memory database, HSQL, with the schema for the application (line 9) and the schema for the job repository (line 10). The former is available as a resource of the application, the file called <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/resources/schema-all.sql" title="src/main/resources/schema-all.sql" target="_blank">schema-all.sql</a>, and the latter in the spring-batch-core jar (spring-batch-core-3.0.1.RELEASE.jar at the time of this writing)</p>
<h3>Alternate Configuration</h3>
<p>The official documentation shows an slightly different <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#javaConfig" title="Java Config" target="_blank">configuration</a> by using the <a href="http://docs.spring.io/spring/docs/4.0.6.RELEASE/javadoc-api/index.html?org/springframework/beans/factory/annotation/Autowired.html" title="Annotation Type Autowired" target="_blank">@Autowired</a> annotation for the beans that <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/step/builder/StepBuilder.html" title="Annotation Type EnableBatchProcessing" target="_blank">@EnableBatchProcessing</a> will create. Use the one that you like most. In this case they also imports the data base configuration.</p>
<p></p><pre class="crayon-plain-tag">@Configuration
@EnableBatchProcessing
@Import(DataSourceConfiguration.class)
public class AppConfig {

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    // Input, processor, and output definition omitted

    @Bean
    public Job importUserJob() {
        return jobs.get(&quot;importUserJob&quot;).incrementer(new RunIdIncrementer()).flow(step1()).end().build();
    }

    @Bean
    protected Step step1(ItemReader&lt;Person&gt; reader, ItemProcessor&lt;Person, Person&gt; processor, ItemWriter&lt;Person&gt; writer) {
        return steps.get(&quot;step1&quot;)
            .&lt;Person, Person&gt; chunk(10)
            .reader(reader)
            .processor(processor)
            .writer(writer)
            .build();
    }

}</pre><p></p>
<p>We chose another approach: we load it when configuring the application in the main method as you&#8217;ll see shortly. besides, we imported an additional batch configuration (see line 28 at <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/BatchConfiguration.java" title="BatchConfiguration.java" target="_blank">BatchConfiguration.java</a>) to provide an alternate way to launch the application.</p>
<h3>Enable Batch Processing: how it works</h3>
<p>As we said before, we will go a little deeper in how the annotation <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.html" title="EnableBatchProcessing API" target="_blank">@EnableBatchProcessing</a> works.</p>
<p>To remind its goal, this annotation provides a base configuration for building batch jobs by creating a list of beans available to be autowired. An extract of the source code gives us a lot of information:</p>
<p></p><pre class="crayon-plain-tag">@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(BatchConfigurationSelector.class)
public @interface EnableBatchProcessing {

	/**
	 * Indicate whether the configuration is going to be modularized into multiple application contexts. If true then
	 * you should not create any &amp;#64;Bean Job definitions in this context, but rather supply them in separate (child)
	 * contexts through an {@link ApplicationContextFactory}.
	 */
	boolean modular() default false;

}</pre><p></p>
<p>As you can see at line 4, this annotation <a href="http://docs.spring.io/spring/docs/4.0.6.RELEASE/javadoc-api/index.html?org/springframework/context/annotation/Import.html" title="Annotation Type Import" target="_blank">imports</a> an implementation of an <a href="http://docs.spring.io/spring/docs/4.0.6.RELEASE/javadoc-api/index.html?org/springframework/context/annotation/ImportSelector.html" title="Interface ImportSelector" target="_blank">ImportSelector</a>, one of the options to import beans in a configuration class, in particular, to selective import beans according to certain criteria.</p>
<p>This particular implementation, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/BatchConfigurationSelector.html" title="Class BatchConfigurationSelector" target="_blank">BatchConfigurationSelector</a>, instantiates the expected beans for providing common structure for enabling and using Spring Batch based in the EnableBatchProcessing&#8217;s attribute <strong>modular</strong>.</p>
<p>There are two implementations depending on whether you want the configuration to be modularized into multiple application contexts so that they don’t interfere with each other with the naming and the uniqueness of beans (for instance, beans named <strong>reader</strong>) or not. They are <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.html" title="Class ModularBatchConfiguration" target="_blank">ModularBatchConfiguration</a> and <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.html" title="Class SimpleBatchConfiguration" target="_blank">SimpleBatchConfiguration</a> respectively. Mainly they both do the same, but the former using an <a href="AutomaticJobRegistrar" title="Class AutomaticJobRegistrar" target="_blank">AutomaticJobRegistrar</a> which is responsible for creating separate <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/ApplicationContext.html" title="Interface ApplicationContext" target="_blank">ApplicationContext</a>s for register isolated jobs that are later accesible via the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/JobRegistry.html" title="nterface JobRegistry" target="_blank">JobRegistry</a>, and the latter just creates the main components as lazy proxies that only initialize when a method is called (in order to prevent configuration cycles)</p>
<p>The key concept here is that both extends <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.html" title="Class AbstractBatchConfiguration" target="_blank">AbstractBatchConfiguration</a> that uses the core interface for this configuration: <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/BatchConfigurer.html" title="Interface BatchConfigurer" target="_blank">BatchConfigurer</a>.</p>
<p>The default implementation, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.html" title="Class DefaultBatchConfigurer" target="_blank">DefaultBatchConfigurer</a>, provides the beans mentioned above (jobRepository, jobLauncher, jobRegistry, transactionManager, jobBuilders and stepBuilders), for doing so it <u>doesn&#8217;t require a dataSource</u>, it&#8217;s Autowired with required to false, so it will use a Map based JobRepository if its dataSource is null, but you have take care if you have a dataSource eligible for autowiring that doesn&#8217;t contain the expected database schema for the job repository: the batch process will fail in this case.</p>
<p>Spring Boot provides another implementation, <a href="http://docs.spring.io/spring-boot/docs/current/api/index.html?org/springframework/boot/autoconfigure/batch/BasicBatchConfigurer.html" title="Class BasicBatchConfigurer" target="_blank">BasicBatchConfigurer</a>, but this is out of the scope of this entry.</p>
<p>With all this information, we already have a Spring Batch application configured, and we more or less know how this configuration is achieved using Java.</p>
<p>Now it&#8217;s time to run the application. </p>
<h3>Running the sample: JobLauncher</h3>
<p>We have all we need to launch a batch job, the Job to be launched and a JobLauncher, so wait no more and execute this main class: <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/MainJobLauncher.java" title="MainJobLauncher.java" target="_blank">MainJobLauncher</a>.</p>
<p></p><pre class="crayon-plain-tag">@Component
public class MainJobLauncher {

    @Autowired
    JobLauncher jobLauncher;

    @Autowired
    Job importUserJob;

    public static void main(String... args) throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);

        MainJobLauncher main = context.getBean(MainJobLauncher.class);

        JobExecution jobExecution = main.jobLauncher.run(main.importUserJob, new JobParameters());

        MainHelper.reportResults(jobExecution);
        MainHelper.reportPeople(context.getBean(JdbcTemplate.class));

        context.close();

    }

}</pre><p></p>
<p>First things first. This is the way I like to write main classes. Some people from Spring are used to writing main classes annotated with <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/annotation/Configuration.html" title="Annotation Type Configuration" target="_blank">@Configuration</a>, but I&#8217;d rather to annotate them as <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/stereotype/Component.html" title="Annotation Type Component" target="_blank">@Component</a>s in order to separate the actual application and its configuration from the classes that test the functionality.</p>
<p>As Spring component (line 1), it only needs to have the dependencies <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/beans/factory/annotation/Autowired.html" title="Annotation Type Autowired" target="_blank">@Autowired</a>.</p>
<p>That&#8217;s the reason for the <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/ApplicationConfiguration.java" title="ApplicationConfiguration.java" target="_blank">ApplicationConfiguration</a> class. It&#8217;s a <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/annotation/Configuration.html" title="Annotation Type Configuration" target="_blank">@Configuration</a> class that also performs a @ComponentScan from its own package, that will find the very <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/MainJobLauncher.java" title="MainJobLauncher.java" target="_blank">MainJobLauncher</a> and the remain <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/annotation/Configuration.html" title="Annotation Type Configuration" target="_blank">@Configuration</a> classes, because they are also <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/stereotype/Component.html" title="Annotation Type Component" target="_blank">@Component</a>s: <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/BatchConfiguration.java" title="BatchConfiguration.java" target="_blank">BatchConfiguration</a> and <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/DataSourceConfiguration.java" title="DataSourceConfiguration.java" target="_blank">DataSourceConfiguration</a>.  </p>
<p>As a main class, it creates the Spring Application Context (line 12), it gets the component as a Spring bean (line 14) and then it uses its methods (or attributes in this example. Line 16)</p>
<p>Let&#8217;s back to the Batch application: the line 16 is the call to the JobLauncher that will run the Spring Batch process.</p>
<p>The remaining lines are intended to show the results, both from the job execution and the results in the database.</p>
<p>It will be something like this:</p>
<p></p><pre class="crayon-plain-tag">***********************************************************
importUserJob finished with a status of  (COMPLETED).
* Steps executed:
	step1 : exitCode=COMPLETED;exitDescription=
StepExecution: id=0, version=3, name=step1, status=COMPLETED, exitStatus=COMPLETED, readCount=5, filterCount=0, writeCount=5 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0
***********************************************************

***********************************************************
* People found:

* Found firstName: JILL, lastName: DOE in the database

* Found firstName: JOE, lastName: DOE in the database

* Found firstName: JUSTIN, lastName: DOE in the database

* Found firstName: JANE, lastName: DOE in the database

* Found firstName: JOHN, lastName: DOE in the database
***********************************************************</pre><p></p>
<h3>Running the sample: CommandLineJobRunner</h3>
<p><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/support/CommandLineJobRunner.html" title="Class CommandLineJobRunner" target="_blank">CommandLineJobRunner</a> is a main class provided by Spring Batch as the primary entry point to <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#commandLineJobRunner" title="The CommandLineJobRunner" target="_blank">launch a Spring Batch Job</a>.</p>
<p>It requires at least two arguments: <strong>JobConfigurationXmlPath/JobConfigurationClassName</strong> and <strong>jobName</strong>. With the first, it will create an <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/ApplicationContext.html" title="Interface ApplicationContext" target="_blank">ApplicationContext</a> by loading a Java Configuration from a class with the same name or by loading an XML Configuration file with the same name.</p>
<p>It has a <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#domainJobLauncher" title="JobLauncher" target="_blank">JobLauncher</a> attribute that is autowired with the application context via its <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/beans/factory/config/AutowireCapableBeanFactory.html" title="Interface AutowireCapableBeanFactory" target="_blank">AutowireCapableBeanFactory</a> exposed, that is used to autowire the bean properties by type.</p>
<p>It accepts some options (&#8220;-restart&#8221;, &#8220;-next&#8221;, &#8220;-stop&#8221;, &#8220;-abandon&#8221;) as well as parameters for the <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#domainJobLauncher" title="JobLauncher" target="_blank">JobLauncher</a> that are converted with the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/converter/DefaultJobParametersConverter.html" title="Class DefaultJobParametersConverter" target="_blank">DefaultJobParametersConverter</a> as <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/converter/JobParametersConverter.html" title="Interface JobParametersConverter" target="_blank">JobParametersConverter</a> that expects a &#8216;name=value&#8217; format.</p>
<p>You can declare this main class in the manifest file, directly or using some maven plugin as maven-jar-plugin, maven-shade-plugin or even exec-maven-plugin.</p>
<p>That is, you can invoke from your command line something like this:</p>
<p><strong>$ java CommandLineJobRunner job.xml jobName parameter=value</strong></p>
<p>Well, the sample code is a maven project that you can install (it&#8217;s enough if you package the application) and it allows to manage the dependencies (the mvn dependency:copy-dependencies command copies all the dependencies in the target/dependency directory)</p>
<p>To simplify, I&#8217;ll also copy the generated jar to the same directory of the dependencies in order to invoke the java command more easily:</p>
<p></p><pre class="crayon-plain-tag">~/Documents/git/spring-batch-sample$mvn clean install
[INFO] Scanning for projects...
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
~/Documents/git/spring-batch-sample$ mvn dependency:copy-dependencies
[INFO] Scanning for projects...
...
[INFO] Copying spring-batch-core-3.0.1.RELEASE.jar to ~/Documents/git/spring-batch-sample/target/dependency/spring-batch-core-3.0.1.RELEASE.jar
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
~/Documents/git/spring-batch-sample$ cp target/spring-batch-sample-0.0.1-SNAPSHOT.jar ./target/dependency/
~/Documents/git/spring-batch-sample$ java -classpath "./target/dependency/*" org.springframework.batch.core.launch.support.CommandLineJobRunner com.malsolo.springframework.batch.sample.ApplicationConfiguration importUserJob
...
12:32:17.039 [main] INFO  o.s.b.c.l.support.SimpleJobLauncher 
- Job: [FlowJob: [name=importUserJob]] 
completed with the following parameters: [{}] 
and the following status: [COMPLETED]
...</pre><p></p>
<p>That&#8217;s all for now.</p>
<p>Since this entry is becoming very large, I&#8217;ll explain other ways to run Spring Batch Jobs in a next post.</p>
]]></content:encoded>
			<wfw:commentRss>http://malsolo.com/blog4java/?feed=rss2&#038;p=260</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Try to avoid copy-paste. Fatal error compiling: invalid target release: 1.8.0_11</title>
		<link>http://malsolo.com/blog4java/?p=297</link>
		<comments>http://malsolo.com/blog4java/?p=297#comments</comments>
		<pubDate>Tue, 12 Aug 2014 11:35:15 +0000</pubDate>
		<dc:creator><![CDATA[Javier (@jbbarquero)]]></dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Compile]]></category>
		<category><![CDATA[Error]]></category>
		<category><![CDATA[Plugin]]></category>

		<guid isPermaLink="false">http://malsolo.com/blog4java/?p=297</guid>
		<description><![CDATA[Bazinga! Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project&#8230;: Fatal error compiling: invalid target release: 1.8.0_11 -&#62; [Help 1] To summarize, I want to compile a maven project using Java 8, that is possible thanks to the JAVA_HOME configuration: [crayon-69f0b2838a0b8982177559/] &#8230; <a href="http://malsolo.com/blog4java/?p=297">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><strong>Bazinga!</strong></p>
<p><font color=red>Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project&#8230;: <strong>Fatal error compiling: invalid target release: 1.8.0_11</strong> -&gt; [Help 1]</font></p>
<p>To summarize, I want to compile a maven project using Java 8, that is possible thanks to the JAVA_HOME configuration:</p><pre class="crayon-plain-tag">$ mvn -version
Apache Maven 3.2.1 (ea8b2b07643dbb1b84b6d16e1f08391b666bc1e9; 2014-02-14T18:37:52+01:00)
Maven home: /home/jbeneito/Applications/apache-maven-3.2.1
Java version: 1.8.0_11, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-8-oracle/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "3.13.0-32-generic", arch: "amd64", family: "unix"</pre><p></p>
<p>But I copied the maven compiler plugin configuration from another maven project without putting special attention:</p><pre class="crayon-plain-tag">&lt;plugin&gt;
                &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
                &lt;version&gt;3.1&lt;/version&gt;
                &lt;configuration&gt;
                    &lt;source&gt;${java.version}&lt;/source&gt;
                    &lt;target&gt;${java.version}&lt;/target&gt;
                    &lt;encoding&gt;${project.build.sourceEncoding}&lt;/encoding&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;</pre><p>In programming the error usually contains the solution. I&#8217;m trying to use the current Java version (1.8.0_11) as the option for the javac command, that is not the expected one.</p>
<p><strong><em>${java.version}</em></strong> is a environment variable whose value is currently <strong><em>1.8.0_11</em></strong>, but the <a href="http://maven.apache.org/plugins/maven-compiler-plugin/index.html" title="Maven compiler plugin" target="_blank">Maven Compiler Plugin</a> expects the standard options of the <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javac.html" title="javac" target="_blank">javac command</a> for <a href="http://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html" title="Setting the -source and -target of the Java Compiler" target="_blank">Setting the -source and -target of the Java Compiler</a>.</p>
<p>That is:</p>
<ul>
<li><strong>1.3</strong> for Java SE 1.3</li>
<li><strong>1.4</strong> for Java SE 1.4</li>
<li><strong>1.5</strong> for Java SE 5</li>
<li><strong>5</strong> synonym for 1.5</li>
<li><strong>1.6</strong> for Java SE 6</li>
<li><strong>6</strong> synonym for 1.6</li>
<li><strong>1.7</strong> the default value. The compiler accepts code with features introduced in Java SE 7. (Yes, as it appears in the <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javac.html" title="javac 8" target="_blank">Java 8 official documentation</a>)</li>
<li><strong>7</strong> Synonym for 1.7</li>
</ul>
<p>Actually I only use the values with the format 1.X, that includes 1.8, that I assume is the default value for Java 8 SE.</p>
<p>Why did I use this variable?</p>
<p>Because in my previous project it wasn&#8217;t an environment variable, but a custom property in the pom.xml:</p>
<p></p><pre class="crayon-plain-tag">&lt;properties&gt;
        &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
        &lt;java.version&gt;1.8&lt;/java.version&gt;
...
    &lt;/properties&gt;</pre><p></p>
<p>But this time I have another two custom properties:</p><pre class="crayon-plain-tag">&lt;properties&gt;
        &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
        &lt;maven.compiler.source&gt;1.8&lt;/maven.compiler.source&gt;
        &lt;maven.compiler.target&gt;1.8&lt;/maven.compiler.target&gt;</pre><p></p>
<p>Thus the solution is easy:</p>
<ol>
<li>Try to not copy-paste</li>
<li>Pay attention in any case</li>
<li>Just use the appropriate variables</li>
</ol>
<p></p><pre class="crayon-plain-tag">&lt;plugin&gt;
                &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
                &lt;version&gt;3.1&lt;/version&gt;
                &lt;configuration&gt;
                    &lt;source&gt;${maven.compiler.target}&lt;/source&gt;
                    &lt;target&gt;${maven.compiler.source}&lt;/target&gt;
                    &lt;encoding&gt;${project.build.sourceEncoding}&lt;/encoding&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;</pre><p></p>
]]></content:encoded>
			<wfw:commentRss>http://malsolo.com/blog4java/?feed=rss2&#038;p=297</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Just for fun: trying the best 3 IDEs for Java</title>
		<link>http://malsolo.com/blog4java/?p=228</link>
		<comments>http://malsolo.com/blog4java/?p=228#comments</comments>
		<pubDate>Fri, 08 Aug 2014 12:52:45 +0000</pubDate>
		<dc:creator><![CDATA[Javier (@jbbarquero)]]></dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Springsource]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[IntelliJ IDEA]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[NetBeans]]></category>
		<category><![CDATA[Spring Tool Suite]]></category>
		<category><![CDATA[STS]]></category>

		<guid isPermaLink="false">http://malsolo.com/blog4java/?p=228</guid>
		<description><![CDATA[Not only for fun. It&#8217;s also to open my mind. Introduction Since a few years ago, I try to use several OS in order to improve my computing skills: Windows 7/Vista, OS X (Lion currently) and my favorite Linux distribution, &#8230; <a href="http://malsolo.com/blog4java/?p=228">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Not only for fun. It&#8217;s also to open my mind.</p>
<h3>Introduction</h3>
<p>Since a few years ago, I try to use several OS in order to improve my computing skills: Windows 7/Vista, OS X (Lion currently) and my favorite Linux distribution, Ubuntu (Sheldon Cooper dixit). You can also include Android (my wife&#8217;s smartphone) and iOS (my iPhone and our iPad)</p>
<p>Suddenly, I realize that I&#8217;ve been enriched, and you’re able to do a lot of more things because you have your mind really prepared for thinking instead of conditioned by a single line of sight.</p>
<p>I observed the same improvement when I began to use Maven for Java development. I didn&#8217;t quit my IDE, but regarding compilation, the important things are the source code and bytecode. You shouldn&#8217;t think about settings, preferences, project configuration and some other artificial stuff that the IDE needs, but that is not your concern.</p>
<p>So I&#8217;ve decided to try the 3 most popular IDEs for Java currently available.</p>
<h3>Context</h3>
<p>During the last 2 months, I&#8217;ve been changing between projects I work in more quickly than I used to be accustomed, and that has allowed me to choose the IDE for working.</p>
<p>The title says it&#8217;s been for fun, but I&#8217;m using them in professional environment. Besides, the goal is not to decide which is better (it&#8217;s hard to be that rude with the others) or worst (well, it seems it&#8217;s an easy decision, because the worst Java IDE is <strong>JDeveloper</strong>, doubtless). What I want to find out is which of them is more productive for me.</p>
<p>Let&#8217;s see the first impressions.</p>
<h3>Eclipse</h3>
<p>Actually I don&#8217;t use Eclipse, but <a href="http://spring.io/tools/sts" title="Spring Tool Suite" target="_blank">Spring Tool Suite</a>, <em>&#8220;an Eclipse-based development environment that is customized for developing Spring applications&#8221;</em>. You know, Eclipse on Spring steroids.</p>
<p><u>I&#8217;ve been using Eclipse as my main IDE for years</u>, even before it was released (Visual Age for Java was the IDE that I used in my first professional project). Thus, I&#8217;m very used to writing programs with Eclipse. </p>
<p>The version that I&#8217;m currently using is 3.6.0, that is based on Eclipse 4.4 (Luna)</p>
<p>Let&#8217;s summarize my first impressions:</p>
<p>Pros:</p>
<ul>
<li>It comes in a compressed file, no native installer. That allows me to place the program in the same location on every OS (in my case, an Application folder within my user home)</li>
<li>The shortcut keys</li>
<li>Typing assistant. I love to type &#8220;main&#8221; and have an entire main method written, or &#8220;sysout&#8221; and obtain a complete log sentence.</li>
<li>The view and the perspectives is the most interesting way of organizing the IDE</li>
</ul>
<p>Cons:</p>
<ul>
<li>It crashes from time to time. Annoying.</li>
<li>It seems to consume a lot of memory</li>
<li>The TC server that it includes is based on Tomcat 7, so it doesn&#8217;t recognize Servlet 3.1 projects</li>
<li>A custom way of building code. No native support for tools like maven, gradle or ant. There are appropriate plugins, but having to update Eclipse projects to reflect maven changes is somewhat annoying</li>
<li>On Ubuntu and on OS X, the icon in the Docker runs the previously installed 3.5.1 version. Maybe is the OS fault, due to the lack of installation.
</ul>
<h3>NetBeans</h3>
<p>I&#8217;m talking about <a href="https://netbeans.org/" title="NetBeans 8.0" target="_blank">NetBeans 8.0</a>.</p>
<p>It&#8217;s hard for me to evaluate Eclipse, because it is the IDE that I use on a daily basis since a long years ago.</p>
<p>On the other hand, it&#8217;s very easy to describe the first impressions with NetBeans.</p>
<p>The installer works fine and the application runs smoothly, but I miss the way Eclipse are organized and its shortcuts (delete line: Ctrl/Cmd+D vs Ctrl/Cmd+E)</p>
<p>However <u>NetBeans is likely the best among the three IDEs</u> (not so hard to decide, apparently)</p>
<p>I got used to NetBeans in a few hours. Yes, hours. NetBeans has the more natural appearance for programming.</p>
<p>Actually, it includes all the options that Eclipse has, but sometimes with different key combination.</p>
<p>Besides, NetBeans is pure Java using external tools for compiling (maven, for instance)</p>
<p>Furthermore, it comes with Tomcat and GlassFish and a several of useful tools easy to configure with pluggins.</p>
<p>Does it have flaws? Of course, sometimes it get locked in a long wait operation and you can do nothing but wait.</p>
<p>Another tricky issue is that it uses an external tool to compile, maven for instance, so the program doesn&#8217;t exist until the project is built and neither you have the dependencies until maven downloads them. But worst than that is, if you compile successfully, but later on you introduce a compilation error, when you execute again, it runs the previously compiled version, because the current can&#8217;t be compiled due to the error.</p>
<p>Eclipse shows you an alert if there are compilation errors in your project before executing it.</p>
<h3>IntelliJ IDEA</h3>
<p>I&#8217;m sure that this is the best IDE ever, it seems so, but it makes me a little bit unproductive.</p>
<p>Eclipse is some kind of a de facto standard, and NetBeans is an easy to use program. But thanks to <a href="http://www.jetbrains.com/idea/" title="IntelliJ IDEA 13.1" target="_blank">IntelliJ IDEA 13.1</a>, the JetBrains Web Help has been the most visited page this week.</p>
<p>Besides, I don&#8217;t know what is doing the IDE. I don&#8217;t know whether the files are saved automatically, I don&#8217;t know when compilation is performed, and so on.</p>
<p>The worst thing in my humble opinion is that it doesn&#8217;t have any application server in the community edition. Please, at least Tomcat. But it has not.</p>
<p>Regarding shortcuts, it uses Ctrl/Cmd+Y for deleting lines, seriously?, the universal shortcut for “redo”? Yepes. And the rest of shortcut keys are really hard to do (Ctrl+F4 for closing a file)</p>
<p>I will try it later again, but currently it&#8217;s not my preferred choice.</p>
<p>However, once you discover how to use it, it&#8217;s the one that runs better. It seems not consume a lot of memory and it never blocks nor has crashes.</p>
<p>On Ubuntu, I have to start it via command line.</p>
<h3>Summary</h3>
<p>Of course the three programs are very good IDEs, but one by one:</p>
<ul>
<li>I feel a little bit lost with IntelliJ IDEA. It&#8217;s great but it&#8217;s hard to find the standard options.</li>
<li>I love Eclipse and its shortcut keys, and I don&#8217;t care its flaws because I&#8217;m used to them after all these years. It will be my preferred IDE for a while, but NetBeans is now here.</li>
<li>I didn&#8217;t like NetBeans, but the version 8 is a great program. It doesn&#8217;t matter if you haven&#8217;t use it before, is a very natural program. It makes Java development the way it has to be. Now I like it a lot.</li>
</ul>
<p>Some final words: they are all very good and easy to use for Java debugging. And I&#8217;m glad now I can use any of them if I had to.</p>
<p>An alternative for short projects is a text editor (Sublime Text, for instance) and a good build tool (maven or gradle, as you wish)</p>
<p>I have to try Web Based IDEs, <a href="http://nerds-central.blogspot.co.uk/2014/08/10-kickass-software-technologies.html" title="10 Kickass (software) Technologies - Gauntlet Picked Up" target="_blank">as Alexander J Turner suggested</a>.</p>
<p>That&#8217;s all for now.</p>
]]></content:encoded>
			<wfw:commentRss>http://malsolo.com/blog4java/?feed=rss2&#038;p=228</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
