Docker Cloud Spring Boot Integration

It’s been a long time since my last post, but I am still up and running!

Lately I have been taking a deeper look into docker and how I could integrate my Spring Boot Applications or basically any application. I think Docker can especially be helpful in microservice environments, where you deal with a lot of small services, which interact with each other and somehow have to be linked.
Using docker-compose you even can define and bootstrap whole environments based on any docker image within minutes!

Since Docker requires you to specify your environment (dependencies, installation, ports ..) in a dedicated file called “Dockerfile”, it also serves as a basic documentation.

Anyway, this article should handle dockers latest creation “Docker Cloud”.

Docker Cloud (formerly tutum.co) allows seamless integration of docker images for existing Cloud Providers (right now AWS and Digital Ocean) as well as your own nodes, which could be any server.

So here is what we want to try to achieve in this post:

  1. Integrate a node (in this case a vServer) into our Docker Cloud
  2. Integrate Docker into a Spring Boot Application
  3. Push the built image into the central DockerHub Repository
  4. Configure a Service based on our Image in Docker Cloud

Once we completed all these steps, we will have a continuous integration of our docker based application into our vServer: Every time we push a new docker image to our DockerHub repository, it will immediately be redeployed on our vServer. Awesome!

In future you might want to enhance this setup using a CI environment. In this case our CI Server would be responsible for publishing the docker image!

1. Integrate your node into Docker Cloud

What you need to start:

  • vServer (with docker installed)
  • a Docker/Docker Cloud Account

Integrating your node is as simple as this:

Open the Nodes Tab in your Docker Cloud Dashboard and “bring your own node”. This will ask you to execute the given command on your server shell. Once the installation is done, you should be able to see your host in the nodes list. That’s it!

2/3. Integrate your Spring Boot Application

To integrate your existing Spring Boot Application, you first have to “dockerize” your application.

First step is to create your Dockerfile in src/main/docker. Here a very basic sample file:

FROM java:8
ADD api-gateway.jar app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom", "-jar","/app.jar"]

Once you have done, that, we need to configure the docker-maven-plugin as following:

<build>
	<finalName>${project.artifactId}</finalName>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>

		<plugin>
			<groupId>com.spotify</groupId>
			<artifactId>docker-maven-plugin</artifactId>
			<version>0.3.9</version>
			<configuration>
				<imageName>yourdockerhubusername/${project.artifactId}</imageName>
				<dockerDirectory>src/main/docker</dockerDirectory>
				<resources>
					<resource>
						<targetPath>/</targetPath>
						<directory>${project.build.directory}</directory>
						<include>${project.build.finalName}.jar</include>
					</resource>
				</resources>
			</configuration>
		</plugin>
	</plugins>
</build>

Hint: As you might have seen, we changed our final jar name to omit the version number, otherwise we would need to change our Dockerfile, every time the version changes.

Make sure you have the docker repository created in your DockerHub Account!

Having the docker-maven-plugin in place, we can now build our docker image as follows:

mvn clean package

mvn docker:build

mvn docker:push

You might need to add your dockerhub credentials to your maven settings.xml to be able to push. As an alternative, just run “docker login” and “docker push youraccountname/yourartifactid”.

After your image has been pushed, your are now able to set up a service or stack in Docker Cloud, which uses your image.

4. Configure your Docker Cloud Service

Now that our image is published, we can configure a service based on our Docker Image.

Go to the Docker Cloud Service Tab and create a new service:

  • Choose your docker image
  • Choose your node
  • Enable autodeployment
  • Save and run!

Once you completed this, it will automatically be deployed to your Server. To verify, run “docker ps” on your server and it should appear in the list.

Done!

Having all steps completed you should now see your service being redeployed, every time you push a new release of your image.

In the future you might define your whole environment using a stack. The stack configuration is similar to docker-compose!

Remarks:

  • Docker Cloud will just provide you one free node configuration. Additional nodes are around 14$
  • You just get one free private repository. If you don’t mind making your image publicly available use the public unlimited repositories!
Advertisements

Liferay: Test your Spring MVC Portlets easily!

Hey folks, just on short notice: I recently released spring-test-portlet-mvc, a framework which makes integration testing of Spring MVC Features like Controller or Interceptors very easy. Checkout the project at Check out the project including basic samples at Github: https://github.com/markusf/spring-test-portlet-mvc

There will be an upcoming blog post about this in the near future!

Liferay: Share Object in session between a Hook and Portlet

Since Liferay maintains several Sessions – yes, there is even more than a Portlet and HttpSession thanks to Liferays wrapped and nested *ServletRequests – there is no obvious way to share a session object between a hook (or maybe a servlet filter) and a portlet for example.

Here is the way how you can do it easily:

In your hook, just use the default HttpSession like this:

public class MyAction extends Action {

public void run(HttpServletRequest req, HttpServletResponse res) {

req.getSession().setAttribute("foo", "bar");

...

In your portlet you can now access the session via PortalSessionThreadLocal:

String foo = (String) PortalSessionThreadLocal.getHttpSession().getAttribute("foo");

System.out.println(foo); // prints out "bar"

Jackrabbit Explorer / Browser

Just recently I was in need of a standalone Jackrabbit Explorer.

After some research I found these two:

JCR Browser 0.9.6 – by sandro_boehme (http://sourceforge.net/projects/jcrbrowser/)

Subshell Toromiro (http://www.subshell.com/en/toromiro/)

JCR Browser
Almost any Jackrabbit Explorer is named some kind of “JCR Browser”. “JCR Browser 0.9.6” is being developed actively and free for use / open source. Browsing is based heavily on XPath (have fun copying UUIDs ;)). It does not support JCR 2.x repositories.

Subshell Toromiro
Tomiro is a commercial explorer, which comes with a 30 day trial. It also supports JCR 2.0 repositories. Browsing is easy: Parent / Child / Connected nodes can be reached by simple clicks.

Fazit
If you are working with jackrabbit on a day to day basis, use Toromiro. If you just want to take a quick glance at your repository, take a look at JCR Browser!

Tapestry: yuicompressor not working on tomcat / jboss

I just wanted to deploy my web application on tomcat and realized that my javascript libraries wouldn’t be minified. Minification failed with strange “StringIndexOutOfBoundsException” Exceptions:

[ERROR] AssetsModule.ResourceMinimizer String index out of range: 142644
java.lang.StringIndexOutOfBoundsException: String index out of range: 142644
        at java.lang.String.substring(String.java:1934)
        at com.yahoo.platform.yui.compressor.JavaScriptCompressor.printSourceString(JavaScriptCompressor.java:267)

There seems to be a bug with yuicompressor and some specially patched rhino classes. See https://github.com/greenlaw110/greenscript/pull/29#issuecomment-4017147 and http://stackoverflow.com/questions/6652550/yui-compressor-stringindexoutofboundsexception-on-jboss.

The solution was to modify the pom.xml as follows:

        <dependency>
            <groupId>org.apache.tapestry</groupId>
            <artifactId>tapestry-yuicompressor</artifactId>
            <version>${tapestry-release-version}</version>
            <exclusions>
				<exclusion>
					<artifactId>yuicompressor</artifactId>
					<groupId>com.yahoo.platform.yui</groupId>
				</exclusion>
	     </exclusions>
        </dependency>
        

		<dependency>
			<groupId>com.yahoo.platform.yui</groupId>
			<artifactId>yuicompressor</artifactId>
			<version>2.4.7</version>
			<exclusions>
				<exclusion>
					<groupId>rhino</groupId>
					<artifactId>js</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

Liferay: PortletDisplay is empty in ActionRequests -Update-

Recently I wanted to do a simple permission check in a portlet based on the “RootPortletId” and the “PortletResourcePK” (InstanceID), which I retrieved from the PortletDisplay-Object.
In RenderRequests the permission check worked just fine, however in ActionRequests the current user never had the given permission, though he should have had.
I then discovered, that all PortletDisplay Values are empty, if the request is an ActionRequest.

My next step was to find out, how to retrieve the RootPortletId and the PortletResourcePK without accessing the PortletDisplay.

– Update –
The PortletId is accessible via the Request-Attribute “WebKeys:

String portletResourcePK = (String) request.getAttribute(WebKeys.PORTLET_ID);

The PortletResourcePK (Portlet Primary Key) is not equal to the PortletID, it can be retrieved via PortletPermissionUtil:

		String portletPrimaryKey = PortletPermissionUtil.getPrimaryKey(
				themeDisplay.getLayout().getPlid(), portletId);

Finally, the RootPortletID can be retrieved by the PortletID:

String rootPortletId = PortletConstants.getRootPortletId(portletId);