使用Lombock和Constructor注入,春季注入的bean为空

时间:2019-06-06 18:34:49

标签: spring spring-boot

我正在将使用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均为空,如下图所示。

enter image description here

但是当我使用启用端点时,它可以正常工作。两个端点都调用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进行部署

这个错误杀死了我,这是一种奇怪的行为。

1 个答案:

答案 0 :(得分:3)

最后,我解决了这个问题。

它与finalupdate方法签名中的UserServiceImpl关键字有关。

似乎不允许注入过程正常工作,这是完全有道理的,因为用@Transactional注释的类永远不必是最终的。

我将其删除,现在一切正常。示例代码为here