我正在将使用Spring实现的Maven项目迁移到Spring Boot 1.5.20.RELEASE。
我有一个Adapter类,必须由我的RestControllers进行扩展,以保证与前端的向后兼容性
public class RestControllerAdapter {
private MessageTemplate messageTemplate;
private MessageTemplate getMessageTemplate() {
if (messageTemplate == null) {
messageTemplate = ApplicationContextUtils.getBean(MessageTemplate.class);
}
return messageTemplate;
}
protected final String message(@NonNull String code) {
return getMessageTemplate().getMessage(code);
}
protected final String message(@NonNull String code, Object... args) {
return getMessageTemplate().getMessage(code, args);
}
protected final ModelMap success() {
val map = new ModelMap();
map.put("success", true);
map.put("message", getMessageTemplate().getMessage("message.success.default"));
return map;
}
protected final ModelMap error(@NonNull String message) {
val map = new ModelMap(2);
map.put("success", false);
map.put("error", message);
return map;
}
protected final ModelMap retry(@NonNull Exception ex) {
val map = new ModelMap(3);
map.put("success", false);
map.put("error", ex.getMessage());
map.put("confirmar", true);
return map;
}
protected final ModelMap empty() {
return new ModelMap();
}
@ExceptionHandler(JpaSystemException.class)
public ModelMap handleJpaSystemException(JpaSystemException ex) {
log.error(ex.getMessage(), ex);
return createError(ex.getMostSpecificCause());
}
@ExceptionHandler(DataIntegrityViolationException.class)
public ModelMap handleDataIntegrityViolationException(DataIntegrityViolationException ex) {
log.error(ex.getMessage(), ex);
return createError(ex.getMostSpecificCause());
}
private ModelMap createError(Throwable ex) {
val modelMap = new ModelMap();
modelMap.put("error", translateErrorMessage(ex));
modelMap.put("success", false);
return modelMap;
}
protected String translateErrorMessage(@NonNull Throwable ex) {
String message = ex.getLocalizedMessage().isEmpty() ? ex.getMessage() : ex.getLocalizedMessage();
if (message.contains("12519")) {
message = getMessageTemplate().getMessage("db.connection.error");
} else if (message.contains("SYS_C0015328")) {
message = getMessageTemplate().getMessage("plan.tasks.successors.sequence.error");
} else if (message.contains("SYS_C0012415")) {
message = getMessageTemplate().getMessage("positions.sequence.error");
} else if (message.contains("SYS_C006343")) {
message = getMessageTemplate().getMessage("documents.sequence.error");
} else if (message.contains("UNIQUE_EMAIL")) {
message = getMessageTemplate().getMessage("user.email.unique");
} else if (message.contains("FK_PLTASK_TASK")) {
message = getMessageTemplate().getMessage("task.delete.error");
}
return message;
}
}
我有一个RestController类用于用户管理
@RestController
@RequestMapping(value = "/usuario")
@RequiredArgsConstructor
public class UserRestController extends RestControllerAdapter {
private final UserService usersService;
private final UsersRepository usersRepository;
private final UserBackupRepository userBackupRepository;
private final AreaRepository areaRepository;
private final PositionRepository positionRepository;
private final UserMapper userMapper;
@PreAuthorize(value = SecurityUtils.ADMIN_EDIT_AUTHORITY)
@PutMapping("/{userId}")
public ModelMap update(@Valid @RequestBody UserCommand userCommand,
@PathVariable int userId) {
try {
usersService.update(userId, userCommand);
return success();
} catch (DuplicateHolderException ex) {
return retry(ex);
}
}
@PreAuthorize(value = SecurityUtils.ADMIN_EDIT_AUTHORITY)
@PostMapping("/activarUsuario")
public ModelMap enable(@RequestParam("usuario_id") Integer id,
@AuthenticationPrincipal Users user) {
if (user.getRol().getId() == 1 || user.getRol().getId() == 3) {
usersService.enable(id);
return success();
}
return empty();
}
@Override
protected String translateErrorMessage(@NonNull Throwable ex) {
String message = ex.getMessage();
if (message.contains("correo_unico")) {
message = "Ya este correo está asigado a un usuario.";
} else if (message.contains("SYS_C0012422") ||
message.contains("SYS_C0015349")) {
message = "La secuencia de usuarios no está correctamente
configurada.";
} else if (message.contains("UNIQUE_BACKUP")) {
message = "Un usuario no puede ser backup mas de una ocasión.";
} else if (message.contains("UNIQUE_EMAIL")) {
message = "No se puede insertar el usuario porque este correo ya
está en uso.";
} else if (message.contains("FK_PLAN_USER_ACTIVADO")) {
message = "No se puede insertar el usuario porque existe un plan que
ha sido activado por dicho usuario.";
} else if (message.contains("FK_TASK_EXECUTED_BY")) {
message = "No se puede insertar el usuario porque existen tareas
ejecutadas por dicho usuario.";
}
return super.translateErrorMessage(ex);
}
}
当我使用更新端点时,会抛出NullPointerException,因为UserServiceImpl中的所有bean均为空,如下图所示。
但是当我使用启用端点时,它可以正常工作。两个端点都调用UserServiceImpl Service类中的方法。
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
class UserServiceImpl implements UserService {
private static final int POSITION_USERS_LIMIT = 3;
private static final int BACKUPS_LIMIT = 2;
private static final String POSITION_LIMIT_ERROR = "user.position.limit";
private static final String BACKUP_LIMIT_ERROR = "user.backup.limit";
private final UsersRepository usersRepository;
private final UserBackupRepository userBackupRepository;
private final RolRepository rolRepository;
private final PositionRepository positionRepository;
private final PlanRepository planRepository;
private final PlTaskRepository plTaskRepository;
private final UserNotificationRepository userNotificationRepository;
private final NotificacionBackupRepository notificacionBackupRepository;
private final UserTokenRepository userTokenRepository;
private final UserMapper userMapper;
private final PasswordTemplate passwordTemplate;
private final MessageTemplate messageTemplate;
@Override
public final Users update(int id, @NonNull UserCommand userCommand) {
val user = usersRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Usuario a editar requerido"));
val role = loadRoleFrom(userCommand);
val newPosition = loadPositionFrom(userCommand);
if (userCommand.isCheckConstraints()) {
assertUserUpdate(userCommand, user, newPosition);
}
if (userCommand.isHolder()) {
if (!user.isTitular() && usersRepository.existsByPositionAndTitularTrue(user.getPosition())) {
userBackupRepository.deleteAllByUsuarioPositionAndUsuarioTitularTrue(user.getPosition());
usersRepository.updateTitularFalse(user.getPosition());
} else if (!user.hasPosition(newPosition) && usersRepository.existsByPositionAndTitularTrue(newPosition)) {
userBackupRepository.deleteAllByUsuarioPositionAndUsuarioTitularTrue(newPosition);
usersRepository.updateTitularFalse(newPosition);
} else if (user.isTitular()) {
userBackupRepository.deleteAllByUsuarioPositionAndUsuarioTitularTrue(user.getPosition());
}
} else {
userBackupRepository.deleteAllByUsuarioPositionAndUsuarioTitularTrue(user.getPosition());
}
user.setEmail(userCommand.getEmail());
user.setUsuario(userCommand.getEmail());
user.setName(userCommand.getName());
user.setLastname(userCommand.getLastname());
user.setActive(userCommand.isEnabled());
user.setTitular(userCommand.isHolder());
user.setPosition(newPosition);
user.setRol(role);
if (!StringUtils.isEmpty(userCommand.getPassword())) {
user.setKeypass(passwordTemplate.encode(user.getPassword()));
}
usersRepository.save(user);
addBackups(userCommand, user);
return user;
}
@Override
public Users enable(@NonNull Integer id) {
val user = usersRepository.findById(id).orElseThrow(NoSuchElementException::new);
user.setActive(!user.isActive());
usersRepository.save(user);
return user;
}
}
我将应用程序打包为WAR文件,并使用Apache Tomcat 8.5.38进行部署
这个错误杀死了我,这是一种奇怪的行为。
答案 0 :(得分:3)
最后,我解决了这个问题。
它与final
中update
方法签名中的UserServiceImpl
关键字有关。
似乎不允许注入过程正常工作,这是完全有道理的,因为用@Transactional
注释的类永远不必是最终的。
我将其删除,现在一切正常。示例代码为here