Collaboration, built from the sockets up.
WORTH (WORkTogetHer) is a complete client-server system for teams: users register and log in, create projects, add members, put cards on a Kanban board and move them through their life cycle, see who is online and talk in a chat that belongs to each project.
The constraint was the interesting part: no frameworks. Every networking primitive comes from the Java standard library, and each kind of interaction gets the mechanism that suits it, from reliable request-response to server push and group messaging.
One mechanism per job.
port 45678Login, logout and every project and card operation. Each message is a JSON-serialized object preceded by a 4-byte length header, so the receiver allocates exactly the bytes it needs.
registry on port 56789User registration, and server-to-client callbacks: whenever users log in or out or projects change, the server pushes the new state to every connected client.
port 13731A group chat for each project, with automatic notices such as a card moving to done. Addresses come from a pool between 239.255.224.0 and 239.255.255.255.
JSON on diskUsers, projects, members and cards are saved after every state-changing operation and restored when the server starts again.
Many clients, one consistent state.
The main thread restores the saved state, starts the RMI registry and blocks on accept(). Every connection goes to a cached thread pool, where a worker reads the client's requests, runs them against the shared core and sends back the response. Shared users and projects are guarded by synchronized blocks, so concurrent updates stay atomic and consistent.
- Fault tolerance. An abrupt disconnection is detected through the stream's end of file: the user is logged out, the socket closed and the stale callback stub pruned.
- Client threads. The client runs its command line and TCP traffic on the main thread, receives callbacks on an RMI thread, and starts one listener thread per project chat that stores messages until the user reads them.
- Address pool. Each new project takes the smallest free multicast address from a sorted
TreeSet, and gives it back when the project is deleted: 8,192 chats in total.
A board the server enforces.
Every card starts in todo and moves according to fixed rules. Any other move is rejected with MOVE_CARD_FORBIDDEN; every valid one is recorded in the card's history and announced in the project chat, as in the demo at the top.
| From | Allowed destinations |
|---|---|
| todo | inprogress |
| inprogress | toberevised, done |
| toberevised | inprogress, done |
| done | none: a project can be canceled only when all its cards are here |
// source and destination must be different listsif (sourceList.equals(destList)) { message.setResponse(Response.CARD_EXISTS); return message;}// the Kanban rules, checked on every moveswitch (destList) { case "todo" : message.setResponse(Response.MOVE_CARD_FORBIDDEN); return message; case "inprogress" : if (sourceList.equals("done")) { message.setResponse(Response.MOVE_CARD_FORBIDDEN); return message; } break; case "toberevised" : if (!sourceList.equals("inprogress")) { message.setResponse(Response.MOVE_CARD_FORBIDDEN); return message; } break; case "done" : if (sourceList.equals("todo")){ message.setResponse(Response.MOVE_CARD_FORBIDDEN); return message; } break; default :}synchronized (createdProjects) { // the card must really be in the source list int cardIndex = sList.indexOf(new Card(cardName, null)); if (cardIndex == -1) { message.setResponse(Response.NONEXISTENT_CARD); return message; } // move the card, update its history, persist the project Card card = sList.remove(cardIndex); card.updateHistory(destList); dList.add(card); int cardIndex2 = project.getCards().indexOf(card); project.getCards().set(cardIndex2, card); server.saveProject(project);}
Passwords are never stored.
Credentials are hashed with PBKDF2-HMAC-SHA1, a 32-byte random salt and 20,000 iterations, and only the salted hash reaches the disk. It is the small detail that separates a student exercise from a system you could actually trust with a team's accounts.
Sockets, threads and nothing else.
The full source, 19 classes with the server, the client and the protocol, is on GitHub with instructions to run a server and as many clients as you like.