Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
3.4, 3.5
-
None
-
Java 1.8 on Windows 7 x64
Description
It is possible to create a construct, that allows multiple calls of LazyInitializer.initialize, when calculations (which can be very expensive) return null as result.
In the Javadoc is described that the initialize method will be called only on the first access
/** * Creates and initializes the object managed by this {@code * LazyInitializer}. This method is called by {@link #get()} when the object * is accessed for the first time. An implementation can focus on the * creation of the object. No synchronization is needed, as this is already * handled by {@code get()}. * * @return the managed data object * @throws ConcurrentException if an error occurs during object creation */ protected abstract T initialize() throws ConcurrentException;
The Junit Test can be something like this:
(fix can be appplied from attached patch-file)
package edu.test; import static org.junit.Assert.assertEquals; import org.apache.commons.lang3.concurrent.ConcurrentException; import org.apache.commons.lang3.concurrent.LazyInitializer; import org.junit.Test; public class LazyInitializerTest { private int lazyinitCounter = 0; private LazyInitializer<Object> lazyIinit = new LazyInitializer<Object>() { @Override protected Object initialize() throws ConcurrentException { lazyinitCounter++; return doSomeVeryExpensiveOperations(); } }; private Object doSomeVeryExpensiveOperations() { // do db calls // do some complex math calculations // the result of them all is null return null; } @Test public void testInitialization() throws Exception { lazyIinit.get(); lazyIinit.get(); assertEquals("Multiple call of LazyInitializer#initialize", 1, lazyinitCounter); } }