Keep the Desk State After Restart

JavaBeginner
Practice Now

Introduction

A lending desk must remember who holds each tool after the application closes. This independent environment provides working borrowing rules and a new desk file, including existing loans and a maintenance tool. Its incomplete storage code currently loses the saved state when loading and does not write changes.

You will map UTF-8 file records to objects and save only valid changes. You should know the object rules from the previous lab; no files from that environment are needed. This is a single-process teaching application, not a database or a guarantee against power loss. Estimated reading and practice time: 45 minutes.

Load the State That Is Actually on Disk

In this step, you will read one ordinary file record, then repair how saved state and borrower relationships become Java objects.

Open the Terminal tab. cd selects this independent lab's folder. Use Ctrl+U to clear an unfinished mistyped shell line. For a file-path error, return here and retry the correct command.

cd /home/labex/project/tool-library

The application provides working object rules but incomplete storage. First use a small practice file to see the five-field format without risking existing loans. mkdir -p creates the practice directory if needed. printf writes a chosen format: \t makes a tab and \n ends the record; > writes its output to the named file, replacing an earlier practice copy. The single quotes keep the shell from changing the format. cp copies the member list beside that file because the application looks for members.tsv next to its desk input. None of these commands changes the real desk.

mkdir -p work
printf 'S01\tSpare drill\tAVAILABLE\t-\tPractice only\n' > work/sample.tsv
cp members.tsv work/members.tsv

Compile the current source. -encoding UTF-8 selects its text encoding, -d out selects compiled output, and *.java selects this folder's Java files. Continue only if compilation succeeds without errors.

javac -encoding UTF-8 -d out *.java

-cp out tells Java where the classes are. -Dfile.encoding=UTF-8 selects runtime text encoding. The practice input is work/sample.tsv; --memory prevents saving this demonstration.

java -Dfile.encoding=UTF-8 -cp out Desk work/sample.tsv --memory

Inside the program, type these lines, pressing Enter after each:

list
borrow S01 M01
list
quit

S01 starts AVAILABLE with borrower -; its loan to M01 is accepted. This ordinary case works even with the incomplete loader because the practice row already has the state the broken code assumes. It cannot prove preservation of existing loans. The practice change disappears when this process closes.

Read the real desk and registered members. cat displays a file without editing it:

cat desk.tsv
cat members.tsv

There are five tab-separated fields: ID, name, enum state, borrower, note. This controlled format permits spaces and UTF-8 text inside fields, but not tabs or newlines. T24 is already borrowed by M03; T25 is borrowed by M02 and has a Cafe workshop note. T23 is under maintenance. These facts must survive loading. Do not edit desk.tsv, members.tsv or the reference folder directly.

Read the prepared storage code:

cat Store.java

Store is the persistence boundary: records become objects in load; objects become records in save. Files.readAllLines reads UTF-8 explicitly. fields(line) checks the format and yields fields f[0] through f[4]. Find the new Tool(...) call: it currently substitutes Tool.State.AVAILABLE and "-" for every row. Predict the effect on T24's borrower and T23's maintenance state. The loop, list, parsing and validation helpers are already prepared; keep them. You do not need to rewrite their HashSet implementation.

Make a source-only backup before editing:

cp Store.java work/Store-before-load.java.txt
nano Store.java

As in the first lab, Ctrl+W searches, Enter confirms the search, arrow keys move, and Backspace corrects characters. Search for Tool tool = new Tool to locate this one constructor call. Edit its state and borrower arguments so it becomes:

            Tool tool = new Tool(f[0], f[1], Tool.State.valueOf(f[2]), f[3], f[4]);

Tool.State.valueOf(f[2]) converts the saved enum name into its enum value; f[3] restores the saved borrower. Keep the ID, name and note arguments, the surrounding loop and all helpers. You are mapping existing information, not inventing a fresh available tool. Save with Ctrl+O, Enter, then exit with Ctrl+X. To discard an unsaved mistake, use Ctrl+X, N. Reopen and search the call to repair a compiler error. If you deliberately need to restart this edit, cp work/Store-before-load.java.txt Store.java restores only this source file; redo the mapping afterward. Never rerun setup to undo edits.

Here throws IOException declares that file access may fail. The command loop prints Cannot continue and stops for missing or malformed input. This is a file problem, not a refused loan. Correct the named path or source mapping; do not empty or rewrite the original records to remove the error.

Compile the saved source and start the real desk. Unlike the demonstration, omit --memory: the real desk will persist valid changes once you complete saving in the next step. A syntax error names the file and line; repair it in nano and compile successfully before launching rather than running old classes.

javac -encoding UTF-8 -d out *.java
java -Dfile.encoding=UTF-8 -cp out Desk desk.tsv

Type these lines inside the desk:

list
members
quit

The list must retain T24 → M03, T25 → M02, T23's MAINTENANCE state and all notes. members shows the registered IDs. Opening and listing must not rewrite the file. quit returns to the shell. The next step completes actual saving; a success message alone would not prove persistence.

Save Valid Changes and Reopen the Desk

In this step, you will make one new loan and one valid return survive a real process exit.

Start at the shell in the same Terminal tab. Saving serializes every current object, including untouched loans and maintenance records. row(tool) joins the five fields with tabs. The loop adds all rows to a list; Files.write writes those lines as UTF-8. The command loop calls save only after a domain method returns normally. A rejected action must not write the data file, including rewriting identical contents.

Read the command framework to connect that rule to the storage boundary:

cat Desk.java

Find found.borrow(c[2]), found.giveBack(c[2]) and the following Store.save(path, tools). A thrown domain exception skips the save call and becomes a normal refusal. Keep this prepared ordering; adding a write to the refusal handler would violate the contract.

Make a source-only backup that retains your corrected loader:

cp Store.java work/Store-before-save.java.txt
nano Store.java

Press Ctrl+W, search for TODO: write all rows, then Enter. Read the loop immediately above: it collects one serialized row for each tool, including untouched loans. Use the arrow keys to reach the end of that comment and Backspace to remove its characters. Type the write at the same indentation. Replace only the TODO comment with this actual write after the loop and before the method's closing brace:

        Files.write(path, rows, StandardCharsets.UTF_8);

path is the chosen desk file; rows is the complete serialized list, not only the last changed object. The explicit charset preserves the text encoding of every field. Keep the corrected load method, row loop and all helpers. Save with Ctrl+O, Enter, Ctrl+X. For an unsaved error, Ctrl+X, N discards it. For a saved source mistake, reopen and correct it; cp work/Store-before-save.java.txt Store.java is an optional source-only rollback that keeps your loader. Redo the write afterward. Do not reset the desk file or rerun setup.

Compile the saved source again:

javac -encoding UTF-8 -d out *.java
java -Dfile.encoding=UTF-8 -cp out Desk desk.tsv

Type the following inside the desk:

borrow T21 M01
borrow T21 M02
return T24 M01
borrow T23 M01
borrow TYPO M01
return T24 M03
list
quit

T21 is borrowed by M01. The duplicate borrowing, wrong returner, maintenance borrowing and mistyped ID are intentionally refused. Only M03's return of T24 succeeds. T22 stays available, T23 stays under maintenance, and T25 remains borrowed by M02 with its original note. The unknown-ID refusal leaves the command loop usable; correct the ID instead of restarting or resetting.

Now start a new Java process, using the same file:

java -Dfile.encoding=UTF-8 -cp out Desk desk.tsv
list
quit

T21 must still be BORROWED by M01, and T24 must still be AVAILABLE with borrower -. If not, check that you compiled the current Store.java and launched without --memory. Do not edit the final records to imitate a saved loan. If an accepted operation was already saved, do not repeat it just because it is now refused; list shows the current truth.

Back at the shell, read the actual stored result:

cat desk.tsv

The record relationships must agree with the new process's list. Preserve all IDs, names, members, maintenance state, untouched loans and notes. Only T21's state/borrower and T24's state/borrower change. This small writer replaces the file during a successful save; it does not provide concurrent access, crash recovery or an atomic transaction. If a write fails, stop and inspect the error before proceeding.

Summary

You mapped UTF-8 records to Java objects, saved every current record after a valid transition, and reopened the desk in a new process. Existing loans, maintenance and notes stayed intact, while refused operations did not write storage.