Tuesday, July 04, 2017

Apache Maven and SOA 11g. Enable the composite.


Okay everyone, holidays are over and it's time to complete this super long read. If you haven't seen 3 previous posts you may go and check the first one here. Today we will discuss how to enable Maven for the SOA projects. Bad thing - it has a proprietary compiler and there is no Maven plugin at all, good thing the compiler uses Ant tasks to build and deploy Oracle SOA 11g composites. Now we have a plan and our project model should be able to:
  • Compile Java code and package it along with the SOA artifacts. The reason is your composite may use custom Java classes to perform some activities that hard or impossible to implement with the XPath/XQuery/XSLT tools you have. 
  • Test Java code, before build or install, especially if you use JUnit to cover your code. 
  • Build SCA archive with the proper Ant task 
  • Deploy composite archive to the SOA servers.
Rephrasing those steps in the project configuration terms we will talk about:
  • Additional properties for the SOA-specific tasks. 
  • Configure Java compiler and package plugin
  • Configure Ant plugin for Maven 

SOA 11g composite application 

I have created SOA composite int the same project. It's very simple composite with one reference to expose functionality as a service, and two references. The one - points to our PDF print web service, the second one point to the notification services. The main idea is: You call the BPEL it pass the parameters to the PDF generator and delivers the result as an e-mail attachment.
Because the main topic is a Maven, I don't care much about how real-lifish the composite is, we just need some SOA project for compile and package. So, the diagram below is an eye candy, and if you interested you may find the code here.

Before we go to the project and application configuration, let's go and create the new pom.xml file for the new composite application. I assume, that you:

  • Reuse workspace and the environment configuration from the previous posts
  • Create or clone new project with the name: maven-enabled-ca
  • Have created Maven project model with the JAR target before
On the screenshot, you may see the Apache Maven for the Project with all the application parameters. 


Save the new model, add the name property and parent project reference, as we've done for the previous models.

Additional application properties 

Before diving into the composite model, let's finalize application-wide properties, required for the proper project compilation and the deployment.

  1. Update list of the application modules and add the new one with the new artifactId
  2. Populate few more properties.
There is the final application model. Don't forget to put your actual values for the server connections and user names.
<?xml version="1.0" encoding="windows-1252" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>pdf-print-app</groupId>
  <artifactId>soa11g-maven</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>${project.groupId}/${project.artifactId}_v${project.version}</name>
  <properties>
   <serverURL>t3://localhost:7101</serverURL>
   <wlUsername>weblogic</wlUsername>
   <wlPassword>welcome1</wlPassword>
   <soaURL>http://soa.server:8001</soaURL>
   <soaPartition>default</soaPartition>
   <jdev.home>C:/Oracle/Middleware/JDeveloper</jdev.home>   
  </properties>
  <modules>
    <module>pdf-print-servlet</module>
    <module>soa11g-maven-app</module>
    <module>maven-enabled-sca</module>
  </modules>
  <packaging>pom</packaging>
</project>

Also, please note that for the composite deployment we use SOA managed servers HTTP connection rather than T3 AdminServer address for WebLogic applications.  
Now we can finalize project configuration.

Configure Java compiler and package plugin

If you are happy to run SOA composites without a piece of the custom code, you are luckier than I am otherwise, it's better to be sure that your classes and libraries are bundled with the other composite objects.  As for the regular jar file, we instruct Maven how to build code:
        <sourceDirectory>SCA-INF/src/</sourceDirectory>
        <testSourceDirectory>test/</testSourceDirectory>
        <outputDirectory>SCA-INF/classes</outputDirectory>

So far there is no difference with the regular build instructions, but now we should add the new plugin because SOA composite has more than one source directories. Off course you remember that project has two folders: ${basedir}/src and ${basedir}/SCA-INF/src. It's not a big deal for the JDevleoper, but a little bit tricky for the Maven. To address that issue we should use plugin configured as below:
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>1.1</version>
                <executions>
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>src/</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

Another plugin we should use to adjust Maven behavior is the cleaner. Extra configuration instructs how to delete compiled classes from the previous builds.

            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <configuration>
                    <filesets>
                        <fileset>
                            <directory>SCA-INF/classes</directory>
                            <includes>
                                <include>**/*.class</include>
                            </includes>
                            <followSymlinks>false</followSymlinks>
                        </fileset>
                    </filesets>
                </configuration>
            </plugin>

Wit this code we instruct clean plugin to delete all compiled Java classes under SCA-INF/classes with all the subfolders but don't follow the symbolic links. and to complete the Java compiler configuration, target folder for the jar builder is SCA-INF/lib folder.

            <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-jar-plugin</artifactId>
               <configuration>
                  <outputDirectory>SCA-INF/lib</outputDirectory>
               </configuration>
            </plugin>

Configure Ant plugin for Maven

Now, we are looking at the largest part of the project. The great news - you need just Copy/Paste it from project to project. it's very parametrized and uses properties as much as possible.  Configuration blow binds Ant targets to the Maven execution phases.
 
<plugin>
  <artifactId>maven-antrun-plugin</artifactId>
  <version>1.6</version>
  <executions>
    <execution>
       <id>sca-package</id>
       <phase>package</phase>
       <configuration>
          <target>
            <property name="scac.application.home"
                value="${basedir}/.."/>
            <property name="build.compiler"
                value="extJavac"/>
           <property name="compositeName"
               value="${project.artifactId}"/>
           <property name="compositeDir"
               value="${basedir}"/>
           <property name="revision"
               value="${project.version}"/>
           <property name="configplan"
               value="${basedir}/${project.artifactId}_cfgplan.xml"/>           
           <ant antfile="${jdev.home}/bin/ant-sca-package.xml"
               dir="${jdev.home}/bin" target="package"/>
          </target>
       </configuration>
       <goals>
          <goal>run</goal>
       </goals>
    </execution>
    <execution>
       <id>sca-undeploy</id>
       <phase>deploy</phase>
       <configuration>
          <target>
            <property name="serverURL"
                value="${soaURL}"/>
            <property name="user" value="${wlUsername}"/>
            <property name="password"
                value="${wlPassword}"/>
            <property name="compositeName"
                value="${project.artifactId}"/>
            <property name="revision"
                value="${project.version}"/>
            <property name="sarLocation"
                value="${basedir}/deploy/sca_${project.artifactId}_rev${project.version}.jar"/>
            <property name="overwrite" value="true"/>
            <property name="forceDefault" value="true"/>
            <property name="configplan"
                value="${basedir}/${project.artifactId}_cfgplan.xml"/>           
            <property name="partition"
                value="${soaPartition}"/>
            <ant antfile="${jdev.home}/bin/ant-sca-deploy.xml"
                dir="${jdev.home}/bin" target="undeploy"/>
          </target>
       </configuration>
       <goals>
          <goal>run</goal>
       </goals>
    </execution>
    <execution>
      <id>sca-deploy</id>
      <phase>install</phase>
      <configuration>
        <target>
          <property name="serverURL"
              value="${soaURL}"/>
          <property name="user" value="${wlUsername}"/>
          <property name="password"
              value="${wlPassword}"/>
          <property name="sarLocation"
             value="${basedir}/deploy/sca_${project.artifactId}_rev${project.version}.jar"/>
          <property name="overwrite" value="true"/>
          <property name="forceDefault" value="true"/>
          <property name="partition"
            value="${soaPartiiton}"/>
          <property name="configplan"
            value="${basedir}/${project.artifactId}_cfgplan.xml"/>           
          <ant antfile="${jdev.home}/bin/ant-sca-deploy.xml"
            dir="${jdev.home}/bin" target="deploy"/>
         </target>
       </configuration>
       <goals>
         <goal>run</goal>
       </goals>
    </execution>
  </executions>
</plugin>

The first execution prescribes Maven run Ant plugin using the file ${jdev.home}/bin/ant-sca-package.xml and the goal package. It also configures input parameters so the extJavac compiler could find all the necessary components. The similar way plugin describes deploy and undeploy executions. Configuration properties match with the Ant goals parameters, additional information you always could find in the Oracle SOA 11g documentation.  The full code of the SOA project POM is here.

Save your project model, double check all the properties and click on the MVN Build external tool button. Script traverses through all your application and will build your J2EE archive and SOA composite deployment.

Now we have done! All the project components were built with no errors.

Afterwords

It was a long running process and it has taken about 2 months just to pile it up and write it down. I'm soo late with all that information, especially with the all new 12c JDeveloper, where the Maven is an integral part of the IDE and you should not do all those things manually.  
Well, there are a lot of the companies who run SOA 11g and use old JDevelopers, and if you haven't done this before it may help you with the DevOps, continuous integration and old good Oracle environments. 

No comments: