Friday 15 July 2011

Mercurial: .hgignore and eclipse

When using synchronization, you will want mercurial to ignore/not track certain files. otherwise, it is very difficult to check what files to commit from eclipse synchronize view.

Create .hgignore file to your root and add all the files which are required to ignore by mercurial.
example: .hgignore
#-----------------------------------------------------------------------
# Add an entry for .settings folder to ignore
#------------------------------------------------------------------------
syntax: regexp
^common/\.settings$

#----------------------------------------------------------------------------
# Add an entry for target folder to ignore when creating a new module.
# This will ignore all the class files.
#----------------------------------------------------------------------------
syntax: regexp
^common/target$

#-------------------------------------
# Use global syntax
#-------------------------------------
syntax: glob
.obj
.exe

Wednesday 13 July 2011

Error Solution: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role; no session or session was closed

The problem is when I run the test, it failed on the last assert with the “org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role; no session or session was closed” error.

My DAO method and its test is as follows:


DAOImpl:
public List getActivityUIFields(ActivityType activityType) {
List rv = null;
try {
Query query = em.createNamedQuery("mobileWallet.uiConfigDAO.getUIConfigData");
query.setParameter("activityType", activityType.getValue());
rv = query.getResultList();
} catch (NoResultException nre) {
// No record found.
}
return rv;
}

DAOImplTest:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/dao-test.xml" })
@Transactional
public class UIConfigDAOImplTest {
@Autowired
private EntityManagerFactory entityManagerFactory;

private EntityManager em;

@Autowired
private UIConfigDAO uiConfigDAO;

@Before
public void setUp() {
em = entityManagerFactory.createEntityManager();
}

@After
public void tearDown() throws Exception {
}

@Test
public void testGetUIConfigData() {

List list = uiConfigDAO.getActivityUIFields(ActivityType
.getInstance("SELF"));
Assert.assertNotNull(list);
Assert.assertFalse(list.isEmpty());
Assert.assertEquals("FirstName", list.iterator().next().getValue());
Assert.assertNotNull(list.iterator().next().toString());
}
}


Its bit surprising that Assert.assertEquals("FirstName", list.iterator().next().getValue()); got passed but test failed on the next line.

Reason: Once the Hibernate Session is closed anything that hasn't been loaded, can't be loaded without reattaching your entity to a Hibernate Session. The Session will end once the statement has been executed. If I debug the test method, list has all the values and it works if getValue() is called. But fails on accessing the collection.

Solution: The whole test should be running into a transaction. The easiest way is adding @Transactional at class level. This will put the whole test method in one transaction.

We faced the similar situation when business service was called and the reason was the business service was not under one transaction. The method should be in a transaction where the retrieved collection is used. Always keep the business service in a transaction.

Tuesday 12 July 2011

Specifying parameters for Mockito unit testing

Recently we faced a problem where we wanted to unit-test a service operation using mock objects for dependencies, but the objective of the test was to ensure the operation correctly instantiated an entity from the parameters so that it was ready to be persisted.


@Transactional
public User registerUser(Map<UIField,String> details) {
  User user = new User();
  List<UIField> identifierTypes = referenceDataService.
    getUserIdentifierTypeList();
  Set<UserDetail> userDetails = new HashSet<UserDetail>();
  Set<UserIdentifier> userIdentifiers = new   
    HashSet<UserIdentifier>();
  for(UIField key :details.keySet()) {   
    if(isIdentifierField(key,identifierTypes)) {            userIdentifiers.add(createUserIdentifier(key,
        details.get(key)));
    } else {
      userDetails.add(createUserDetail(key,details.get(key)));
    }
  }
  user.setUserIdentifiers(userIdentifiers);
  user.setUserDetails(userDetails);
  UserStatus status = referenceDataService.
    getUserStatus("REGISTERED");
  user.setUserStatus(status);
  return userService.createUser(user);
}
Listing 1

As listing 1 shows, the registerUser operation instantiates a User object and populates its properties using the parameters passed to the operation. Now we would like the unit-test to ensure this User instance is correctly constructed and its properties correctly populated so that the userService can persist the user. Listing 2 shows the unit-test.


@Test
public void testRegisterUser() {
//need a map of the data that is being submitted for registration.
  Map<UIField,String> data = new HashMap<UIField,String>();
  addUIField(data,"MSISDN","07987654321");
  addUIField(data,"Firstname","Joe");
  addUIField(data,"Lastname","Bloggs");        
  List<UIField> idFieldList = new ArrayList<UIField>();
  idFieldList.add(createUIField("MSISDN"));
     
  Mockito.when(referenceDataService.getUserIdentifierTypeList()).
    thenReturn(idFieldList);
  UserStatus userStatus = new UserStatus();
  userStatus.setValue("REGISTERED");

  Mockito.when(referenceDataService.getUserStatus("REGISTERED")).
    thenReturn(userStatus);
  registrationService.registerUser(data);            
  ArgumentCaptor<User> argument =
    ArgumentCaptor.forClass(User.class);

  Mockito.verify(userService).createUser(argument.capture());
  User user = argument.getValue();
  Assert.assertNotNull(user);

  Assert.assertEquals(user.getUserStatus().getValue(),"REGISTERED");
  Assert.assertEquals(1, user.getUserIdentifiers().size());
  Assert.assertEquals(2, user.getUserDetails().size());
}
 Listing 2

The userService and referenceDataService are mock objects which get injected into the RegistrationService. The concern was how to retrieve the user instance from the registerUser operation so that it can be inspected. For this, Mockito provides the ArgumentCaptor class and its use is highlighted in bold showing how to retrieve the User instance and then carry out further assertions.

JPA / Hibernate Relationship Mapping

Here's a good blog on how to implement entity relationships (one-to-many, many-to-many etc.) using JPA annotations.


http://tadtech.blogspot.com/2007/09/hibernate-annotation-one-to-many.html

Interestingly,
"JPA 1.0 requires that any @OneToMany mapping not using a join table have an inverse @ManyToOne mapping. In general the foreign key in the target object needs to be mapped and a @ManyToOne mapping is normally the best way to map it."
"Using a JoinColumn on a OneToMany is not allowed by JPA 1.0. JPA 1.0 does not support unidirectional OneToMany without a JoinTable. It is possible in JPA 2.0 though. "

References:
http://forums.oracle.com/forums/thread.jspa?threadID=544985

Wednesday 6 July 2011

Configure Glassfish with Log4J

In order to configure GlassFish with Log4J, add a log4j.properties to the glassfish server.

1. Copy log4j.jar inside the GlassFish_Home/lib.
2. Put the Log4J configuration file inside GlassFish_Home/lib
3. Fire up GlassFish and open the admin web UI inside a browser (for example http://localhost:4848).
4. Click on 'Server(Admin Server)' -> Click on 'server-config' Configuration -> JVM Settings -> JVM Options.
5. Now Add new property
'-Dlog4j.configuration=file:///${com.sun.aas.instanceRoot}/lib/log4j.properties' based on as you have copied log4j.properties under lib folder in above Step 2. (basically specify the path of log4j.properties file)
6. Click on the Save button and restart glassfish.

Sample content of Log4J properties file (log4j.properties):
log4j.rootLogger=DEBUG

# enabling Logging for my application
log4j.logger.=DEBUG

# enabling Logging for the spring framework
log4j.logger.org.springframework=DEBUG

log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.MaxFileSize=100KB
log4j.appender.FILE.MaxBackupIndex=1
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%d{DATE} %-5p %c{1} : %m%n

Transaction demarcation

Should the transaction be demarcated at the service layer or DAO layer? The best or normal practice is to mark the service layer operation as transactional since this will represent the single unit-of-work (or use-case) that we would like to execute in a all-or-nothing manner. Furthermore, the service operation may invoke multiple DAOs which together may need to work in a single transaction and constitute the unit-of-work.


Reference: This article gives a good discussion: http://stackoverflow.com/questions/1079114/spring-transactional-annotation-best-practice

Use of entityManager flush during persist

We encountered a scenario where persisting some duplicate data correctly caused a data integrity issue and needed to translate that into an application exception. Our exception was declared within the service operation by wrapping the call to the DAO within a try-catch block and catching any exception. During runtime we noticed that our exception wasn’t being thrown. It transpired that as the service operation was marked as transactional, the persisting of the data and execution of the SQL statements was not occurring when the DAO operation completed but after the service operation (i.e. end of the transaction). Hence the constraint violation exception was not being caught within the service operation as had been planned. For cases like this where an exception is required to be caught the solution is to flush the SQL cache immediately after persisting the data.

@Transactional
@Override
public void storeTopupVouchers(List list) throws CreateVoucherException {
  try {
    TopUpDAO.create(list);
  } catch (Exception e) {
    throw new CreateVoucherException("Failed to create voucher -
    "+e.getMessage(),e);
  }
}


@Override
public void create(List list) {
  for(Topup topup : list) {
    em.persist(topup);
  }
    em.flush();
}

Reference: http://stackoverflow.com/questions/4275111/correct-use-of-flush-in-jpa-hibernate

Simple Example - Use of Mockito

Mockito is very helpful for junit testing, especially for the mocking the object. No need for having setters for injecting the mock object to the bean, mockito does it in very simple way. The following example will help to understand the use of mocking of injected bean.

Service:
public class UIConfigServiceImpl implements UIConfigService {

  @Autowired
  private UIConfigDAO uiConfigDAO;

  public List getUIConfigData(UIConfigType configType) {
    logger.debug("Inside UiConfigService");
    return uiConfigDAO.getUIConfigData(configType);
  }
}

Junit Test:
@RunWith(MockitoJUnitRunner.class) // Run the Junit with Mockito Junit Runner
public class UIConfigServiceTest {

  @InjectMocks // Inject Mock objects into the service. Mockito allows to inject beans where @Autowired is used without requiring setters.
  private UIConfigService uiConfigService = new UIConfigServiceImpl();

  @Mock // Creating a mock for injected object
  private UIConfigDAO mock;

  @Test
  public void testGetUIConfigData() {
    List list = new ArrayList();
    UserDetailType suc = new UserDetailType();
    list.add(suc);
    Mockito.when(mock.getUIConfigData(null)).thenReturn(list);
    List rv = uiConfigService.getUIConfigData(null);
    Assert.assertNotNull(rv);
    Assert.assertFalse(rv.isEmpty());
  }
}