Here’s a little more detail on how to use <environment> profiles within the cloudbees-web.xml deployment descriptor to control the build/deployment options for both local and cloud PaaS deployments with CloudBees. I covered this in my recent series of blogs (Getting Started with CloudBees and Eclipse) and I thought it was worth a short write-up, as it’s a very useful feature.
In my simple example, I have a basic JDBC web application that I can point at either a local Derby database, or a MySQL database instance that I created as a CloudBees PaaS service. When doing local testing using mvn bees:run I would like to be able to choose which database to run against, but of course I don’t want to make code changes to do that; and when I push my code to the CloudBees Forge Repository to kick off a Jenkins build and deploy the application as a cloud service, then of course I want to run against the MySQL database, rather than the local Derby instance.
In my project’s WEB-INF/web.xml, I have the following <resource-ref>, and this is what the application uses to query the database:
<resource-ref> <res-ref-name>jdbc/countries</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
I also have a WEB-INF/cloudbees-web.xml descriptor, which looks like this:
<?xml version="1.0"?> <cloudbees-web-app xmlns="https://www.cloudbees.com/xml/webapp/1"> <environment name="cloud"> <appid>mqprichard/tutorial</appid> <context-param> <param-name>application.environment</param-name> <param-value>cloud</param-value> </context-param> <resource name="jdbc/countries" auth="Container" type="javax.sql.DataSource"> <param name="username" value="mp_bees" /> <param name="password" value="welcome1" /> <param name="url" value="jdbc:cloudbees://mp_countries" /> </resource> </environment> <environment name="local"> <appid>mqprichard/tutorial</appid> <context-param> <param-name>application.environment</param-name> <param-value>local</param-value> </context-param> <resource name="jdbc/countries" auth="Container" type="javax.sql.DataSource"> <param name="username" value="bees" /> <param name="password" value="bees" /> <param name="url" value="jdbc:derby://localhost:1527/countries" /> <param name="driverClassName" value="org.apache.derby.jdbc.ClientDriver"/> </resource> </environment> </cloudbees-web-app>
Notice that I have two separate <environment> sections, one named “cloud” that has the JDBC connection parameters for the CloudBees-hosted MySQL database and a second one named “local” with the connection info for the local Derby instance. Since the MySQL database instance is hosted by the CloudBees PaaS platform, note also that I don’t have to provide any address/port information in the url param: I don’t need to know or care about those details, so jdbc:cloudbees://mp_countries is fine and the PaaS takes care of the rest.
Now I can use Maven profiles to run the application against whichever database I choose. Using the SDK to run the app locally (using the embedded Tomcat server), mvn bees:run -P local will run with the local Derby database and mvn bees:run -P cloud will run against the cloud-hosted MySQL DB instance. To verify this, I added a few lines to the Servlet code to print the application.environment <context-param> from the ServletContext: this is set to either “cloud” or “local” in corresponding profiles in cloudbees-web.xml.
ServletContext application = config.getServletContext(); String environment = application.getInitParameter("application.environment"); out.println("Environment is ["+ environment + "] <br/><br/>");
If you want to run the profiles from within Eclipse using the m2e plugin, then all you have to do is to create separate Run Configurations for each profile and add the Maven profile name in the Profiles field. Then just right-click on the project and go down to Run As … to run with that profile. Here’s an example:
Finally, how do I do the same thing when deploying the application to the CloudBees PaaS? It’s very simple: just remember to add the appropriate Environment profile when deploying (hint: click on the Advanced button to get to the Environment settings). Here’s an example of how to do from within the Jenkins CI dashboard (Deploy Now).
Of course, the real value of using <environment> profiles is to allow you to have multiple builds for different aspects of the development cycle (such as development, test, staging, production etc.) but this example helps to illustrate how useful they are, and how easy to use.
By Mark Prichard, CloudBees
Mark Prichard is Java PaaS Evangelist and Senior Director of Product Management at CloudBees. He came to CloudBees after 13 years at BEA Systems and Oracle, where he was Product Manager for the WebLogic Platform. A graduate of St John’s College, Cambridge and the Cambridge University Computer Laboratory, Mark is based at the CloudBees office in Los Altos, CA.