Monday, September 12, 2016

Java Annotation PostConstruct and Inheritance

It is quite confusing when the Java inheritance is mingled with the PostConstruct annotation. Based on my tests, I found the following. Suppose there are two classes.
  class A {
    @PostConStruct
    private void init(){
 
    }
  }

  class B extends A {

   }


Case 1

For the above case, the execution order is
  1. Constructor of A
  2. Constructor of B
  3. init method of A.
So the annotation @PostConstruct is inherited even when the annotated method is private in the parent class.

Case 2

Now if the class B has its own @PostConstruct method such as the following:
      @PostConstruct
      private void my_init(){
      }
   
Then the init() method of A will not be called. Instead, my_init() is called. So it seems that in the class hierarchy, only one PostConstruct annotated method is called.

Case 3

Now if the class B does not have its own @PostConstruct. But it overrides the @PostConstruct annotated method in its parent class.
  class A {
    @PostConStruct
    public void init(){
       System.out.println("A init()");
    }
  }

  class B extends A {
   @Override
   public void init(){
      System.out.println("B init()");
    }
   }
In this case the @PostConstruct method init() is called. But the init() method used is from class B. So it will print "B init()". Note that if the init() method in class A is private, then "A init()" will be printed out. In this case, the init() method of B is not an override method. Actually you have to remove its @Override annotation. Otherwise it won't compile.

Conclusion

In summary, if there is a method with the annotation @PostConstruct in a class C or its parent classes, then the annotated method will be called after the constructor of C is called. In case that @PostConstruct appears in multiple classes in the class hierarchy, the one closest to the class C will be called. Furthermore, if that annotated method is overridden by its subclasses, then the overriding method will be called. Of course, I think it is bad to declare the @PostConstruct annotated method as public or protected. It should be private so it won't be overridden.

Wednesday, July 27, 2016

A Simple Example to Use Spring BeanWrapper and PropertyAccessorFactory

The Spring classes BeanWrapper and PropertyAccessorFactory can be used to make it easier to set the nested property values of an object. You can also use the BeanWrapper to get the values of the properties.

First suppose there are the following two object classes. One class has a property that is the other class.

public class Animal {
 private String name;
 private Body body;
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public Body getBody() {
  return body;
 }
 public void setBody(Body body) {
  this.body = body;
 }
 @Override
 public String toString() {
  return "Animal [name=" + name + ", body=" + body + "]";
 }
}

public class Body {
 private double weight;
 private double height;
 public double getWeight() {
  return weight;
 }
 public void setWeight(double weight) {
  this.weight = weight;
 }
 public double getHeight() {
  return height;
 }
 public void setHeight(double height) {
  this.height = height;
 }
 @Override
 public String toString() {
  return "Body [weight=" + weight + ", height=" + height + "]";
 }
}

Below is the test class.

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.PropertyValue;

public class PropertyAccessTest {
 public static void main(String[] args) {
  Animal animal = new Animal();
  animal.setBody(new Body());
  System.out.println("animal=" + animal);

  // use the wrapper to set the property values
  BeanWrapper wrapper = PropertyAccessorFactory
    .forBeanPropertyAccess(animal);
  PropertyValue p1 = new PropertyValue("body.weight", 123);
  wrapper.setPropertyValue(p1);
  PropertyValue p2 = new PropertyValue("name", "tiger");
  wrapper.setPropertyValue(p2);
  System.out.println("animal=" + animal);

  // use the wrapper to get the property values
  String[] properties = { "name", "body.weight" };
  for (String p : properties) {
  Object v = wrapper.getPropertyValue(p);
  System.out.println(p + ": " + v.getClass() + " " + v);
  }
 }
}
Running the test class generates the following result:
animal=Animal [name=null, body=Body [weight=0.0, height=0.0]]
animal=Animal [name=tiger, body=Body [weight=123.0, height=0.0]]
name: class java.lang.String tiger
body.weight: class java.lang.Double 123.0

Friday, January 29, 2016

Use WebLogic Maven Plugin

This is for WebLogic 12c. First follow the instructions in reference [1] to install the WebLogic Maven Plugin. Then in the pom.xml file, you can use something like the following:
           <plugin>
                <groupId>com.oracle.weblogic</groupId>
                <artifactId>wls-maven-plugin</artifactId>
                <version>12.1.2.0</version>
                <configuration>
                  <middlewareHome>C:/oracle/wl12.1.2.0</middlewareHome>
                  <weblogicHome>C:/oracle/wl12.1.2.0/wlserver</weblogicHome>
                  <domainHome>C:/oracle/wl12.1.2.0/user_projects/domains/mydomain</domainHome>
                  <source>path/to/myApp.war</source>
                  <user>weblogic</user>
                  <password>welcome1</password>
                  <name>myApp</name>
                </configuration>
            </plugin>
 

The property values in the configuration may have their default values. You can configure the values as needed.

The goal for deployment is com.oracle.weblogic:wls-maven-plugin:deploy.

Reference

  1. https://docs.oracle.com/middleware/1212/wls/WLPRG/maven.htm

Friday, November 20, 2015

Configuraion for Spring transaction management

Trying to understand the declarative transaction management of Spring. The following is from the document of Spring Release 3.2.1.
<!-- from the file 'context.xml' -->
<?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"
 xsi:schemaLocation="
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
     http://www.springframework.org/schema/tx/spring-tx.xsd
     http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop.xsd">

 <!-- this is the service object that we want to make transactional -->
 <bean id="fooService" class="x.y.service.DefaultFooService" />
 <!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean 
  below) -->

 <tx:advice id="txAdvice" transaction-manager="txManager">
  <!-- the transactional semantics... -->
  <tx:attributes>
   <!-- all methods starting with 'get' are read-only -->
   <tx:method name="get*" read-only="true" />
   <!-- other methods use the default transaction settings (see below) -->
   <tx:method name="*" />
  </tx:attributes>
 </tx:advice>

 <!-- ensure that the above transactional advice runs for any execution of 
  an operation defined by the FooService interface -->
 <aop:config>
  <aop:pointcut id="fooServiceOperation"
   expression="execution(* x.y.service.FooService.*(..))" />
   <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation" />
 </aop:config>

 <!-- don't forget the DataSource -->
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy- method="close">
  <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
  <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis" />
  <property name="username" value="scott" />
  <property name="password" value="tiger" />
 </bean>

 <!-- similarly, don't forget the PlatformTransactionManager -->
 <bean id="txManager"
  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource" />
 </bean>
 <!-- other <bean/> definitions here -->
</beans>

The central part is the advisor in the <aop:config> section. It takes two arguments "advice-ref" and "pointcut-ref". Roughly speaking, an advisor advices "someone" to do "something". Here pointcut-ref is that "someone". And advice-ref is that "something". Basically what it says is to apply the advices given in "advice-ref" to those classes and/or methods defined in "pointcut-ref". So actually it is a generic thing of AOP. It is not just for transaction management.

A common requirement is to make an entire service layer transactional.The best way to do this is simply to change the pointcut expression to match any operation in your service layer. For example:

<aop:config>
 <aop:pointcut id="fooServiceMethods" expression="execution(* x.y.service.*.*(..))" />
 <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceMethods" />
</aop:config>
In this example it is assumed that all your service interfaces are defined in the x.y.service package.

Spring's declarative transaction support is enabled via AOP proxies. The AOP proxy uses a TransactionInterceptor. In the Spring Framework, an AOP proxy will be a JDK dynamic proxy or a CGLIB proxy. So underneath, the implementation uses interceptor. You can actually configure org.springframework.transaction.interceptor.TransactionInterceptor directly in XML for transaction management without using AOP.

AOP expression

Below is from Spring document (see the Reference).

Spring AOP users are likely to use the execution pointcut designator the most often. The format of an execution expression is:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
throws-pattern?)
All parts except the returning type pattern (ret-type-pattern in the snippet above), name pattern, and parameters pattern are optional. The returning type pattern determines what the return type of the method must be in order for a join point to be matched. Most frequently you will use * as the returning type pattern, which matches any return type. A fully-qualified type name will match only when the method returns the given type. The name pattern matches the method name. You can use the * wildcard as all or part of a name pattern. The parameters pattern is slightly more complex: () matches a method that takes no parameters, whereas (..) matches any number of parameters (zero or more). The pattern (*) matches a method taking one parameter of any type, (*,String) matches a method taking two parameters, the first can be of any type, the second must be a String. Consult the Language Semantics section of the AspectJ Programming Guide for more information.

Some examples of common pointcut expressions are given below.

  • the execution of any public method:
    execution(public * *(..))
  • the execution of any method with a name beginning with "set":
    execution(* set*(..))
  • the execution of any method defined by the AccountService interface:
    execution(* com.xyz.service.AccountService.*(..))
  • the execution of any method defined in the service package:
    execution(* com.xyz.service.*.*(..))
  • the execution of any method defined in the service package or a sub-package:
    execution(* com.xyz.service..*.*(..))


Rollback Configuration

Spring by default marks a transaction for rollback when a runtime exception is thrown. However you can customize the behavior to let the rollback happen for checked exceptions. The following is an example.

<tx:advice id="txAdvice" transaction-manager="txManager">
 <tx:attributes>
  <tx:method name="get*" read-only="true" rollback-for="CheckedException1, CheckedException2" />
  <tx:method name="*" />
 </tx:attributes>
</tx:advice>
Note that you use comma-delimited expression in the value for rollback-for. There is another attribute no-rollback-for to mark exceptions that should not trigger rollback.

Using transaction annotation

You can annotate the class with @Transactional. The following is from Spring doc.


// the service class that we want to make transactional
@Transactional
public class DefaultFooService implements FooService {
 Foo getFoo(String fooName);
 Foo getFoo(String fooName, String barName);
 void insertFoo(Foo foo);
 void updateFoo(Foo foo);
}

<!-- from the file 'context.xml' -->
<?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"
 xsi:schemaLocation="
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/tx
     http://www.springframework.org/schema/tx/spring-tx.xsd
     http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop.xsd">
     
 <!-- this is the service object that we want to make transactional -->
 <bean id="fooService" class="x.y.service.DefaultFooService" />
 
 <!-- enable the configuration of transactional behavior based on annotations -->
 <tx:annotation-driven transaction-manager="txManager" />
 
 <!-- a PlatformTransactionManager is still required -->
 <bean id="txManager"
  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <!-- (this dependency is defined somewhere else) -->
  <property name="dataSource" ref="dataSource" />
 </bean>
 <!-- other <bean/> definitions here -->
</beans>

Comparing this annotation method against the AOP XML method, you may ask what are the things corresponding to "someone" and "something" of the advisor? The annotation seems to solve the problems altogether in a completely different way. The annotation location indicates the "someone" part. And the annotation name itself indicates that transaction management needs to be carried out, which is "something".

References

  1. http://docs.spring.io/spring/docs/3.2.1.RELEASE/spring-framework-reference/pdf/spring-framework-reference.pdf

Wednesday, November 11, 2015

Notes on using the Spring annotation

Assuming that Spring 3.2.1.Release or above is used in the following notes.
  1. You can use <context:annotation-config/>. It will look for annotations on the properties and methods of a bean, but not the bean class itself.
  2. You use <context:component-scan base-package="org.example" /> to automatically detect classes and register bean definitions. The use of this implicitly enables the functionality of <context:annotation-config>. Also be aware of the following.
    • When <context:component-scan/> is used, the java classes involved need to be annotated with @Component, @Service, etc. Otherwise they would not be recognized.
    • The annotated classes are put into the Spring IoC container. You need to get a bean from this container to get the beans with all the injected properties. Outside this container, the instances of those classes are just plain instances. The annotations have no effect on them.
    • An interesting case is about the servlet. Below is an example.
              @Component
              public class myServlet extends HttpServlet {
                 private @Autowired FooService fooService;
              }
              
      Even though this class is annotated with @Component, the fooService will still be null when this servlet is called in the web application. I think this is because the servlet instance used here is from the Web container. It is NOT from the Spring IoC container. The Spring IoC container may have a copy of this class with fooService injected. But it is not used. So how to still use annotation in a servlet? First of all, the @Component annotation can be removed on servlet. It is not needed since the servlets follow the standard Web container life cycle. The servlet that gets called is from the Web container instead of Spring IoC container. Inside the servlet, you can make annotation work by overriding the init() method as in the following:
         public void init(ServletConfig config) throws ServletException {
            super.init(config);
            SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,config.getServletContext());
        }
      

      Or you can just declare fooService as a plain non-annotated field:

            private FooService fooService;
          
      Then in the code inside the servlet, you can get this object from Spring IoC container as below:
            ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
      
            FooService service = (FooService)applicationContext.getBean("fooService");
        
  3. Annotation injection is performed before XML injection. So the latter configuration will override the former for properties wired through both approaches. You can inject some properties using annotations and other properties using XML. For example, you can have the following:
      public class Foo{
        private @Autowired  Bar bar;
        private DataSource dataSource;
    
      }
    
    
    You can use XML to inject dataSource.
  4. You can use @Configuration class so no XML configuration file is needed. But a cost is that you have to create new java classes with the @Configuration annotation.
  5. To use a @Configuration class, you use AnnotationConfigApplicationContext to include the class. Say that AppConfig is annotated with @Configuration, you can use the following when the application is started.
         public static void main(String[] args){
             ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
             MyService myService = ctx.getBean(MyService.class);
             myService.doStuff();
         }
    
    AnnotationConfigApplicationContext actually is more versatile than that. It can also be used to scan annotated classes as this: ctx.scan("com.sample"). For more information, see Spring documentation.

    In the Web application, you use AnnotationConfigWebApplicationContext. The web.xml file can be configured as below:

      <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext instead of
            the default XmlWebApplicationContext -->
     <context-param>
         <param-name>contextClass</param-name>
         <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
     </context-param>
     
     <!-- Configuration location must consist of one or more comma- or space-delimited fully-qualified @Configuration classes. 
     Fully-qualified packages may also be specified for component-scanning -->
     <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>com.myapp.AppConfig</param-value>
     </context-param>
     
     <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
     </listener>
    
    If you look at the above code snippet, you may wonder how the parameter name "contextClass" is used. It is declared but not referenced anywhere. I think the secret lies in the comment above that parameter. This parameter is implicitly used by the Spring ContextLoaderListener class. As that comment says, ContextLoaderListener uses XmlWebApplicationContext as the contextClass by default. Now we are not using the Spring XML bean definition files, so we change this to AnnotationConfigWebApplicationContext!
  6. There are debates about which way is better, annotation or XML? Both actually have their own pros and cons. Spring's @Configuration class support does not aim to be a 100% complete replacement for Spring XML. You can choose to use "XML-centric" way or java "Annotation-centric" way.

References

  • https://www.mkyong.com/spring3/spring-3-and-jsr-330-inject-and-named-example
  • http://stackoverflow.com/questions/18387993/spring-jsf-integration-how-to-inject-a-spring-component-service-in-jsf-managed
  • http://www.beyondjava.net/blog/integrate-jsf-2-spring-3-nicely
  • Friday, October 23, 2015

    Maven phases and goals

    Maven has a life cycle in its build process. The key concept is "Phase". Do not be confused by another concept "goal". There are different but related. For example, "package" is a phase. It is not a goal.

    Maven can support a number of different life cycles. But the mostly used one is the default Maven life cycle.

    The default life cycle has the following phases (For a more detailed description, see reference[1]). And they are stepped through in order until it reaches at the phase that is specified in the Maven command.

    1. process-resources
    2. compile
    3. process-classes
    4. process-test-resources
    5. test-compile
    6. test
    7. prepare-package
    8. package
    9. install

    Maven delegates the work to Maven plugins.

    Plugin goals can be attached to a life cycle phase. When Maven moves through the phases, it executes the goals attached to each phase. Each phase can have zero or more goals bound to it.

    A phase may mean different things to different projects. For example, for the package phase, a JAR project will produce a JAR file, while a web application will produce a WAR file.

    If no plugin is specified in the pom file, Maven seems to use its default plugins. See reference[2].

    You can run Maven by specifying a phase as in "mvn install". You can also run Maven by specifying the actual goals as in "mvn resources:resources compiler:compile".

    References

    [1] https://maven.apache.org/ref/3.3.3/maven-core/lifecycles.html
    [2] https://maven.apache.org/ref/3.3.3/maven-core/default-bindings.html

    Wednesday, October 21, 2015

    Spring session scoped bean and HTTP session attribute

    A simple JSF application app has a jsf file a.faces and a jsp file b.jsp. The jsp file has the following:
    <%
        HttpSession sess = rquest.getSession();
        FooBean foo = (FooBean)sess.getAttribute("fooBean");
        foo.someMethod();
    %>
    
    And the jsf file has the following:
    <ice:form onsubmit="#{fooBean.doAction}">
    
    Here the tag ice is used because it is using icefaces. The name fooBean is for a Spring bean defined in applicationContext.xml as below:
    <bean id="fooBean" class="FooBean" scope="session">
       <constructor-arg><ref bean="x" /> <constructor-arg>
       <constructor-arg><ref bean="y" /> <constructor-arg>
    </bean>
    
    <bean id="x" class="X"/>
    <bean id="y" class="Y" scope="session"/>
    
    And in the faces-config.xml, there is the following:
    <faces-config>
     <application>
      <variable-resolver>
       org.springframework.web.jsf.DelegatingVariableResolver
      </variable-resolver>
     </application>
    </faces-config>
    

    The application is accessed by app/a.faces. And then you can access the jsp file app/b.jsp without any problem. But if you access the application using app/b.jsp as the first step, it will give NullPointerException when calling foo.someMethod() because foo is null.

    The tricky thing here is how the "fooBean" is put into the session as an attribute. The answer is in the Spring DelegatingVariableResolver class and DefaultListableBeanFactory class.

    When user types app/a.faces, the resolver sees #{fooBean.doAction}. It checks the applicationContext.xml and finds the bean definition. So it creates the bean x, y, and then fooBean. The bean x is a singleton. It is already created at the application startup. So the resolver only needs to get the cached instance of x. But the bean y has a scope of session. So the resolver calls DefaultListableBeanFactory and creates a brand new instance of y. And it puts it as an attribute into the HTTP Session object. After both x and y are created, a new fooBean is created and put into the session as an attribute since its scope is also session. So these session beans are created lazily when there are referenced.

    Now if you access app/b.jsp without firstly accessing app/a.faces, the Spring resolver is not invoked. The session object has no attribute named "fooBean". And you will get a null object for this attribute.

    The following is the method stacks showing the Spring bean is resolved and set into the HTTP session as an attribute.

    owns: InterceptingServletSession  (id=15648) 
     MyAttributeListener.attributeAdded(HttpSessionBindingEvent) line: 13 
     EventsManager.notifySessionAttributeChange(HttpSession, String, Object, Object) line: 302 
     MemorySessionContext(SessionContext).notifySessionAttributeChange(HttpSession, String, Object, Object) line: 1479 
     MemorySessionData(SessionData).setAttribute(String, Object, boolean) line: 1121 
     MemorySessionData(SessionData).setAttribute(String, Object) line: 959 
     InterceptingServletSession(ProxyHttpSession).setAttribute(String, Object) line: 107 
     ServletSessionAttributeMap.setAttribute(String, Object) line: 20 
     ServletSessionAttributeMap(AbstractAttributeMap).put(Object, Object) line: 157 
     FacesRequestAttributes.setAttribute(String, Object, int) line: 108 
     SessionScope(AbstractRequestAttributesScope).get(String, ObjectFactory) line: 44 
     SessionScope.get(String, ObjectFactory) line: 90 
     DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 298 
     DefaultListableBeanFactory(AbstractBeanFactory).getBean(String, Class, Object[]) line: 185 
     DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 164 
     XmlWebApplicationContext(AbstractApplicationContext).getBean(String) line: 881 
     DelegatingVariableResolver.resolveSpringBean(FacesContext, String) line: 136 
     DelegatingVariableResolver.resolveVariable(FacesContext, String) line: 109 
     NamedValue.evaluate(ExpressionInfo) line: 145 
     ComplexValue.evaluate(ExpressionInfo) line: 166 
     ExpressionEvaluatorImpl.evaluate(ExpressionInfo) line: 263 
     ValueBindingImpl.getValue(FacesContext, String) line: 160 
     ValueBindingImpl.getValue(FacesContext) line: 143 
     HtmlForm(HtmlForm).getOnsubmit() line: 501