[CT414]: Assignment 1 error handling and testing

This commit is contained in:
2025-02-02 18:21:18 +00:00
parent 5cfe0a42a3
commit 66bffe0d85
9 changed files with 54 additions and 12 deletions

View File

@ -1,5 +1,7 @@
package client; package client;
import exceptions.InvalidCredentialsException;
import exceptions.InvalidSessionIDException;
import interfaces.ApplicationForm; import interfaces.ApplicationForm;
import interfaces.ApplicationHandler; import interfaces.ApplicationHandler;
@ -21,14 +23,22 @@ public class ApplicationClient {
System.out.println("ApplicationHandler found in registry"); System.out.println("ApplicationHandler found in registry");
// login // login
long sessionID;
while (true) {
try {
System.out.printf("Enter your username\n> "); System.out.printf("Enter your username\n> ");
String username = scanner.nextLine(); String username = scanner.nextLine();
System.out.printf("Enter your password\n> "); System.out.printf("Enter your password\n> ");
String password = scanner.nextLine(); String password = scanner.nextLine();
long sessionID = handler.login(username, password); sessionID = handler.login(username, password);
System.out.println("Successfully logged in with session ID: " + sessionID); System.out.println("Successfully logged in with session ID: " + sessionID);
break;
} catch (Exception e) {
System.out.println("Username or password incorrect, try again.");
}
}
// download application form // download application form
ApplicationForm form = handler.downloadApplicationForm(sessionID); ApplicationForm form = handler.downloadApplicationForm(sessionID);
@ -52,6 +62,8 @@ public class ApplicationClient {
handler.submitApplicationForm(sessionID, form); handler.submitApplicationForm(sessionID, form);
System.out.println("Successfully submitted application form."); System.out.println("Successfully submitted application form.");
} catch (InvalidSessionIDException e) {
System.out.println("Invalid session ID, exiting...");
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} finally { } finally {

View File

@ -2,7 +2,7 @@ package exceptions;
import java.rmi.RemoteException; import java.rmi.RemoteException;
public class InvalidCredentialsException extends RemoteException { public class InvalidCredentialsException extends Exception {
public InvalidCredentialsException() { public InvalidCredentialsException() {
super("Invalid username or password."); super("Invalid username or password.");
} }

View File

@ -2,7 +2,7 @@ package exceptions;
import java.rmi.RemoteException; import java.rmi.RemoteException;
public class InvalidSessionIDException extends RemoteException { public class InvalidSessionIDException extends Exception {
public InvalidSessionIDException() { public InvalidSessionIDException() {
super("Invalid or expired session ID."); super("Invalid or expired session ID.");
} }

View File

@ -10,6 +10,13 @@ import java.io.*;
public class ApplicationHandlerImpl implements ApplicationHandler { public class ApplicationHandlerImpl implements ApplicationHandler {
private ArrayList<Long> sessions = new ArrayList<Long>(); private ArrayList<Long> sessions = new ArrayList<Long>();
// private method to validate session ids
private boolean isSessionIDValid(long sessionID) {
// check that session is valid and has not expired
// letting session ids expire after 60 seconds for easier testing, a more practical number would be something like 10 minutes
return sessions.contains(sessionID) && ((System.currentTimeMillis()) - sessionID < 6000);
}
@Override @Override
public long login(String username, String password) throws RemoteException, InvalidCredentialsException { public long login(String username, String password) throws RemoteException, InvalidCredentialsException {
// hardcoded username and password (great practice for security) // hardcoded username and password (great practice for security)
@ -21,13 +28,15 @@ public class ApplicationHandlerImpl implements ApplicationHandler {
return sessionId; return sessionId;
} else { } else {
System.out.println("Login failed with user " + username + " and password " + password);
throw new InvalidCredentialsException("Invalid username or password."); throw new InvalidCredentialsException("Invalid username or password.");
} }
} }
@Override @Override
public ApplicationForm downloadApplicationForm(long sessionID) throws RemoteException, InvalidSessionIDException { public ApplicationForm downloadApplicationForm(long sessionID) throws RemoteException, InvalidSessionIDException {
if (sessions.contains(sessionID)) { // check that session is valid and has not expired
if (isSessionIDValid(sessionID)) {
System.out.println("Returning application form for session ID: " + sessionID); System.out.println("Returning application form for session ID: " + sessionID);
return new ApplicationFormV1(); return new ApplicationFormV1();
} else { } else {
@ -37,7 +46,7 @@ public class ApplicationHandlerImpl implements ApplicationHandler {
@Override @Override
public void submitApplicationForm(long sessionID, ApplicationForm applicationForm) throws RemoteException, InvalidSessionIDException { public void submitApplicationForm(long sessionID, ApplicationForm applicationForm) throws RemoteException, InvalidSessionIDException {
if (sessions.contains(sessionID)) { if (isSessionIDValid(sessionID)) {
String filename = applicationForm.getName().replaceAll("\\s", "_") + ".txt"; String filename = applicationForm.getName().replaceAll("\\s", "_") + ".txt";
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) { try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {

View File

@ -14,4 +14,4 @@ $TERM -e java -cp $src_path -Djava.rmi.server.codebase=file:$src_path/ server.Ap
sleep 1 sleep 1
# start client (in a new terminal) # start client (in a new terminal)
$TERM -e java -cp $src_path -Djava.rmi.server.codebase=file:$src_path/ client.ApplicationClient $TERM -e bash -c "java -cp $src_path -Djava.rmi.server.codebase=file:$src_path/ client.ApplicationClient ; zsh"

View File

@ -71,7 +71,8 @@
Assignment 1: Java RMI Assignment 1: Java RMI
\end{center} \end{center}
\hrule \hrule
\medskip
\section{Testing}
To run and test the code, I wrote a short shell script based off those provided in RMI Compute Server Example code provided on Canvas which compiles the code and launches three terminals: one running the \mintinline{shell}{rmiregistry}, one running the \mintinline{java}{ApplicationServer}, and one running the \mintinline{java}{ApplicationClient}. To run and test the code, I wrote a short shell script based off those provided in RMI Compute Server Example code provided on Canvas which compiles the code and launches three terminals: one running the \mintinline{shell}{rmiregistry}, one running the \mintinline{java}{ApplicationServer}, and one running the \mintinline{java}{ApplicationClient}.
@ -97,5 +98,25 @@ The details entered were saved into a file called \verb|Michael_D_Higgins.txt|,
The output file contained all the questions and answers from the application form, as expected. The output file contained all the questions and answers from the application form, as expected.
\subsection{\mintinline{java}{InvalidCredentialsException}}
To test that an appropriate exception was thrown when a user attempted to login with invalid credentials, I tried a few invalid logins.
The desired behaviour, as can be seen in the output screenshot below, was that the \mintinline{java}{ApplicationHandlerImpl} class would throw an \mintinline{java}{InvalidCredentialsException} when the \mintinline{java}{ApplicationClient} invoked its \mintinline{java}{ApplicationHandler.login()} method.
The \mintinline{java}{ApplicationClient} would then handle this exception gracefully, prompting the user to re-enter their login details until they entered valid details.
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{./images/inalidcred.png}
\caption{Failed logins with invalid credentials, handled gracefully }
\end{figure}
\subsection{\mintinline{java}{InvalidSessionIDException}}
Since my \mintinline{java}{ApplicationHandlerImpl} class would reject session IDs older than 60 seconds (the low value being chosen for testing purposes, a more practical value would be, say, 10 minutes), I simply waited 60 seconds after logging in to answer the very last question, ensuring that the form submission method would be invoked with an expired session ID, the desired behaviour (as can be seen in the output below) being that the client would receive an \mintinline{java}{InvalidSessionIDException}, and gracefully terminate the program.
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{./images/invalidsessionid.png}
\caption{Session ID expiring after 60 seconds}
\end{figure}
\end{document} \end{document}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB