注册方法在我的控制器类中抛出空指针异常
Posted
技术标签:
【中文标题】注册方法在我的控制器类中抛出空指针异常【英文标题】:Signup method throw null pointer Exception in my controller class 【发布时间】:2021-10-07 22:15:00 【问题描述】:我想在我的数据库中使用UserService
类创建用户。为此,我使用 findByUserEmail 方法检查用户电子邮件是否不存在。我使用Optional
来面对NullpointerException
问题。 signup
方法的目的是如果在数据库中找不到提供的电子邮件,则在数据库中创建一个新用户。我只是删除了 userService 类中的其余方法,只留下了有问题的方法,即 findUserByEmail 方法. ComanLineRuner 接口用于将用户添加到数据库。我想知道为什么我使用的这种方法不起作用。
这个 UserService 实现类:
@Service
@Transactional
@Slf4j
public class UserServiceImpl implements UserService
private final UserRepository userRepository;
private final RoleRepository roleRepository;
private final ModelMapper modelMapper;
private final BCryptPasswordEncoder passwordEncoder;
@Autowired
public UserServiceImpl(UserRepository userRepository, RoleRepository roleRepository, ModelMapper modelMapper,
BCryptPasswordEncoder bCryptPasswordEncoder)
super();
this.userRepository = userRepository;
this.roleRepository = roleRepository;
this.modelMapper = modelMapper;
this.passwordEncoder = bCryptPasswordEncoder;
@Override
public UserDto findUserByEmail(String email)
Optional<User> user = userRepository.findUserByEmail(email);
if (user.isPresent())
log.debug("findUserByEmail:", user.get());
return UserMapper.userToUserDto(user.get());
throw exception(EntityType.USER, ExceptionType.ENTITY_NOT_FOUND, "User with this: " + email + "Not found");
@Override
@SneakyThrows
public UserDto signup(UserDto userDto)
Optional<User> user = userRepository.findUserByEmail(userDto.getEmail());
Role userRole = new Role();
if (user.isPresent())
if (userDto.isAdmin())
userRole = roleRepository.findRoleByUserRoleName(UserRole.ADMIN);
else
userRole = roleRepository.findRoleByUserRoleName(UserRole.STUDENT);
user = Optional.ofNullable(new User().setEmail(userDto.getEmail()).setFirstName(userDto.getFirstName())
.setLastName(userDto.getLastName()).setPassword(passwordEncoder.encode(userDto.getPassword()))
.setRoles(new HashSet<>(Arrays.asList(userRole))).setMobileNumber(userDto.getMobileNumber()));
log.debug("signup new user:", UserMapper.userToUserDto(userRepository.save(user.get())));
return UserMapper.userToUserDto(userRepository.save(user.get()));
throw exception(EntityType.USER, ExceptionType.ENTITY_NOT_FOUND, userDto.getEmail());
用户类别是:
public class User implements Serializable
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "user_id",nullable = false,unique = true)
private Long id;
@Column(name = "email", unique = true, updatable = true)
@NotNull
private String email;
@Column(name = "firstName")
@NotNull
private String firstName;
@Column(name = "lastName")
@NotNull
private String lastName;
@Column(name = "password")
@NotNull
private String password;
@Column(name = "mobile_number")
private String mobileNumber;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id") , inverseJoinColumns =
@JoinColumn(name = "role_id") )
private Set<Role> roles = new HashSet<Role>();
public String getFullName()
return firstName != null ? firstName.concat(" ").concat(lastName) : "";
用户 Dto 类是:
public class UserDto
private String email;
private String firstName;
private String lastName;
private String password;
private boolean isAdmin;
private String mobileNumber;
private Set<RoleDto> roleDtos = new HashSet<>();
public String getFullName()
return firstName != null ? firstName.concat(" ").concat(lastName) : "";
我的控制器类是:
public class AdminController
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;
@GetMapping(value = "/signup")
public ModelAndView signup()
ModelAndView modelAndView = new ModelAndView("signup");
modelAndView.addObject("adminSignupCommand", new AdminSignupCommand());
return modelAndView;
/**
* @param adminSignupCommand
* @param bindingResult
* @param redirectAttributes
* @return modelAndView
*/
@PostMapping(value = "/signup")
public ModelAndView creatnewUserAdmin(
@Valid @ModelAttribute("adminSignupCommand") AdminSignupCommand adminSignupCommand,
BindingResult bindingResult, RedirectAttributes redirectAttributes)
// *Check user email in database before to save it*
UserDto userDto = userService.findUserByEmail(adminSignupCommand.getEmail());
ModelAndView modelAndView = new ModelAndView("signup");
if (userDto !=null)
bindingResult.reject("There is already a user registered with the email provided");
log.debug("There is already a user registered with the email provided");
if (bindingResult.hasErrors())
return modelAndView;
else
registerUserAdmin(adminSignupCommand);
redirectAttributes.addFlashAttribute("message", "SuccesFully added the new user with admin role");
modelAndView.addObject("successMessage", redirectAttributes);
log.debug(" A user registered with the email provided");
return new ModelAndView("login");
/**
* @param adminSignupCommand
* @return userDto
*/
private UserDto registerUserAdmin(@Valid AdminSignupCommand adminSignupCommand)
UserDto userDto = new UserDto().setEmail(adminSignupCommand.getEmail())
.setFirstName(adminSignupCommand.getFirstName()).setLastName(adminSignupCommand.getLastName())
.setPassword(adminSignupCommand.getPassword()).setAdmin(true);
UserDto userDto2 = userService.signup(userDto);
return userDto2;
*CommandLineRunner*
public class KalanblowApplication
public static void main(String[] args)
SpringApplication.run(KalanblowApplication.class, args);
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Bean
public CommandLineRunner addNewRole(RoleRepository roleRepository, UserRepository userRepository,
UserService userService)
return (args) ->
log.debug("CommandLineRunner start");
// create role in database
Role adminRole = roleRepository.findRoleByUserRoleName(UserRole.ADMIN);
// Create new User with role
UserDto adminDto = userService.findUserByEmail("admin3@example.com");
if (adminDto ==null)
adminDto = new UserDto();
adminDto.setEmail("admin3@example.com");
adminDto.setFirstName("admin3");
adminDto.setLastName("admin3");
adminDto.setPassword(passwordEncoder.encode("Example2021!"));
adminDto.setMobileNumber("0256369645");
adminDto.setRoleDtos(new HashSet<>(Arrays
.asList(new ModelMapper().map(adminRole, RoleDto.class))));
System.out.println("adminDto is:" + adminDto);
userService.signup(adminDto);
;
StackTrace return a java.lang.NullPonterException when saving Spring Entity
**java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:794) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:775) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:345) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332) ~[spring-boot-2.5.3.jar:2.5.3]
at ml.kalanblowSystemManagement.KalanblowApplication.main(KalanblowApplication.java:34) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[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:566) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.5.3.jar:2.5.3]
Caused by: java.lang.NullPointerException: null
at ml.kalanblowSystemManagement.exception.KalanblowSystemManagementException.format(KalanblowSystemManagementException.java:92) ~[classes/:na]
at ml.kalanblowSystemManagement.exception.KalanblowSystemManagementException.throwException(KalanblowSystemManagementException.java:80) ~[classes/:na]
at ml.kalanblowSystemManagement.exception.KalanblowSystemManagementException.throwException(KalanblowSystemManagementException.java:38) ~[classes/:na]
at ml.kalanblowSystemManagement.service.impl.UserServiceImpl.exception(UserServiceImpl.java:286) ~[classes/:na]
at ****ml.kalanblowSystemManagement.service.impl.UserServiceImpl.findUserByEmail(UserServiceImpl.java:86) ~[classes/:na]****
at ml.kalanblowSystemManagement.service.impl.UserServiceImpl$$FastClassBySpringCGLIB$$d9d5886b.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.9.jar:5.3.9]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) ~[spring-aop-5.3.9.jar:5.3.9]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.9.jar:5.3.9]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.9.jar:5.3.9]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.9.jar:5.3.9]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.9.jar:5.3.9]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.9.jar:5.3.9]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.9.jar:5.3.9]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.9.jar:5.3.9]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.9.jar:5.3.9]
at ml.kalanblowSystemManagement.service.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$aac12850.findUserByEmail(<generated>) ~[classes/:na]
at ml.kalanblowSystemManagement.KalanblowApplication.lambda$0(KalanblowApplication.java:68) ~[classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:791) ~[spring-boot-2.5.3.jar:2.5.3]
... 10 common frames omitted**
【问题讨论】:
通常当你使用 optional 和isPresent
时,你做事的方式是错误的。我们还必须猜测代码中的第 86 行是什么?请注意,这与您的控制器无关,而是与您编写的启动代码有关(CommandLIneRunner
.
第 86 行对应的是 throw exception(EntityType.USER, ExceptionType.ENTITY_NOT_FOUND, "User with this:" + email + "Not found");,就是触发的异常方法。对不起,我刚刚添加了 CommandLinerRuner
哪个是方法调用,哪个做什么?
findUserByemail throw null pointer exception if email is not found 是异常原因
【参考方案1】:
您的方法架构存在一些缺陷。
首先,如果没有找到User
,findUserByEmail
方法总是会引发Exception
。
您的Exception
似乎扩展了NullPointerException
,我会考虑改用自定义异常。
所以当你调用findUserByEmail
方法,而User
不存在时,总是会引发异常。假设您想保持异常引发,您需要在每次调用该方法时捕获异常,以便应用对错误的缓解。
例如,您的 CommandLineRunner
可能是:
@Bean
public CommandLineRunner addNewRole(RoleRepository roleRepository, UserRepository userRepository,
UserService userService)
return (args) ->
log.debug("CommandLineRunner start");
// create role in database
Role adminRole = roleRepository.findRoleByUserRoleName(UserRole.ADMIN);
// Create new User with role
UserDto adminDto = null;
try
adminDto = userService.findUserByEmail("admin3@example.com");
catch (Exception ex)
adminDto = null;
if (adminDto ==null)
adminDto = new UserDto();
adminDto.setEmail("admin3@example.com");
adminDto.setFirstName("admin3");
adminDto.setLastName("admin3");
adminDto.setPassword(passwordEncoder.encode("Example2021!"));
adminDto.setMobileNumber("0256369645");
adminDto.setRoleDtos(new HashSet<>(Arrays
.asList(new ModelMapper().map(adminRole, RoleDto.class))));
System.out.println("adminDto is:" + adminDto);
userService.signup(adminDto);
;
我宁愿建议不要在您的 findUserByEmail
方法上引发 Exception。请改用Optional<UserDto>
,以使您的流程更清晰。
【讨论】:
【参考方案2】:你说的很对,但我通过添加一个布尔方法 emailExist(String email) 解决了这个问题,我在其中调用了 findUserByEmail 方法。感谢大家的建议和反馈。 `public boolean emailExist(String email)
return userRepository.findUserByEmail(email) != null;
所以我修改了注册方式
@Override
@SneakyThrows
public UserDto signup(UserDto userDto)
if (!emailExist(userDto.getEmail()))
throw exception(EntityType.USER, ExceptionType.DUPLICATE_ENTITY,
"An user with that email adress already exists:" + userDto.getEmail());
Role userRole = new Role();
if (userDto.isAdmin())
userRole = roleRepository.findRoleByUserRoleName(UserRole.ADMIN);
else
userRole = roleRepository.findRoleByUserRoleName(UserRole.STUDENT);
User user = new User().setBirthDate(userDto.getBirthDate()).setEmail(userDto.getEmail())
.setFirstName(userDto.getFirstName()).setLastName(userDto.getLastName())
.setMatchingPassword(userDto.getMatchingPassword()).setPassword(userDto.getPassword())
.setMobileNumber(userDto.getMobileNumber()).setRoles(new HashSet<>(Arrays.asList(userRole)));
return UserMapper.userToUserDto(userRepository.save(user));
【讨论】:
以上是关于注册方法在我的控制器类中抛出空指针异常的主要内容,如果未能解决你的问题,请参考以下文章