Java Guild course · Lesson 0001
Lesson 0001 · reading the brief
The README describes a blank page. The repository contains a finished program. Only one of those is the exercise.
Open the README and it reads like a first-year assignment: “Create a
simplified Library Management System…”, followed by a list of
classes and method signatures. A candidate who reads only that will start typing
class Book and never notice that Book already exists,
fully written, in the repository they were sent.
This lesson gets you to the point where you can describe, out loud, what Solirius is really asking for — before you write a line of code.
This is not a greenfield exercise. It is a legacy-code exercise: here is a working program with defects in it, extend it and improve it, and show us your judgement. The README's method list is a description of what you were given, not a specification of what to build.
Build it, then break it with your own hands. Three commands:
cd ~/Desktop/java-guild-candidate-test-intermediate-main
export JAVA_HOME=$(/usr/libexec/java_home -v 25)
~/.local/maven/bin/mvn clean test
Then run the program and type a book title that does not exist:
printf '4\nGone With The Wind\n' | \
~/.local/maven/bin/mvn -q compile exec:java 2>/dev/null || \
"$JAVA_HOME/bin/java" -cp target/classes com.solirius.intermediate.library.Main <<< $'4\nGone With The Wind\n'
Then run it again and type banana at the menu. Come back when
you have seen both stack traces with your own eyes.
Here is the interesting line from mvn test on the code as supplied:
[INFO] --- surefire:3.2.5:test (default-test) @ java-guild-candidate-test ---
[INFO] No tests to run.
[INFO] BUILD SUCCESS
The brief's Graduate tier — the tier every candidate must clear before their own tier counts — asks for “Unit Tests: Write test cases for Book and Library classes”. There are none. Zero. The build is green because there is nothing to be red about.
src/test/. It does not exist in the repository you were sent.
Whatever else you do, that directory must be full and meaningful.
Look at what is in src/main/java/…/library/exceptions/:
exceptions/
├── AlreadyBorrowedException.java
├── BookNotFoundException.java
├── NotBorrowedException.java
└── package-info.java
Three exception classes, each fully written with javadoc. Now grep the rest of the source for any of those names:
$ grep -rn "AlreadyBorrowedException\|BookNotFoundException\|NotBorrowedException" \
src/main/java --include=*.java | grep -v "^src/main/java/.*exceptions/"
(no output)
Not one of them is referenced anywhere. They are imported by nothing, thrown by nothing, caught by nothing. They are dead code.
Now read the Intermediate requirement again, slowly:
Exception Handling: Handle scenarios where a book is already borrowed, does not exist, or cannot be returned.
Three scenarios. Three exception classes, named after exactly those three scenarios, sitting unused in the repository. This is not an accident and it is not a coincidence. It is the exercise, left on the table with a note on it.
Here is Library.borrowBook as supplied:
public boolean borrowBook(final String title) throws IOException {
Book book = searchBook(title);
if (book == null || !book.borrowBook()) {
throw new IOException("Book not found: " + title);
}
return true;
}
Three separate things are wrong with those five lines, and you should be able to name all three in one breath:
IOException means a stream, a file, a socket failed. Nothing here
performs I/O. A caller who sees IOException in the signature will
reasonably conclude this method touches a disk.|| collapses two entirely different situations — no such
book and the book is here but already on loan — into one branch
with one message. Borrow the same book twice and the library tells you it has
never heard of it.boolean, but the only path that reaches return returns
true. It can never return false. Every caller writing
if (library.borrowBook(t)) is writing a branch that cannot be taken.Every claim in this course was reproduced against the real starter code on
2026-08-30. Borrowing an already-borrowed Dune really does produce:
java.io.IOException: Book not found: Dune
The book is right there. The library is lying to you. See the defect inventory for the full list with reproduction steps.
Most candidates skim pom.xml for the Java version and move on. Read
it as a statement of what a good answer contains:
| What is declared | What is uses it today | What it is telling you |
|---|---|---|
| junit-jupiter 5.10.0 | Nothing | Tests are expected, in JUnit 5, not 4. |
| mockito-core 5.15.2 | Nothing | They expect classes with collaborators — i.e. that you will not leave everything static in Main. |
| sqlite-jdbc 3.47.2.0 | Nothing | The Advanced tier's “portable file-based database”. Note it is compile scope, not test. |
| maven-checkstyle-plugin | Reporting only | Style is graded. The existing code is written to pass sun_checks — final parameters, javadoc on every member. |
| source/target 11 | The compiler | No records, no sealed types, no switch expressions. Work inside it deliberately. |
Verified on this machine: javac --release 11 rejects records
outright —
error: records are not supported in -source 11
(use -source 16 or higher to enable records)
JDK 25's compiler still accepts --release 8, 11, 17, 21 and 25,
so staying on 11 is safe on any assessor's machine. Knowing precisely what you
gave up — and saying so — scores better than quietly bumping the version.
Why does the presence of an unused exceptions package matter more than any other single detail?
Checkstyle's Sun rules do not flag unused classes, and deleting them would be the exact opposite of what is wanted.
Deleting them would throw away the strongest hint in the repository. They are not clutter — they are an unopened gift.
Right. Already borrowed, does not exist, cannot be returned — the Intermediate requirement lists three scenarios and the repository ships three exception classes with matching names. Wiring them up is the single highest-value change you can make.
Plenty of failures are properly signalled by a return value or an Optional. The argument for exceptions here is specific to this brief, not general.
What is the strongest argument against throws IOException on borrowBook?
A real debate, but not this one — you can hold either view and still see that this particular type is wrong. Argue the type, not the category.
This is Effective Java Item 73: throw exceptions appropriate to the abstraction. IOException leaks a claim about file handling into a method that only inspects a list in memory. It makes the caller reason about the implementation to understand the signature.
A domain exception would too, if you keep it checked. The try-catch is not the objection; what the type means is.
It carries the message fine. The problem is that the message is attached to a type that misdescribes what went wrong.
The brief says “visibility at candidate discretion” beside every class and method. Why?
Read it alongside the evaluation criterion “proper use of object-oriented programming principles”. They are declining to specify encapsulation because encapsulation is the thing being assessed. A brief that told you to make books private would be marking nothing.
They have a very strong preference — the criteria say so. What they lack is a wish to hand you the answer.
Default visibility rules have not changed. Nothing about Java 11 versus 21 bears on this.
Nothing in the project uses the module system; there is no module-info.java and no requirement for one.
If an interviewer opens with “so, tell me about the exercise”, the first thirty seconds decide how the rest goes. Rehearse this shape:
“The first thing I noticed was that the README describes building it from
scratch, but the repo already has a working implementation — so I read it as a
legacy-code exercise instead. There were three exception classes in the repo that
nothing referenced, and the Intermediate requirement names exactly those three
scenarios, so that told me where to start. And mvn test said
no tests to run, which is the Graduate requirement unmet.”
The brief itself — README.md in the starter repo.
Read it three times. Once for the requirements, once for the Evaluation
Criteria at the bottom, and once asking “which sentence in here does
the code I was given already violate?” The five evaluation criteria are the
marking scheme; everything this course does is aimed at them.
Disagree with any of this? Bring it to me. If you think the
IOException is defensible, argue it — being able to defend the code
you were given is as much a skill as criticising it.