Changes between Initial Version and Version 1 of AdvancedApplicationDevelopment


Ignore:
Timestamp:
07/03/26 14:28:29 (7 days ago)
Author:
223091
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AdvancedApplicationDevelopment

    v1 v1  
     1= Advanced Application Development =
     2
     3This page documents the advanced application development implemented for Phase P8 of the Room Reservation System project. The goal of this phase is to extend the Java prototype application with transaction handling and database connection pooling.
     4
     5The prototype was extended in two main directions:
     6
     7* multi-operation database transactions were added for scenarios where several related database changes must be executed as one unit of work;
     8* database connection pooling was added using HikariCP, so the application does not create a new database connection manually for every operation.
     9
     10The implementation affects the following source files:
     11
     12* ''src/main/java/mk/finki/roomreservation/App.java''
     13* ''src/main/java/mk/finki/roomreservation/DatabasePool.java''
     14* ''pom.xml''
     15
     16The application still connects to the same PostgreSQL database schema named ''project'' through the SSH tunnel on ''localhost:9999''.
     17
     18== Database Connection Pooling ==
     19
     20=== Description ===
     21
     22In the previous prototype version, the application used a direct JDBC connection. In Phase P8, the application was changed to use a database connection pool.
     23
     24Connection pooling is useful because database connections are expensive to create and close repeatedly. Instead of creating a new physical connection for every database operation, the application initializes a pool of reusable connections. The application then requests a connection from the pool, uses it for the current operation, and returns it to the pool automatically when the operation finishes.
     25
     26The connection pool is implemented in the class:
     27
     28{{{
     29src/main/java/mk/finki/roomreservation/DatabasePool.java
     30}}}
     31
     32The application initializes the pool after the user enters the database URL, database username, and database password. The pool is then used by the main application class when executing the implemented use-cases.
     33
     34=== Implementation ===
     35
     36The application uses HikariCP as the connection pooling library. The dependency is included in the Maven configuration file ''pom.xml''.
     37
     38The pool is initialized with the database connection parameters and a pool name. The console output confirms that the pool is started successfully.
     39
     40[[Image(p8_connection_pool_initialized.png, width=100%)]]
     41
     42The important result shown in the screenshot is that the application no longer connects only through a single direct JDBC connection. Instead, it initializes the connection pool first and then successfully connects to the database.
     43
     44The application displays:
     45
     46{{{
     47Database connection pool initialized successfully.
     48
     49Connected to database successfully.
     50}}}
     51
     52After the pool is initialized, the main menu is displayed:
     53
     54{{{
     55Main menu
     56
     571. Search available rooms
     582. Create reservation request
     593. Approve or reject reservation
     604. Exit
     61   Choose option:
     62   }}}
     63
     64=== Usage in the application ===
     65
     66The application uses connections from the pool when executing database operations. The connection is obtained from the pool, used inside the selected use-case, and then closed in the Java code. Closing the connection does not close the physical database connection immediately; it returns the connection to the pool so that it can be reused.
     67
     68This is used in the implemented use-cases:
     69
     70* ''Search available rooms''
     71* ''Create reservation request''
     72* ''Approve or reject reservation''
     73
     74== Transactions ==
     75
     76Transactions are needed when one logical application operation modifies multiple related database tables. If one part of the operation succeeds and another part fails, the database must not remain in a partially modified state.
     77
     78The Java application therefore uses explicit transaction control for the use-cases where several related database operations are executed together.
     79
     80The transaction logic follows this structure:
     81
     82{{{
     83connection.setAutoCommit(false);
     84
     85try {
     86// execute several related SQL statements
     87connection.commit();
     88} catch (SQLException e) {
     89connection.rollback();
     90throw e;
     91} finally {
     92connection.setAutoCommit(true);
     93}
     94}}}
     95
     96This means that all database changes inside the transaction are saved only if the whole operation is successful. If an error occurs, all changes from that transaction are rolled back.
     97
     98== Transaction 1: Create reservation request ==
     99
     100=== Data requirements description ===
     101
     102Creating a reservation request can require changes in more than one table.
     103
     104A reservation request may include:
     105
     106* only a room;
     107* only requested equipment;
     108* both a room and requested equipment.
     109
     110When the requester creates a reservation with additional equipment, the application must insert a new record into:
     111
     112* ''project.reservations''
     113
     114and then insert one or more related records into:
     115
     116* ''project.reservation_equipment''
     117
     118These operations must be executed in one transaction. If the reservation is inserted successfully, but the equipment insert fails, the whole operation must be rolled back. Otherwise, the database could contain an incomplete reservation.
     119
     120=== Implementation ===
     121
     122The transaction is implemented in the ''Create reservation request'' use-case in ''App.java''.
     123
     124The application performs the following steps:
     125
     1261. The requester is selected from the displayed list of users.
     1272. The reservation date, start time, and end time are entered.
     1283. The requester chooses whether the reservation includes a room.
     1294. If a room is included, the application displays available rooms and the requester selects one of them.
     1305. The requester chooses whether additional/general equipment should be requested.
     1316. If equipment is requested, the application displays available equipment and the requester selects equipment items and quantities.
     1327. The application starts a transaction.
     1338. The application inserts the reservation into ''project.reservations''.
     1349. If requested equipment exists, the application inserts the related rows into ''project.reservation_equipment''.
     13510. If all SQL statements are successful, the transaction is committed.
     13611. If any SQL statement fails, the transaction is rolled back.
     137
     138=== Demo execution ===
     139
     140The following screenshot shows the creation of a reservation request with additional equipment.
     141
     142[[Image(p8_transaction_create_reservation_input.png, width=100%)]]
     143
     144In this test, the requester creates a reservation for room ''LAB-1'' on ''2026-06-01'' from ''09:00'' to ''10:00'' and additionally requests ''HDMI Cable''.
     145
     146The following screenshot shows that the reservation request was created successfully.
     147
     148[[Image(p8_transaction_create_reservation_success.png, width=100%)]]
     149
     150The application displays the generated reservation ID and the created reservation details.
     151
     152=== Database verification ===
     153
     154The result can be verified in DBeaver by checking the base tables.
     155
     156{{{
     157SELECT *
     158FROM project.reservations
     159ORDER BY reservation_id DESC;
     160
     161SELECT *
     162FROM project.reservation_equipment
     163ORDER BY reservation_id DESC;
     164}}}
     165
     166The following screenshot shows that the reservation was inserted into ''project.reservations'' and that the requested equipment was inserted into ''project.reservation_equipment''.
     167
     168[[Image(p8_transaction_create_reservation_db_verification.png, width=100%)]]
     169
     170=== Transaction discussion ===
     171
     172This operation is a transaction because the reservation and the requested equipment represent one logical request. The database should not contain requested equipment without the corresponding reservation, and it should not contain a partially created reservation if the equipment insert fails.
     173
     174Therefore, the application commits the transaction only after all related inserts are successful.
     175
     176== Transaction 2: Approve or reject reservation ==
     177
     178=== Data requirements description ===
     179
     180Approving or rejecting a reservation also requires more than one database change.
     181
     182When an approver makes a decision, the application must:
     183
     184* update the status of the selected reservation in ''project.reservations'';
     185* insert the approval decision into ''project.approvals''.
     186
     187These two operations must be executed consistently. The reservation status and the approval record must always match. If the approval record cannot be inserted, the reservation status should not remain changed.
     188
     189=== Implementation ===
     190
     191The transaction is implemented in the ''Approve or reject reservation'' use-case in ''App.java''.
     192
     193The application performs the following steps:
     194
     1951. The approver opens the ''Approve or reject reservation'' option from the main menu.
     1962. The application lists all pending reservations.
     1973. The approver selects a reservation from the displayed list.
     1984. The application lists users who are allowed to approve reservations.
     1995. The approver selects the approving user.
     2006. The approver chooses either ''approved'' or ''rejected''.
     2017. The approver enters an optional decision note.
     2028. The application starts a transaction.
     2039. The application updates the reservation status in ''project.reservations''.
     20410. The application inserts a new approval record into ''project.approvals''.
     20511. If both operations are successful, the transaction is committed.
     20612. If an error occurs, the transaction is rolled back.
     207
     208=== Demo execution ===
     209
     210The following screenshot shows the approval process in the Java prototype.
     211
     212[[Image(p8_transaction_approve_reservation_input.png, width=100%)]]
     213
     214The approver selects a pending reservation, selects the approving user, chooses the decision, and enters the decision note.
     215
     216The following screenshot shows the successful result of the approval transaction.
     217
     218[[Image(p8_transaction_approve_reservation_success.png, width=100%)]]
     219
     220The application displays the final reservation details, including the updated status, decision, decision time, and approver.
     221
     222=== Database verification ===
     223
     224The result can be verified in DBeaver by checking the reservations and approvals tables.
     225
     226{{{
     227SELECT *
     228FROM project.reservations
     229ORDER BY reservation_id DESC;
     230
     231SELECT *
     232FROM project.approvals
     233ORDER BY approval_id DESC;
     234}}}
     235
     236The following screenshot shows that the reservation status was updated and that the corresponding approval record was inserted.
     237
     238[[Image(p8_transaction_approve_reservation_db_verification.png, width=100%)]]
     239
     240=== Transaction discussion ===
     241
     242This operation is a transaction because approval is not just one table change. The reservation status and approval decision must be saved together. If only the reservation status were updated without inserting an approval record, the database would lose information about who made the decision and when it was made.
     243
     244Therefore, the application treats the approval operation as one atomic unit of work.
     245
     246== Rollback behavior ==
     247
     248The transaction implementation also protects the database from partial changes. If an error happens during a transaction, the application executes rollback.
     249
     250For example, in the create reservation transaction, if the reservation insert succeeds but a related requested equipment insert fails, the reservation should not remain saved as an incomplete request. Similarly, in the approval transaction, if the reservation status update succeeds but the approval insert fails, the status update should be rolled back.
     251
     252This behavior is important because it preserves database consistency.
     253
     254[[Image(p8_transaction_rollback_test.png, width=100%)]]
     255
     256The screenshot above demonstrates that an invalid or failing operation does not leave incomplete data in the database.
     257
     258== Maven configuration ==
     259
     260The Maven configuration file ''pom.xml'' was updated to include the required dependencies for PostgreSQL JDBC and HikariCP.
     261
     262The PostgreSQL JDBC driver is required so the Java application can connect to the PostgreSQL database.
     263
     264HikariCP is required so the application can use database connection pooling.
     265
     266The relevant configuration is stored in:
     267
     268{{{
     269pom.xml
     270}}}
     271
     272== Final discussion ==
     273
     274Phase P8 improves the Java prototype by adding application-level transaction handling and database connection pooling.
     275
     276The most important improvements are:
     277
     278* the application uses a reusable connection pool instead of relying on a single direct JDBC connection;
     279* the connection pool is initialized once and then reused by the implemented use-cases;
     280* creating a reservation request is executed as a transaction;
     281* inserting requested equipment for a reservation is included in the same transaction as the reservation insert;
     282* approving or rejecting a reservation is executed as a transaction;
     283* reservation status updates and approval record inserts are saved together;
     284* rollback is used when a multi-step operation fails;
     285* database consistency is preserved even when a use-case requires several SQL statements.
     286
     287These improvements make the prototype more reliable and closer to a real database application, while still keeping the application intentionally simple for the project phase.