We Stealz Your Dataz (WSYD) social network

This document is created as index.md in Markdown text. It can be manually converted to HTML using pandoc with the command:

pandoc --standalone --self-contained --css styles.css --toc --from=markdown --to=html5 --output=index.html index.md

The To Do list.

Introduction

In this Java project I wanted to challenge myself to use some of the same concepts I've used in previous C++ projects in order to contrast and understand the different approaches taken in both languages.

The project criteria already suggested to me that the design would need to implement multi-threading and as there was no specific requirement to use a database I opted to use object serialization which would provide two useful functions: persisting the member data to file and passing pure java objects over the network.

I adopted the Javadoc standard for all my code annotations and as a result the entire code base is consistently documented in the same style as the Java API in HTML without requiring me to write separate documentation.

I used Remarkable, a Markdown text editor with live HTML preview, to create this report and allow the report and the Javadoc to link together as one HTML web.

After becoming familiar with the NetBeans IDE I explored its Test-Driven Development (TDD) support using Junit and found it provided valuable feedback on bugs in my code that were not obvious before the tests were written.

I set out to implement the assessment criteria specified for a First class result.

Design

The criteria requires a minimum of three separate executable processes: GUI User client, Social Server and Chat Server. I opted to add a fourth: GUI Server Management client. This allowed me to implement the Social and Chat servers as true background service daemons and have them communicate with the GUI Server Management client over the network.

As well as displaying log messages received from the servers the GUI Server Management client allows the independent restarting or stopping of each server.

The GUI User client makes extensive use of Swing components. The NetBeans IDE is responsible for generating most of the GUI skeleton code for handling user actions via ActionEvent and PropertyChange event listeners and several function-specific child windows and dialogs for presentation during log-in, profile editing, chat and configuration. After the GUI skeleton code was complete I added support for the network services background threads and then implemented the links between them and the GUI components.

Since the criteria requires a range of network functionality shared across clients and servers I implemented a common network library. This network library, and the server services it implements, needs to support multi-threading especially on the client since listening for incoming connections is an operation that blocks in the operating system kernel. If those blocking operations were performed on the GUI Event Dispatch thread it would cause poor response in the user interface.

Fortunately the javax.swing.SwingWorker class was designed especially for this purpose. As it implements the java.lang.Runnable interface too it made the perfect base class for my own NetworkServerAbstract class because I could use it for both service daemon (non-GUI) and client (Swing GUI) applications.

I considered adopting an existing network protocol (or designing my own) for the communications between servers and clients and clients with clients. I considered Hyper Text Transport Protocol (HTTP) for the server to client connections. For client chat I looked at Internet Relay Chat (IRC) and its related Client To Client Protocol (CTCP) and the Direct Client Connect (DCC) sub-protocol (that supports file transfer) which together implement a server-mediated peer-to-peer (P2P) approach as a chat solution that has been in use since the 1990s.

The problem I found was that each type of communication would require a different protocol to be implemented. As well as requiring a lot of work to implement this had the risk of introducing subtle hard-to-find runtime bugs in the live communications.

I investigated using some form of pre-existing Message Queue implementation such as Java Enterprise Edition (EE) Java Message Service (JMS) but decided most of these would be too over-engineered and complex for my requirements and therefore I would create a simple message queue implementation myself.

I'd already decided I'd use serialization for persisting member data and after looking at some examples of how easy it is to serialize Java objects over any kind of stream, including network streams, I realised it could make network communications reliable and consistent with minimal additional code both at run-time and at coding time since Java provides serialization as part of the Virtual Machine. The only requirement to support serialization is that each class of object that would be passed over the network should implement java.io.Serializable - which usually only requires a single addition:

public MyClass extends SomeClass implements java.io.Serializable {

This design decision makes it as easy to pass an image or other file-type over the network as it does to send simple text and with 100% reliability. In my implementation I wrapped each object being sent over the network in a NetworkMessage wrapper class that contains additional information such as sender and target service and the intent of the message.

A further issue I considered was how the clients would discover the servers. Since in the lab setting there will be no facility for adding Domain Name System (DNS) records to the local DNS server zone file it would require either:

  1. hard-coding an IP address into the source-code and rebuilding the code each time the project was demonstrated
  2. providing for the user to enter the IP address manually when each application starts
  3. Using some form of automatic network discovery

I decided to opt for (3) implemented using java.net.MulticastSocket with a fall-back to (2) in case automatic discovery fails.

Clients will create long-running Transmission Control Protocol (TCP) connections to the server for passing serialized NetworkMessage objects back and forth, starting with log-in.

Clients can discover each other via the Organisation-scope Multicast group, or if it isn't available, by requests to the Chat server which will mediate chat authorisations.

I implemented the asynchronous update from server to client requirement with User Datagram Protocol (UDP). If the Multicast group isn't active the update service will fall-back to using Unicast to each known client.

To avoid using something other than object serialization for sending notifications via UDP packets (which do not have support for streams) I used the NetworkMessage serialize() and deserialize() methods to convert the object to and from a byte[] that can be transported by java.net.DatagramPacket.

Functionality

==TODO:== Describe each application's core functionality and stand-out features

Social Server

Chat Sever

GUI Server Management client

GUI User client

Code

I began by designing and creating the skeleton GUI client using the NetBeans IDE.

Questions that came up during GUI client design led to coding WSYD_Member, the class that wraps the data structure representing each member of the WSYD social network. As well as data storage I implemented a static CSV parser createWYSD_Member(), the inverse method toString(), and support for the java.lang.Comparable interface in compareTo(). I inherited serialization for free because all the attribute classes already support the java.io.Serializable interface.

The networking library was the next task. I investigated Java's networking support and looked at several code snippets and examples at sites such as StackOverflow as well as the official Java API documentation. I realised there were two requirements: the network services themselves, and the object passing.

Objects being passed need to encode the destination. For example, a "Friend Is Online" notification needs to be handled by a client method that knows what to do with that information. The network services only deal with transport not context. Therefore NetworkMessage objects know their sender, target and the intent - java.lang.Strings that allow received messages to be dispatched by the server service to the correct handler and for acknowledgements to be sent in return.

The mechanism for passing received objects from the server service to the GUI (or server process) implements a custom event NetworkMessageEvent which extends java.util.EventObject and adds interface NetworkMessageEventGenerator to NetworkServerAbstract which registers objects of classes that implement the NetworkMessageEventListener interface. These objects are notified when a new NetworkMessage is received.

The network server classes all inherit their core functionality from NetworkServerAbstract. Common functionality implemented here includes javax.swing.SwingWorker multi-threading, NetworkMessageEvent dispatching, the socket listener main loop in doInBackground(), logging, and unsolicited outbound message queuing via queueMessage() and dequeueMessage().

The implementing classes NetworkServerTCP, NetworkServerUDP and NetworkServerMulticast add minimal code via method overrides to support protocol specific functionality.

==TODO:== discuss other classes and notable features and coding/learning experiences

I used NetBeans Action Items to keep track of TODO: and FIXME: outstanding tasks, and XXX: to call attention to important notes.

Testing

I used the NetBeans-generated JUnit version 4 test class templates as the basis for my Unit Tests, creating close to 100% coverage of the non-network library code. I didn't write tests for network connections functionality although they would have been very useful due to the amount of time, and the difficulty, I estimated it would require to develop them - much more than writing the network library itself.

==TODO:== add examples of bugs the testing revealed and experiences in writing the more complicated test cases.

Bibliography

This is a list of many, but not all, of the very many resources I looked at in developing this project. Some were of more use than others but all of these contributed something to the development, design and coding.

References

Administratively Scoped IPv4 Multicast Addresses

HTML formatted note taking

Pandoc extended Markdown syntax

Markdown syntax

NetBeans IDE

How to configure @author tag

Writing JUnit tests

How to set command line arguments for Run File

Java documentation

Java Platform Standard Edition 7 Documentation

Java SE 7 API

Controlling Access to Members of a Class

Nested and Anonymous Classes - access to outer class variables

Java Generics

Java Tutorials: Generics

Java Tutorials: Generics (by Gilad Bracha)

Serialization

Serialize Object over UDP

Deep cloning techniques

Why should a Comparator implement Serializable

Multi-threading

Using SwingWorker to implement a UDP Client/Server

Multi-threaded Network Server

How do I use SwingWorker in Java

Concurrency in Swing (multi-threading for background tasks)

Synchronized Methods

Synchronized Statements

Network

Getting Network Interface Parameters

Testing a socket is listening on all network interfaces/wildcard interface

Socket Logging (network logger)

Tutorials

How to Write Doc Comments for the Javadoc Tool

Write Image to File

Iterating over a TreeMap

How do I call one constructor from another in Java

James Gosling's explanation of why Java's byte is signed

When to use flush() in Java

How do I check if a file exists in Java

Java String.equals() versus ==

Calculating byte-size of Java object

Mr. Happy Object teaches custom events

Multiple Swing Timers

Launching a browser for a web page

Jbutton that does not show focus

Set JFrame iconImage in NetBeans

JTable scrolling to a specific row