Tutorial for understanding KS Framework

In class on Monday I presented the outline of the CIPC and SIPC structure for communication in the planned-for KombatSolitaire application.

Here is some more information to make it real for you.

Preliminaries

There are some things you must properly retrieve from various CVS repositories to be able to make this work. You should be familiar with the WPI SourceForge CVS repository (see here). You need to connect to the following TWO repositories:

Once you have connected to these repositories, you need to check out the following projects. It helps to check them out in this order:

Platform Warning

The above tutorial was tested only on PCs. There are some known issues with using CompUnit on Macintosh and Linux (essentially a windowing toolkit known as SWT needs to be configured properly). Since this tutorial doesn't use SWT it is not expected that you will run into these problems.

Time Estimation

I expect it will take about 1 hour to execute the application as directed by this tutorial and understand the various steps below. I expect that you will find time to complete this tutorial with your group teammates.

Steps

The Framework project contains the components that I am providing to the class to enable the distributed connection between client(s) and centralized server. You can read the documentation to see more of how it works, but the best thing to do is to look at the components FrontEnd and Processor which I will now describe in some detail.

As an aside, note that in this tutorial, you will be working directly with Java code, accessing the CompUnit infrastructure only tangentially. It is not ideal for the long run, but for small example applications it quickly gets the point across.

How to run the Exercise

In the Development project, you will find a test source file, within which a package bb, and within the package two files MainClient and MainServer. Launch the MainServer class by right-clicking on its icon and selecting "Run As --> Java Application". You will see "Accepting calls on 7878" in the console window. Now launch the client by right clicking on the MainClient class and selecting "Run As --> Java Application". You will see a GUI window appear:

Click on the "Connect" button and you will see a message appear "Connected to: localhost@7878". Now type the string "Hello" in the lower left text area and click on the "Post" button. The upper area will now say "heineman: Hello".

Can multiple clients connect? Sure. Launch "AnotherClient" which is a class found in the bb package as well. Click on its "Connect" button and you will see that it, too, is connected to localhost@7878. Then post a comment in the same way, and both clients receive it.

The client is responsible for two functionalities: Logging in and posting a message. To see how this is done, let's review the FrontEnd class. It is worthwhile to note that the FrontEnd Java class is the primary class for the FrontEnd component (which shall be shown in bold font).

What happens when MainClient application is launched?

Let's review the main method for MainClient.java

Given your understanding of CompUnit (see document that is available within CompUnitEnvironment/docs/CompUnit.doc) you should be able to decipher that two components are instantiated (cipc and fe). Component fe requires two interfaces from cipc (IConnection and IProcessMessage) while component cpic requires two interfaces from cipc (IConnectionHandler and IProcessMessage). The components are both activated and the application starts.

What happens when user clicks on "Post"?

While this is out of sequence in time, this is the easier one to understand, so I start here.

The goal is to send a command to the server to tell the server of this chat.

First we clear the input for the next chat. Then we construct a properly formatted XML string to represent the chat command as defined within the XML schema definition file (http://www.wpi.edu/~heineman/xml).

What you see here is my helper classed at work. Starting with a raw String of XML text, a Message class (which I provide for you in ks.framework.common.Message) parses the XML string to ensure it is properly validated according to the XML schema definition that you can find at http://www.wpi.edu/~heineman/xml. Once done, it wraps the resulting object within a Message to be delivered to the server. But how is it to be sent to the server?

Well component FrontEnd requires that some component provide to it the capability to process a message, namely IProcessMessage. This is taken care of in the MainClient main method with the line: "fe.connect(cipc, IProcessMessage.class.getName())". What this lines means is that cipc provides the interface which is required by FrontEnd. And when the time comes, FrontEnd simply delegates the responsibility to the cipc component. So at this point, the command is sent to the server. Note that we don't "wait" for a response with a synchronous block since that is inappropriate given the distributed nature of this application. Instead, let's see how the server processes the request

How does the server process the CHAT command.

Observe that in the main method of the MainServer class in bb.MainServer you find the statement "s.connect(proc, IProcessMessage.class.getName())" which tells the sipc component which component is responsible for processing messages.

Let's look at the Processor component which provides this IProcessMessage functionality. The Processor.java class is the primary class for the Processor component. Aside from the methods which are required as part of the CompUnit technology for this primary class, you find the following method:

Given the CHAT command, this processing logic extracts the text from the command (in time you will learn the API necessary to extract information from XML commands and requests) and constructs a new request object. This is done using the Message helper class, as before. Once this message is created it is marked as being a Broadcast request, which means that all connected clients shall receive this request object. The Processor component is unable to send information to anyone, so it relies on a required interface IOutput, which it was provided during the line "proc.connect(comm, IOutput.class.getName())" in MainServer.

The Communicator component provides the IOutput interface, thus enabling the Processor component to focus on just the task at hand.

How does the client process the OUTPUT request?

Once the request is generated to be sent to the client, what does the client do with it? First observe that the cipc client requires some component to provide the IProcessMessage capability to answer just this question. And in the MainClient java class, you find the statement "cipc.connect(fe, IProcessMessage.class.getName())" which wires together the cipc component and the FrontEnd component.

So we turn to the process method within the FrontEnd class.

This method determines whether the message is something it must process. Once it determines this, the text contents of the message are extracted from the message and appended to the output text area.

What happens when user clicks on "Connect"?

Note that the login capability is inherent in the logic of both cipc and sipc, so some of this logic is going to be a bit more complicated than the other sections of the tutorial.

Reviewing the bb.client.FrontEnd code, I find the following ActionListener handler:

Now 'connection' is an instance attribute of the object of type IConnection. Thus FrontEnd requires this capability from some other component. From whence did this component providing IConnection come? Well, during the main method described earlier, note the line "fe.connect(cipc, IConnection.class.getName()". Here we explicitly tell FrontEnd to remember the cipc component, which it does, if you review the "connect(IComponent, String)" method.

So if you want to really get into the details (not required at this point) you can dive into the ks.framework.cipc package where you will find a class Talker, inside of which you will see code that looks like the following:

What you see here is my helper classed at work. Starting with a raw String of XML text, a Message class (which I provide for you in ks.framework.common.Message) parses the XML string to ensure it is properly validated according to the XML schema definition that you can find at http://www.wpi.edu/~heineman/xml. Once done, it wraps the resulting object within a Message to be delivered to the server.

So the Login command, which I alluded to in class, is generated and processed by the cipc component. When the connection has been validated, cipc wants to alert someone, but it doesn't know whom. Fortunately, it has been configured in the MainClient class by the line "cipc.connect(fe, IConnectionHandler.class.getName())". Thus whenever cipc completes the connection, it requires someone to be told, and this will be the FrontEnd component through its provided interface IConnectionHandler. There is only one method of this interface, and if you inspect the FrontEnd class you will see the implementation of this method:

which simply disables the connect method and enables the text area where chat texts are to be stored.

What happens when server receives the LOGIN command?

Note that the login capability is inherent in the logic of both cipc and sipc, so some of this logic is going to be a bit more complicated than the other sections of the tutorial.

Deep within the sipc component there is a class Listener which has a handleSession() method to process all input from the client. It assumes the first communication it must deal with is the LOGIN command. Here is a fragment of code showing how it processes the command:

The API for extracting information from the parsed XML object is available as part of the standard JDK.

Note that there is currently no authorization agent connected to the sipc component so all LOGIN commands are accepted without question. This is certainly not the proper behavior, and you can expect to see the UserManager component playing a role here.

When does the client send a LOGOUT command?

Returning to the FrontEnd primary class for the FrontEnd component, you will see the deactivate() method, which is intended to be invoked when an application is terminating. Here is the code for the deactivate method:

Note how it, too, constructs a parsed command XML object to be sent to the server by means of the processor which provides the interface required by the FrontEnd component. After this logout command is sent, the client simply disonnects from the server and disposes of the frame.