Skip to content

Be sure to perform dependency validation using the Spring container’s initialization callback mechanism

February 23, 2012

A Spring Container In The Real World

Ala JavaSpecialists’ newsletter, this post comes to you from the beautiful Kuils River region of greater Cape Town, also known as the Kuils Riviera. Here you are reminded that to some “life is not a beach”, in particular when passing by the local township where dismal poverty and a hand to mouth existance reigns.

On that note, lets dive straight into the subject matter of this post, performing the most basic validation in your Spring beans to quickly detect stupid mistakes.

Now, as a Spring user you have a number of options when it comes to configuring dependencies you wish to have injected into a given bean. You can use autowiring, which itself has further options, such as autowiring by type or name, or you can use xml configuration with explicit bean references. Regardless of what you use, it pays to use the Spring container’s initialization callback mechanism to avoid or easily detect basic mistakes that can easily eat up hours of development time. This entails validating your dependencies, at the very least in terms of whether they are null or not, in a consistent fashion in any given project.

Lets first get onto an example of such a basic mistake, in which a suspected wiring configuration error, which turned out to be a programmer error, cost precious time, and then move onto what do to, consistently, to avoid future similar wasteage.

BEFORE

Herewith a class under test, note the @Autowired bean propertyService.

public class ConfigServiceImpl implements ConfigService {

    @Autowired
    @Qualifier("propertyServiceBean")
    protected PropertyService propertyService;

    // NO INIT METHOD

...
}

Here is the stupid mistake.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/com/mayloom/activiti/config/spring-context.xml"})
public class ConfigServiceTest {

   @Autowired
   private ConfigService configService;

   @Test
   public void updateConfiguration() {

      ConfigService configService = new ConfigServiceImpl(); // This line must be removed

      Properties props = configService.getProperties();

The mistake is the programmer is autowiring the configService yet also instatiating it. The latter renders Autowiring of dependencies in configService as useless, the entire line must be removed. It could be that this was a class that was later turned into a Spring bean, so just an oversight.

This the the result of the mistake, or at least a snippet of the surefire report showing the offending NullPointerException.

-------------------------------------------------------------------------------
Test set: com.mayloom.config.ConfigServiceTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.282 sec <<< FAILURE!
updateConfiguration(com.mayloom.config.ConfigServiceTest)  Time elapsed: 0.266 sec  <<< ERROR!
java.lang.NullPointerException
	at com.mayloom.config.ConfigServiceImpl.getProperties(ConfigServiceImpl.java:72)

Now, if you had been making various Spring configuration changes in your project, and you see the above, one could start thinking that a wiring configuration error is the cause and waste hours reconfiguring and basically looking in the wrong place, even though the mistake made is quite obvious to us now.

AFTER

To quickly rule out wiring errors as a cause, in this case, and in general, all one has to do is to check that wired dependencies are not null as shown in the Default initialization and destroy methods section of the Spring manual.

So, we would end up with the pertitent section of our spring configuration looking as as shown below, with the default-init-method being what we want to include.

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
		   http://www.springframework.org/schema/context/spring-context-3.0.xsd" default-init-method="init">

Next, we’ll update ConfigServiceImpl as shown below.

public class ConfigServiceImpl implements ConfigService {
	
  @Autowired
  @Qualifier("propertyServiceBean")
  protected PropertyService propertyService;
	
  // this is (unsurprisingly) the initialization callback method
  public void init() {
    	log.info("==================== ConfigServiceImpl =========================");
        if (this.propertyService == null) {
            throw new IllegalStateException("The [propertyService] property must be set.");
        }
    }

Thats pretty much it, no advanced concurrency lesson here, no generics to marvel at, but it may save you time.

java.lang.OutOfMemoryError: unable to create new native thread

February 5, 2012

If you’ve been spending too much time dealing with higher level business logic, it’s easy to start losing touch with JVM performance tuning, and the OS in general. A recent bout of java.lang.OutOfMemoryError: unable to create new native thread forced me to spend some time initially barking up the wrong tree, and then fixing it by brute force.

Brute Force Fix

To get onto the fix first. All I needed to do was to configure the nproc settings for the user in question (it happened to be jenkins) upwards in /etc/security/limits.conf

Playing

Before getting onto the most obvious fix, I went off on a tangent and refreshed my memory on the effects of the heap size, permanent generation size, thread stackĀ  size and other related topics (the bash based thread count script is a work in progress). A simple program to help you determine how many threads you can create can be found below if you are also keen on experimentation.

public class RunOutOfMemory {
	
/**
* Results
* 
* ==== Environment: 32bit Win 7, 2GB RAM, Java 7 ====
* 
* Reducing the default maximum thread stack size allows more of the process' virtual 
* memory address space to be used by the Java heap and vice-versa.
* 
* Note, when it comes to virtual memory usage consumed by the jvm process, we are 
* not including the heap and permanent generation allocation.
* 
* Test: 1. ALL VM arguments at default values: OutOfMemory with 3974 threads = 
*                                                       1238 MB (320k / thread)
* 	2. -Xss1m, rest VM arguments at default values: OutOfMemory with 1211 threads 
*                                                                           = 1211 MB  
* 	3. -Xss2m, rest VM arguments at default values: OutOfMemory with 533 threads 
*                                                                           = 1066 MB
*       4. -Xss128k, rest VM arguments at default values: OutOfMemory with 10358 threads 
*                                                                           = 1294 MB
* 
* "On Windows, the default thread stack size is read from the binary (java.exe). As of 
* Java SE 6, this value is 320k in the 32-bit VM and 1024k in the 64-bit VM." oracle.com
* 
* ==== Linux ====
* 
* NOTE: Pay close attention to your limits configured in /etc/security/limits.conf You 
* may want to adjust the nproc setting for your process upwards if you are seeing a 
* "cannot create native thread" message
*/
		public static void main(String[] pArgs) {

			try {
				// keep spawning new threads forever
				while (true) {
					// thread begins execution, JVM calls run method of this new thread
					new TestThread().start();
				}
			} catch (java.lang.OutOfMemoryError e ) {
    	  
				// when out of memory error is reached, print out the number of
				// successful threads spawned and exit
				System.out.println(TestThread.CREATE_COUNT);
				System.exit(-1);
			}
		}

		
		static class TestThread extends Thread {
			
			private static int CREATE_COUNT = 0;
			
			public TestThread() {
				CREATE_COUNT++;
			}
			
			// make the thread wait for eternity after being spawned
			public void run() {
				this.suspend();
			}
		}
}

Follow

Get every new post delivered to your Inbox.