Last week I got a request from one of my colleague to help her in deploying one of their application to Bluemix. This application is an enterprise application and I have been given an ear file and a readme file which just provide me step to step instruction of installing the application in a local liberty profile.
To start with, the task seems to be easy as we already have the step to step instruction for local liberty profile and Bluemix use the liberty runtime only. My understanding was that there wont be much differences accept I don't need the liberty installation (as I will get it on the Bluemix), but as I moved on I started seeing some challenges which is very much particular to cloud environment. These challenges has changed my view and clarified some differences between, how the application should be developed and deployed in a cloud environment Vs in premise development.
The first step I did is to push the ear file to Bluemix using cf push and that worked smoothly. My web module is up and running within couple of minutes. The next task was now to have the database up and running and configured with the application. I have added an sqldb service and bound it to the application. Till now its was smooth selling, but the real challenge came now. How to make sure that application configured and connect to the database ? Literally without changing the application code ?
If I think of how we do it in a local environment, we do put the details of database like db name, user name, password, host name, port number etc in server.xml file of the liberty profile and give it a JNDI name. This JNDI name is then referred in the application to connect to the database. This server.xml file is part of the liberty server and not application. In cloud environment we generally don't get access to the server and hence has no control on the server.xml file of the default liberty runtime on Bluemix. The step by step instruction given to me says to copy, server.xml file zipped along with application, to my server profile. But this is not possible when working with the cloud. Same problem goes with the database driver jars. In local installation we generally copy them to the server library. In case of cloud we need to make it part of the application library (under WEB-INF/lib). Both of these alternatives are not possible with the standard liberty build pack and with a ear which can not be changed.
After some understanding of build pack and how I can push changes to build packs, I got the solution to the problem. So here is what I did.
Install a local liberty server and create a defaultProfile.
Install my ear file in the local liberty profile.
Edit local server.xml (generally found in LIBERTY_HOME/usr/servers/<profile name>) file to create the JNDI name used in the application. I actually copied the data source cconfiguration from the server.xml file given to me as part of the application zip and edit it to add credentials from the sqldb service I created on Bluemix keeping the JNDI name same (as that is used in the application to connect).
Used server package command to zip the usr directory which contains my server runtime and the application details. Command used here is
LIBERTY_HOME/bin/server package <profile name> --include=usr
this will create a zip file under LIBERTY_HOME/usr/servers/<profile name>
Now I have used cf push command to push both the liberty runtime and application together from LIBERTY_HOME/usr/servers/<profile name>. Command user here is
cf push -p <profile name>.zip <application name>
once the push command is successful, your application will be able to use the JNDI name and connect to the new Bluemix sqldb service.
So what this solution is actually doing. When you run the server package command with usr directory included, It actually zipping all the server runtime and application in one folder. When you push this to Bluemix, Bluemix actually detect the server.xml file inside the zip and understand that the zip file contain both the application and the runtime and overwrite the existing configuration file (server.xml) with the one you have created and zipped.
The same solution works for the driver jars file too. You can add the driver file in your local liberty profile under shared resources directory (LIBERTY_HOME/usr/shared/resources) and this will be zipped as part of your server package. Upon cf push, will become part of your customized build back accessible to application. When you do this, make sure that your server.xml file actually has the correct path for these JDBC driver jars, other wise liberty will not be able to find it at the time connection request..
So this solved my problem and application was deployed successfully and was using my customized liberty build pack and sqldb service on the cloud.
This process can be used to do anything which require you to change your build pack including adding new liberty feature in your cloud liberty build pack.
So happy developing :)