Thursday, June 29, 2017

Apache Maven and SOA 11g. Configure J2EE Applications

Hello there,
I have selected the shortest night in the year to continue the story of the Apache Maven and Oracle SOA 11g marriage. If you haven't read my previous posts, please check them here. Last time I stopped on the Maven-enabled project. Now I'm going to finish Java/J2EE part and build Enterprise Java Archive (EAR).



Application structure

To do so, we need to create another folder to separate a new project model with the target - ear and to link both projects together we should create another one on the workspace level.  IThis time there is nothing to do with the JDeveloper compatibility issues, rather Maven approach to get things done. The diagram below describes how all project models are related, and why the separate folder is the easiest way to create new modules.


Main application model refers to all application projects by module names. The project folder on the file system should have the very same name otherwise, you will have FileNotFound exception. When you run Maven with some goal on the application level, it loops through all the modules, goes down recursively, and applies the very same operation on the project model. 
To maintain the proper order, project model declares dependencies similarly to the external dependencies. Maven uses those declarations to identify the proper execution order. Additionally, for the modules, I use a reference to the parent pom so all children could share global properties. 

Application project model

Let's start with the adding Application level pom at the project workspace level. Maven plugin wizard has special document type, so we simply follow steps we have done already:
  1. Open "New ..." wizard 
  2. Search for Maven under  All Technologies tab 
  3. Select "Maven POM for Applications" 
  4. Fill all the project fields. You may use screenshot below for the reference.


If the wizard wouldn't discover all the projects for you, add our two projects manually. 
Also, lets some preparation ahead the time and define application level properties which we will use for the deployment a little bit later. So the final application model would look like the code below.

<?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>

 <properties>
  <serverURL>t3://localhost:7101</serverURL>
  <wlUsername>weblogic</wlUsername>
  <wlPassword>welcome1</wlPassword>
 </properties>

 <modules>
  <module>pdf-print-servlet</module>
  <module>soa11g-maven-app</module>
 </modules>
 <packaging>pom</packaging>
</project>

J2EE project model

We have one module defined already, now it's time to create project description for the enterprise application archive.  To build an application in the EAR let's perform some easy tasks:
  1. Under main application folder to create the new folder, let's say soa11g-maven-app. In my case, full patch to the ear module is C:\JDeveloper\mywork\soa11g-maven\soa11g-maven-app
  2. Open JDeveloper and modify your web application project settings, so your new folder will be visible as a resource. The only reason to do so: the convenient way to access your ear project model from the JDeveloper interface.


  3. Save project configuration 
  4. From the "New ..." wizard create new "Maven POM for the Project", the same way as we did for the web application, with the only difference - place document in our soa11g-maven-app folder, and set packaging as the ear.
  5. Now all 3 project models should be visible in the application navigator tree. The main one in the application resources section, the Web application in the project resources, as well as the new one. Hint: It may be useful to enable  Group by Directory option in the Projects view. 
  6. Add parent reference and the web service project dependency so the new pom.xml would look like the code below.
<?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-app</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <parent>
    <groupId>pdf-print-app</groupId>
    <artifactId>soa11g-maven</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <relativePath>../pom.xml</relativePath>
  </parent>
  <packaging>ear</packaging>
  <dependencies>
    <dependency>
      <groupId>pdf-print-app</groupId>
      <artifactId>pdf-print-servlet</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <type>war</type>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-ear-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

Will we deploy or what?

Yes, we will, but we should configure maven-ear-plugin first. Although, this plugin build packages, not deploys it, so we should put another plugin to the build list. It will be WebLogic deployer plugin that we discussed a month ago.  
For a fine tuning maven plugins uses configuration subtree where you can put all the application or environment specific details. In the plugin configuration section, you should place a list of the modules in the application and specify where we are going to keep shared libraries. It worth to mention that if you are going to use shared libraries, you should add them to the project dependencies.
 <configuration>
 <defaultLibBundleDir>APP-INF/lib</defaultLibBundleDir>
 <skinnyWars>true</skinnyWars>
 <modules>
  <webModule>
   <groupId>pdf-print-app</groupId>
   <artifactId>pdf-print-servlet</artifactId>
   <contextRoot>/pdfprint</contextRoot>
  </webModule>
 </modules>
</configuration>

Now I will add external dependencies to the ear module. Along with this change, we should change external modules scope for the web application, otherwise, we will get library duplicates twice: once for the .war archive and the second time on the .ear level. You can open servlet pom file and copy paste dependency to the current model. To properly build our J2EE project we also should refer to the web application project. So J2EE dependencies section will have two entries:
 
    <dependency>
        <groupId>org.apache.xmlgraphics</groupId>
        <artifactId>fop</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
      <groupId>pdf-print-app</groupId>
      <artifactId>pdf-print-servlet</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <type>war</type>
    </dependency>

And for the web application let's put scope section to the dependency description. It means, that Maven will use those libraries for the compilation, but will not pack them along with project code because we know that these libraries will be available for the project at the deployment time.

    <dependency>
        <groupId>org.apache.xmlgraphics</groupId>
        <artifactId>fop</artifactId>
        <version>2.2</version>
        <scope>provided</scope>
    </dependency>

Don't forget to save all the changes.

Configure WebLogic Deployer

Do you see the light in the tunnel? I do! The final plugin to configure is the WebLogic Deployer.
This plugin description below mostly is project unaware, so you may just copy and paste into your J2EE project model into build/plugins section. Tace a look and I will explain 
 <plugin>
    <groupId>com.oracle.weblogic</groupId>
    <artifactId>weblogic-maven-plugin</artifactId>
    <version>10.3.4</version>
    <configuration>
      <adminurl>${serverURL}</adminurl>
      <user>${wlUsername}</user>
      <password>${wlPassword}</password>
      <upload>true</upload>
      <action>deploy</action>
      <remote>true</remote>
      <stage>true</stage>
      <verbose>true</verbose>
      <source>
          ${project.build.directory}/${project.build.finalName}.${project.packaging}
       </source>
      <name>${project.build.finalName}</name>
    </configuration>
    <executions>
      <execution>
       <phase>install</phase>
       <goals>
         <goal>deploy</goal>
       </goals>
      </execution>
    </executions>
 </plugin>

Plugin starts with the usual plugin declaration such as groupID, arthifactID, and desired version. As for the previous plugin, we have large configuration section with all the parameters required to install WebLogic application.  I'd like to stress the fact that we use properties defined in the application POM.  Reference to the custom property looks like exactly the same as Maven predefined one. The combination of upload, remote, and stage parameters allows you perform remote deployment, for example from the build VM.
Addition execution instructions instruct Maven when WebLogic plugin should be activated.  This particular execution will be activated when you run maven with the command with the goal install at the moment when a project will be ready for deployment.Documentation for the Weblogic 11g describes all the plugin configuration details, so if I missed some parameters or you have doubts, here is a great source fo the truth.

Save all the changes and now we are ready to build our J2EE application. If you have been lost (TBH, I'm lost already), you may refer to the GitHub repository and check POM files there.

Build and deploy

It's time to gather all the stones. 
  1. Make sure that you are in the application scope (JDeveloper has a file from the current workspace open)
  2. Click the toolbar button MVN Clear (If you haven't followed my Maven posts, you could configure environment now )
  3. If everything is fine Maven shows you the banner in the MVN Clean log window.

If you get success messages for all projects, go ahead and try to install EAR application. You actually don't need any WebLogic server for the tests. The configuration in my example points to the integrated WebLogic instance. 
  1. Prior the application installation, sure that your server is up and running To do so, select Run/Start Server Instance from the JDeveloper main menu.
  2. Connect to the WebLogic Console using URL http://localhost:7101 and credentials you have specified at the time of the instance configuration (in my case it's always weblogic/welcome1).
  3. Click on the install external tool button or use Tools/MVN Install menu


Apache Maven states that installation has been successful. From the WebLogic Console, we may validate that the application has been deployed with no errors and it's ready to serve requests.


Now, you have JDeveloper with the Maven-enabled application. It may not worth all the efforts if you face a simple application with the few projects. However, for the complex solutions with 4+ projects and application cross-dependencies, it would be a handful. The final long read about SOA projects will be coming soon. We are facing long-long weekend. 

Happy Independence Day for all and everyone!

No comments: