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
journal capturing best practises, patterns and solutions to problems encountered in the design and development of enterprise software.
Friday, 15 July 2011
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:
DAOImplTest:
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.
My DAO method and its test is as follows:
DAOImpl:
public List List 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 .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.
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.
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.
@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); } |
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()); } |
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
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.
# 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 try { TopUpDAO.create(list); } catch (Exception e) { throw new CreateVoucherException("Failed to create voucher - "+e.getMessage(),e); } } @Override public void create(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 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 UserDetailType suc = new UserDetailType(); list.add(suc); Mockito.when(mock.getUIConfigData(null)).thenReturn(list); List Assert.assertNotNull(rv); Assert.assertFalse(rv.isEmpty()); } } |
Subscribe to:
Posts (Atom)