Acceptedboy
Acceptedboy

Reputation: 65

NullPointerException In Spring-boot and how do I fix it?

Today, I encountered a bug in my spring-boot project. In my code, I want to get the ApplicationContext, but it's null, so I couldn't use getBean().

This is Application.java for config:

@SpringBootApplication
@EnableAspectJAutoProxy
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(
            SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    @Bean
    public ServletRegistrationBean readHitchEventServletBean() {

        ServletRegistrationBean readHitchEventServletBean = 
                new ServletRegistrationBean();
        readHitchEventServletBean.setServlet(new ReadHitchEventServlet());
        readHitchEventServletBean.setLoadOnStartup(5);
        return readHitchEventServletBean;
    }

    public static void main(String[] args) throws Exception {

        SpringApplication.run(Application.class, args);
    }
}

Then the servlet :

@Component
public class ReadHitchEventServlet extends HttpServlet implements ApplicationContextAware {

    private static final long serialVersionUID = 1L;
    private static ApplicationContext applicationContext;

    @SuppressWarnings("static-access")
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException {
    // TODO Auto-generated method stub
        this.applicationContext = applicationContext; 
    }

    public static ApplicationContext getApplicationContext() {  
        return applicationContext;  
    } 

    public static Object getBean(String name) throws BeansException {  
        return applicationContext.getBean(name);  
    }

    @Override
    public void init() {
        getBean("heheda");
    }
}

And I am getting the below error:

java.lang.NullPointerException: null
at com.gdut.dongjun.ActiveSwitchThread.getBean(ReadHitchEventServlet.java:126) ~[classes/:na]
at com.gdut.dongjun.ActiveSwitchThread.<init>(ReadHitchEventServlet.java:66) ~[classes/:na]
at com.gdut.dongjun.ReadHitchEventServlet.init(ReadHitchEventServlet.java:56) ~[classes/:na]
at javax.servlet.GenericServlet.init(GenericServlet.java:158) ~[tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1231) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1034) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4914) [tomcat-embed-core-8.0.23.jar:8.0.23]
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedContext.deferredLoadOnStartup(TomcatEmbeddedContext.java:66) [spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.startConnector(TomcatEmbeddedServletContainer.java:209) [spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.start(TomcatEmbeddedServletContainer.java:152) [spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.startEmbeddedServletContainer(EmbeddedWebApplicationContext.java:288) [spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:141) [spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.__refresh(AbstractApplicationContext.java:483) [spring-context-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.jrLockAndRefresh(AbstractApplicationContext.java) [spring-context-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java) [spring-context-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) [spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686) [spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320) [spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:957) [spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:946) [spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
at com.gdut.dongjun.Application.main(Application.java:282) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_79]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_79]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_79]
at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_79]
at org.springframework.boot.maven.RunMojo$LaunchRunner.run(RunMojo.java:418) [spring-boot-maven-plugin-1.2.5.RELEASE.jar:1.2.5.RELEASE]
at java.lang.Thread.run(Thread.java:745) [na:na]

How do I fix it?

Upvotes: 1

Views: 11354

Answers (2)

Jon Peterson
Jon Peterson

Reputation: 2996

On line:

readHitchEventServletBean.setServlet(new ReadHitchEventServlet());

You are creating a new instance of the servlet object that is not a Spring Bean and thus it is not being wired-up correctly. If you want to do it this way, consider doing the following:

Application.java:

@Bean
public ServletRegistrationBean readHitchEventServletBean(ApplicationContext applicationContext) {
    ServletRegistrationBean readHitchEventServletBean = new ServletRegistrationBean();
    readHitchEventServletBean.setServlet(new ReadHitchEventServlet(applicationContext));
    readHitchEventServletBean.setLoadOnStartup(5);
    return readHitchEventServletBean;
}

ReadHitchEventServlet.java:

public class ReadHitchEventServlet extends HttpServlet {
    private final ApplicationContext applicationContext;

    ReadHitchEventServlet(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public void init() {
        applicationContext.getBean("heheda");
    }
}

Or even better would be to just leave out the ApplicationContext entirely and just wire the bean you ultimate want.

Application.java:

@Bean
public ServletRegistrationBean readHitchEventServletBean(Heheda heheda) {
    ServletRegistrationBean readHitchEventServletBean = new ServletRegistrationBean();
    readHitchEventServletBean.setServlet(new ReadHitchEventServlet(heheda));
    readHitchEventServletBean.setLoadOnStartup(5);
    return readHitchEventServletBean;
}

ReadHitchEventServlet.java:

public class ReadHitchEventServlet extends HttpServlet {
    private final Heheda heheda;

    ReadHitchEventServlet(Heheda heheda) {
        this.heheda = heheda;
    }

    @Override
    public void init() {
        // do something with heheda
    }
}

Upvotes: 0

vinayknl
vinayknl

Reputation: 1252

It would be good to have a separate class which implements ApplicationContextAware to provide application context to required classes. The problem here appears to be Spean bean life cycle and servlet container life cycle performing different operations.

i.e init can be called before context could be set by spring.

Upvotes: 2

Related Questions