Sharing spring context between web apps

Load all jars part of server classpath loading which will be used to create the spring application context and can be shared/available between Web apps/EARs.

Web.xml (in all WEB apps)

<context-param>
  <param-name>parentContextKey</param-name>
  <param-value>beanRefFactory</param-value>
 </context-param>
 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

 It looks for beanRefContext.xml part of classpath and a spring bean named “beanRefFactory”

beanRefContext.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"
 xsi:schemaLocation="
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 <bean id="beanRefFactory"
  class="org.springframework.context.support.ClassPathXmlApplicationContext">
  <constructor-arg >
    <list>
      <value>classpath*:spring-context.xml</value>
   </list> 
  </constructor-arg>
 </bean>
</beans>

spring-context.xml contains spring beans definition needed by the application and been loaded to create spring application context. This will be the parent application context.

Ensure that applicationContext.xml is placed in WEB-INF folder, used to create its own spring context which extends the parent application context created already. Define the spring beans specific to web modules here. if not, have dummy declaration given below.

applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
</beans>

How to configure number of views in session – Perfomance tuning in JSF

JSF will maintain all its views & its state in HTTP session object if state saving method is server which will cause increased usage of memory. To avoid it, we can minimize the number of views stored in session which suits to the application need that can be defined in web.xml given below

<context-param>
 <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
 <param-value>server</param-value>
</context-param>

<context-param>
 <param-name>com.sun.faces.numberOfViewsInSession</param-name>
 <param-value>3</param-value>
</context-param>

<context-param>
 <param-name>com.sun.faces.numberOfLogicalViews</param-name>
 <param-value>10</param-value>
</context-param>

numberOfViewsInSession defines the number of view states (pages) to support back button operation.

numberOfLogicalViews defines the number of logical views (frames) that can present in a page.

Merging two persistence units

We can merge two persistence unit if both have same persistence-unit name. This can be done using persistence unit post processor.

Note: “default” is the PU name for both persistence1.xml and persistence2.xml given below.

persistence1.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" 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_1_0.xsd">
<persistence-unit name="default">
    <class>examples.A</class>
    .
    .
    .
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
</persistence>

persistence2.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" 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_1_0.xsd">
<persistence-unit name="default">
    <class>samples.A</class>
    .
    .
    .
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
</persistence>

2. Persistence post processor is used to merge all entities present in persistence1.xml & persistence2.xml and be

part of persistence unit manager.

package examples;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MergingPersistenceUnitPostProcessor
implements PersistenceUnitPostProcessor {
Map<String, List<String>> puiClasses = new HashMap<String, List<String>>();

public void postProcessPersistenceUnitInfo( MutablePersistenceUnitInfo pui ) {
List<String> classes = puiClasses.get( pui.getPersistenceUnitName() );
if ( classes == null ) {
classes = new ArrayList<String>();
puiClasses.put( pui.getPersistenceUnitName(), classes );
}
pui.getManagedClassNames().addAll( classes );
final List<String> names = pui.getManagedClassNames();
classes.addAll( pui.getManagedClassNames() );
}
}

3. Configure the merging persistence unit post processor in persistence unit manager.

    <bean    class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
    <bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="websphereDataSource" />
        <property name="persistenceUnitManager" ref="pum" />
        <property name="jpaVendorAdapter">
            <bean
                class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database" value="ORACLE" />
                <property name="showSql" value="true" />
            </bean>
        </property>
    </bean>

    <bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
        <property name="persistenceXmlLocations">
            <list>
             <value>classpath*:META-INF/persistence1.xml</value>
             <value>classpath*:META-INF/persistence2.xml</value>
            </list>
        </property>
        <property name="defaultDataSource" ref="websphereDataSource"/>
        <property name="persistenceUnitPostProcessors">
            <bean class="examples.MergingPersistenceUnitPostProcessor"/>
        </property>
    </bean>

JAD Eclipse plugin

1. Download the Jad executable file.

http://www.varaneckas.com/jad
http://www.softpedia.com/get/Programming/Debuggers-Decompilers-Dissasemblers/JAD.shtml

2. Download Jad Eclipse plugin
http://sourceforge.net/projects/jadclipse/

3. Copy the downloaded Jad Eclipse plugin – Jabclipse(jadclipse_x.x.x.jar) to Eclipse plugin folder.

4. Restart Eclipse to make the plugin take effect.

5. In Eclipse, Click Window –> Preference –> Java –> Jadclipse , Key in Jad’s path in “Path to Decompiler” field
E.G d:\j2ee\jad\jad.exe

6. In Eclipse, try F3 into any class which does not has the source, Jad will decompile it automatically.

Equals and HashCode in Java

Equals checks for values equality of an object. You can override the equals () method to implement the equality conditions based on your need.

Hashcode represents the memory address where your java object lives. You can get this using System.identityHashCode( anObject ).

package examples;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class EqualsHashCodeTest {
 public static void main( String[] args ) {
  System.out.println( "Checking Equals operations..." );
  Emp emp1 = new Emp( 1, "John" );
  Emp emp2 = new Emp( 1, "John" );

  if ( emp1.equals( emp2 ) ) {
   System.out.println( "Both are equal" );
  } else {
   System.out.println( "Both are not equal" );
  }
  System.out.println( "\nAdding duplicate employees into list..." );
  List<Emp> emps = new ArrayList<Emp>();
  emps.add( new Emp( 1, "John" ) );
  emps.add( new Emp( 2, "David" ) );
  emps.add( new Emp( 1, "John" ) );
  System.out.println( "List Size:" + emps.size() );

  System.out.println( "\nAdding duplicate employees into set..." );
  Set<Emp> empsSet = new HashSet<Emp>( emps );
  System.out.println( "Set Size:" + empsSet.size() );

 }
}

class Emp {
 private int empId;

 private String empName;

 Emp(int empId, String empName) {
  this.empId = empId;
  this.empName = empName;
 }

 @Override
 public int hashCode() {
  System.out.println( "Inside hashCode()" );
  final int prime = 31;
  int result = 1;
  result = prime * result + empId;
  result = prime * result + ( ( empName == null ) ? 0 : empName.hashCode() );
  System.out.println( "EmpId:" + empId + "\t EmpName:" + empName );
  System.out.println( "HashCode value :" + result );
  return result;
 }

 @Override
 public boolean equals( Object obj ) {
  System.out.println( "Inside equals()" );
  if ( this == obj )
   return true;
  if ( obj == null )
   return false;
  if ( getClass() != obj.getClass() )
   return false;
  Emp other = (Emp) obj;
  System.out.println( "this.empId :" + this.empId + "\t Other.empId :" + other.empId );
  System.out.println( "this.empName :" + this.empName + "\t Other.empName :" + other.empName );
  if ( empId != other.empId )
   return false;
  if ( empName == null ) {
   if ( other.empName != null )
    return false;
  } else if ( !empName.equals( other.empName ) )
   return false;
  return true;
 }

}

Output:

Checking Equals operations...
Inside equals()
this.empId :1 Other.empId :1
this.empName :John Other.empName :John
Both are equal

Adding duplicate employees into list...
List Size:3

Adding duplicate employees into set...
Inside hashCode()
EmpId:1 EmpName:John
HashCode value :2315531
Inside hashCode()
EmpId:2 EmpName:David
HashCode value :65806931
Inside hashCode()
EmpId:1 EmpName:John
HashCode value :2315531
Inside equals()
this.empId :1 Other.empId :1
this.empName :John Other.empName :John
Set Size:2

In the above code,

1. We are comparing two objects using equals() method. Hope it is clear.

2. I am adding list of employees having some duplicate employee details. When i get the size, it gives me 3 , not able to find the duplicates in list. No equals() and hashCode() in Emp class are being invoked.

3. I am adding list of employees in the Set collection. For each Object, it calls the hashcode(), Once the hashcode is equals for two objects, it calls the equals() method to check whether the object is having equal values for all member attributes. Ofcourse, you can change the equality check based on your need. Once it is found as equals, those object will not be added into Set. Hence the size of set is 2.

That’s all. Hope you have got the usage of equals() and hashCode()  now.

ThreadLocal Usage

ThreadLocal can be used if you want variable/object to be maintained till the end of thread execution.

 

public class ThreadLocalTest extends Thread {
    // Define/create thread local variable
    static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
    int serialNo;
    public ThreadLocalTest(int serialNo) {
        this.serialNo = serialNo;
    }
    public void run() {
        threadLocal.set( serialNo );
        System.out.println( “Thread name:”+ Thread.currentThread().getName() +“\tSerialNo:” + threadLocal.get() );
    }
    public static void main( String args[] ) {
        for ( int cnt = 0; cnt < 5; cnt++ ) {
            Thread t = new Thread( new ThreadLocalTest( cnt ), “Thread-“ + cnt );
            t.start();
        }
    }
}

 

Output:

Thread name:Thread-1 SerialNo:1

Thread name:Thread-3 SerialNo:3

Thread name:Thread-0 SerialNo:0

Thread name:Thread-2 SerialNo:2

Thread name:Thread-4 SerialNo:4

Duplicate child inserts during merge operation in hibernate

Parent entity has list of child object marked as “LAZY” with CascadeType.ALL. When I tried to add child into parent and merge it, it tries to inserts two child records.

This issue can be fixed in following ways

Solution 1:

    Retrieve the child list size() to initialize lazy child collections, add the new child and merge it.

It will insert one child record only. Ensure that it is bounded in a transaction.

parent.getChilds().size();

    parent.getChilds().add(child);

    entityManager.merge(parent);

 

Solution 2:

    Simply add the new child into parent and don’t call merge operation. Ensure that it is bounded in a transaction.

    

parent.getChilds().add(child);

Pick up any solution that works out for you.

This is a bug in Hibernate marked as closed but not fixed https://hibernate.onjira.com/browse/HHH-3332.