Friday, January 30, 2015

Tomcat7 Spring Annotation

The following is the list of the related files and the related contents.

pom.xml

                <properties>
   <org.springframework.version>3.1.4.RELEASE</org.springframework.version>
         </properties>

                <!--   SpringFramework  -->
                <dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-core</artifactId>
   <version>${org.springframework.version}</version>
  </dependency>

  <dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-web</artifactId>
   <version>${org.springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-config</artifactId>
   <version>${org.springframework.version}</version>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>${org.springframework.version}</version>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>${org.springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-beans</artifactId>
   <version>${org.springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>${org.springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context-support</artifactId>
   <version>${org.springframework.version}</version>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-expression</artifactId>
   <version>${org.springframework.version}</version>
  </dependency>
  
  
  <!-- JSR-330 and CDI -->
  <dependency>
   <groupId>javax.inject</groupId>
   <artifactId>javax.inject</artifactId>
   <version>1</version>
  </dependency>
  
  <dependency>
   <groupId>javax.enterprise</groupId>
   <artifactId>cdi-api</artifactId>
   <version>1.2</version>
  </dependency>

Note that the dependency cdi-api is included to test the use of the annotations from CDI. The tests will show that it does not work. The annotation @javax.enterprise.context.SessionScoped is from CDI. But the annotations @Named and @Inject are from JSR330.

Note that another name of CDI is JSR299. Though the number 299 is less than 330, JSR299 is actually on top of JSR330.

web.xml

 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/spring-security.xml,
                  /WEB-INF/application-context.xml
                </param-value>
 </context-param>

 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

Note that two xml files are included. The file spring-security.xml has mostly the security URL configurations. It also has some bean declarations. The file application-context.xml will scan the beans with annotations. It also has some bean declarations.

faces-config.xml

       <faces-config 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-facesconfig_2_1.xsd"
 version="2.1">
 
 <application>
  <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
 </application>

spring-security.xml

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

 <authentication-manager alias="authenticationManager">
  <authentication-provider user-service-ref='omsUserDetailsService' />
 </authentication-manager>

 <beans:bean id="omsUserDetailsService"
  class="com.lakexy.oms.security.OmsUserDetailService">
  <beans:property name="userDao" ref="userDao" />
 </beans:bean>

 <beans:bean id="userDao" class="com.lakexy.oms.dao.security.UserDaoImpl">
  <beans:property name="dataSource" ref="omsDataSource" />
 </beans:bean>

 <http auto-config="true">
  <intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY" />
  <intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
  <logout logout-success-url="/index.jsp" />

 </http>

</beans:beans>

application-context.xml

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">

 <context:component-scan base-package="com.lakexy" />
 
 <bean id="omsDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
  <property name="jndiName" value="java:comp/env/jdbc/inventory" />
 </bean>

 
 <!-- *********************************************************** -->
 <!--            T R A N S A C T I O N  S E T U P                 -->
 <!-- *********************************************************** -->


 <!--
  Transaction Interceptor set up to do PROPAGATION_REQUIRED on all
  methods
 -->
 <!--
  <bean id="omsTransactionManager"
  class="org.springframework.transaction.jta.JtaTransactionManager">
  </bean>
 -->

 <bean id="omsTransactionManager"
  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource">
   <ref local="omsDataSource" />
  </property>
 </bean>

 <bean id="matchAllWithPropReq"
  class="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource">
  <property name="transactionAttribute">
   <value>PROPAGATION_REQUIRED,-OmsCheckedException</value>
  </property>
 </bean>
 <bean id="matchAllTxInterceptor"
  class="org.springframework.transaction.interceptor.TransactionInterceptor">
  <property name="transactionManager">
   <ref bean="omsTransactionManager" />
  </property>
  <property name="transactionAttributeSource">
   <ref bean="matchAllWithPropReq" />
  </property>
 </bean>
 <!--
  One BeanNameAutoProxyCreator handles all beans where we want all
  methods to use PROPAGATION_REQUIRED
 -->
 <bean id="autoProxyCreator"
  class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  <property name="interceptorNames">
   <list>
    <idref bean="matchAllTxInterceptor" />
   </list>
  </property>
  <property name="beanNames">
   <list>
    <idref bean="customerBo" />
    <idref bean="locationBo" />
    <idref bean="orderBo" />
    <idref bean="omsUserDetailsService" />
    <idref bean="shipmentBo" />
    <idref bean="invoiceBo" />
   </list>
  </property>
 </bean>

</beans>

Notes:

  1. application-context.xml mixed the component-scan and the explicit bean declaration for those beans that are used in transaction management.
  2. The base-package is "com.lakexy" in component-scan. But that does not mean that any classes in the package com.lakexy will be registered as a bean in the spring container. A class will be registered in the spring container only when it has the annotation such as @Named.

Lastly, the actual java classes with annotations.

Example:

import javax.inject.Inject;
import javax.inject.Named;
import org.springframework.context.annotation.Scope;

@Named
// @SessionScoped
@Scope("session")
// @RequestScoped
public class CustomerBean {

 private String customerName;
 private List<Customer> customers;
 private CustomerTableData customersTableData;
 @Inject
 private ICustomer customerBo;
...
}

Notes

  1. @Named is from standard java annotation. But nevertheless, spring recognize this annotation.
  2. By default, the bean scope in Spring is singleton. So if @Named is the only annotation, this CustomerBean will be a singleton, which essentially make it an Application scoped bean.
  3. I tested the use of different scope annotations. Confusingly, there are several variations of session scope.The @SessionScoped can mean one of the followings:
    javax.faces.bean.SessionScoped
    javax.enterprise.context.SessionScoped;
    
    But nevertheless, the tests show that this annotation does not have effects. The same CustomerBean instance is used even if you use the application in different browsers. So it acts like a singleton just as when only @Named is used. But the spring annotaion @Scope("session") as in the above code works. The tests do show that it acts as a session bean. So it looks like that Spring supports JSR330 but not CDI. The annotations @Named and @Inject are from JSR330. The annotation javax.enterprise.context.SessionScoped is from CDI. I did some search on internet and did find articles saying that Spring3 supports JSR330 but not JSR299. And there is a way to use JSR299 in Spring3.
  4. When @Inject is used, no need to write the getter and setter for the annotated field.
  5. Injection is type-based. So in the example above, it will search for a bean of the type ICustomer. The name of the bean does not necessarily have to be "customerBo".

References

  1. http://www.mkyong.com/jsf2/jsf-2-0-spring-integration-example
  2. https://www.mkyong.com/spring3/spring-3-and-jsr-330-inject-and-named-example
  3. http://stackoverflow.com/questions/18387993/spring-jsf-integration-how-to-inject-a-spring-component-service-in-jsf-managed
  4. http://www.beyondjava.net/blog/integrate-jsf-2-spring-3-nicely

No comments:

Post a Comment