У меня есть созданная MongoDB с данными, но при извлечении всех документов в определенной коллекции моя программа выдает исключение нулевого указателя.
Вот мой код, 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;
}
}
Пользователь.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;
}
}
Ошибка в том,
java.lang.NullPointerException: невозможно вызвать «com.weatherdata.api.dbconnector.UserRepository.findAll()», поскольку «this.userRepository» имеет значение null в com.weatherdata.api.users.UserSeeder.getAllUsers(UserSeeder.java:13) ~[classes/:na] в com.weatherdata.api.filter.Alert.isExceeded(Alert.java:20) ~[classes/:na] в com.weatherdata.api.controller.SensorController.insert(SensorController.java:56) ~[classes/:na] в java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (собственный метод) ~[na:na] в java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na] в java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] в java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na] в org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.2.jar:5.3.2] в org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.2.jar:5.3.2] в org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.2.jar:5.3.2] в org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.2.jar:5.3.2] в org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal (RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.2.jar:5.3.2] в org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.2.jar:5.3.2] в org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1061) ~[spring-webmvc-5.3.2.jar:5.3.2] в org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961) ~[spring-webmvc-5.3.2.jar:5.3.2] в org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.2.jar:5.3.2] в org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.2.jar:5.3.2]
Но та же самая функция в остальном API работает нормально.
Вот как я использую UserSeedder в 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;
}
}
Вы должны аннотировать класс UserSeeder
с помощью @Service
или @Component
, чтобы Spring мог создавать и обрабатывать экземпляр этого класса как управляемый bean-компонент Spring, и таким образом внедрение зависимостей должно работать правильно, предполагая, что Spring сканирует пакет com.weatherdata.api.users
.
Другой альтернативой может быть определение @Bean
в классе @Configuration
.
Вы можете найти больше информации о внедрении зависимостей в Spring во многих статьях и соответствующей документации в Интернете (например, ссылка 1 или ссылка 2 и т. д.).
Обновлять
Внедрение зависимостей не работает, когда вы вручную создаете экземпляры объектов, вы используете
new UserSeeder()
Один из способов решить вашу проблему - сделать Alert
подкласс Spring управляемым и использовать @Autowired
для экземпляра свойства типа UserSeeder
и, таким образом, удалить new
использование.
Вы можете использовать что-то вроде (изменить в соответствии с вашими потребностями)
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);
}
}
не могли бы вы добавить, как вы вызываете класс UserSeeder? вы используете новое ключевое слово?
Отредактировано и добавлено к вопросу
Обновлен мой ответ, внедрение зависимостей не работает при использовании ключевого слова new
для создания экземпляров ваших объектов.
Давайте продолжим обсуждение в чате.
Как заставить подкласс Spring управлять Alert?
Вы должны использовать аннотацию SterioType @Service поверх классов, которые имеют бизнес-логику, и @Component поверх классов, которые являются общими для всех уровней приложений или служебных классов, когда вы аннотируете @Springbootapplication поверх основного класса, в котором он имеет базовый @ComponentScan(basePackages=" имя пакета, в котором находится основной класс"), он автоматически создает экземпляры классов, которые находятся в базовом пакете.
пакет сканируется весной (
@ComponentScan(basePackages = "com.weatherdata.api.users")
? вы используете загрузку Spring?