HUMAN ERROR. THE CODE BELOW DOES NOT HAVE ERROR
Moderators: Please remove this. If possible, please send 25 of my reputation to Peter Lawrey as he has helped me a lot, even reading through thick stacks of log data. Thanks!
Hi I’m having trouble with a Serializable database.
After closing the program (through the logout button), the database is supposed to be stored. This is the code:
FileOutputStream f_out = null;
try {
f_out = new FileOutputStream("database.data");
ObjectOutputStream obj_out = new ObjectOutputStream(f_out);
obj_out.writeObject(database);
System.out.println("Stored!");
} catch (Exception ex) {
Logger.getLogger(BankMainFrameGUI.class.getName()).log(Level.SEVERE, null, ex);
JOptionPane.showMessageDialog(null, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
} finally {
try {
f_out.close();
} catch (IOException ex) {
Logger.getLogger(BankMainFrameGUI.class.getName()).log(Level.SEVERE, null, ex);
JOptionPane.showMessageDialog(null, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
new BankMainFrameGUI();
this.dispose();
The database is then restored upon login with this code:
try {
FileInputStream f_in = new FileInputStream("database.data");
ObjectInputStream obj_in = new ObjectInputStream(f_in);
database = (BankSystem) obj_in.readObject();
System.out.println("FOUND!");
} catch (Exception e) {
System.out.println("New database!");
database = new BankSystem();
}
The database and all its internal classes have been set to be serializable. However, upon restarting the program, all data is lost (of clients, accounts, transactions). However, the database is still detected as a “Found!” statement is shown in my compiler’s CLI, but not the “New database!” statement.
I used both linked lists and array lists.
Thank you so much! I will up-rate all workable solutions.
SPOILER: LOTS OF POSSIBLY UNNECESSARY INFORMATION
Extra information if required:
Main BankSystem() constructor + important variables:
public class BankSystem implements Serializable {
Transaction transactionManager;
Identity identityManager;
Account accountManager;
dayFirstTransaction dayFirstTransactionManager;
public BankSystem() {
transactionManager = new Transaction();
identityManager = new Identity();
accountManager = new Account();
dayFirstTransactionManager = new dayFirstTransaction();
}
...
Example of a LinkedList node:
class Transaction implements Serializable { //Database for TransactionNode
TransactionNode lastTransaction = null;
long lastTransactionId = -1;
//Unchangable location settings defined. Prevents ability to manipulate timestamp by changing computer clock. Acts as a security feature.
//Timestamps are also finalised to ensure security (prevent manipulation)
final TimeZone tz = TimeZone.getTimeZone("Singapore");
final Locale lc = new Locale("en", "SG");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS EEEE");
final private Calendar cal = Calendar.getInstance(tz, lc);
public long newTransaction(dayFirstTransaction dFTM,
Client identity, AccountNode account, boolean action, long actionAmount,
String location, String comments) throws IOException {
//Setting timings
long timeMilli = cal.getTimeInMillis();
String timeStamp = dateFormat.format(cal.getTime());
TransactionNode previous = lastTransaction;
TransactionNode previousUserTransaction = account.GetLastTransaction();
long transactionId = ++lastTransactionId;
long initialBalance = account.getBalance();
long finalBalance;
if(action) {
finalBalance = initialBalance + actionAmount;
} else {
if(initialBalance < actionAmount) throw new IOException("There is not enough funds present in account " + account.accountId + ". \nAvailable balance: $" + account.getBalance());
finalBalance = initialBalance - actionAmount;
}
lastTransaction = new TransactionNode(previous, previousUserTransaction, timeMilli, timeStamp,
transactionId, identity, account, action, actionAmount,
initialBalance, finalBalance, location, comments);
dFTM.checkTransaction(lastTransaction);
account.setLastTransaction(lastTransaction);
return transactionId;
}
public void newTransaction (dayFirstTransaction dFTM, long timeMilli, String timeStamp,
Client identity, AccountNode account, boolean action, long actionAmount,
long initialBalance, long finalBalance, String location, String comments) throws IOException {
TransactionNode previous = lastTransaction;
TransactionNode previousUserTransaction = account.GetLastTransaction();
long transactionId = ++lastTransactionId;
lastTransaction = new TransactionNode(previous, previousUserTransaction, timeMilli, timeStamp,
transactionId, identity, account, action, actionAmount,
initialBalance, finalBalance, location, comments);
dFTM.checkTransaction(lastTransaction);
account.setLastTransaction(lastTransaction);
}
...
And the node for this linked list:
class TransactionNode implements Serializable {
//Node direction pointers
final private TransactionNode previous;
final private TransactionNode previousUserTransaction;
//Declarations
//For action:
final public boolean CREDIT = true;
final public boolean DEBIT = false;
//Variables for each transaction
final public long timeMilli; //Automated. For time comparisons
final public String timeStamp;//Automated. For user reference
final public long transactionId; // Automated at Transaction LinkedList
final public Client identity;
final public AccountNode account;
final public boolean action; //true: Credit. false:Debit
final public long actionAmount;
final public long initialBalance;
final public long finalBalance;
final public String location;
final public String comments;
public TransactionNode(TransactionNode previous, TransactionNode previousUserTransaction, long timeMilli, String timeStamp,
long transactionId, Client identity, AccountNode account, boolean action, long actionAmount,
long initialBalance, long finalBalance, String location, String comments) {
this.previous = previous;
this.previousUserTransaction = previousUserTransaction;
this.timeMilli = timeMilli;
this.timeStamp = timeStamp;
this.transactionId = transactionId;
this.identity = identity;
this.account = account;
this.action = action;
this.actionAmount = actionAmount;
this.initialBalance = initialBalance;
this.finalBalance = finalBalance;
this.location = location;
this.comments = comments;
}
//Getters & setters
public TransactionNode getPreviousTransaction() {
return previous;
}
public TransactionNode getPreviousUserTransaction() {
return previousUserTransaction;
}
}
The most likely cause is that you are not closing the stream you wrote to. ObjectOutputStream is buffered and if you close the file it is writing to instead of closing it, you won’t have written all the data and when you try to read it you will get an exception.