0

I'm trying to do this:

@Controller    
public class HomeController {

        @Autowired
        private TemplatesService templatesService;    

        public final String TEST = templatesService.getUri();

The getUri:

@SuppressWarnings("unchecked")
    public String getUri() {

        return (String) sessionFactory.getCurrentSession()
                .createQuery("select uri from Templates WHERE state=1")
                .uniqueResult();
    }

It will work correctly, if I'll declare TEST in any method. But now I'm having this:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController' defined in file [C:\Users\anton\springsource\vfabric-tc-server-developer-2.8.2.RELEASE\base-instance\wtpwebapps\blog\WEB-INF\classes\net\babobka\blog\controller\HomeController.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [net.babobka.blog.controller.HomeController]: Constructor threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:997)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:943)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:385)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:284)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111) 

My root-context(I don't think it's helpful):

    <context:annotation-config />


    <context:component-scan base-package="net.babobka.blog" />
    <mvc:resources mapping="/resources/**" location="/resources/" />
    <cache:annotation-driven />

    <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
        <property name="caches">
            <set>
                <bean
                    class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
                    p:name="template" />
                <bean
                    class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
                    p:name="headHunter" />

            </set>
        </property>
    </bean>

    <bean id="converter" class="net.babobka.blog.headHunter.Converter" />


    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
        p:location="/WEB-INF/db/jdbc.properties" />

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
        p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}" />
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation">
            <value>/WEB-INF/db/hibernate.cfg.xml</value>
        </property>
        <property name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${jdbc.dialect}</prop>
                <prop key="hibernate.show_sql">${jdbc.show_sql}</prop>
                <prop key="hibernate.connection.useUnicode">true</prop>
                <prop key="hibernate.connection.characterEncoding">UTF-8</prop>
                <prop key="hibernate.connection.charSet">UTF-8</prop>
            </props>
        </property>
    </bean>




    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    <mvc:annotation-driven />
    <tx:annotation-driven />
    <task:annotation-driven />



    <bean id="Backupper" class="net.babobka.blog.backupper.Backupper"></bean>

    <bean id="OldDataRemoval" class="net.babobka.blog.termination.OldDataRemoval"></bean>

    <bean id="HeadHunterImport" class="net.babobka.blog.headHunter.HeadHunterImport"></bean>

    <bean id="urlForwardController"
        class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />

    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles.xml</value>
            </list>
        </property>
    </bean>

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.tiles2.TilesView" />
    </bean>





</beans>

What's wrong?

5
  • Paste the complete code of HomeController. Commented Sep 24, 2013 at 16:25
  • I think we see the relevant part. Commented Sep 24, 2013 at 16:28
  • Provide spring configuration and also the annotated part of the controller class Commented Sep 24, 2013 at 16:29
  • Ok. But others services works. Commented Sep 24, 2013 at 16:31
  • Also getUri is cached Commented Sep 24, 2013 at 16:37

2 Answers 2

3

It's not working because templatesService is not yet injected when you reference it to set TEST. Fields injection will only work after the instantiation of your Object. What you need to solve this is use @PostConstruct to set test.

@Controller    
public class HomeController {

    @Autowired
    private TemplatesService templatesService;    

    public String test;

    @PostConstruct
    public void init() {
       this.test = templatesService.getUri();
    }

if you still want to use final, you can use injection by constructor and set TEST then.

  @Controller    
  public class HomeController {

    private TemplatesService templatesService;    

    public final String TEST;

    @Autowired
    public HomeController(TemplatesService templatesService) {
        this.templatesService = templatesService;
        this.TEST = templatesService.getUri();
    }
Sign up to request clarification or add additional context in comments.

3 Comments

Seems nice. Could you tell me about PostConstruct in three words?
@Tony PostConstruct is from JSR250. There's lot of material in the internet: docs.oracle.com/javaee/6/tutorial/doc/gmgkd.html
@Tony basically is a way to declare that your bean have some computing to do after it's created. There's @PreDestroy for you to use when you need to something before destroying your bean. It's important to understand the lifecycle of creation/destruction of your beans. If you need anything else, just let me know.
1

This is a problem of initialization order. Spring will inject dependencies into @Autowired fields after it has invoked a bean's constructor, but a field initializer is executed during object construction - and therefore before the field has been autowired. The field is therefore still null, which is why attempting to invoke a method throws a NullPointerException.

Alternatives:

  • pass the TemplatesService by constructor injection, and assign the final field from the constructor rather than the field initializer
  • continue to inject the TemplatesService by field injection, but move initialization of the bean into a @PostConstruct method. You will have to remove final to pacify the compiler.
  • inject the TemplatesService by setter injection, and perform the necessary initialization in the setter. You will have to remove final to pacify the compiler.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.