← Back to Lecture
Practical Work 3

Library Management System - Foundation

Set up your development environment and create the first Java classes

Duration 3 hours
Difficulty Beginner
Session 3 - Java Syntax and IDE Setup

Objectives

By the end of this practical work, you will be able to:

  • Set up a Java project in IntelliJ IDEA
  • Create Java classes with proper package structure
  • Implement fields with appropriate data types
  • Write constructors to initialize objects
  • Create getters and setters following encapsulation principles
  • Use the var keyword for local variable type inference

Prerequisites

  • JDK 21 or later installed on your machine
  • IntelliJ IDEA (Community or Ultimate edition)
  • Basic understanding of OOP concepts (from Lecture 1)

Verify Your Installation

Open a terminal and run:

java --version
javac --version

Expected: Both commands should show version 21 or higher.

Part 1: Project Setup

Step 1.1: Create a New Project

  1. Open IntelliJ IDEA
  2. Click New Project
  3. Configure:
    • Name: LibrarySystem
    • Location: Choose your workspace folder
    • Language: Java
    • Build system: IntelliJ
    • JDK: 21 (or your installed version)
  4. Click Create

Step 1.2: Create Package Structure

Right-click on src folder and create the following packages:

  • src/
    • com.library/
      • model/
      • service/
      • Main.java

Tip: In IntelliJ, right-click on srcNewPackage and type com.library.model to create nested packages in one step.

Part 2: Create the Book Class

Step 2.1: Create Book.java

In the com.library.model package, create Book.java:

package com.library.model;  // (#1:Package declaration)

public class Book {  // (#2:Class declaration)

    // Fields (attributes)
    private String isbn;  // (#3:Private field - encapsulation)
    private String title;
    private String author;
    private int publicationYear;
    private boolean available;

    // Constructor
    public Book(String isbn, String title, String author, int publicationYear) {  // (#4:Parameterized constructor)
        this.isbn = isbn;
        this.title = title;
        this.author = author;
        this.publicationYear = publicationYear;
        this.available = true;  // (#5:Default value)
    }

    // Getters
    public String getIsbn() {  // (#6:Getter method)
        return isbn;
    }

    public String getTitle() {
        return title;
    }

    public String getAuthor() {
        return author;
    }

    public int getPublicationYear() {
        return publicationYear;
    }

    public boolean isAvailable() {  // (#7:Boolean getter uses "is" prefix)
        return available;
    }

    // Setters
    public void setAvailable(boolean available) {  // (#8:Setter method)
        this.available = available;
    }

    // Note: ISBN, title, author typically shouldn't change after creation
    // so we don't provide setters for those fields
}

Step 2.2: Add a Display Method

Add this method to the Book class to display book information:

    public void displayInfo() {
        System.out.println("========== Book Info ==========");
        System.out.println("ISBN: " + isbn);
        System.out.println("Title: " + title);
        System.out.println("Author: " + author);
        System.out.println("Year: " + publicationYear);
        System.out.println("Available: " + (available ? "Yes" : "No"));
        System.out.println("===============================");
    }

Step 2.3: Test the Book Class

Create Main.java in the com.library package:

package com.library;

import com.library.model.Book;

public class Main {
    public static void main(String[] args) {
        // Create a book using the constructor
        var book1 = new Book(  // (#1:Using var for type inference)
            "978-0-13-468599-1",
            "Effective Java",
            "Joshua Bloch",
            2018
        );

        // Display book information
        book1.displayInfo();

        // Test getters
        System.out.println("\nAccessing via getters:");
        System.out.println("Title: " + book1.getTitle());
        System.out.println("Is available: " + book1.isAvailable());

        // Test setter - mark book as borrowed
        book1.setAvailable(false);
        System.out.println("\nAfter borrowing:");
        System.out.println("Is available: " + book1.isAvailable());
    }
}

Run the program (Shift + F10 or click the green play button).

Expected Output:

========== Book Info ==========
ISBN: 978-0-13-468599-1
Title: Effective Java
Author: Joshua Bloch
Year: 2018
Available: Yes
===============================

Accessing via getters:
Title: Effective Java
Is available: true

After borrowing:
Is available: false

Part 3: Create the Member Class

Step 3.1: Create Member.java

In the com.library.model package, create Member.java:

package com.library.model;

public class Member {

    // Fields
    private String memberId;
    private String firstName;
    private String lastName;
    private String email;
    private int borrowedBooks;  // Track number of currently borrowed books
    private static final int MAX_BOOKS = 5;  // (#1:Constant - maximum books allowed)

    // Constructor
    public Member(String memberId, String firstName, String lastName, String email) {
        this.memberId = memberId;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.borrowedBooks = 0;
    }

    // Getters
    public String getMemberId() {
        return memberId;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public String getFullName() {  // (#2:Computed property)
        return firstName + " " + lastName;
    }

    public String getEmail() {
        return email;
    }

    public int getBorrowedBooks() {
        return borrowedBooks;
    }

    // Setters
    public void setEmail(String email) {
        // Simple validation
        if (email != null && email.contains("@")) {  // (#3:Validation in setter)
            this.email = email;
        } else {
            System.out.println("Invalid email address!");
        }
    }

    // Business methods
    public boolean canBorrow() {  // (#4:Business logic method)
        return borrowedBooks < MAX_BOOKS;
    }

    public void borrowBook() {
        if (canBorrow()) {
            borrowedBooks++;
        } else {
            System.out.println("Maximum books limit reached!");
        }
    }

    public void returnBook() {
        if (borrowedBooks > 0) {
            borrowedBooks--;
        }
    }

    public void displayInfo() {
        System.out.println("========== Member Info ==========");
        System.out.println("ID: " + memberId);
        System.out.println("Name: " + getFullName());
        System.out.println("Email: " + email);
        System.out.println("Books borrowed: " + borrowedBooks + "/" + MAX_BOOKS);
        System.out.println("=================================");
    }
}

Step 3.2: Test the Member Class

Update Main.java to test the Member class:

package com.library;

import com.library.model.Book;
import com.library.model.Member;

public class Main {
    public static void main(String[] args) {
        // Create a member
        var member = new Member("M001", "Alice", "Johnson", "alice@example.com");
        member.displayInfo();

        // Test borrowing logic
        System.out.println("\n--- Testing Borrow Logic ---");
        System.out.println("Can borrow: " + member.canBorrow());

        // Borrow some books
        for (int i = 0; i < 6; i++) {
            System.out.println("Attempting to borrow book " + (i + 1) + "...");
            member.borrowBook();
            System.out.println("Books borrowed: " + member.getBorrowedBooks());
        }

        // Return a book
        System.out.println("\n--- Returning a book ---");
        member.returnBook();
        System.out.println("Books borrowed: " + member.getBorrowedBooks());
        System.out.println("Can borrow now: " + member.canBorrow());

        // Test email validation
        System.out.println("\n--- Testing Email Validation ---");
        member.setEmail("invalid-email");  // Should fail
        member.setEmail("alice.new@example.com");  // Should succeed
        System.out.println("New email: " + member.getEmail());
    }
}

Part 4: Working with Data Types

Step 4.1: Create BookCategory Enum (Preview)

Create a simple enum for book categories (we'll expand this in the next practical work):

package com.library.model;

public enum BookCategory {
    FICTION,
    NON_FICTION,
    SCIENCE,
    TECHNOLOGY,
    HISTORY,
    BIOGRAPHY,
    CHILDREN
}

Step 4.2: Add Category to Book

Update the Book class to include a category:

// Add this field
private BookCategory category;

// Update constructor
public Book(String isbn, String title, String author, int publicationYear, BookCategory category) {
    this.isbn = isbn;
    this.title = title;
    this.author = author;
    this.publicationYear = publicationYear;
    this.category = category;
    this.available = true;
}

// Add getter
public BookCategory getCategory() {
    return category;
}

// Update displayInfo to include category
public void displayInfo() {
    System.out.println("========== Book Info ==========");
    System.out.println("ISBN: " + isbn);
    System.out.println("Title: " + title);
    System.out.println("Author: " + author);
    System.out.println("Year: " + publicationYear);
    System.out.println("Category: " + category);
    System.out.println("Available: " + (available ? "Yes" : "No"));
    System.out.println("===============================");
}

Step 4.3: Explore var Usage

Practice using var with different types:

// Good uses of var
var count = 0;                                    // int
var message = "Hello";                           // String
var book = new Book("123", "Test", "Auth", 2024, BookCategory.FICTION);  // Book
var price = 19.99;                               // double

// With collections (we'll cover in detail later)
var books = new ArrayList<Book>();              // ArrayList<Book>

// Avoid var when type is unclear
// var result = getResult();  // What type is this?
// var x = 0;                 // Prefer: int x = 0;

Exercises

Exercise 1: Create a Loan Class

Create a Loan class to track book loans with the following:

  • Fields: loanId (String), book (Book), member (Member), loanDate (String for now)
  • Constructor: Initialize all fields
  • Methods: getters for all fields, displayInfo()

Exercise 2: Add Validation

Add validation to the Book constructor:

  • ISBN must not be null or empty
  • Title must not be null or empty
  • Publication year must be between 1450 and current year

Print an error message if validation fails.

Exercise 3: Calculate Late Fee

Add a method to calculate late fees:

// In Member class
public double calculateLateFee(int daysLate) {
    // Implement: 0.50 euros per day, maximum 20 euros
    // Return 0 if daysLate is 0 or negative
}

Exercise 4: Book Statistics

Create a static method in the Book class to display statistics:

private static int totalBooksCreated = 0;  // Increment in constructor

public static void displayStatistics() {
    // Display total books created
}

Expected Output

After completing all exercises, your project structure should be:

  • LibrarySystem/
    • src/
      • com/library/
        • model/
          • Book.java
          • BookCategory.java
          • Member.java
          • Loan.java
        • service/
        • Main.java

Deliverables

  • Source Code: Complete Java project with all classes
  • Screenshots: Project structure in IntelliJ IDEA
  • Output: Console output showing all tests passing

Bonus Challenges

  • Challenge 1: Add a toString() method to each class
  • Challenge 2: Create a Library class to hold multiple books
  • Challenge 3: Add input validation using regular expressions for ISBN
  • Challenge 4: Implement a simple command-line menu to interact with the library

Resources