Creating the worklist project

This post is part of a series on building a custom worklist for BPM/SOA 11g.

We are using Maven as our project and build management software.  We used Maven 2 on Mac OS X.  Let’s set up our skeleton project and get the POM ready.

We will create the skeleton project using the webapp-javaee6 archetype.  Issue the following command:

# mvn archetype:generate

Select the webapp-javaee6 archetype and enter the coordinates for your project.  We used the following:

groupId:    com.oracle.ateam
artifactId: worklist
version:    1.0-SNAPSHOT
package:    com.oracle.ateam

Maven will create a new project for us in the directory called worklist (the directory will have the same name as we specified for the artifactId).  Inside our new project we will find the following structure:

/                    project root
  - src              source files
    - main           source files for our application
      - java         java source files
      - webapp       web source files (JSPs, CSS, etc.)
    - test           source code for our test cases
  - target           output files from builds
  - pom.xml          The Maven POM

Let’s create a few more directories to organise our artifacts.  Inside src/main/java you will find a set of directories matching the package you specified when you created the project, in our case we have src/main/java/com/oracle/ateam.  We will use this directory to hold our Spring Controllers.  Inside this directory we will create another directory called src/main/java/com/oracle/ateam/domain to hold our ‘business logic’ – the Model, or classes that deal with the BPM API and some wrapper classes to simplify our View design.  Also we will create src/main/java/com/oracle/ateam/util to hold utility classes, such as logging.

Inside the src/main/webapp directory, we will create a new directory to hold our deployment descriptors and configuration files, called src/main/webapp/WEB-INF, and inside that directory another to hold our JSP files, called src/main/webapp/WEB-INF/jsp, and inside that another to hold our common/include files, called src/main/webapp/WEB-INF/jsp/common.  We will also create a directory called src/main/webapp/images to hold images we use in our view (user interface).

So now our project structure looks like this:

/                    project root
  - src                           source files
  | - main                        source files for our application
  | | - java                      java source files
  | | | - com
  | | | | - oracle
  | | | | | - ateam               Spring Controllers
  | | | | | | - domain            'business logic' - the Model
  | | | | | | - util              utility classes
  | | - webapp                    web source files (JSPs, CSS, etc.)
  | | | - WEB-INF                 deployment descriptors and config files
  | | | | - jsp                   Spring Views (JSPs)
  | | | | | - common              common JSP fragments (headers, etc.)
  | | | - images                  images
  | - test                        source code for our test cases
  - target                        output files from builds
  - pom.xml                       The Maven POM

We don’t want to version control the target directory, which contains our builds, so we create a .svnignore file in the project root directory, which contains the following text:

target*

Then we run the following command to tell Subversion to read this file and set up the ignore rules:

# svn propset svn:ignore -F .svnignore .

Now, let’s set up our POM.  We need to add dependencies, configure the WebLogic Maven plugin to allow deployment to WebLogic as part of our build, configure source code management and distribution.  Here is the complete POM:

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.oracle.ateam</groupId>
    <artifactId>worklist</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <developers>
      <developer>
        <id>markxnelson</id>
        <name>Mark Nelson</name>
        <timezone>+12</timezone>
      </developer>
    </developers>

    <name>Custom BPM Worklist</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <repositories>
      <repository>
        <id>local</id>
        <url>file:///home/mark/.m2/repository</url>
      </repository>
    </repositories>
    <pluginRepositories>
      <pluginRepository>
        <id>localPlugins</id>
        <url>file:///home/mark/.m2/repository</url>
      </pluginRepository>
    </pluginRepositories>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.oracle.soa</groupId>
            <artifactId>bpminfra</artifactId>
            <version>11.1.1.4</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.oracle.soa</groupId>
            <artifactId>bpmservices</artifactId>
            <version>11.1.1.4</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.oracle.soa</groupId>
            <artifactId>wlthinclient</artifactId>
            <version>11.1.1.4</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.oracle.soa</groupId>
            <artifactId>wsclient</artifactId>
            <version>11.1.1.4</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.oracle.soa</groupId>
            <artifactId>xml</artifactId>
            <version>11.1.1.4</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.oracle.soa</groupId>
            <artifactId>xmlparserv2</artifactId>
            <version>11.1.1.4</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
          <version>1.1.1</version>
        </dependency>
        <dependency>
          <groupId>commons-fileupload</groupId>
          <artifactId>commons-fileupload</artifactId>
          <version>1.1.1</version>
        </dependency>
        <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
          <version>1.3.2</version>
        </dependency>
        <dependency>
          <groupId>taglibs</groupId>
          <artifactId>standard</artifactId>
          <version>1.1.2</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jstl</artifactId>
          <version>1.1.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.1</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>6.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
              <groupId>com.oracle.weblogic</groupId>
              <artifactId>weblogic-maven-plugin</artifactId>
              <version>10.3.4</version>
              <configuration>
                 <adminurl>t3://ofm1.au.oracle.com:7001</adminurl>
                 <user>weblogic</user>
                 <password>welcome1</password>
                 <name>worklist</name>
                 <remote>true</remote>
                 <upload>true</upload>
                 <targets>soa_server1</targets>
                 <jvmArgs>
                   <jvmArg>-Xmx1024m</jvmArg>
                 </jvmArgs>
               </configuration>
               <executions>
                 <execution>
                   <id>deploy</id>
                   <phase>pre-integration-test</phase>
                   <goals>
                      <goal>deploy</goal>
                   </goals>
                   <configuration>
                      <source>target/worklist.war</source>
                   </configuration>
                 </execution>
              </executions>
            </plugin>
        </plugins>
        <finalName>worklist</finalName>
    </build>

  <scm>
    <connection>scm:svn:file:///home/mark/svnrepos/worklist/trunk</connection>
    <developerConnection>scn:svn:file:///home/mark/svnrepos/worklist/trunk</developerConnection>
    <url>file:///home/mark/svnrepos/worklist/trunk</url>
  </scm>

  <distributionManagement>
    <!-- use the following if you're not using a snapshot version. -->
    <repository>
      <id>local</id>
      <name>local repository</name>
      <url>file:///home/mark/.m2/repository</url>
    </repository>
    <!-- use the following if you ARE using a snapshot version. -->
    <snapshotRepository>
      <id>localSnapshot</id>
      <name>local snapshot repository</name>
      <url>file:///home/mark/.m2/repository</url>
    </snapshotRepository>
  </distributionManagement>

</project>

Now let’s walk through and look at each of the sections we need to add/modify, starting with the dependencies.  Maven dependencies are expressed as a set of ‘coordinates’ – groupId, artifactId, version, type.  These uniquely identify the dependency and allow Maven to retrieve the necessary libraries for use in compilation and packaging.  We can also specify a ‘scope’ which tells Maven whether the dependency needs to be packaged into the deployment archive, or whether it is already available in the runtime environment.  We can also specify dependencies that are only needed during the testing phase.

Here are the dependencies included in our POM.  These are listed in the format groupId:artifactId:type:version (scope).  You will note in the POM above that the type is omitted if it is jar and the scope is ommited if it is compile.  These are the default values, so they are implied by convention if not specified.

javax:javaee-web-api:jar:6.0 (provided)
  This provides the necessary Java EE libraries for a web application.
junit:junit:jar:4.8.1 (test)
  This is the libraries necessary to run JUnit tests.
com.oracle.soa:bpminfra:jar:11.1.1.4 (compile)
com.oracle.soa:bpmservices:jar:11.1.1.4 (compile)
com.oracle.soa:wlthinclient:jar:11.1.1.4 (compile)
com.oracle.soa:wsclient:jar:11.1.1.4 (compile)
com.oracle.soa:xml:jar:11.1.1.4 (compile)
com.oracle.soa:xmlparserv2:jar:11.1.1.4 (compile)
  These are the BPM API libraries which we installed into our local Maven
  repository in the previous post.
org.springframework:spring-core:jar:3.0.5-RELEASE (compile)
org.springframework:spring-webmvc:jar:3.0.5-RELEASE (compile)
  These are the Spging core and Web MVC libraries.
commons-logging:commons-logging:jar:1.1.1 (compile)
commons-fileupload:commons-fileupload:jar:1.1.1 (compile)
commons-io:commons-io:jar:1.3.2 (compile)
  These are Apache Commons libraries that are use for logging and for
  the upload of files (for the 'attachment' capability).
taglibs:standard:jar:1.1.2 (compile)
javax.servlet:jstl:jar:1.1.2 (compile)
  These are the Java Standard Tag Library (JSTL) libraries that we use
  to create the View.

Next, we want to set up our Maven repositories, source code management and distribution management.  Here are the appropriate parts of the POM:

    <repositories>
      <repository>
        <id>local</id>
        <url>file:///home/mark/.m2/repository</url>
      </repository>
    </repositories>
    <pluginRepositories>
      <pluginRepository>
        <id>localPlugins</id>
        <url>file:///home/mark/.m2/repository</url>
      </pluginRepository>
    </pluginRepositories>

  <scm>
    <connection>scm:svn:file:///home/mark/svnrepos/worklist/trunk</connection>
    <developerConnection>scn:svn:file:///home/mark/svnrepos/worklist/trunk</developerConnection>
    <url>file:///home/mark/svnrepos/worklist/trunk</url>
  </scm>

  <distributionManagement>
    <!-- use the following if you're not using a snapshot version. -->
    <repository>
      <id>local</id>
      <name>local repository</name>
      <url>file:///Users/mark/.m2/repository</url>
    </repository>
    <!-- use the following if you ARE using a snapshot version. -->
    <snapshotRepository>
      <id>localSnapshot</id>
      <name>local snapshot repository</name>
      <url>file:///Users/mark/.m2/repository</url>
    </snapshotRepository>
  </distributionManagement>

You will need to update this section to match your environment.

Finally, we want to configure the project to use the WebLogic Maven Plugin so that we can have Maven deploy the project for us as part of the build.

First, you will need to actually set up and install the plugin.  See this post for instructions on how to do that.  Once you have it installed, you need to add some settings to the POM to tell Maven how to deploy our application.  Here is the relevant section of our POM:

            <plugin>
              <groupId>com.oracle.weblogic</groupId>
              <artifactId>weblogic-maven-plugin</artifactId>
              <version>10.3.4</version>
              <configuration>
                 <adminurl>t3://ofm1.au.oracle.com:7001</adminurl>
                 <user>weblogic</user>
                 <password>welcome1</password>
                 <name>worklist</name>
                 <remote>true</remote>
                 <upload>true</upload>
                 <targets>soa_server1</targets>
                 <jvmArgs>
                   <jvmArg>-Xmx1024m</jvmArg>
                 </jvmArgs>
               </configuration>
               <executions>
                 <execution>
                   <id>deploy</id>
                   <phase>pre-integration-test</phase>
                   <goals>
                      <goal>deploy</goal>
                   </goals>
                   <configuration>
                      <source>target/worklist.war</source>
                   </configuration>
                 </execution>
              </executions>
            </plugin>

You will need to modify this to suit your environment.  The adminurl needs to point to the AdminServer in your WebLogic domain.  The name controls the name of the web application, and targets defines the managed server (or cluster) to deploy the web application to.

At this stage, we will also create some simple deployment descriptors so that we can test the deployment.  Create a file called src/main/webapp/WEB-INF/web.xml with the following contents.  This is the standard Java EE Web Application deployment descriptor.

<?xml version="1.0" encoding="UTF-8"?>
<web-app
  xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  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/web-app_2_5.xsd"
  id="worklist" version="2.5">
  <display-name>Custom BPM Worklist</display-name>
</web-app>

Create the WebLogic deployment descriptor src/main/webapp/WEB-INF/weblogic.xml with the following contents:

<!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web Application 9.1//EN"
   "http://www.bea.com/servers/wls810/dtd/weblogic 810-web-jar.dtd">
<weblogic-web-app>
  <context-root>/worklist</context-root>
  <jsp-descriptor>
    <page-check-seconds>1</page-check-seconds>
  </jsp-descriptor>
</weblogic-web-app>

In the WebLogic deployment descriptor, we set the context-root for the application, and also we have set page-check-seconds to 1 to tell WebLogic to reload JSPs every time it gets a request.  This will slow down performance, but makes testing a lot easier.  When you are ready to deploy the application for actual users, you will want to remove this setting.

Having now got our skeleton project configured, you should be able to build and deploy the skeleton application using the command:

# mvn deploy

The first time you do this, Maven will download all of the necessary dependencies, compile the source code (there are a couple of examples included in the standard archetype), run the tests, package it up into a web deployment archive and deploy it to WebLogic Server.

Creating Spring Controllers

Our application will use two ‘utility’ Controller classes, let’s take a look at these now.  First of all, we want to have the ability for a Controller to forward the user to a ‘success’ or ‘failure’ view depending on some logic in the Controller itself.  The AbstractController in Spring only lets us send the user to a single view, so we are going to use the SimpleSuccessFailureController from Professional Oracle WebLogic Server by Robert Patrick et al.  Here is the code:

package com.oracle.ateam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

public class SimpleSuccessFailureController extends AbstractController {
  private String successView;
  private String failureView;

  @Override
  protected ModelAndView
  handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
  throws Exception {
    return new ModelAndView(getSuccessView());
  }

 public String getSuccessView() {
    return successView;
  }

  public void setSuccessView(String pSuccessView) {
    successView = pSuccessView;
  }

  public String getFailureView() {
    return failureView;
  }

  public void setFailureView(String pFailureView) {
    failureView = pFailureView;
  }
}

We will use this Controller as a superclass, that most of our other Controllers will extend.  We will see how our Controllers are built over several posts.

The other ‘generic’ or ‘utility’ Controller is our ErrorController which we will use to handle errors.  Since the only kind of error that can really get us to this point is a ‘pretty bad one’ we will go ahead and end the user’s session.  All of the ‘not so bad’ errors are handled where they occur.  Here is the code for the ErrorController:

package com.oracle.ateam;

import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.oracle.ateam.util.MLog;
import com.oracle.ateam.domain.MTaskList;
import com.oracle.ateam.domain.ContextCache;

public class ErrorController extends SimpleSuccessFailureController {
  @Override
  protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    MLog.log("ErrorController", "Entering handleInternalRequest()");
    // destroy the context
    ContextCache.getContextCache().remove(request.getRemoteUser());
    // invalidate the session
    request.getSession().invalidate();
    // inform the user
    request.getSession(true).setAttribute("message", "Your session has become invalid and has been reset.");
    return super.handleRequestInternal(request, response);
  }
}

So this Controller will remove the user’s credentials from the cache – we will learn about this soon – and log the user out (by invalidating their session).  It will also pass a message to the view to inform the user what happened.  We will see how this works later on.

In the next post, we will create the business logic layer and some utility classes.

About Mark Nelson

Mark Nelson is an Architect (an "IC6") in the Fusion Middleware Central Development Team at Oracle. Mark's job is to make Fusion Middleware easy to use in the cloud and at home, for developers and operations folks, with special focus on continuous delivery, configuration management and provisioning - making it simple to manage the configuration of complex environments and applications built with Oracle Database, Fusion Middleware and Fusion Applications, on-premise and in the cloud. Before joining this team, Mark was a senior member of the A-Team since 2010, and worked in Sales Consulting at Oracle since 2006 and various roles at IBM since 1994.
This entry was posted in Uncategorized and tagged , , , , . Bookmark the permalink.

One Response to Creating the worklist project

  1. Pingback: Setting up the development environment for the Worklist | RedStack

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s