Oracle WebLogic Server: automatic deploy

19 Mar 2013    

Some time ago, I did an article on Continuous Deployment, using LiveRebel. While I still think LiveRebel is a very interesting product, it has two important drawbacks:

  1. It is not cheap.
  2. It has no support for Oracle WebLogic.

In my current project, I have to do a migration of 110+ applications from Sun Java Application Server 8, with JDK5 and GlassFish 2.1.1, with JDK6 to Oracle WebLogic 10.3 with JDK7, on Solaris. Of course I have no intention to do this manually; hence I need an automated solution.

Application Migration:

Application Migration was a no-brainer:

  • Make a feature branch for the migration in Subversion. I decided to make a feature branch of our current production release to make sure the migration didn't interfere with potential bugfix releases.
  • Set up the feature branch as a Jenkins job, linked with JDK7. The Jenkins build server plays nicely with our older Ant-build projects as well with the Maven-build projects.

After this, all I needed to do was hit the “Build now” button and my application was built with JDK7.

Automatic deployment:

Now that the EAR of WAR has been built, it still needed to be deployed to a specific Managed Server on our WebLogic Server. To achieve this, I looked into a Jenkins plugin called: WebLogic Deployer Plugin. This plugin looked promising, but I was reluctant to couple our build server with our application server. An alternative was found in the WebLogic Maven Plug-In for Deployment that is provided and supported by Oracle. A colleague (Geroen Dierckx) had already succesfully used this in his project, so expectations were high. Installation of the plugin is covered in the WebLogic documentation. This meant adding the plugin to the application’s Maven Pom:

        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>com.oracle.weblogic</groupId>
                    <artifactId>weblogic-maven-plugin</artifactId>
                    <version>10.3.6.0</version>

                    <configuration>
                        <adminurl>${weblogic-maven-plugin.adminurl}</adminurl>
                        <user>${weblogic-maven-plugin.user}</user>
                        <password>${weblogic-maven-plugin.password}</password>
                        <remote>${weblogic-maven-plugin.remote}</remote>
                        <verbose>${weblogic-maven-plugin.verbose}</verbose>
                        <debug>${weblogic-maven-plugin.debug}</debug>
                        <targets>${weblogic-maven-plugin.targets}</targets>
                        <name>${weblogic-maven-plugin.name}</name>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>

with the following properties:

<weblogic-maven-plugin.targets>ms</weblogic-maven-plugin.targets>
<weblogic-maven-plugin.adminurl>t3://localhost:7001</weblogic-maven-plugin.adminurl>
<weblogic-maven-plugin.user>xx</weblogic-maven-plugin.user>
<weblogic-maven-plugin.password>xx</weblogic-maven-plugin.password>
<weblogic-maven-plugin.remote>false</weblogic-maven-plugin.remote>
<weblogic-maven-plugin.verbose>true</weblogic-maven-plugin.verbose>
<weblogic-maven-plugin.debug>false</weblogic-maven-plugin.debug>
<weblogic-maven-plugin.name>Demo</weblogic-maven-plugin.name>

After this, I also added a WebLogic profile to the POM:

<profiles>
        <profile>
            <id>weblogic-deploy</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>com.oracle.weblogic</groupId>
                        <artifactId>weblogic-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>deploy</id>
                                <phase>install</phase>
                                <goals>
                                    <goal>deploy</goal>
                                </goals>
                                <configuration>
                                    <upload>true</upload>
                                    <source>${project.build.directory}/${project.build.finalName}.ear</source>
                                </configuration>
                            </execution>
                            <execution>
                                <id>start-app</id>
                                <phase>install</phase>
                                <goals>
                                    <goal>start-app</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
	</profiles>

It is also possible to add an undeploy profile .. however I didn’t add that as we currently don’t need this functionality.

After committing these changes to the feature branch, I set up a Post Step in Jenkins:

install -P weblogic-deploy -Dwls.targets=ms -Dwls.adminurl=t3://localhost:7001 -Dwls.user=xx -Dwls.password=xx

If all went well, the Console Output will display the state of the deploy.

I mentioned we also had to migrate older applications, built in Ant. Jenkins makes this very easy. Add the above configuration to a new Maven POM file. After configuring the Ant build in Jenkins, add a new Post Step task that will execute the Maven build. An additional advantage of this setup is the possibility to reuse a Jenkins Job configuration for different environments. Changing the JVM params in the weblogic-deploy Post Step makes it possible to deploy to the UAT or PRD environment. Deploying from source also enables the developer to add environment-specific properties to the application (eg. passwords, URL’s, ..)

The application is now automatically build and deployed to an Oracle WebLogic Server. Going from this to Continuous Deployment, would be as simple as configuring a build trigger in Jenkins. The WebLogic Maven Plug-In uses the native webLogic.Deployer, meaning it’s supported and recommended by Oracle. In many projects, this can be a useful advantage.

Disclaimer: I don’t consider feature branching to be a best practice per se. I think this article by Martin Fowler on Promiscuous Integration vs Continuous Integration is a recommended read on the subject and a good start to make any related decisions. In my situation (migration) it made sense.