0

I keep getting a nullpointer exception when trying to invoke a method on an autowired object and I don't know why. I am doing everything by the book. (spring in action in this case). I know that it is included in the application context correctly because I can see a print appearing whenever a singleton instance of the injectable object is created. Here is the code and the pom.xml (its a Netbeans maven spring boot project). Please help!

main class

package com.example;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
public class BasicApplication {

    public static void main(String[] args) {             
        SpringApplication.run(BasicApplication.class, args);
        new UsingAutoWired();
    }
}

configuration file (with unused imports I know) /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.example;

import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;

/**
 *
 * @author maurice
 */
@Configuration
public class ComponentScanConfig {

  @Bean
  public testclass testclass(){
      return new testclass();
  }

}

the test class that gets injected

package com.example;

import org.springframework.stereotype.Component;

/**
 *
 * @author maurice
 */
@Component
public class testclass {

    public void hoi(){
        System.out.println(" ----------moiiii");
    }

    public testclass(){
        System.out.println(" ----------------hoiii");
    }
}

the POM file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>basic</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>basic</name>
    <description>Basic project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.7</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.25</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

usingAutoWired class

package com.example;

import org.springframework.beans.factory.annotation.Autowired;

/**
 *
 * @author maurice
 */
public class UsingAutoWired {

    @Autowired
    testclass testclass;

    public UsingAutoWired(){
        testclass.hoi();
    }
}

As you can see this is as simple as it can get and yet I get an error on line 26 of the basic application class. Can anyone please tell me why?

Thank you

EDIT: I've changed the example and removed the static variable, it still gives me a nullpointer exception!

Raphael Amoedo
  • 4,233
  • 4
  • 28
  • 37
Maurice
  • 6,698
  • 9
  • 47
  • 104
  • Are you autowiring an static variable? – Raphael Amoedo Jul 31 '17 at 20:04
  • As Raphael Amoedo suggest, you can't use autowired on static variable. The object need to be instanciated by a Spring container, to object members with @autowired annotation and doing the job. – crashxxl Jul 31 '17 at 20:05
  • yes I am, but this shoulden't be a problem. I am doing this because you cant refer to an instance variable from a static context ( from main method in this case). I' ve had the same problem occur with autowired instance variables. So its not the cause of the problem – Maurice Jul 31 '17 at 20:05
  • please look at the edited example, i' ve changed the example so that it no longer includes a static variable.. I still get a nullpionter exception when it invokes the method. why? – Maurice Jul 31 '17 at 20:13
  • its not a netbeans problem either, i' ve run the project in intelliJ and it gives the exact same nullpointer exception – Maurice Jul 31 '17 at 20:17
  • The problem is that you create an instance of the class yourself. Annotate UsingAutowired with `@Component` and let Spring handle the instance creation. Then just inject the class wherever you need it. – dunni Jul 31 '17 at 21:01

2 Answers2

1

You cannot autowire a static variable. For more information:

Can you use @Autowired with static fields?

EDIT: After your edits, you can access your bean like these:

@SpringBootApplication
public class BasicApplication implements ApplicationContextAware {

    private static ApplicationContext ac;

    public static void main(String[] args) {
        SpringApplication.run(BasicApplication.class, args);
        testclass bean = ac.getBean(testclass.class);
        bean.hoi();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ac = applicationContext;
    }
}

You get the ApplicationContext of Spring in a static context and then you get the Bean, which is going to be autowired.

Raphael Amoedo
  • 4,233
  • 4
  • 28
  • 37
  • Already answered in the link you gave, so you should have voted to close as duplicate. – Andreas Jul 31 '17 at 20:07
  • i' ve edited the example and included another class, I no longer autowire a static variable but I still get a nullpointer exception – Maurice Jul 31 '17 at 20:12
  • You're still trying to autowire `static testclass testclass;`... If you set the UsingAutoWired class as `@Component`, remove the `static` from testclass and autowiring on ComponentScanConfig instead of `new UsingAutoWired()` (because like this it will NEVER autowire)... then should work. In your example you probably need to autowire ComponentScanConfig too – Raphael Amoedo Jul 31 '17 at 20:14
  • sorry, I removed static from UsingAutoWired and the problem still persists.. what do you mean with autowire ComponentScanConfig too? – Maurice Jul 31 '17 at 20:23
  • Check my edit now – Raphael Amoedo Jul 31 '17 at 20:32
  • I don't want to use getBean, I want to use @Autowired to get the instance. – Maurice Jul 31 '17 at 21:41
  • Then you shouldn't use an static variable... See this project as example: https://github.com/ralphavalon/java-sample-project – Raphael Amoedo Jul 31 '17 at 21:42
  • If your application is a web application, SpringApplication.run will start your server and then you can use @Autowired on your Controllers variables, Services and everything else... – Raphael Amoedo Jul 31 '17 at 21:44
1
new UsingAutoWired();

from you main class and

@Autowired
    testclass testclass;

from your UsingAutoWired class will not work together. You need to get an instance of UsingAutoWired from Spring container and testclass will be injected.

  • yes I've found it to be the cause of the problem. As soon as you use the new operator Spring is no longer aware of that instance and cannot inject any objects inside that instance. https://stackoverflow.com/questions/18347518/spring-autowiring-not-working-from-a-non-spring-managed-class – Maurice Aug 01 '17 at 07:20