30 KiB
30 KiB
Database Guidelines
MySQL data and DAO conventions for the library-management system.
Overview
MySQL is the project data layer. DAO classes perform CRUD and query operations
against MySQL. The initial scaffold schema exists at
src/main/resources/db/schema.sql; future module tables should follow the same
DDL style and DAO boundaries.
Core Tables
Use primary keys for every table and foreign keys for cross-entity integrity.
Implemented scaffold tables:
roles: administrator, librarian, reader, and future role definitions.permissions: permission definitions for protected actions.role_permissions: role-to-permission mapping.users: login accounts for administrator, librarian, and reader roles.system_logs: key operation logs, backup events, and exception traces.book_categories: category names and descriptions for catalog grouping.books: book information, category reference, inventory counts, and catalog status.readers: reader profiles, optional login-account linkage, borrowing eligibility, contact information, and management status.borrow_records: book-reader borrowing, return, renew, and overdue data.
Record new schema changes in src/main/resources/db/schema.sql and update this
spec with exact table names, key columns, and DAO/service contracts.
DAO Responsibilities
- DAOs own database CRUD and query details.
- Use parameterized SQL or prepared-statement style access; never concatenate raw request parameters into SQL.
- Keep transaction boundaries in the service layer for workflows that span multiple DAO calls, such as borrow/return operations that also update inventory status.
- Return entities or small query result objects to services, not HTML or servlet response objects.
- Keep MySQL connection details in
src/main/resources/db.propertiesloaded byJdbcUtil. The required keys aredb.driver,db.url,db.username, anddb.password.
Query Guidance
- Book search must support combined lookup by title, author, category, and ID.
- Statistics queries should cover borrowing rankings, inventory reports, and overdue reports.
- Borrowing records should preserve enough dates/status fields for borrow, return, renew, overdue calculation, and automatic collection status updates.
- Permission queries should support role-based checks for administrator, librarian, and reader workflows.
Integrity Constraints
books.category_idshould referencebook_categories.borrow_records.book_idshould referencebooks.borrow_records.reader_idshould referencereaders.- Administrator-role and role-permission mapping tables should use foreign keys to preserve authorization integrity.
users.role_codemust referenceroles.code.role_permissions.role_codemust referenceroles.code.role_permissions.permission_codemust referencepermissions.code.books.statusmust matchBookStatusenum codes:available,unavailable, andarchived.readers.user_idmay referenceusers.idwhen a reader profile is linked to a login account.readers.statusmust matchReaderStatusenum codes:active,suspended, andinactive.readers.max_borrow_countmust stay between 1 and 50.
Scenario: Book Catalog And Management Slice
1. Scope / Trigger
- Trigger: the first concrete business module introduced catalog search and basic book management across MySQL, DAO, service, Servlet, and JSP layers.
- Schema path:
src/main/resources/db/schema.sql. - JSP paths:
WEB-INF/jsp/books/catalog.jsp,books/manage.jsp, andbooks/form.jsp.
2. Signatures
- DAO signatures:
BookDao.findAllCategories(),BookDao.search(BookSearchCriteria criteria),findById(long id),findByIdentifier(String identifier),create(Book book),update(Book book), anddelete(long id). - Entity/search signatures:
Bookfields areid,identifier,title,author,categoryId,categoryName,totalCopies,availableCopies,status,createdAt, andupdatedAt;BookSearchCriteriafields areidentifier,title,author, and nullablecategoryId. - Service signatures:
BookService.listCategories(),searchBooks(BookSearchCriteria criteria),findBook(long id),createBook(AuthenticatedUser actor, Book book),updateBook(AuthenticatedUser actor, Book book), anddeleteBook(AuthenticatedUser actor, long id), all returningServiceResult<T>. - Read route:
GET /catalogwith optionalidentifier,title,author, andcategoryIdquery fields. - Management routes:
GET /books,GET /books/new,GET /books/edit?id=...,POST /books,POST /books/update, andPOST /books/delete. - Protected permissions:
/catalogrequiresVIEW_CATALOG;/books*requiresMANAGE_BOOKS. - DB signatures:
book_categories(id, name, description, created_at, updated_at), with unique keyuk_book_categories_name(name).books(id, book_identifier, title, author, category_id, total_copies, available_copies, status, created_at, updated_at), with unique keyuk_books_identifier(book_identifier), indexes on title, author, category, and status, foreign keyfk_books_category, and checks for non-negative copy counts and allowed status values.
3. Contracts
book_categories.nameis unique and displayed through category selectors.books.book_identifieris the unique user-facing book ID.books.category_idreferencesbook_categories.id.books.total_copiesandbooks.available_copiesare non-negative, and available copies cannot exceed total copies.books.statusstores the JavaBookStatuscode exactly.- Servlet controllers parse request fields and set JSP attributes such as
criteria,categories,books,book,statuses,errors,errorMessage, andsuccessMessage. ServiceResult<T>is the service-to-controller response contract:successful, nullabledata, nullablemessage, and field-levelerrors. Controllers must pass validation errors to JSPs so form/search redisplay can highlight the exact field, for exampleerrors.categoryId.- JSP pages render JavaBean properties only; they must not call DAOs or embed SQL.
4. Validation & Error Matrix
- Missing identifier, title, author, category, copy counts, or status -> return
to
books/form.jspwith field errors. - Negative total or available copies -> return a field error.
- Available copies greater than total copies -> return
Available copies cannot exceed total copies. - Duplicate
book_identifier-> return a field error onidentifier. - Reader or unauthenticated actor attempts write -> HTTP 403 through authorization filter or service denial.
- DAO failure during list/search/write -> log server-side details and return
Book service is temporarily unavailable. Please try again later. - Successful create/update/delete -> redirect to
/bookswith a short flash message.
5. Good/Base/Bad Cases
- Good: a librarian creates
BK-1002, sees it in/books, and readers can find it from/catalogwithout write controls. - Base: catalog search with no filters lists available records ordered by title, author, and identifier.
- Bad: a JSP opens JDBC, builds SQL from request parameters, or renders a stack trace from a failed DAO call.
6. Tests Required
- Run
BookServiceCheckor equivalent assertions for invalid inventory, duplicate identifiers, reader write denial, successful librarian CRUD, search, and DAO failure fallback. - Run
PermissionPolicyCheckto confirm readers lackMANAGE_BOOKSand retainVIEW_CATALOG. - Scan JSPs for scriptlets and SQL/JDBC references.
- When Maven/Tomcat dependencies are installed, run
mvn clean packageto compile Servlets and package JSP resources.
7. Wrong vs Correct
Wrong
books/form.jsp -> JDBC -> INSERT INTO books using request parameters
Correct
books/form.jsp -> BookManagementServlet -> BookService -> BookDao -> books
Scenario: Book Category Maintenance Slice
1. Scope / Trigger
- Trigger: category maintenance completes the book-management core requirement
by adding staff-managed CRUD for
book_categories, while existing book forms and catalog searches continue to consume the same category source. - Schema path:
src/main/resources/db/schema.sql. - JSP paths:
WEB-INF/jsp/books/categories.jspandWEB-INF/jsp/books/category-form.jsp.
2. Signatures
- DAO signatures:
BookDao.findAllCategories(),findCategoryById(long id),findCategoryByName(String name),createCategory(BookCategory category),updateCategory(BookCategory category),deleteCategory(long id), andcountBooksByCategoryId(long categoryId). - Entity signature:
BookCategory(id, name, description). - Service signatures:
BookService.listCategories(),findCategory(long id),createCategory(AuthenticatedUser actor, BookCategory category),updateCategory(AuthenticatedUser actor, BookCategory category), anddeleteCategory(AuthenticatedUser actor, long id), all returningServiceResult<T>. - Routes:
GET /book-categories,GET /book-categories/new,GET /book-categories/edit?id=...,POST /book-categories,POST /book-categories/update, andPOST /book-categories/delete. - Protected permission:
/book-categories*requiresMANAGE_BOOKS.
3. Contracts
book_categories.nameis unique and is the display value used in book forms, catalog filters, and management filters.book_categories.descriptionis optional and limited to the database column size.- Book category deletes must check
books.category_idusage before deletion and return a safe validation result when the category is in use. - Servlet controllers set JSP attributes such as
categories,category,formTitle,formAction,formValues,errors,errorMessage, andsuccessMessage. - JSP pages render JavaBean properties only; they must not call DAOs or embed SQL.
4. Validation & Error Matrix
- Missing category name -> field error on
name. - Category name longer than 96 characters -> field error on
name. - Description longer than 255 characters -> field error on
description. - Duplicate category name -> field error on
name. - Missing or non-positive category id for edit/delete ->
Select a valid category. - Delete category used by any
booksrow ->Category is used by existing books and cannot be deleted. - Reader or unauthenticated actor attempts mutation -> permission denial through filter/service.
- DAO failure during list/search/write -> log server-side details and return
Book service is temporarily unavailable. Please try again later.
5. Good/Base/Bad Cases
- Good: a librarian creates
Architecture, selects it on a book form, and sees it in catalog filters. - Base:
/book-categorieslists seed categories ordered by name. - Bad: deleting a category with existing books surfaces a MySQL foreign-key stack trace or lets JSP code perform the delete.
6. Tests Required
- Run
BookServiceCheckassertions for reader category-write denial, duplicate category names, successful create/update/delete, and used-category delete rejection. - Run
PermissionPolicyCheckto confirmMANAGE_BOOKSremains staff-only. - Scan category JSPs for scriptlets and SQL/JDBC references.
- When Maven/Tomcat dependencies are installed, run
mvn clean packageto compile Servlets and package JSP resources.
7. Wrong vs Correct
Wrong
categories.jsp -> JDBC -> DELETE FROM book_categories WHERE id = request.id
Correct
categories.jsp -> BookManagementServlet -> BookService -> BookDao -> book_categories
Scenario: Reader Information Management Slice
1. Scope / Trigger
- Trigger: the reader profile foundation was implemented after login, permissions, catalog search, and book management.
- Schema path:
src/main/resources/db/schema.sql. - JSP paths:
WEB-INF/jsp/readers/manage.jspandreaders/form.jsp.
2. Signatures
- DAO signatures:
ReaderDao.search(ReaderSearchCriteria criteria),findById(long id),findByIdentifier(String identifier),findByUserId(long userId),create(Reader reader),update(Reader reader), anddeactivate(long id). - Entity/search signatures:
Readerfields areid,identifier, nullableuserId, nullableusername,fullName,phone,email,status,maxBorrowCount,createdAt, andupdatedAt;ReaderSearchCriteriafields areidentifier,name,contact, andstatusCode. - Status signature:
ReaderStatusenum codes areactive,suspended, andinactive. - Service signatures:
ReaderService.searchReaders(ReaderSearchCriteria),findReader(long id),createReader(AuthenticatedUser actor, Reader reader),updateReader(AuthenticatedUser actor, Reader reader), anddeactivateReader(AuthenticatedUser actor, long id), all returningServiceResult<T>. - Management routes:
GET /readers,GET /readers/new,GET /readers/edit?id=...,POST /readers,POST /readers/update, andPOST /readers/delete. - Protected permission:
/readers*requiresMANAGE_READERS. - DB signature:
readers(id, reader_identifier, user_id, full_name, phone, email, status, max_borrow_count, created_at, updated_at), with unique keys onreader_identifierand nullableuser_id, indexes on name/contact/status, a foreign key tousers(id), and checks for supported status values and borrow-limit range.
3. Contracts
readers.reader_identifieris the unique user-facing reader ID.readers.user_idis optional; when present, only one reader profile may link to the same login account.readers.statusstores the JavaReaderStatuscode exactly. Soft-delete behavior deactivates the profile by setting status toinactive.- Reader searches support partial identifier, full-name, and phone/email contact matching plus exact status filtering.
- Servlet controllers parse request fields and set JSP attributes such as
criteria,readers,reader,statuses,formValues,errors,errorMessage, andsuccessMessage. - JSP pages render JavaBean properties only; they must not call DAOs or embed SQL.
- Navigation should expose reader management to administrator/librarian users,
matching the current
MANAGE_READERSpolicy.
4. Validation & Error Matrix
- Missing identifier or full name -> return to
readers/form.jspwith field errors. - Missing both phone and email -> return a field error on
phone. - Invalid phone or email format -> return field errors on
phoneoremail. - Unsupported status -> return a field error on
status. - Max borrow count outside 1 to 50 -> return a field error on
maxBorrowCount. - Non-positive linked
user_id-> return a field error onuserId. - Duplicate
reader_identifier-> return a field error onidentifier. - Duplicate linked
user_id-> return a field error onuserId. - Reader or unauthenticated actor attempts write -> HTTP 403 through authorization filter or service denial.
- DAO failure during list/search/write -> log server-side details and return
Reader service is temporarily unavailable. Please try again later. - Successful create/update/deactivate -> redirect to
/readerswith a short flash message.
5. Good/Base/Bad Cases
- Good: a librarian creates
RD-1003, searches by email, edits the borrow limit, and can later deactivate the profile without deleting future borrowing history. - Base:
/readerswith no filters lists reader records ordered by full name and reader identifier. - Bad: normal readers access
/readers, a JSP opens JDBC, or deleting a reader profile removes rows that future borrow records need to reference.
6. Tests Required
- Run
ReaderServiceCheckor equivalent assertions for invalid contact, invalid borrow limit, duplicate identifiers, duplicate linked users, reader write denial, successful librarian CRUD-like operations, search, deactivate, and DAO failure fallback. - Run
PermissionPolicyCheckto confirm librarians haveMANAGE_READERSand readers do not. - Scan reader JSPs for scriptlets and SQL/JDBC references.
- When Maven/Tomcat dependencies are installed, run
mvn clean packageto compile Servlets and package JSP resources.
7. Wrong vs Correct
Wrong
readers/form.jsp -> JDBC -> DELETE FROM readers using request parameters
Correct
readers/form.jsp -> ReaderManagementServlet -> ReaderService -> ReaderDao -> readers.status = inactive
Scenario: Borrowing Circulation Management Slice
1. Scope / Trigger
- Trigger: borrowing circulation now spans
borrow_records, book inventory, reader eligibility, Servlet routes, service transactions, DAO locks, and JSP management/history screens. - Schema path:
src/main/resources/db/schema.sql. - JSP paths:
WEB-INF/jsp/borrowing/manage.jsp,borrowing/form.jsp, andreader/loans.jsp.
2. Signatures
- Entity signatures:
BorrowRecordfields areid,readerId,readerIdentifier,readerName,bookId,bookIdentifier,bookTitle,borrowedAt,dueAt, nullablereturnedAt,renewalCount,status,createdAt, andupdatedAt. - Status signature:
BorrowRecordStatusenum codes areactiveandreturned; overdue is derived from active, non-returned rows wheredue_at < CURRENT_TIMESTAMP. - Search signature:
BorrowRecordSearchCriteria(readerIdentifier, bookIdentifier, statusCode)wherestatusCodemay be empty,active,returned, or the derived filteroverdue. - DAO signatures:
BorrowRecordDao.search(criteria),findByReaderId(readerId),findReaderByUserId(userId),findReaderByIdentifierForUpdate(connection, identifier),findBookByIdentifierForUpdate(connection, identifier),findByIdForUpdate(connection, id),countActiveByReaderId(connection, readerId),create(connection, record),decrementAvailableCopies(...),incrementAvailableCopies(...),markReturned(...), andrenew(...). - Service signatures:
BorrowingService.searchRecords(actor, criteria),borrowBook(actor, readerIdentifier, bookIdentifier),returnBook(actor, recordId),renewLoan(actor, recordId), andlistCurrentReaderHistory(actor), all returningServiceResult<T>. - Management routes:
GET /borrowing,GET /borrowing/new,POST /borrowing/create,POST /borrowing/return, andPOST /borrowing/renew. - Reader route:
GET /reader/loans. - Protected permissions:
/borrowing*requiresMANAGE_BORROWING;/reader/loansrequiresBORROW_BOOKSand thereaderrole because it displays only the signed-in reader's own history. - DB signature:
borrow_records(id, reader_id, book_id, borrowed_at, due_at, returned_at, renewal_count, status, created_at, updated_at), with foreign keys toreaders(id)andbooks(id), indexes on reader, book, status, and due date, and checks for non-negative renewal count and supported statuses.
3. Contracts
- Borrow operations require an active reader and a borrowable book with
BookStatus.AVAILABLEandavailable_copies > 0. - Reader active-loan count is rows with
status = activeandreturned_at IS NULL; overdue rows still count towardmax_borrow_count. - Borrowing creates one
borrow_recordsrow and decrementsbooks.available_copiesin the same transaction. - Returning an active loan sets
status = returned, storesreturned_at, and incrementsbooks.available_copieswith a cap attotal_copiesin the same transaction. - Renewing an active loan extends
due_at, incrementsrenewal_count, and is limited to one renewal per MVP loan. JdbcUtil.executeInTransactionis the local transaction helper for multi-table borrowing workflows. Services decide the workflow boundary; DAOs own SQL and row-lock statements.- Demo
readersandbooksseed rows must not overwrite existing rows during schema replay, because resetting reader eligibility oravailable_copiescan corrupt live borrowing state. - Servlet controllers set JSP attributes such as
criteria,statuses,overdueStatus,maxRenewals,borrowRecords,formValues,errors,errorMessage, andsuccessMessage. - JSP pages render JavaBean properties only; they must not call DAOs or embed SQL.
4. Validation & Error Matrix
- Missing reader ID or book ID -> return to
borrowing/form.jspwith field errors. - Unknown reader -> field error on
readerIdentifier. - Inactive or suspended reader -> field error on
readerIdentifier. - Reader at or above
max_borrow_countactive loans -> field error onreaderIdentifier. - Unknown book -> field error on
bookIdentifier. - Unavailable, archived, or zero-copy book -> field error on
bookIdentifier. - Missing or non-positive record ID for return/renew -> flash error.
- Returning or renewing a returned loan -> validation failure on
status. - Renewing after the renewal limit -> validation failure on
renewalCount. - DAO/transaction failure -> log server-side details and return
Borrowing service is temporarily unavailable. Please try again later.
5. Good/Base/Bad Cases
- Good: a librarian creates a loan for active reader
RD-1000and available bookBK-1000; the loan appears in/borrowingand book availability is decremented. - Base:
/borrowing?status=overduelists active, non-returned loans past due without requiring a scheduler or stored overdue status. - Bad: a Servlet updates
books.available_copiesoutside the borrowing transaction or a JSP issues SQL to filter loan records.
6. Tests Required
- Run
BorrowingServiceCheckassertions for permission denial, inactive readers, unavailable/no-copy books, max active loan count, successful borrow, return inventory restoration, one-renewal limit, overdue search, reader loan history, and DAO failure fallback. - Run
PermissionPolicyCheckto confirm readers haveBORROW_BOOKS, readers lackMANAGE_BORROWING, and librarians lack reader self-borrow permission. Service or filter checks should also confirm staff use/borrowing, not the reader-only/reader/loanshistory route. - Scan JSPs for scriptlets and SQL/JDBC references.
- When Maven/Tomcat dependencies are installed, run
mvn clean packageto compile Servlets and package JSP resources.
7. Wrong vs Correct
Wrong
borrowing/manage.jsp -> JDBC -> UPDATE books SET available_copies = ...
Correct
borrowing/form.jsp -> BorrowingManagementServlet -> BorrowingService -> BorrowRecordDao -> borrow_records + books in one transaction
Scenario: Report Center Slice
1. Scope / Trigger
- Trigger: the report center adds staff-only operational reporting across
books,readers, andborrow_recordswithout adding report tables. - Schema path:
src/main/resources/db/schema.sql. - JSP path:
WEB-INF/jsp/reports/dashboard.jsp.
2. Signatures
- Entity signatures:
InventorySummary(totalTitles, totalCopies, availableCopies, unavailableOrEmptyTitles).BorrowingSummary(activeLoans, returnedLoans, overdueLoans).OverdueReportRow(readerIdentifier, readerName, bookIdentifier, bookTitle, dueAt, overdueDays).PopularBookReportRow(bookIdentifier, title, author, borrowCount).ReportCenter(inventorySummary, borrowingSummary, overdueRows, popularBooks).
- DAO signatures:
ReportDao.loadInventorySummary(),loadBorrowingSummary(),findOverdueRows(), andfindPopularBooks(int limit). - Service signature:
ReportService.loadReportCenter(AuthenticatedUser actor)returningServiceResult<ReportCenter>. - Servlet route:
GET /reports. - Protected permission:
/reportsrequiresVIEW_REPORTS.
3. Contracts
- Report data is read-only and derived from existing
books,readers, andborrow_recordsrows; do not introduce aggregate/cache tables for the MVP. unavailableOrEmptyTitlescounts book rows wherebooks.statusis notavailableorbooks.available_copies <= 0.activeLoanscounts active borrow rows wherereturned_at IS NULL.returnedLoanscounts rows withstatus = returned.overdueLoansand overdue rows use the derived rulestatus = active AND returned_at IS NULL AND due_at < CURRENT_TIMESTAMP.- Popular book ranking groups by book and orders by borrow record count descending, with a service/DAO limit for the top rows.
ReportServletsets thereportCenterrequest attribute on success anderrorMessageon safe service failure.- JSP pages render JavaBean properties only; they must not call DAOs or embed SQL.
- Dashboard, role-home, and header navigation should expose reports only to administrator/librarian users.
4. Validation & Error Matrix
- Missing or unauthenticated actor ->
You do not have permission to view reports. - Reader actor ->
You do not have permission to view reports. - DAO failure while loading any report section -> log server-side details and
return
Report service is temporarily unavailable. Please try again later. - Empty overdue list -> render a stable empty state, not an error.
- Empty popular ranking -> render a stable empty state, not an error.
5. Good/Base/Bad Cases
- Good: a librarian opens
/reportsand sees inventory totals, borrowing counts, active overdue rows, and top borrowed books. - Base: no borrowing records exist; summaries show zero counts and tables show empty states.
- Bad: a reader reaches
/reports, a JSP performsSELECTqueries directly, or report queries update inventory/borrow state.
6. Tests Required
- Run
ReportServiceCheckassertions for reader denial, librarian success, report section composition, and DAO failure fallback. - Run
PermissionPolicyCheckto confirm administrator/librarian roles allowVIEW_REPORTSand readers do not. - Scan report JSPs for scriptlets and SQL/JDBC references.
- When Maven/Tomcat dependencies are installed, run
mvn clean packageto compile Servlets and package JSP resources.
7. Wrong vs Correct
Wrong
reports/dashboard.jsp -> JDBC -> SELECT COUNT(*) FROM borrow_records
Correct
reports/dashboard.jsp <- ReportServlet <- ReportService <- ReportDao <- books/readers/borrow_records
Scenario: Login And Permission Scaffold Schema
1. Scope / Trigger
- Trigger: the initial Java Web scaffold introduced a concrete MySQL schema and login contract.
- Schema path:
src/main/resources/db/schema.sql. - Example configuration path:
src/main/resources/db.properties.example.
2. Signatures
- DAO signature:
UserDao.findActiveByUsername(String username). - Service signature:
AuthService.authenticate(String username, String password). - Permission signature:
AuthService.hasPermission(AuthenticatedUser user, Permission permission). - Servlet route:
POST /loginwithusername,password, and optional same-applicationredirect. - Protected routes:
/dashboard,/admin/home,/librarian/home, and/reader/home. - Session keys:
authenticatedUser,userRole, anduserPermissions. - DB config keys:
db.driver,db.url,db.username, anddb.password. - Login tables:
roles,permissions,role_permissions,users, andsystem_logs.
3. Contracts
users.username: unique login identifier submitted byLoginServlet.users.password_hash: PBKDF2 hash inpbkdf2_sha256$iterations$saltBase64$hashBase64format.- Local scaffold demo users must have documented, known initial passwords for
new deployments:
admin/admin123,librarian/librarian123, andreader/reader123. Theirschema.sqlhashes must verify throughPasswordHasher.verifyand must be treated as local/demo-only credentials, never production credentials. schema.sqlusesINSERT IGNOREfor demousersrows. Replaying the schema must not be assumed to reset existing account passwords; README reset guidance must call this out explicitly.users.role_code: foreign key toroles.code; supported scaffold values areadministrator,librarian, andreader.users.active: only rows withactive = 1can authenticate.roles.code,permissions.code, androle_permissionsmust match the JavaRoleandPermissionenum codes exactly.db.propertiesmust be local configuration. Commitdb.properties.example, but do not commit real credentials.- Session state stores an
AuthenticatedUsersnapshot, role code, and permission-code set. It must not store raw passwords or DAO result objects with password hashes. - Login redirects must stay inside the current application context. Reject
values that do not start with a single
/or that contain CR/LF characters.
4. Validation & Error Matrix
- Missing username or password -> request returns to login JSP with
Username and password are required. - Unknown user, inactive user, or hash mismatch -> request returns to login JSP
with
Invalid username or password. - Unsafe or blank redirect -> ignore and route to
/dashboardafter success. - Missing
db.properties, JDBC failure, or unsupported role code -> request returns a generic service-unavailable message and logs server-side details. - Authenticated user missing a required permission -> HTTP 403 and
WEB-INF/jsp/auth/unauthorized.jsp.
5. Good/Base/Bad Cases
- Good:
adminresolves toadministrator, receives all scaffold permissions, and can access/admin/home. - Base:
readerresolves toreader, can access/reader/home, and cannot access/admin/home. - Bad: a JSP reads SQL or password hashes directly from the database. Keep that logic in DAO/service code.
6. Tests Required
- Compile service/DAO/entity/util classes with
javacwhen Maven is unavailable. - Run
PermissionPolicyCheckor equivalent assertions for administrator, librarian, and reader permissions. - Run
AuthServiceCheckor equivalent assertions for required-field failures, invalid credentials, success, permission checks, and DAO failure fallback. - When Maven/Tomcat dependencies are installed, run
mvn testormvn clean packageto compile Servlet and JSP integration.
7. Wrong vs Correct
Wrong
// JSP, Servlet, or session code opens JDBC and stores password_hash.
Correct
login.jsp -> LoginServlet -> AuthService -> UserDao -> users/roles tables
session -> AuthenticatedUser snapshot + role/permission codes only