0
votes

I have a created MongoDB with data, But when retrieving all documents in a specific collection my program gives a null pointer exception.

Here is my code, UserRepository.java

package com.weatherdata.api.dbconnector;

import com.weatherdata.api.users.User;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface UserRepository extends MongoRepository<User,String> {
    
}


UserSeeder.java

package com.weatherdata.api.users;

import com.weatherdata.api.dbconnector.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

public class UserSeeder {
    @Autowired
    UserRepository userRepository;

    public List<User> getAllUsers(){
        List <User> allUsers = this.userRepository.findAll();
        return allUsers;
    }
}

User.java

package com.weatherdata.api.users;


import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.HashSet;
import java.util.Set;
@Document(collection = "users")
public class User {
    @Id
    private String id;
    private String username;
    private String email;
    private String mobile;
    private String method;
    private String password;

    @DBRef
    private Set<Role> roles = new HashSet<>();

    public User() {
    }

    public User(String username, String email,String mobile,String method, String password) {
        this.username = username;
        this.email = email;
        this.mobile = mobile;
        this.method = method;
        this.password = password;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }
}


Error is,

java.lang.NullPointerException: Cannot invoke "com.weatherdata.api.dbconnector.UserRepository.findAll()" because "this.userRepository" is null at com.weatherdata.api.users.UserSeeder.getAllUsers(UserSeeder.java:13) ~[classes/:na] at com.weatherdata.api.filter.Alert.isExceeded(Alert.java:20) ~[classes/:na] at com.weatherdata.api.controller.SensorController.insert(SensorController.java:56) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.2.jar:5.3.2] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.2.jar:5.3.2] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1061) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.2.jar:5.3.2]

But the thig is same function in rest api is working finely.

This is how I use UserSedder in Alert.java

package com.weatherdata.api.filter;

import com.weatherdata.api.users.User;
import com.weatherdata.api.users.UserSeeder;

import java.util.List;

public abstract class Alert implements AlertType {
    private double thresholdValue;
    private List<User> userList;

    @Override
    public double getThreshold() {
        return this.thresholdValue;
    }

    @Override
    public boolean isExceeded(double dataValue) {
        if(thresholdValue < dataValue){
            userList = new UserSeeder().getAllUsers();
            System.out.println(userList.stream().count());
            return true;
        }
        else{
            return false;
        }
    }

    public double getThresholdValue() {
        return thresholdValue;
    }

    public void setThresholdValue(double thresholdValue) {
        this.thresholdValue = thresholdValue;
    }
}

2

2 Answers

0
votes

You must use SterioType Annotation @Service over a Classes which has business logic and @Component over a Classes which is generic to all layers of application or Utility classes cause when you annotate @Springbootapplication over the main class it has underlying @ComponentScan(basePackages=" package name where main class lies ") it automatically creates the instance of classes which are under the basepackage.

0
votes

You should annotate class UserSeeder with @Service or @Component to let Spring create and handle an instance of this class as spring managed bean, and this way, dependency injection should work properly, assuming Spring scans package com.weatherdata.api.users.

Another alternative would be to define a @Bean in a @Configuration class.

You can find more info about dependency injection in Spring in many articles and relevant documentation online (eg. link 1 or link 2 etc).

Update

Dependency injection does not work when you are manually instantiating objects, you are using

new UserSeeder()

One way to solve your problem is to make Alert subclass spring managed too, and use @Autowired to instance property of type UserSeeder and thus removing new usage.

You can use something like (change according to your needs)

public abstract class Alert implements AlertType {

  private UserSeeder userSeeder;

  public Alert (UserSeeder userSeeder) {
    this.userSeeder = userSeeder;
  }

  // change new UserSeeder() with this.userSeeder
}

@Service
public class AlertService extends Alert {

  @Autowired
  public AlertService(UserSeeder userSeeder) {
    super(userSeeder);
  }
}