Java Interfaces and Exception Handling - Practice Problem with Solution

Problem Statement:
Create a UserService Interface with following methods signatures.

void addUser(User user) throws UserAlreadyExistException
User getUser(int userID) throws UserAccountIsBlockedException
void updateUser(User user)
void deleteUser(int userID)
void unblockUser(int userID)
ArrayList getAllUsers()

Define InMemoryUserService class that shall implement UserService interface. In InMemoryUserService class, use User ArrayList for storage of user objects. The methods shall change/read this list to perform the required operations. Test all methods from UserTest class. Getting information from user input is encourged but optional.

Define and properly encapsulate atleast id, name and status instance attributes in User class of type int, String and boolean. How you check whether a user account is blocked? If status attribute is false, it means user account is blocked. True represent the account is active.

UserAlreadyExistException exception shall be thrown if user already exist in the users array list. The exception object shall also store the user ID for which the exception occured. Check using equals methods (override the method in User class, based on user ID). Make UserAlreadyExistException, a runtime exception. UserAccountIsBlockedException should be thrown if status attribute of the user object (in the array list) is false, define this exception as checked.

Update the test class by handling both exceptions. Call different methods passing parameters that shall make the user service to throw the exception to demonstate you handled them appropriately.

Make a test class to test all the functionality of UserService. Call its different methods to see how it works, keep printing related information on console to show what the program is doing. You must also handle above defined exceptions from your test class.

Solution:

Lets first define the user class, that contains 3 instance attributes. We have also overriden the toString method to easily print all attributes values of user object. equals method is also overriden, as multiple methods of ArrayList class use it.


package com.bitspedia.labtasks.task10;

import java.util.ArrayList;

class User {
    private int id;
    private String name;
    private boolean status;

    public User(int id, String name) {
        setId(id);
        setName(name);
        setStatus(true);
    }

    public User(int id) {
        setId(id);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null) return false;

        User user = (User) o;
        return id == user.id;
    }

    public void setStatus(boolean status) {
        this.status = status;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isStatus() {
        return status;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", status=" + status +
                '}';
    }
}


As you know, interface contains methods that tell what the object must perform. How this operations would be performed is defined by the classes that impelement this interface. One implementation may provide defition that store all data in primary memory, another implementations may define these methods to save the data in database.

interface UserService {
    void addUser(User user) throws UserAlreadyExistException;

    User getUser(int userId) throws UserAccountIsBlockedException;

    void updateUser(User user);

    void deleteUser(int userID);

    void unblockUser(int userID);

    ArrayList<User> getAllUsers();
}

Lets define InMemoryUserService class that implement UserService, it uses ArrayList to save all data. This class do not store the data in database.

class InMemoryUserService implements UserService {
    static ArrayList<User> users = new ArrayList<>();

    @Override
    public void addUser(User user) throws UserAlreadyExistException {
        if (users.contains(user))
            throw new UserAlreadyExistException(user.getId());
        users.add(user);
    }

    @Override
    public User getUser(int userId) throws UserAccountIsBlockedException {
        User user = null;
        int index = users.indexOf(new User(userId));
        if (index >= 0) {
            user = users.get(index);
            if (!user.isStatus())
                throw new UserAccountIsBlockedException(user.getId());
        }
        return user;
    }

    /* id attribute must be defined of the passed user object */
    @Override
    public void updateUser(User user) {
        if (users.contains(user)) {
            users.set(users.indexOf(user), user);
        }
    }

    @Override
    public void deleteUser(int userId) {
        users.remove(new User(userId));
    }

    @Override
    public void unblockUser(int userID) {
        int indexOfUser = users.indexOf(new User(userID));
        if (indexOfUser >= 0) {
            User user = users.get(indexOfUser);
            user.setStatus(true);
            System.out.println("User unblocked.");
        }
    }

    public ArrayList<User> getAllUsers() {
        return new ArrayList<User>(users);
    }
}

Below we have defined both exception classes. As methods declared in UserService class throw them.

class UserAlreadyExistException extends RuntimeException {
    private int userId;

    public UserAlreadyExistException(int userId) {
        this.userId = userId;
    }

    @Override
    public String getMessage() {
        return String.format("User with userId : " + userId + " already exist\n");
    }
}

class UserAccountIsBlockedException extends Exception {
    private int userId;

    public UserAccountIsBlockedException(int userId) {
        this.userId = userId;
    }

    @Override
    public String getMessage() {
        return String.format("Account having userId : " + userId + " is block.\n");
    }
}


Finally its time to test what we have done so far. In below test class, we have added two objects. Then updated on, retrieved, and deleted from the userservice. The output generated by program is also given at end.

public class UserTest {
    public static void main(String[] args) {
        UserService userService = new InMemoryUserService();

        User user1 = new User(1, "Abdullah");
        User user2 = new User(2, "Ali");

        try {
            userService.addUser(user1);
            userService.addUser(user2);
            System.out.println("Two users added. ");
            printAllUsersList(userService.getAllUsers());
            System.out.println();

            System.out.println("Updating User1 Name to Zia.");
            user1.setName("Zia");
            userService.updateUser(user1);
            System.out.println("Current Data in List: ");
            printAllUsersList(userService.getAllUsers());
            System.out.println();

            System.out.println("Getting user by Id : 1");
            User u = userService.getUser(1);
            System.out.println(u);
            System.out.println();

            System.out.println("Removing User of ID 1");
            userService.deleteUser(1);
            System.out.println("After removing ... Data in list: ");
            printAllUsersList(userService.getAllUsers());
            System.out.println();

        } catch (UserAlreadyExistException | UserAccountIsBlockedException exp) {
            System.out.println(exp.getMessage());
        }
    }

    public static void printAllUsersList(ArrayList<User> users){
        for(User user: users){
            System.out.println(user);
        }
    }
}

When you run above UserTest class, it generates following ouput:

Two users added. 
User{id=1, name='Abdullah', status=true}
User{id=2, name='Ali', status=true}

Updating User1 Name to Zia.
Current Data in List: 
User{id=1, name='Zia', status=true}
User{id=2, name='Ali', status=true}

Getting user by Id : 1
User{id=1, name='Zia', status=true}

Removing User of ID 1
After removing ... Data in list: 
User{id=2, name='Ali', status=true}

Comments