Configuration

In the following sections we'll go through some configuration of the various layers. This is necessary before we can write some presentation code and deploy the web application.

JPA annotations for domain objects

We'll start with the persistence layer. All objects that are going to be persisted need to be mapped. This includes the Customer, Address, Account, and Loan objects. The validation message objects don't need to be mapped because they are not going to be persisted. Most of the time the default mapping settings will be used. The @Entity annotation will be used to declare that a class should be persistent, and we'll also explicitly specify the table name. Every entity needs an ID. A uuid field of type String will be added to every entity. The @Id annotation will declare that this uuid field is the ID of an entity. The customer's accounts will be mapped with a @OneToMany annotation, which declares that one customer can have many accounts. Let's now look at a mapping of the Customer class:

@Entity
@Table(name = "app_customer")
public class Customer implements Serializable {
  @Id private String uuid;
  private String firstName;
  private String lastName;
  private Date dateOfBirth;
  private Address address;
  
  @OneToMany(mappedBy="owner") private Set<Account> accounts;
  private String phoneNumber;  

Code listing 1: Code extract from the Customer class (the Customer.java file)

Please consult the hibernate manual for advanced mapping (http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/).

We're using uuids as IDs, because they are much easier to work with. We can assign them at object-creation time instead of object-persistence time as is the case with database-assigned IDs. The standard java.util.UUID class will be used to generate the uuid fields. We can define a factory for creating our domain objects that will automatically assign an uuid object to every new object:

public class DefaultBankingFactory implements BankingFactory {
  @Override
  public Customer createCustomer() {
    Customer customer = new Customer();    
    customer.setUuid(UUID.randomUUID().toString());
    Set<Account> accounts = new HashSet<Account>(); 
    customer.setAccounts(accounts);
    return customer;
  }

Code listing 2: The DefaultBankingFactory class that follows the Factory design pattern (the DefaultBankingFactory.java file)

Our factory implements the BankingFactory interface, which contains all the factory methods such as createCustomer, createAddress, createAccount, and so on. These methods make sure that all created objects have their references correctly set, for example, the createAccount method takes a customer as an argument and adds the newly created account to the collection of the customer's accounts and also sets this customer as the owner of this account. This keeps the referential integrity intact. We can even declare a domain object's constructors as "package private" so that new instances can be created only through this factory.

JPA configuration

Next, we'll work on the JPA 2.0 provider configuration. This configuration also defines the classes that should be made persistent. All this information will be contained in a so-called persistence-unit. This configuration is as follows:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
  version="2.0">
  <persistence-unit name="droolsbook.persistence"
    transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <mapping-file>META-INF/Taskorm.xml</mapping-file>
    <mapping-file>META-INF/JBPMorm-JPA2.xml</mapping-file>
    <mapping-file>META-INF/ProcessInstanceInfoMapping-JPA2.xml</mapping-file>
    <class>droolsbook.bank.model.Customer</class>
    <class>droolsbook.bank.model.Address</class>
    <class>droolsbook.bank.model.Account</class>
    <class>droolsbook.bank.model.LoanApprovalHolder</class>
    <class>org.drools.persistence.info.SessionInfo</class>
    <class>org.drools.persistence.info.WorkItemInfo</class>
    <class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class>
    <class>org.jbpm.persistence.processinstance.ProcessInstanceEventInfo</class>
    <class>org.jbpm.task.Attachment</class>
    <class>org.jbpm.task.Content</class>
    <class>org.jbpm.task.BooleanExpression</class>
    <class>org.jbpm.task.Comment</class>
    <class>org.jbpm.task.Deadline</class>
    <class>org.jbpm.task.Comment</class>
    <class>org.jbpm.task.Deadline</class>
    <class>org.jbpm.task.Delegation</class>
    <class>org.jbpm.task.Escalation</class>
    <class>org.jbpm.task.Group</class>
    <class>org.jbpm.task.I18NText</class>
    <class>org.jbpm.task.Notification</class>
    <class>org.jbpm.task.EmailNotification</class>
    <class>org.jbpm.task.EmailNotificationHeader</class>
    <class>org.jbpm.task.PeopleAssignments</class>
    <class>org.jbpm.task.Reassignment</class>
    <class>org.jbpm.task.Status</class>
    <class>org.jbpm.task.Task</class>
    <class>org.jbpm.task.TaskData</class>
    <class>org.jbpm.task.SubTasksStrategy</class>
    <class>org.jbpm.task.OnParentAbortAllSubTasksEndStrategy</class>
    <class>org.jbpm.task.OnAllSubTasksEndParentEndStrategy</class>
    <class>org.jbpm.task.User</class>
  </persistence-unit>
</persistence>

Code listing 3: JPA 2.0 configuration (the persistence.xml file)

All this information is stored in a file called persistence.xml. This file should be stored on the classpath under the META-INF/ folder. The name of our persistence unit is droolsbook.persistence. The transaction type we're using is RESOURCE_LOCAL, which is enough since we'll be working with one resource only, that is, database. The <provider> element specifies the actual provider; in our case, it is org.hibernate.ejb.HibernatePersistence. Next, we load JPA mapping files as we've seen in Chapter 8, Defining Processes with jBPM, and tell the hibernate provider what additional files to look into Customer, Address, Account, and LoanApprovalHolder, including the standard jBPM classes for JPA annotations. All these classes are declared to be persistent.

Spring framework configuration

We'll configure the Spring framework. This can be done in various ways. XML is the most commonly used. The configuration will reside in three XML files. We'll start with a file called applicationContext.xml that will hold configuration related to the service layer (persistence, transactions, knowledge base configuration, and individual services configurations):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:drools="http://drools.org/schema/drools-spring"
  xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
       http://drools.org/schema/drools-spring http://drools.org/schema/drools-spring.xsd">

Code listing 4: Extract from the Spring configuration (the applicationContext.xml file)

The various Spring configuration files will use more or less the same header (as seen in Code listing 4); they will differ only in the XSD namespaces used. The previous file declares four namespaces that will be used: beans as the default one, and aop, tx, and drools from the drools-spring module. For more information about the Spring namespaces please consult the Spring documentation (http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/).

We've already defined the persistence configuration in the persistence.xml file. These were just the very basics. We'll now enhance this configuration in Spring. The Spring configuration files will be the ultimate place where everything is configured. The following is the definition of an entityManagerFactory interface that will be responsible for creating EntityManagers, which will store our objects into the dataSource persistent store. The entityManagerFactory interface references the persistence-unit configuration named droolsbook.persistence defined earlier. It also specifies a bunch of properties that will be simply passed to the persistence provider:

<bean id="entityManagerFactory"
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="persistenceUnitName"
    value="droolsbook.persistence" />
  <property name="jpaPropertyMap" ref="jpaPropertyMap" />
</bean>

<bean id="jpaPropertyMap" class="org.springframework.beans.factory.config.MapFactoryBean">
  <property name="sourceMap">
    <map>
      <entry key="hibernate.dialect" 
        value="org.hibernate.dialect.H2Dialect" />
      <entry key="hibernate.show_sql" value="true" />
      <entry key="hibernate.format_sql" value="true" />
      <entry key="hibernate.use_sql_comments" value="true"/>
      <entry key="hibernate.hbm2ddl.auto" 
        value="create-drop" />
    </map>
  </property>
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="org.h2.Driver" /> 
  <property name="url" value="jdbc:h2:droolsBookDatabaseH2" />
  <property name="username" value="sa" />
  <property name="password" value="sasa" />
</bean>

Code listing 5: Extract from the Spring configuration (the applicationContext.xml file), entityManagerFactory bean definition

The entityManagerFactory interface is an instance of LocalContainerEntityManagerFactoryBean. It will read the contents of the persistence.xml file, and based on them and value-pairs in the jpaPropertyMapit method, it will create the entityManagerFactory interface. The jpaPropertyMap method is declared as a separate bean so that it can be easily reused later on.

The first JPA property, hibernate.dialect, specifies a class that represents the dialect of our database. As you can see we'll use the H2 database (http://www.h2database.com). It can run entirely in memory, which is ideal for our purposes. The next few properties are self-explanatory. Then, we'll see the hibernate.hbm2ddl.auto property, whose value is set to create-drop, which specifies that we want to recreate the database (structure and data) every time we start the application. Finally, we're also defining the data source itself.

The applicationContext.xml file also defines some beans that we'll use later:

<bean name="bankingFactory" 
  class="droolsbook.bank.model.DefaultBankingFactory" />
<bean name="reportFactory"
  class="droolsbook.bank.service.impl.DefaultReportFactory" />

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean name="customerRepository"
  class="droolsbook.sampleApplication.repository.jpa.JPACustomerRepository" />

Code listing 6: Extract from the Spring configuration (the applicationContext.xml file), which shows various bean definitions

The first two are factories. We've already seen the DefaultBankingFactory interface in Code listing 2 and the DefaultReportFactory interface was described in Chapter 3, Validating. The next two beans configure a customer repository. The PersistenceAnnotationBeanPostProcessor method is responsible for injecting EntityManagers into repositories. We'll see how it's done in the next few.

Web application setup

The core components of the persistence and service layers are there. We can start work on the presentation layer. We'll start with the web.xml web application configuration file. It is a standard web-app configuration file that defines the basics of a web application such as the name, welcome file list, and some initialization servlets. The initialization servlets will be called when we start the application in a server:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
      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_3_0.xsd"
      version="3.0">
  <display-name>sampleApplication</display-name>
  <servlet>
    <servlet-name>sampleApplication</servlet-name>
    <servlet-class>
      org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>sampleApplication</servlet-name>
    <url-pattern>*.htm</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

Code listing 7: Web application configuration (the web.xml file)

As can be seen from the previous code, Spring's DispatcherServlet is loaded on the startup. This servlet by default looks for the sampleApplication-servlet.xml configuration file. We'll soon define this file. Just make sure it is placed in the webRoot/WEB-INF/ directory. The configuration also defines a servlet mapping for all resources ending with .htm to this DispatcherServlet. The welcome file is set to index.jsp. This file has to be present in the webRoot/ directory. For testing purposes index.jsp will contain a listing of various entry points into the application (list all customers link, add customer link, request loan link, and so on).

As promised, the sampleApplication-servlet.xml Spring configuration file is given next. It will import the already defined applicationContext.xml configuration file.

Furthermore, the configuration file will define a standard "view resolver". This view resolver will be set to look for views in the webRoot/WEB-INF/jsp/ directory—view as in model-view-controller (MVC) that can be found at http://en.wikipedia.org/wiki/Model-view-controller. This will help us to separate our controllers from the view implementations. We'll see how it works in a few sections:

<import resource="classpath:applicationContext.xml" />
<context:annotation-config />
<context:component-scan
  base-package="droolsbook.sampleApplication.web"/>
<bean id="viewResolver"
  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass"
    value="org.springframework.web.servlet.view.JstlView" />
  <property name="prefix" value="/WEB-INF/jsp/" />
  <property name="suffix" value=".jsp" />
</bean>

Code listing 8: Extract from the Spring configuration (the sampleApplication-servlet.xml file), which is an initial configuration

The import resource elements are simply importing the contents of the resource into one big Spring application context. The <context:annotation-config /> element activates Spring's annotation support for easier configuration of controllers. For the interface layer we'll use full Spring annotation auto-wiring, because the presentation layer changes more frequently. In the persistence and services layer, reliability is the most important, so we define the wiring ourselves. Then the <context:component-scan ..> element tells Springs to scan the given package for various components; in our case it is controllers, so we don't have to define them in the XML file.

Deployment

The deployment involves copying the contents of the webRoot directory into Tomcat's webapps directory and renaming it to sampleApplication. Then create a new lib directory under webapps/sampleApplication/WEB-INF/ and copy all libraries that are on the classpath into this directory. All other resources on the classpath should go to the webapps/sampleApplication/WEB-INF/classes directory. That is all in terms of deployment. Tomcat can be started, and we can access the application at http://localhost:8080/sampleApplication/. The index.jsp welcome page should be displayed.

The deployment can be even easier if you have installed an Eclipse plugin called Web Tools Platform (WTP). You can then create a dynamic web project; set up a server (Tomcat) and the WTP plugin will do the deployments for you. Note that the WTP plugin is a standard part of Eclipse IDE for Java EE Developers (http://www.eclipse.org/downloads/).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.34.146