Skip to content
Advertisement

Exceptions or null in java

I have the next doubt. According to good practices of java, how to manage the cases in which the object can not be found and we want to know why.

For example, if someone has problems logging in our system and we want to inform them exactly what is the problem, we cannot return null because we lose the reason for not being able to log in. For example:

public User login(String username, String password) {
    boolean usernameEmpty = (credentials.getUsername()==null || credentials.getUsername().isEmpty());
    boolean passwordEmpty = (credentials.getPassword()==null || credentials.getPassword().isEmpty());
    //getUserPassword return null if doesn't exist an user with username and password return null
    User user = getUserPassword(username,password);

    if (!usernameEmpty && !passwordEmpty && user!=null) {
        LOGGER.info("Found " + username);
    } else if (!usernameEmpty && !passwordEmpty && user==null) {
        LOGGER.info("There is no such username and password: " + username);
    } else if (usernameEmpty) {
        LOGGER.info("Username can not be empty ");
    } else if (passwordEmpty) {
        LOGGER.info("Password can not be empty ");
    }

    return user;
}

I can think of two options with pros and cons to resolve it.

The first one consists in using Exceptions but I think that is not a good idea use different scenarios than expected like exceptions. For that reason, I discard it.

The second one is involve the object (User) in another object to manage the differents posibilities. For example, use something like this:

public class EntityObject<t> {
    //Is used to return the entity or entities if everything was fine
    private t entity;
    //Is used to inform of any checked exception
    private String exceptionMessage;

    //getters / setters / ..
}

public EntityObject<User> login(String username, String password) {
    boolean usernameEmpty = (credentials.getUsername()==null || credentials.getUsername().isEmpty());
    boolean passwordEmpty = (credentials.getPassword()==null || credentials.getPassword().isEmpty());
    User user = getUserPassword(username,password);
    EntityObject<User> entity = null;

    if (!usernameEmpty && !passwordEmpty && user!=null) {
        LOGGER.info("Found " + username);
        entity = new EntityObject<User>(user);
    } else if (!usernameEmpty && !passwordEmpty && user==null) {
        entity = new EntityObject<User>("There is no such username and password: " + username); 
    } else if (usernameEmpty) {
        entity = new EntityObject<User>("Username can not be empty ");
    } else if (passwordEmpty) {
        entity = new EntityObject<User>("Password can not be empty ");
    }

    return entity;
}

I like more this second option than the first one but i don’t like that i have to change the method signature to return a different class (EntityObject) than the usual (User).

What is the usual? How is it usually managed? many thanks

Advertisement

Answer

An exception should be used when there is something exceptional happening in the system. For a normal flow and something that is expected to happen you should avoid using exceptions.

Following the good SOLID principals your method should do just one thing. So if it is a method to find user by username and password I would say the best would be to return null (or empty optional if using optionals). The reason is not lost. Actually it is pretty clear – there is not such user found with the supplied username and password (this reason includes the problem with empty username and it’s the user of the method’s fault to supply empty username to a login method). Adding complex logic to the method and additional entities for such things will make your code harder to maintain and to understand. This method’s job is not to handle validation anyway.

If that class is used by a website or its some kind of API then they can handle the validation (if username or password is empty).

Advertisement