Virtual box, Vagrant and docker to setup & up machines instantly

Its always a pain point to test application on different operating systems with all the dependency software installed that your application might require. It would be nice if we get a pre-configured box where we add all the required softwares (databases, web servers etc.) and just use one command to bring it up and later hand over the same box to ops/admins who can just bring it up with one command without messing around with dependency software and versions.

Opensource solution Virtual box allows you to create & run virtual machines (Linux, Mac, Windows), Vagrant allows you to create and configure environments, Docker is a container that allows you to package and ship softwares.

Following we will create a Ubuntu Linux box with mongo db installed on it.

Download and install
1. Virtual box
2. Vagrant

To create a virtual machine create a directory vagrant_getting_started and do

$vagrant init ubuntu/trusty64

--Output
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

A Vagrant file is created that holds all the configurations for our virtual box. To install and run mongo db add following configuration

#Port forwarding mongodb can be accessed from your machine using port 27017
config.vm.network "forwarded_port", guest: 27017, host: 27017

config.vm.provision "docker" do |d|
d.run "mongoDB",image:"mongo:2",args:" -p 27017:27017"
end

Start up the virtual box

$vagrant up

-- Can take a while, Hint! Cachier plugin can be installed and that will speed up things later
https://github.com/fgrehm/vagrant-cachier

--Output (machine is started and can be seen running in the Oracle Virtual Box Manager, Docker is installed on the machine and mongodb is started)
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Mounting shared folders...
default: /vagrant => C:/Users/muhammed01/test
==> default: Running provisioner: docker...
default: Installing Docker (latest) onto machine...
default: Configuring Docker to autostart containers...
==> default: Starting Docker containers...
==> default: -- Container: mongoDB

Now ssh to this machine (vagrant/vagrant) is the username/password the host and port is listed in the output

==> default: Setting the name of the VM: test_default_1430814667041_78006
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
==> default: Forwarding ports...
default: 27017 => 27017 (adapter 1)
default: 22 => 2222 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2222
default: SSH username: vagrant

After login if we grep for mongo db we can see the process is running

vagrant@vagrant-ubuntu-trusty-64:~$ ps -ef|grep mongo
999 14147 13903 0 08:33 ? 00:00:02 mongod
vagrant 14267 14248 0 08:40 pts/2 00:00:00 grep --color=auto mongo

That’s it we got a Linux box running with dependency in few minutes, now you can give the VagrantFile to any one and he can have the same instance up and running with one command.

Create maven archetype project

A simple maven archetypes with most common set of libraries, configured property files and some boiler plate code that you often copy past in every project can be of great help. I had similar requirements and here I am sharing my experience of creating a maven archetype project.

The source code is available here
Java-maven-archetype-github

All the dependencies and properties define in pom.xml will be included in the generated project.
java-maven-archetype\src\main\resources\archetype-resources\pom.xml

Interesting to look how to include the properties and properties with default values

 ${project.basedir}/src/main/resources/app.properties

And if you look at the app.properties file ${property1} will be asked while generating the project.

property1=${property1}

Now to install this archetype locally do

#mvn install

And to create a project out of it do

#mvn archetype:generate -DarchetypeGroupId=com.asciimango.app  -DarchetypeArtifactId=hello-app-archetype -DarchetypeVersion=1.0.0-SNAPSHOT -DgroupId=com.test.app  -DartifactId=testapp

That’s it then wish you happy coding in the newly generated project.

Dynamic SOAP web service endpoint address

Every one prefers REST API’s now a days but hard luck lots of back end systems are SOAP XML based. There are some nice benefits e.g a contract (WSDL xsd) and of course web service client code generation that can easily be integrated into the client application.

However you can have several environments continuous integration, staging and production and the web service endpoint to the target SOAP service most likely will be different for all three environments so how to manage the WSDL files in an application? how to point to a different endpoint in test environment and in a different one in production?

Following is an approach that have worked quite well for me in a standard Java maven web project.

1. Download and place the WSDL (plus any required xsd schema files) to directory
src->main->resources->wsdl

2. We would also like to generate the client and source files so we apply the Apache CXF plugin in POM.xml
(this step is optional incase you already have the sources as a jar etc.)

<plugin>
 <groupId>org.apache.cxf</groupId>
 <artifactId>cxf-codegen-plugin</artifactId>
 <version>2.7.8</version>
 <executions>
 <execution>
 <id>generate-sources</id>
 <phase>generate-sources</phase>
 <configuration>
 <sourceRoot>${project.basedir}/src/generated/TestService/</sourceRoot>
 <wsdlOptions>
 <wsdlOption>
 <wsdl>${project.basedir}/src/main/resources/wsdl/TestWebservice.wsdl</wsdl>
 <wsdlLocation>wsdl/TestWebservice.wsdl</wsdlLocation>
 </wsdlOption>
 </wsdlOptions>
 </configuration>
 <goals>
 <goal>wsdl2java</goal>
 </goals>
 </execution>
 </executions>
 </plugin>

Now when you do mvn clean install you will get the generated sources.

3. Now you have the client code generated to access the web service I would suggest writing a wrapper class that creates a web service client instance. This class also has a webserviceEndPointURL as a property.

public class TestWebserviceWrapper {

         private String webserviceEndPoint;

        public TestWebserviceWrapper(String webserviceEndPoint) {

                     this.webserviceEndPoint = webserviceEndPoint;

       }

      public TestPortType getWebServiceClient() {
                 TestPortType testPortType = new TestWSServiceagent()
               .getCIACSAPortTypeEndpoint();
             ((BindingProvider) testPortType).getRequestContext().put(
               BindingProvider.ENDPOINT_ADDRESS_PROPERTY,                       webserviceEndPoint);

         return testPortType;
     }

}

No magic just override the BindingProvider.ENDPOINT_ADDRESS_PROPERTY with the one set in wrapper constructor.

Now in your code just instantiate the wrapper class (or create a bean and inject) set the proper URL in constructor and use the endpoint of your choice  🙂

Web application reading configuration files

Almost all applications running in some web container need access to some configuration file. I always wondered what was the best path and approach to refer it with in your application so you don’t need to worry a lot like redeploying application, rebuild just for changing the configuration file path.

This example assumes it’s a spring web application (however the approach should still work even if it’s not a Spring project just refer to the propertiesLocation env-entry defined in web.xml in your Java code 😦 haven’t tested though !) here is how the application-context file looks like.

<beans>
<context:property-placeholder location="${propertiesLocation}" />
<!--Specific Context file imports-->
<import resource="classpath:/META-INF/main-context.xml"/>
</beans>

Now add the following environment entry into web.xml file.

<env-entry>
<env-entry-name>propertiesLocation</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type> 
</env-entry>

Now add the following to you web server configuration xml file

For jetty: (the propertiese file will be picked up from src/main/resources/app.properties) good for running locally 🙂

<New id="propertiesLocation" class="org.eclipse.jetty.plus.jndi.Resource">
 <Arg></Arg>
 <Arg>propertiesLocation</Arg>
 <Arg>file:src/main/resources/app.properties</Arg>
 </New>

For tomcat: (the propertiese file will be picked up from opt/projectname/tomcat7/conf/app.properties)

Add to TOMCAT_HOME/tomcat7/conf/context.xml:

<Parameter name="propertiesLocation" value="file:///opt/projectname/tomcat7/conf/app.properties" override="true"/>

Great we are done now and can refer to properties file location without messing with directory paths.