0

I have had a good look in books and the internet but cannot find a solution to my specific problem.Im really worried as time is running out.

I am writing code for an account. Each transaction, if it is add or withdraw is an object. Information such as the add amount, withdraw amount, transaction number,balance and total spending in a particular category is an object. Each object is stored in an arrayList. There is also code for logging in because this will eventually be an app. It requires the user to input their student number(last 4 digits).

The code runs ok and it serializes on termination. Upon running the code i can see it has de serialized the file as there is a list of objects in the arrayList printed.

My problem is that the values such as student number and balance are 0 when the code runs.Also the transaction number does not increment. It does increment while the code runs but stops upon termination, starting at 1 when the code is run again.

I expected all values to be the same when de serailized as those in the last object in the arrayList before serialization.

I dont expect anyone to post the answer but if someone could point me in the right direction i could try to work it out myself.

Best regards

Richard

PS. transaction number is the first in the object, balance in the middle and student number the four digits at the end. I have added the main class and serialization class, if anyone wants to see the login, transaction or other classes i can post these too.

`

    /**
     * Created by Richard on 16/07/2014.
     */
    public class AccountTest implements Serializable {

        public static Scanner keyboard = new Scanner(System.in);
        //Declare an ArrayList called 'transactions' which will hold instances of AccountInfo.
        public static ArrayList transactions = new ArrayList<AccountInfo>();
        //Declare and initiate variables relating to the AccountTest class.
        private static int transactionNum = 0;
        private static double depositAmount = 0;
        public static double withdrawAmount = 0;
        private static double currentBalance = 0;

        // A method which prompts the user to either withdraw, add funds or quit,
        //this method also updates the balance and transaction number.
        public static void addOrSpend() {
            do {//A do while loop to ensure that the method repeatedly asks the user for input.
                System.out.println("Enter a 1 to deposit, 2 to withdraw, 3 to terminate:");
                int choice = keyboard.nextInt();

                if (choice == 1) {//The deposit choice that also sets transaction no. and the balance.
                    System.out.println("Enter an amount to deposit ");
                    depositAmount = keyboard.nextInt();
                    transactionNum = transactionNum + 1;
                    withdrawAmount = 0;
                    currentBalance = currentBalance + depositAmount;
                    //System.out.println("You entered: " + depositAmount);
                }//if

                if (choice == 2) {//The withdraw choice that also sets transaction num, balance and calls chooseCategory method.
                    System.out.println("Enter an amount to withdraw ");
                    withdrawAmount = keyboard.nextInt();
                    transactionNum = transactionNum + 1;
                    depositAmount = 0;
                    currentBalance = currentBalance - withdrawAmount;
                    AccountCategory.chooseCategory();
                }//if

                if (choice == 3) {//User option to quit the program.
                    AccountSerialize.serialize();
                    System.out.println("App terminated...");
                    System.exit(1);
                }//if

                AccountInfo acc = new AccountInfo();//creates an object of the AccountInfo class


                //Setters for the various methods in the AccountInfo class,
                // these initiate variables for instances of the class.

                acc.setTransactionNum(transactionNum);
                acc.setDepositAmount(depositAmount);
                acc.setWithdrawAmount(withdrawAmount);
                acc.setCurrentBalance(currentBalance);
                acc.setAccommodation(AccountCategory.accommodation);
                acc.setTransport(AccountCategory.transport);
                acc.setUtilities(AccountCategory.utilities);
                acc.setEntertainment(AccountCategory.entertainment);
                acc.setEssentials(AccountCategory.essentials);
                acc.setStudentNo(AccountLogin.studentNo);

                transactions.add(acc);//Adds each new 'acc' object to the ArrayList 'transaction'.
                //System.out.println("List:" + transactions);Unused print statement which shows contents of ArrayList for testing.

                Formatter x = new Formatter();//Series of formatted print statements which allow the information to be displayed in tabular format with headings.
                System.out.println(String.format("%-20s %-20s %-20s %-20s ", "Transaction No.", "Deposit amount", "Withdraw amount", "Current balance"));
                System.out.println(String.format("%-20s %-20s %-20s %-20s", transactionNum, depositAmount, withdrawAmount, currentBalance));
                System.out.println(String.format("%-20s %-20s %-20s %-20s %-20s ", "Accommodation", "Transport", "Utilities", "Entertainment", "Essentials"));
                System.out.println(String.format("%-20s %-20s %-20s %-20s %-20s", AccountCategory.accommodation, AccountCategory.transport, AccountCategory.utilities,
                        AccountCategory.entertainment, AccountCategory.essentials));

            } while (transactions.size() >= 0);//End of do while statement that repeatedly prompts the user.
        }

        //Main method from where the program starts and user logs in. Starts with request for user to login.
        // This then allows the user to continue with the program.
        public static void main(String args[]) {
            AccountSerialize.deSerialize();

            System.out.println("Testing to see if student num is saved, login is..." +AccountLogin.studentNo );
            System.out.println("Testing to see if balance is saved, balance is..." +currentBalance );
            if (AccountLogin.studentNo == 0)
            {
                AccountLogin.numberSave();
            }
            else
            {
                AccountLogin.login();
            }

        }//main
    }//class AccountTest


    import java.io.*;
    import java.util.ArrayList;
    import java.util.List;

    /**
     * Created by Richard on 24/07/2014.
     */
    public class AccountSerialize {

        public static String filename = "budgetApp.bin";
        public static String tmp;

        public static void serialize() {
            try {
                FileOutputStream fos = new FileOutputStream("budgetApp.bin");
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                oos.writeObject(AccountTest.transactions);
                oos.close();
                fos.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
            System.out.println("Done writing");
        }//serialize()

       public static void deSerialize(){
            try
            {
                FileInputStream fis = new FileInputStream("budgetApp.bin");
                ObjectInputStream ois = new ObjectInputStream(fis);
                AccountTest.transactions = (ArrayList) ois.readObject();
                ois.close();
                fis.close();
            }catch(IOException ioe){
                ioe.printStackTrace();
                return;
            }catch(ClassNotFoundException c){
                System.out.println("Class not found");
                c.printStackTrace();
                return;
            }
            for( Object tmp:AccountTest.transactions){
                System.out.println(tmp);
            }

        }//deSerialize()
    }//class

import java.util.Scanner;

/**
 * Created by Richard on 22/07/2014.
 */
public class AccountCategory {

    static Scanner keyboard = new Scanner(System.in);

    //Declare and initiate variable to be used in this class.
    public static double accommodation = 0;
    public static double transport = 0;
    public static double utilities = 0;
    public static double entertainment = 0;
    public static double essentials = 0;

    //A method which prints a set of spending category choices and asks the user to choose.
    //Also updates each category variable with the total amount spent in that category
    public static void chooseCategory() {

        System.out.println("Please choose a category of spending, enter corresponding number");
        System.out.println("1:\tAccommodation \n2:\tTransport \n3:\tUtilities \n4:\tEntertainment " +
                "\n5:\tEssentials ");

        double choice = keyboard.nextInt();//User input.

        if (choice == 1) {
            accommodation = accommodation + AccountTest.withdrawAmount;
        }//if
        if (choice == 2) {
            transport = transport + AccountTest.withdrawAmount;
        }//if
        if (choice == 3) {
            utilities = utilities + AccountTest.withdrawAmount;
        }//if
        if (choice == 4) {
            entertainment = entertainment + AccountTest.withdrawAmount;
        }//if
        if (choice == 5) {
            essentials = essentials + AccountTest.withdrawAmount;
        }//if

    }//chooseCategory

}//Class AccountCategory


import java.io.Serializable;
import java.util.Scanner;

/**
 * Created by Richard on 16/07/2014.
 */
public class AccountInfo implements Serializable {

    //Declare variables for types of transaction, balance and categories of spending.
    public int studentNo;
    public int transactionNum;
    public double depositAmount;
    public double withdrawAmount;
    public double currentBalance;
    public double accommodation;
    public double transport;
    public double utilities;
    public double entertainment;
    public double essentials;

    //Series of mutator methods which take and validate the user input from the Test class, setting new variable values
    //for objects of this AccountInfo class.
    public void setStudentNo(int studentNo) {
        this.studentNo = studentNo;
    }

    public void setTransactionNum(int transactionNum) {
        this.transactionNum = transactionNum;
    }

    public void setDepositAmount(double depositAmount) {
        this.depositAmount = depositAmount;
    }

    public void setWithdrawAmount(double withdrawAmount) {
        this.withdrawAmount = withdrawAmount;
    }

    public void setCurrentBalance(double currentBalance) {
        this.currentBalance = currentBalance;
    }

    public void setAccommodation(double accommodation) {
        this.accommodation = accommodation;
    }

    public void setTransport(double transport) {
        this.transport = transport;
    }

    public void setUtilities(double utilities) {
        this.utilities = utilities;
    }

    public void setEntertainment(double entertainment) {
        this.entertainment = entertainment;
    }

    public void setEssentials(double essentials) {
        this.essentials = essentials;
    }

    //A toString method to ensure printed information is user readable
    public String toString() {
        return "AccountInfo[" + transactionNum + "," + depositAmount + "," + withdrawAmount + "," + currentBalance + "," +
                accommodation + "," + transport + "," + utilities + "," + entertainment + "," + essentials + ","+studentNo+"]";
    }//toString

}//class AccountInfo


import java.util.InputMismatchException;
import java.util.Scanner;

/**
 * Created by Richard on 20/07/2014.
 */
public class AccountLogin {

    public static Scanner keyboard = new Scanner(System.in);

    //Declare and initiate variables.
    public static int studentNo=0;
    public static int login=0;

    public static void login() {
        if (studentNo > 0 && Integer.toString(studentNo).length() == 4)//Validation test.
        {
                System.out.println("Log in with last four digits of your student number:");
                 login = keyboard.nextInt();//User input.
            }//if
        if(login==studentNo){
            AccountTest.addOrSpend();//If validated
        }//if
        else{
            enterNoAgain();
        }//else
    }//login()

    //This method checks to see if the user has already entered and saved their details, if not the user is prompted to do so.
    //If the user has already entered their details
    public static void numberSave() {

        if (studentNo == 0) {//Checks to see if student number has already been entered.
            System.out.println("Enter and save the last four digits of your student number, use this to login to the Budgeting app:");
            studentNo = keyboard.nextInt();//User input.

            if (studentNo > 0 && Integer.toString(studentNo).length() == 4) {//Checks that user input meets requirements.
                System.out.println("You are now logged in:");
                AccountTest.addOrSpend();//Program starts at this point once user input is validated.
            }//if

            else {//If user input does not meet criteria, the following method is called.
                enterNoAgain();
            }//else
        }//if
    }//numberSave()


    // This method takes over if the user has not input valid data.
    // The user is instructed to do so and is given a further 2 opportunities before the program exits
    public static void enterNoAgain() {

        System.out.println("Invalid input: Use 4 numbers only, try again");//Prompt.
        studentNo = keyboard.nextInt();//User input.
        if (studentNo > 0 && Integer.toString(studentNo).length() == 4) {//Validation test.
            AccountTest.addOrSpend();//If validated
        }//if

        else {
            System.out.println("Last attempt, input last four digits of your student number");//Prompt.
            studentNo = keyboard.nextInt();//User input.
            if (studentNo > 0 && Integer.toString(studentNo).length() == 4) {//Validation test.
                AccountTest.addOrSpend();//If validated
            }//if
            else {
                AccountSerialize.serialize();//Save to file
                System.out.println("You failed to login");
                System.out.println("App terminated...");
                System.exit(1);//Program exits due to invalid user input.
            }//else
        }//else

    }//enterNoAgain()

}//class AccountLogin
 `
AccountTest
AccountInfo[1,1000.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,1234]
AccountInfo[1,1000.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,1234]
AccountInfo[1,50.0,0.0,50.0,0.0,0.0,0.0,0.0,0.0,3333]
AccountInfo[1,50.0,0.0,50.0,0.0,0.0,0.0,0.0,0.0,1234]
AccountInfo[1,1000.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,1234]
AccountInfo[1,1000.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,6666]
AccountInfo[1,1000.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,1234]
AccountInfo[2,0.0,50.0,950.0,50.0,0.0,0.0,0.0,0.0,1234]
AccountInfo[1,1000.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,1234]
AccountInfo[1,500.0,0.0,500.0,0.0,0.0,0.0,0.0,0.0,1234]
AccountInfo[1,1000.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,1234]
AccountInfo[2,0.0,50.0,950.0,0.0,0.0,50.0,0.0,0.0,1234]
AccountInfo[1,1000.0,0.0,1000.0,0.0,0.0,0.0,0.0,0.0,1234]
AccountInfo[2,0.0,50.0,950.0,50.0,0.0,0.0,0.0,0.0,1234]
Testing to see if student num is saved, login is...0
Testing to see if balance is saved, balance is...0.0
Enter and save the last four digits of your student number, use this to login to the Budgeting app:
1234
You are now logged in:
Enter a 1 to deposit, 2 to withdraw, 3 to terminate:
1
Enter an amount to deposit 
1000
Transaction No.      Deposit amount       Withdraw amount      Current balance      
1                    1000.0               0.0                  1000.0              
Accommodation        Transport            Utilities            Entertainment        Essentials           
0.0                  0.0                  0.0                  0.0                  0.0                 
Enter a 1 to deposit, 2 to withdraw, 3 to terminate:
2
Enter an amount to withdraw 
50
Please choose a category of spending, enter corresponding number
1:  Accommodation 
2:  Transport 
3:  Utilities 
4:  Entertainment 
5:  Essentials 
1
Transaction No.      Deposit amount       Withdraw amount      Current balance      
2                    0.0                  50.0                 950.0               
Accommodation        Transport            Utilities            Entertainment        Essentials           
50.0                 0.0                  0.0                  0.0                  0.0                 
Enter a 1 to deposit, 2 to withdraw, 3 to terminate:
3
Done writing
App terminated...

Process finished with exit code 1
Richard74
  • 11
  • 4
  • 2
    Please include the definition of AccountInfo; it would help us if the code supplied was runnable and self contained. – Chris K Aug 06 '14 at 08:47
  • Consider providing a [runnable example](https://stackoverflow.com/help/mcve) which demonstrates your problem. This will result in less confusion and better responses – MadProgrammer Aug 06 '14 at 08:48
  • Also take a look at [Java static serialization rules?](http://stackoverflow.com/questions/6429462/java-static-serialization-rules) – MadProgrammer Aug 06 '14 at 08:49
  • Your `AccountTest` doesn't have any instance fields, so you can't expect it to do anything. – Peter Lawrey Aug 06 '14 at 08:53
  • When you `deSerialize` the `AccountInfo` `ArrayList`, you are making no changes to the `transactionNum`, `depositAmount`, `withdrawAmount` or `currentBalance` `static` fields, so they will remain `0`, which is what they were initialized to when you started the program... – MadProgrammer Aug 06 '14 at 08:57
  • I had a look at the Java static serialization rules but do not understand the conversation that went on there. If static variables cannot be serialized then why does my arrayList of objects get save to file? Is the fact that my variable and methods static the problem when de serializing? – Richard74 Aug 06 '14 at 09:24
  • @Richard74, thank you for posting the full code. I have run it and had a read, and I am having a hard time understanding what the problem is. The objects that get serialised out are being correctly read back in. That is the array list AccountTest.transactions, which is the only field that is being written out and read back in. Is your problem the other static fields on AccountTest which are not modified after reading the file budgetApp.bin in? – Chris K Aug 06 '14 at 13:20
  • @Chris K. Many thanks for running the code. Yes I agree that the file containing the arrayList transactions is read back in on running the code. My problem was i didnt understand why student number which is used as login wasnt saved, rather it was 0 which meant that the user has to keep going through the initial entering of their number on running the code, also account balance shows as 0 when i did a test print statement. Bear in mind this will be an app so i need the last balance to be on display on running the app at the start. – Richard74 Aug 07 '14 at 15:58
  • @Chris K, I also meant to add that the transaction number does not increment either. On starting the program it always starts from 0 rather than the number it reached while the code was running last. Thanks. – Richard74 Aug 07 '14 at 16:12
  • @Richard74, in that case your problem is as MadProgrammer described above. You currently only persist the array, the other static variables on the same class are not persisted. You have two options, 1) move away from statics and persist the entire object with denormalised data or 2) remove the denormalised data and add getter methods that fetch the equivalent data directly from the array. – Chris K Aug 07 '14 at 16:17
  • @Chris K. If I undo the static then my program goes red underlined everywhere and im not sure how to fix it. Im not sure what you mean by your 2nd point but it might be easiest for me to do, Could you possibly explain it a bit further? Many thanks – Richard74 Aug 07 '14 at 16:25
  • @Richard74, that is right. Just removing the statics will not be enough by itself. You would have to construct the object and persist/read that containing object in too. – Chris K Aug 07 '14 at 16:38
  • @Richard74, The second approach works by observing that the static fields can all be calculated directly from the array, you could remove the static fields and replace their uses with method calls. Where the method call would go into the array to figure out what the value is. For example, consider 'currentBalance'; a getCurrentBalance() method would have to iterate over every element in the array and sum up the deposits and withdraws. Obviously that uses more CPU than before, so you have a trade off. – Chris K Aug 07 '14 at 16:39
  • At this point I would usually craft an answer with code to demonstrate, however this feels to me like a homework assignment (apologies if it is not, but I cannot tell from here). – Chris K Aug 07 '14 at 16:40
  • @Chris K. Thank you for your time and advice Chris. You are right that this is an assignment, its for final project. I wouldn't expect you to give me the answer though as i need to understand this for my own sanity,(and learn). I appreciate your pointing me in the right direction, considering CPU usage i think the first option might be best, i will have a go and see if i can work this one out. I might have to ask more questions though if thats ok. All the best, Richard – Richard74 Aug 07 '14 at 17:12
  • I was able to figure this one out. I created another 'acc' object under the main method straight after the call to de serialize. I created a 'lastAcc' object which i made equal to the last object in the de serialized arrayList. I made 'acc' equal to 'lastAcc' then made all the variables equal to the variables in 'acc'. Everthing works, on startup balance and transaction number are as they were before termination. I know this is probably a clumsy way to do it and i still dont fully understand the reasons not to have the whole program as static but at this stage i need to move on. – Richard74 Aug 08 '14 at 11:20

0 Answers0