ATM-Simulator: How a Java Swing Project Fakes a Banking Machine
A student-built desktop app turns absolute positioning, JDBC, and a static ATM image into a surprisingly theatrical lesson in state, transactions, and beginner security mistakes.
- This project is most interesting as interface theater, because it tries to feel like an ATM before it tries to behave like one.
- Its real architecture is a window-to-window wizard, with constructor-passed state and MySQL acting as the source of truth.
- Deposits and withdrawals are taught as ledger events, which makes the app a useful lesson in persistence and history.
- The code is instructive partly because it is incomplete, since the security shortcuts are as educational as the features.
The ATM is a costume, not a container. That is the useful way to read shra2103/ATM-Simulator. It is not trying to be a serious banking platform. It is trying to stage the feeling of standing in front of one.
That choice changes everything. The app leans on an atm.jpg backdrop, fixed coordinates, and a narrow set of actions so the interface feels like a device rather than a normal desktop form. In other words, the design constraint is theatrical, not ergonomic.
The whole app is a wizard disguised as a machine
Under the skin, the project is a chain of windows. Login hands control to transaction screens, the signup flow is split across multiple forms, and each step passes just enough state to keep the next screen alive.
That makes the app easy to understand, and easy to break. A beginner can follow the flow because each class owns one screen and one job. But the cost is fragility: once state is spread across constructors and ad hoc queries, there is no real session manager to protect consistency.
Swing does the theater, JDBC does the bookkeeping
The stack is plain Java desktop programming. Swing and AWT draw the interface. JDBC talks to MySQL. The interesting part is not that these pieces exist, but how cleanly the project separates appearance from persistence.
The screens are visual, but the state is database-backed. The login form checks a table. The signup flow writes identity details. The transaction screens read and update persistent records. That means the balance is not a local variable pretending to be money. It is data in a database, which is the right instinct even in a student project.
Constructor-passed state is the app’s fragile memory
One of the most revealing choices is how the project carries identity forward. Instead of a full session layer, it passes the pin through constructors such as new transaction(pin). That is crude, but it is also honest.
For a beginner, this is a legible pattern. You can see where the identity comes from, where it goes, and which window depends on it. For a real system, though, it is a warning sign. Once your session logic lives in object handoffs, every new screen becomes part UI and part authentication plumbing.
Deposits and withdrawals are ledger events, not just balance updates
The most useful lesson in the repo is how it treats money movement. A deposit is not just an updated total. It is a recorded event plus a changed balance. That dual-write pattern is the difference between a toy counter and a usable ledger.
That split matters because it mirrors how real systems think. One table remembers what happened. Another reflects the current state. The mini statement feature then becomes possible without inventing history from scratch.
Security lessons are baked in by accident
The project also shows the classic beginner mistakes clearly enough to be useful. One of them is raw string concatenation in SQL, which makes injection risk obvious. Another is hardcoded credentials, which keeps the code easy to run locally while also making it impossible to call production-ready.
| Area | What this repo does | Why it matters |
|---|---|---|
| SQL access | Builds queries with string concatenation | Makes injection risk visible and easy to fix |
| Credentials | Uses hardcoded local settings | Good for a demo, bad for deployment |
| Error handling | Relies on basic try-catch blocks | Enough for learning, thin for recovery |
| State | Passes pin through constructors | Simple to read, fragile as the app grows |
That is not a flaw in the article-worthy sense. It is the reason the project is worth looking at. The code shows the learner’s model of the problem before the abstractions get polished away.
Where it sits among beginner ATM projects
Compared with a console ATM, this repo is more revealing because it has a real UI layer and persistence. Compared with a more polished Swing plus MySQL project, it is smaller and rougher, but also easier to inspect line by line. Compared with a Spring Boot or microservices version, it is tiny, which is exactly why it is educational.
| Project type | Interface | Persistence | Learning value | Takeaway |
|---|---|---|---|---|
| Console ATM | Text only | Often none or minimal | Good for logic basics | Focuses on control flow |
| This repo | Swing with static ATM art | MySQL via JDBC | Strong for UI state and ledger thinking | Shows how beginners fake a machine convincingly |
| Polished Swing + MySQL | Full forms and reports | Structured database layer | Good for larger project patterns | Adds breadth but less personality |
| Spring Boot or microservices ATM | Web or service APIs | Layered backend architecture | Best for modern architecture | Teaches scaling, not stagecraft |
Its niche is not technical sophistication. Its niche is clarity. It exposes the exact bridge many beginners have to cross: from one-off UI code to database-backed application thinking.
What the code gets right, and what it gets away with
The project is crude, but coherent. It is insecure, but legible. It is not software you would ship, but it is a very honest map of how many first database-backed GUI projects are actually built.
Would it make sense to have an "account" class? So instead of nested dictionaries, you could have a dictionary with the key being the name, and the value being an instance of the account class.
That instinct, to look for a cleaner model, is exactly what this repo helps you develop. Once you can see the ATM as a staged flow of screens, state handoffs, and ledger writes, the next refactor becomes obvious.