Fast Iterative Java Development on OpenShift/Kubernetes Using Rsync

The key to a good development environment almost always comes down to how long it takes for changes you make to take effect. With any compiled language, there is often a lot of setup work involved to optimize deployment speed. Thankfully, one of the promises of containers is it allows for patterns to be standardized and repackaged as reusable images that do a lot of the heavy lifting for you.

In the case of OpenShift, we offer JBoss images for EAP and JWS which have the deployment scanner and exploded war class reloading configurable by simply setting an environment variable. The other critical component necessary to make iterative development possible is oc rsync. OpenShift’s support for rsync means that any framework (not exclusive to java) that supports dynamic reload can be utilized with container development. This is applicable to local scenarios using oc cluster up or the CDK as well with remote development with OpenShift Online, Dedicated, or Container Platform.

Syncing War Files

Let’s start with a simple example:

git clone

cd openshift-jee-sample

sudo oc cluster up --version=latest  # Any OpenShift environment will work

oc login  # as developer:developer

oc new-app

oc expose service/openshift-jee-sample

# Browse to the web console and log in as developer:developer
# Select My Project and click on the url for openshift-jee-sample in the upper right
# You should see the index.html page
# Now add /HelloWorld to the end of the url and you should see the output 
# of the HelloWorld Servlet

mvn package -P openshift # Or build ROOT.war however you wish

oc get pods  # To get the name of the running pod you will sync to

oc rsync --include="ROOT.war" --exclude="*" target/ <pod_name>:/deployments/ --no-perms=true --watch # Replace <pod_name> with the value from the previous step

With oc rsync left running, every change to ROOT.war will automatically be synced and reloaded within a few seconds.


Syncing Class Files

For various reasons such as a large war file, slow network connection, or slow build times, you might prefer to only push class files. Such a workflow can be accommodated as well. Here is an example (picking up where the previous example left off):

oc set env dc/openshift-jee-sample AUTO_DEPLOY_EXPLODED=true

oc get pods  # To get the name of the new running pod you will sync to. You might have to wait a few seconds for the new pod to be deployed.

mvn compile war:exploded -P development # Or build your class files however you wish

oc rsync target/SampleApp.war/ <pod_name>:/deployments/SampleApp.war --watch  # Replace <pod_name> with the value from the previous step

# Go to /SampleApp/HelloWorld in your browser to see the sample app

As with the war example, each change you make to a class file will cause the app to reload within a few seconds.


I have to give a warning associated with individual class reloading that there is a chance of picking up partial changes. So you should never use exploded war class reloading in a non-development scenario. An easy workaround to the partial class reload problem is to touch and sync a <your_war>.war.dodeploy file (as a sibling file to <your_war>.war folder) and rsync or cp that file to force a reload. In that case you do not set the AUTO_DEPLOY_EXPLODED=true environment variable.

No doubt there are even better ways to setup your environment to take advantage of these features. Hopefully I’ve explained enough to show what’s possible and you’ll be able find the best configuration for your application.

The ultimate benefit of using this mechanism is that it lets you use a standardized environment from development to production. And being able to easily deploy, scale, and iteratively develop an application with the speed of local development and the complexity of your production environment is near priceless.

Java, JBoss, News, OpenShift Container Platform, OpenShift Dedicated, OpenShift Online, OpenShift Origin, Tomcat
, , , , , , , ,