WebLogic Split Deployment with Maven

The purpose of this article is to show how to use WebLogic's Split Deployment with Maven without going through Oracle Enterprise Pack for Eclipse thus eliminating the need to use an integration layer (the one between Maven and WTP) and two plug-ins (The Eclipse WTP and Oracle's OEPE), passing only through the pom of the project and the tools made available by Maven itself.

Recipe

How does Split Deployment work

The purpose of the split deployment is to allow the deploy of only altered components in an enterprise application, skipping the steps of packaging and complete application restart. 

Unfortunately this good idea is not supported by a good implementation. Oracle has in fact decided to impose its own quirky layout and its "tools" (some Ant tasks), without any possibility of customization.

Fortunately WebLogic Server instead provides a very intelligent system to map the virtual layout to the real, phisical, layout. A file called .beabuild.txt (on the root of the EAR that we want to deploy) which permits the mapping between virtual file/folder/package to absolute locations on the file-system.

I'll try to give an example of it:

C\:/progetti/xxx/parent/web/src/main/webapp = web.war

C\:/progetti/xxx/parent/web/target/classes = web.war/WEB-INF/classes

C\:/progetti/xxx/parent/ejb/target/classes = ejb.jar

C\:/Users/zzzzzz/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar = APP-INF/lib/commons-logging.jar

these four lines have the following meanings: 

Obviously are also possible other interesting configurations, for instance you could map a web.xml that is different from that in the WebApp's war (eg if we prototype with Google WebToolkit, its shell does not usually use the same web.xml) :

C\:/progetti/xxx/TestSplit/src/main/webapp/web.xml = web.war/WEB-INF/web.xml

Once prepared the file that reflects our folder structure we try to deploy the application, setting the CLASSPATH:

setWLSEnv.cmd

and then running the deployer: 

java weblogic.Deployer -adminurl t3://localhost:7001 -username weblogic -password xxxxxx -name test-split -debug -deploy <path-to-src-main-application>

This will be the command that we'll will launch from out Maven project, using the maven-antrun-plugin.

A bit of foreplay: Creating a Maven Test Project

I organized my test enterprise project with this structure:

    parent (pom)

     |

     |--ear (ear)

     |--wars (war)

     |--ejb (ejb)

We can easily do that creating a parent "pom" project that include the three modules:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

      <modelVersion>4.0.0</modelVersion>

      <groupId>net.lucamasini.splitdeploy</groupId>

      <artifactId>parent</artifactId>

      <packaging>pom</packaging>

      <version>0.0.1-SNAPSHOT</version>

      <modules>

            <module>ear</module>

            <module>ejb</module>

            <module>web</module>

      </modules>

</project>

then inside the pom's folder we can create the three archetyes:

mvn archetype:generate -DgroupId=net.lucamasini.splitdeploy -DartifactId=ear -DarchetypeArtifactId=ear-jee5 -DarchetypeGroupId=org.codehaus.mojo.archetypes 

                       -DinteractiveMode=false -DarchetypeVersion=1.0.1 -Dpackage=net.lucamasini.splitdeploy

mvn archetype:generate -DgroupId=net.lucamasini.splitdeploy -DartifactId=war -DarchetypeArtifactId=webapp-jee5 -DarchetypeGroupId=org.codehaus.mojo.archetypes 

                       -DinteractiveMode=false -DarchetypeVersion=1.0.1 -Dpackage=net.lucamasini.splitdeploy

mvn archetype:generate -DgroupId=net.lucamasini.splitdeploy -DartifactId=ejb -DarchetypeArtifactId=ejb-jee5 -DarchetypeGroupId=org.codehaus.mojo.archetypes 

                       -DinteractiveMode=false -DarchetypeVersion=1.0.1 -Dpackage=net.lucamasini.splitdeploy

Once created we must include the dependencies of the war and ejb into the ear's pom:

<dependency>

    <groupId>test-split</groupId>

      <artifactId>ejb</artifactId>

      <version>0.0.1-SNAPSHOT</version>

      <type>ejb</type>

      <scope>compile</scope>

</dependency>

<dependency>

      <groupId>test-split</groupId>

      <artifactId>web</artifactId>

      <version>0.0.1-SNAPSHOT</version>

      <type>war</type>

      <scope>compile</scope>

</dependency>

Now we can try if everything works doing a "mvn install" and checking if the created ear is correct (we auto-deploy it in WebLogic for a quick and dirty check).

Configuring deployment into Maven project

Oracle also provides an ANT version of its deploy command, that we can quite easily run from within Maven only adding to the dependencies of the maven-antrun-plugin plugin Weblogic jars usually added to the classpath from the setWLSEnv.cmd command:

<plugin>

    <groupId>org.apache.maven.plugins</groupId>

      <artifactId>maven-antrun-plugin</artifactId>

      <version>1.3</version>

    <configuration>

          <tasks>

              <taskdef name="wldeploy" classname="weblogic.ant.taskdefs.management.WLDeploy" classpathref="maven.plugin.classpath"/>

              <wldeploy

               action="deploy" verbose="true" debug="true"

               name="TestSplit" source="src/main/application"

               user="weblogic" password="weblog1c"

               adminurl="t3://localhost:7001" targets="AdminServer" />

     

       </tasks>                                                         

    </configuration>

      <dependencies>

          <dependency>

              <groupId>com.sun</groupId>

              <artifactId>tools</artifactId>

              <version>${java.version}</version>

              <scope>system</scope>

              <systemPath>${java.home}/../lib/tools.jar</systemPath>

           </dependency>

           <dependency>

               <groupId>weblogic</groupId>

               <artifactId>weblogic</artifactId>

               <version>${weblogic.version}</version>

               <scope>system</scope>

               <systemPath>${weblogic.home}/server/lib/weblogic.jar</systemPath>

            </dependency>

            <dependency>

                <groupId>weblogic</groupId>

                <artifactId>webservices</artifactId>

                <version>${weblogic.version}</version>

                <scope>system</scope>

                <systemPath>${weblogic.home}/server/lib/webservices.jar</systemPath>

             </dependency>

    </dependencies>                   

</plugin>

To start the deployment just run the following goal:

mvn antrun:run

from the ear's pom folder, for this to works is necessary to put the .beabuild.txt into the src/main/application of the ear.

This is a clean solution because this is a source folder for Maven, and as such it's readonly during the build goals (it's never written, but only read to create packages).

It's important to notice that against Java EE 5 specifications a correctly configured "application.xml" for the ear is also required,  and we can say that this is another small price we pay to this eccentric deploy architecture.

Generating .beabuild.txt

Generate that file is a trivial task, but can be really annoying. For this exist an experimental plugin, the maven-beabuild-plugin that can generate this for us with few configurations for the most commons enterprise application layout.

If indeed that doesn't apply to our environment we can use the maven-dependency-plugin that can generate for us the most tedious section of the file, which is the paths to the artifacts in the Maven repository that are Enterprise Libraries:

    <plugin>

            <groupId>org.apache.maven.plugins</groupId>

            <artifactId>maven-dependency-plugin</artifactId>

            <version>2.1</version>

            <configuration>

                <outputFile>${project.build.directory}/dependencies.txt</outputFile>

                <excludeScope>provided</excludeScope>

                <excludeTypes>ejb,war</excludeTypes>

                <outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>

                <silent>true</silent>

        </configuration>

    </plugin>

This would generate under our target folder a file containing the list of dependencies with their absolute path, which then can be cut and pasted inside .beabuild.txt. The sections that instead refer to the enterprise components and any configuration files have yet to be written by hand, but in reality this should be pretty simple and do one-off start-up of the project.

Further step: FastSwap

We are never happy, never agile enough, now we want something that can be so fast that we need to deploy only when we add or remove enterprise components. It would be even better if all this were also integrated with the development environment, and maybe you need only a nice CTRL-S or mvn compile .......

This feature exists, is part of WebLogic and is called FastSwap. In practice it is a Java agent that allows the Java Virtual Machine to go beyond what the Java 5 JVM already permit, or the changing of classes already loaded by the classloader of applications that already run without having to create a new one. This agent allows you to load classes that change at all compared to those loaded (classes and methods), simply by recompiling the class itself (the agent monitors the folders containing the classes to see which have been changed).

Enabling this is simple, just add the weblogic-application.xml file configured with the fast-swap into the src/main/application/META-INF folder:

  <?xml version="1.0" encoding="UTF-8"?>

    <wls:weblogic-application xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-application" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

                              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/javaee_5.xsd http://xmlns.oracle.com/weblogic/weblogic-application     http://xmlns.oracle.com/weblogic/weblogic-application/1.0/weblogic-application.xsd">

            <wls:fast-swap>

                <wls:enabled>true</wls:enabled>

            </wls:fast-swap>

    </wls:weblogic-application>

Appendix 1: FastSwap problems with 64-bit systems

If you're running under a 64-bit Operating System you can incur in exception like this during FastSwap:

"Unable to attach to 64-bit process"

The strage part is that this occur also if you're running both the WebLogic Server and the deploy agent under a 32-bit JVM. This is really annoying and due to this piece of code of the Java_sun_tools_attach_WindowsVirtualMachine_openProcess method inside the WindowsVirtualMachine.c file of the Java Virtual Machine:

    /*

     * On Windows 64-bit we need to handle 32-bit tools trying to attach to 64-bit

     * processes (and visa versa). X-architecture attaching is currently not supported

     * by this implementation.

     */

    if (_IsWow64Process != NULL) {

        BOOL isCurrent32bit, isTarget32bit;

        (*_IsWow64Process)(GetCurrentProcess(), &isCurrent32bit);

        (*_IsWow64Process)(hProcess, &isTarget32bit);

        if (isCurrent32bit != isTarget32bit) {

            CloseHandle(hProcess);

            #ifdef _WIN64

              JNU_ThrowByName(env, "com/sun/tools/attach/AttachNotSupportedException",

                  "Unable to attach to 32-bit process running under WOW64");

            #else

              JNU_ThrowByName(env, "com/sun/tools/attach/AttachNotSupportedException",

                  "Unable to attach to 64-bit process");

            #endif

        }

    }

Seems that the FastSwap agent fails to declare that is a 32-bit process running in WoW64 (_IsWow64Process!=NULL but isCurrent32bit != isTarget32bit), and the only solution I've found is to use the generic WebLogic installer, running the Server with a 64-bit JVM.

Appendix 2: spaces in the repository path and temporary directory

We need also to take care that the "java.io.tmpdir" and the Maven repository are on path without trailing spaces. This can be common in some systems like Windows XP, where both are under "C:\Documents and Settings". To solve move the TMP and TEMP user variables to a folder without spaces and change the settings.xml so that the localRepository is not inside the "C:\Document and Settings".

Appendix 3: Problems with Eclipse WTP and Maven Integration for WTP installed

If these plugins are already installed, then there may be problems during the setup of the project. After creating these Maven projects the plugin will try to help by adding facets and starting to claim configurations that in reality will never be used.

To quench their thirst for blood (the red errors in the Problems view) we must follow their needs, remembering to add the correct version of the compiler (1.6 with WebLogic 10.3.2) and soon also add EJB and Web module to the EAR.

Besides this, do not forget to disable the Workspace Resolution on the parent POM, otherwise the ear plugin will try to use the folder of the EJB classes as an archive (oh my !!!).

Appendix 4: Packaging Enterprise Applications

This is a good reference about packaging of Java Enterprise Applications.