Midnight Bank (JavaFX)
Code Challenge: The Midnight Bank
Overview
Welcome to The Midnight Bank.
Your challenge is to build a desktop banking application using Java 25 and JavaFX. The application should allow a user to register, log in, manage their bank accounts, and manage a Line of Credit.
This challenge is designed for Junior Java developers and developers who are beginning to build larger Java applications.
The goal is not simply to make the application work. You should practice designing a program, separating responsibilities, working with persistent data, handling user input, and building a usable JavaFX interface.
Important: This is a programming challenge, not a tutorial. You are expected to make your own implementation decisions and research APIs/documentation when necessary.
Requirements
Technology
You must use:
- Java 25
- JavaFX
- SQLite
You may choose either:
- Maven
- Gradle
You may use any reasonable JavaFX-compatible libraries that help you build the application, but the core application must be written in Java.
Architecture
You are free to choose the architecture of your application.
You may use patterns such as:
- MVC
- Layered architecture
- Repository/Service architecture
- Another architecture of your choice
There is no required package structure.
However, your application should demonstrate a reasonable separation of responsibilities.
For example, your JavaFX controllers should not contain all of your database logic and banking rules.
You should be able to explain:
- Where your UI logic lives
- Where your business logic lives
- Where your database operations live
- How your application moves data between these layers
Application Flow
The application should follow this general flow:
Application Start
|
v
Login
/ \
/ \
Register Login Success
| |
v v
Login Dashboard
|
+------+------+
| |
Bank Accounts Credit Line
Registration
The application must provide a registration screen.
A new user should be able to provide:
- Username
- Password
Registration requirements
The application should:
- Validate that the username is not empty
- Validate that the password is not empty
- Reject usernames that are already registered
- Persist the new user in SQLite
- Provide useful feedback when registration fails
- Return the user to the login screen after successful registration
You may add additional validation if you wish.
For example:
- Minimum password length
- Username length restrictions
- Preventing whitespace-only values
Do not make the validation unnecessarily complicated.
Login
The application must provide a login screen.
The user should enter:
- Username
- Password
The application should:
- Validate the input
- Check the credentials against the SQLite database
- Reject invalid credentials
- Provide useful feedback when authentication fails
- Move the user to the dashboard after successful authentication
The currently authenticated user should be associated with the rest of their banking data.
A user should not be able to see another user's accounts or credit lines.
Dashboard
After successful login, the user should arrive at a dashboard.
The dashboard should provide access to:
- Bank Accounts
- Line of Credit
The dashboard should clearly communicate when the user does not have any accounts or a credit line.
For example:
Welcome back, MidnightCoder!
Bank Accounts
--------------------------------
No bank accounts found.
[ Create Account ]
Line of Credit
--------------------------------
No line of credit found.
[ Create Credit Line ]
The exact design is up to you.
Bank Accounts
Users must be able to create and manage bank accounts.
At minimum, the application must support:
- Create an account
- View accounts
- Deposit money
- Withdraw money
A user may have multiple bank accounts.
Each account should belong to the authenticated user.
Account information
At minimum, an account should have:
- A unique identifier
- An owner
- An account name or identifier
- A balance
You may add additional fields if they make sense for your design.
Deposits
Users must be able to deposit money into an account.
The application should:
- Accept a monetary amount
- Reject invalid amounts
- Reject zero or negative deposits
- Update the account balance
- Persist the updated balance in SQLite
For example:
Current Balance: $500.00
Deposit: $100.00
New Balance: $600.00
Withdrawals
Users must be able to withdraw money from an account.
The application should:
- Accept a monetary amount
- Reject invalid amounts
- Reject zero or negative withdrawals
- Update the account balance
- Persist the updated balance
Overdraft Prevention
An account must never be allowed to have a negative balance.
For example:
Balance: $500.00
Withdrawal: $200.00
Result:
Balance: $300.00
But:
Balance: $500.00
Withdrawal: $600.00
Result:
Transaction rejected.
Balance remains: $500.00
This rule must be enforced by your application's business logic.
Do not rely solely on the JavaFX interface to prevent this.
Line of Credit
Users may create a Line of Credit.
The application must support:
- Viewing the user's Line of Credit
- Creating a Line of Credit
For the core challenge, you do not need to implement borrowing, repayment, interest, or payment processing.
A Line of Credit should have enough information to represent the credit facility.
At minimum, consider:
- Unique identifier
- Owner
- Credit limit
You may add additional fields if you want.
Example
Line of Credit
-------------------------
Credit Limit: $5,000.00
Status: Active
A user should not be able to create or view another user's Line of Credit.
SQLite Persistence
The application must persist its data using SQLite.
Closing and reopening the application should not erase users, accounts, or credit lines.
At minimum, your database should persist:
- Users
- Bank Accounts
- Line of Credit
You should design appropriate relationships between these records.
For example:
User
|
+---- Bank Account
|
+---- Bank Account
|
+---- Line of Credit
You are responsible for designing the database schema.
JavaFX Requirements
The application must use JavaFX for its user interface.
At minimum, you should have separate views/scenes for:
- Login
- Registration
- Dashboard
- Account management
- Credit Line management
You may use:
- FXML
- Programmatically constructed JavaFX nodes
- A combination of both
The choice is yours.
Your UI should provide appropriate feedback for:
- Invalid login credentials
- Invalid registration input
- Duplicate usernames
- Invalid deposit amounts
- Invalid withdrawal amounts
- Insufficient funds
- Database/application errors
Avoid allowing exceptions to simply dump stack traces into the user's experience.
Error Handling
Your application should handle expected failures gracefully.
Examples include:
- Empty fields
- Invalid numeric input
- Duplicate usernames
- Incorrect login credentials
- Attempting to withdraw too much money
- Database connection failures
The user should receive a meaningful message explaining what went wrong.
For example:
Unable to complete withdrawal.
The withdrawal amount exceeds your available balance.
rather than:
Exception in thread "JavaFX Application Thread" ...
Data Integrity
Your application should protect the integrity of the banking data.
At minimum:
- Users must have unique usernames
- Accounts must belong to a user
- Credit lines must belong to a user
- Balances must not become negative
- Invalid monetary values must be rejected
- Data must survive application restarts
Think carefully about where these rules should be enforced.
A JavaFX button being disabled is not sufficient business-rule enforcement.
Recommended Project Structure
You are not required to use this structure.
It is provided only as an example:
src/
└── main/
├── java/
│ └── com.example.midnightbank/
│ ├── Main.java
│ ├── controller/
│ ├── model/
│ ├── repository/
│ ├── service/
│ └── util/
│
└── resources/
├── fxml/
└── styles/
You may structure your application differently.
The important part is that you can explain why you structured it the way you did.
Suggested Domain Model
The following is a starting point, not a strict implementation requirement.
User
├── id
├── username
└── password
BankAccount
├── id
├── userId
├── name
└── balance
CreditLine
├── id
├── userId
└── creditLimit
You may rename, extend, or redesign these models as appropriate.
Security Note
This challenge is focused on Java application development rather than production-grade authentication.
For the core challenge, you may store passwords in a simple form appropriate for demonstrating the application.
However, you should understand that plain-text password storage is not appropriate for a real banking application.
If you choose to implement password hashing as a bonus or enhancement, use an established password-hashing approach rather than inventing your own cryptographic algorithm.
Bonus Challenges
You may complete up to 5 bonus challenges.
Bonus challenges are optional and should not be completed at the expense of the core requirements.
Bonus 1 - Transaction History
Implement a transaction history for bank accounts.
Record transactions such as:
- Deposits
- Withdrawals
Each transaction should contain enough information to determine:
- Which account was affected
- Transaction type
- Amount
- Date/time
Display the transaction history through the JavaFX interface.
Bonus 2 - Password Hashing
Improve the authentication system by storing passwords using a proper password-hashing algorithm.
The application should:
- Hash passwords before storing them
- Never store the original password
- Verify passwords during login
Document which hashing approach you selected and why.
Bonus 3 - Multiple Account Types
Allow users to choose an account type when creating a bank account.
For example:
- Checking
- Savings
Display the account type throughout the application.
You may implement different rules for each account type if you wish, but this is not required.
Bonus 4 - Interest
Add interest calculations to either:
- Savings accounts
- Lines of Credit
You should clearly document:
- The interest rate
- How interest is calculated
- When interest is applied
Keep the implementation understandable rather than attempting to reproduce a real-world banking system.
Bonus 5 - JavaFX Polish
Take the application beyond basic functionality.
Examples include:
- CSS styling
- Responsive layouts
- Navigation components
- Dialogs
- TableView-based account displays
- Improved validation feedback
- Loading indicators
- Dark/light themes
- Better empty states
The goal is to make the application feel like a cohesive desktop application rather than a collection of screens.
What We Are Looking For
This challenge is not primarily about making the prettiest banking application.
We are looking for evidence that you understand how to build a Java application beyond individual classes and small exercises.
Consider the following questions while developing:
Java
- Are your classes responsible for one clear thing?
- Are you using appropriate access modifiers?
- Are you using interfaces where they provide value?
- Are you handling exceptions appropriately?
- Are you using appropriate types for monetary values?
JavaFX
- Is your UI separated from your business logic?
- Are scenes/views easy to navigate?
- Does the application provide useful feedback?
- Does the UI behave correctly when something goes wrong?
Persistence
- Is your database schema sensible?
- Are relationships represented correctly?
- Does your application correctly load and save data?
- What happens if a database operation fails?
Application Design
- Can you explain your architecture?
- Can you explain why you made your design decisions?
- Is your business logic independent from your JavaFX UI where practical?
- Could another developer understand your code?
Submission Requirements
Your project should include:
- Complete source code
- Maven
pom.xmlor Gradle build configuration - SQLite database setup/schema or database initialization code
- README containing setup and execution instructions
- Explanation of the architecture you chose
- Any assumptions you made during development
Your application should be able to be cloned, built, and launched by another developer following your README.