Search code examples
javaspring-bootcomponentsautowired

SpringBootApp NullPointerException with @Autowired repository


This is my Spring Boot Application. when i run the main method always a null pointer exception is thrown. I have no idea why the @Autowired JsonReaderService is null. As i define it as component.

It is a sub folder in the project src folder so the Main Method is above the source folder. So spring should scan it correctly??

I have also a test method which works just fine.

 @SpringBootApplication
 public class DemoApplication {

@Autowired
private JsonReaderService jsonReaderService;

private static JsonReaderService stat_jsonReaderService;

static Logger logger = LoggerFactory.getLogger(DemoApplication.class);

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

    String textFileName = scanFileName();
    Reader reader = Files.newBufferedReader(Paths.get("src/main/resources/" + textFileName));
    // This line is always null pointer exception. The @autowired Annotation don't work with my JsonReaderService????? WHY
    List<EventDataJson> jsonReaderServicesList = stat_jsonReaderService.readEventDataFromJson(reader);
    stat_jsonReaderService.mappingToDatabase(jsonReaderServicesList);

}

public static String scanFileName() {
    logger.info("Scanning keyboard input");
    System.out.println("enter a file to scan");
    Scanner scanInput = new Scanner(System.in);
    String text = scanInput.nextLine();
    logger.info("successful keyboard input was : " + text);
    return text;
}

@PostConstruct
public void init() {
    logger.info("initializing Demo Application");
    stat_jsonReaderService = jsonReaderService;
}

}

Here i have the class which uses the repository @Autowired to save some Entity but i get always a nullpointer exception in the line repository.save(...)

@Component
public class JsonReaderService {
static Logger logger = LoggerFactory.getLogger(DemoApplication.class);
@Autowired
EventDataRepository repository;
private Reader reader;
private List<EventDataJson> eventDataList;

@Autowired
public JsonReaderService(){}

public List<EventDataJson> readEventDataFromJson(Reader reader) throws IOException {

    try {
        logger.info("parsing event data from json started");
        Gson gson = new Gson();
        EventDataJson[] eventData = gson.fromJson(reader, EventDataJson[].class);
        eventDataList = Arrays.asList(eventData);
        reader.close();
    } catch (IOException e) {
        logger.error("Error while reading the json file");
        e.printStackTrace();
    }
    logger.info("parsing json eventData successful finished");
    return eventDataList;
}

public Boolean mappingToDatabase(List<EventDataJson> eventDataList) {
    logger.info("mapping from json to database eventData started ...");

    Set<String> idList = eventDataList.stream().map(EventDataJson::getId).collect(Collectors.toSet());
    for (String id : idList
    ) {
        Stream<EventDataJson> filteredEventDataList1 = eventDataList.stream().filter((item) -> item.getId().equals(id));
        Stream<EventDataJson> filteredEventDataList0 = eventDataList.stream().filter((item) -> item.getId().equals(id));
        EventDataJson startedEvent = filteredEventDataList1.filter((item) -> item.getState().equals("STARTED")).findAny().orElse(null);
        EventDataJson finishedEvent = filteredEventDataList0.filter((item) -> item.getState().equals("FINISHED")).findAny().orElse(null);
        long duration0 = finishedEvent.getTimestamp() - startedEvent.getTimestamp();
        Boolean alert;
        if (duration0 > 4) {
            alert = true;
        } else {
            alert = false;
        }
        try {
            this.repository.save(new EventDataDb(id, duration0, startedEvent.getType(), startedEvent.getHost(), alert));
            logger.info("mapping to Database Repository action successful");

        } catch (Exception e) {
            logger.error("Exception in database mapping occurred");
            e.printStackTrace();
            return false;

        }
    }
    return true;

}
}

Repository with Annotation

@Repository
 public interface EventDataRepository extends JpaRepository<EventDataDb, String> {
 EventDataDb findAllById(String id);
 }

Test case works just fine with @autowired Annotation i Don't know why it don't work in the main method. Is it because it is static?

    @Autowired
       private EventDataRepository repository;

    @Autowired
       private JsonReaderService jReader;
    @Test
    public void whenParseJson_thenTransform_and_save_to_db() throws IOException {
    BufferedReader reader = Files.newBufferedReader(Paths.get("src/main/resources/" + "logfile.txt"));
    List<EventDataJson> eventDataList1 = jReader.readEventDataFromJson(reader);
    if (jReader.mappingToDatabase(eventDataList1)) {
        EventDataDb eventDataFromDb = this.repository.findAllById("scsmbstgra");
        Assertions.assertTrue(eventDataFromDb.getType().equals("APPLICATION_LOG"));
        Assertions.assertTrue(eventDataFromDb.getHost().equals("12345"));
        Assertions.assertTrue(eventDataFromDb.getAlert().equals(true));
        Assertions.assertTrue(eventDataFromDb.getDuration() == 5);
        logger.info("Assert successfully accomplished");
    } else
        logger.error("Could not persist eventData to DB Error");
}

Stack Trace

`Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)

Caused by: java.lang.NullPointerException at com.creditsuisse.demo.DemoApplication.main(DemoApplication.java:33) ... 5 more`


Solution

  • You need to run SpringApplication.run() because this method starts whole Spring Framework. Since you don't have it in your code, the beans are not autowired and JsonReaderService is null. You can do the following in your Application.java. Also, since this involves taking input from the CLI why not use CommandLineRunner as follows:

    @SpringBootApplication
    public class DemoApplication 
      implements CommandLineRunner {
    
        @Autowired
        private JsonReaderService jsonReaderService;
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
     
        @Override
        public void run(String... args) {
            String textFileName = scanFileName();
            Reader reader = Files.newBufferedReader(Paths.get("src/main/resources/" + textFileName));
            List<EventDataJson> jsonReaderServicesList = stat_jsonReaderService.readEventDataFromJson(reader);
            jsonReaderService.mappingToDatabase(jsonReaderServicesList);
        }
    }