简体   繁体   中英

Spring boot rest controller. Return object including heritage properties plus exception handling

I have a struggle in spring boot restcontroller.

UserService

@Service
public class UserService implements IUserService {

    @Autowired
    public PasswordEncoder passwordEncoder;

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public UserLoginResponse register(RegisterUserRequest request) throws NoValidRegisterDataException, Exception {
        UserLoginResponse response = new UserLoginResponse();
        UserEntity user = request.getUser();

        if(!this.checkUserDataValidity(user)) {
            throw new NoValidRegisterDataException();
        }

        user.setPassword(this.encodePassword(user.getPassword()));

        try {
            user = this.userRepository.save(user);
        } catch (Exception e) {
            throw new Exception("Database save error");
        }

        response.addMessage(new ResponseMessage(ResponseMessageType.success, "Uživatel úspěšně registrován"));
        response.setUser(user);

        //TODO token handler

        return response;
    }

    private boolean checkUserDataValidity(UserEntity user) {
        return (user.getEmail() != null && user.getPassword() != null && user.getUsername() != null);
    }

    private String encodePassword(String password) {
        return this.passwordEncoder.encode(password);
    }
}

I have a register (main method) of service so far. Its called by UserController (code below)

@RestController
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @RequestMapping(method = POST, value = "/user/register")
    @CrossOrigin
        public UserLoginResponse register(RegisterUserRequest request,
                                          HttpServletResponse servletResponse) {
            UserLoginResponse response = new UserLoginResponse();

            try {
                response = this.userService.register(request);
            } catch (NoValidRegisterDataException e) {
response.addMessage(new ResponseMessage(ResponseMessageType.danger, e.getMessage()));
                servletResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            } catch (Exception e) {
                response.addMessage(new ResponseMessage(ResponseMessageType.danger, e.getMessage()));
                servletResponse.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
            }

            return response;
        }
}

I return the UserLoginResponse object. I get RegisterUserRequest object in my request (its basically the object with user data)

public class UserLoginResponse extends Response {
    private UserEntity user;

    private String userToken;

    public UserLoginResponse() {}

    public UserLoginResponse(ArrayList<ResponseMessage> messages, UserEntity user, String userToken) {
        super(messages);
        this.user = user;
        this.userToken = userToken;
    }

    public UserEntity getUser() {
        return user;
    }

    public void setUser(UserEntity user) {
        this.user = user;
    }

    public String getUserToken() {
        return userToken;
    }

    public void setUserToken(String userToken) {
        this.userToken = userToken;
    }
}

And It extends the Response object, which has one property inside. The list of messages I want to send to my front-end

public class Response {
    private ArrayList<ResponseMessage> messages;

    public Response() {}

    public Response(ArrayList<ResponseMessage> messages) {
        this.messages = messages;
    }

    public void addMessage(ResponseMessage message) {
        if(this.messages == null) {
            this.messages = new ArrayList<>();
        }

        this.messages.add(message);
    }
}

The first problem is, when something bad happen (bad user data, some other error) I get the empty UserLoginResponse object. Thats mostly okay, but I do not have a messages in it. (the error messages are set in the catch block in the UserController so they should be there.)

The second problem is, even I throw the NoValidRegisterDataException in the first catch block (up the general Exception) in the UserController the exception is handled by the last catch block. How can I fix this? I thought the exception is handled by the first catch block it fits (from the top to the bottom).

EDIT: I've solved the second problem. I didnt noticed that on the condition up the throw exception was the nullpointerexception threw. So it makes sence now. I added the null check and the exceptions works fine now. But I still do not know how ot return whole response including the messages from parent Response object.

There are several probles in my opinion regarding your code:

1) Please refrain from using checked exceptions in Spring services and controllers. They add nothing but noise especially with the various try-catch clauses. Ideally if want to throw an exception just throw a runtime one and have an exception handler in place to catch it and create your appropriate response. You can have a look at these here: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html

2) Avoid using catch clauses catching Exception . In most cases this will mess up your flow in case some unwanted exception occurs. Just let it bubble up to Spring's default exception handler.

3) Avoid inheritance and just favour composition in return. In my opinion extending POJOs is not a very nice thing.

4) Avoid the mix of field injection and constructor injection. In most cases this is a recipe for disaster.

5) I do not see any point in manually setting the servletResponse each time. Just wrap your response object into a ResponseEntity which can effectively carry a status code as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM