/DS_Lab_02

Distributed System's second lab session

Primary LanguageJava

DS_Lab_02

Distributed System's second lab session

Lab#2 – Event Programming and Multi-Threading Objective In this lab you will extend the multi-threading principle to manage multiple and custom events. This is the first part of a two part lab. The next lab will extend the algorithms developed from this lab into a distributed application for the control and monitoring of a robot. A. Servicing Events Patterns A common application is that of servicing multiple events from different sources. This is rather a simple thing to do when the underlying libraries have already defined their Listeners and event generators, as is the case with the Java Graphical User Interfaces such as Swing and AWT components. This is more challenging when has to define their custom events and Listeners.

The servicing of an event in Java is the commonly known Listener Pattern. Below is a brief description of it.

Events are messages that are sent from one object to another. The component that sends the event is said to "fire" the event, while the component that receives the event is said to "handle" the event. An event producer is a class that fires events. It also has the ability to add and delete event listeners (components that receive events). Event listeners, also known as event consumers, "listen" for an event. In programmatic terms, a method on the event listener object is called when an event that it is listening for is fired.

The base class that defines an event in Java is called java.util.EventObject. This is extended by applications to define user-defined events. All event objects should extend this class. An event producer/source implements methods that allow the event listeners to register and unregister its interest in the event that it produces. An event listener in Java is any class that implements the java.util.Eventlistener interface. The EventListener interface is an empty (tag or marker) interface that doesn't contain any methods. A class that implements this interface should typically provide a method that should be called when the event listener object receives an event. B. Java AWT and Swing Events In Java the details of Graphical User Interface (GUI) events are abstracted from the developers with the use of the AWT and Swing GUI components. For any AWT or Swing component that can generate an event the procedure involves the definition of a Listener to service the event generated by a graphic component. Several examples are shown below.

JMenuItem menuItem = new JMenuItem("Exit", KeyEvent.VK_X); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); }});

Code 1. Example of the definition of a listener to service an Exit menu choice.

JTextField inputText = new JTextField("Type here",20); inputText.addActionListener(new MyTextActionListener());

class MyTextActionListener implements ActionListener { /** Handle the text field Return. */ public void actionPerformed(ActionEvent e) { System.out.println(inputText.getText());
} }

Code 2. Example of the definition of a listener to service a text input.

A more concrete example of this is the MyGUI.java Class related to this lab.

  1. Spend some time looking through this the MyGUI.java Class to understand what it is doing.

  2. Write a test driver to exercise this GUI interface.

  3. Create a sequence diagram of its operation for when a user enters some input as well as when the user exits or closes the application. Presentation to the TA: Show the TA the running test program. C. Defining your own Custom Events When defining your own custom event there is a series of steps that need to be taken. Four things that you need are:

  4. An Event Class

  5. An Interface

  6. An event source

  7. An event listener

The event class should extend java.util.EventObject like this:

public class MyEventClass extends java.util.EventObject { //here's the constructor public MyEventClass(Object source) { super(source); } }

Code 3. The MyEventClass Class.

The Listener interface will look something like this:

public interface MyEventClassListener { public void handleMyEventClassEvent(EventObject e); }

Code 4. The MyEventClassListener Class.

The source code that generates the event will look something like this:

public class MyEventSource { private List _listeners = new ArrayList(); public synchronized void addEventListener(MyEventClassListener listener) { _listeners.add(listener); } public synchronized void removeEventListener(MyEventClassListener listener) { _listeners.remove(listener); }

// call this method whenever you want to notify
//the event listeners of the particular event
private synchronized void fireEvent()	{
	MyEventClass event = new EventClass(this);
	Iterator i = _listeners.iterator();
	while(i.hasNext())	{
		(MyEventClassListener) 
		  i.next().handleMyEventClassEvent(event);
	}
}

} Code 5. The MyEventSource Class.

The event listener will look something like this:

public class MyEventListener implements MyEventClassListener { // ... code here

//implement the required method(s) of the interface
public void handleMyEventClassEvent(EventObject e)	{
	// handle the event any way you see fit
}

} Code 6. The MyEventListener Class.

  1. Create a class diagram for the classes listed above.

  2. A simple way to test this code is to trigger MyEventSource using a Timer object with a pre-defined delay time. For the MyEventSource class write a constructor with the following signature MyEventSource(int delay) that creates an ActionListener object to service an event created by a Timer event (example: new Timer(delay, taskPerformer).start();) that you can use to fire the custom events by calling fireEvent() when the timer goes off. Below is an example of that.

    ActionListener taskPerformer = new ActionListener() { public void actionPerformed(ActionEvent evt) { fireEvent(); } }; new Timer(delay, taskPerformer).start();

  3. Write a driver program to test the custom event. You might want to create a small ServiceMyEvent Class that implements MyEventListener Class, defines a method to service the event and registers itself with MyEventSource object by calling its addEventListener method.

    // Create a new MyEventClass MyEventSource myEvent = new MyEventSource(10000); myEvent.addEventListener(this); synchronized (this) {

    try { // Object will wait for an interrupt wait(); } catch (InterruptedException e){ System.out.println("My thread message has been interrupted"); // not doing anything because handleMyEventClassEvent() is called }

    public void handleMyEventClassEvent(EventObject e) { JOptionPane.showMessageDialog(null,"A custom event occurred", "Message Dialog",JOptionPane.PLAIN_MESSAGE); } Code 7. The ServiceMyEvent Class.

Presentation to the TA: Show the TA your test program for the custom event.

D. Creating a Thread to manage a Custom Event.

The final component to this application is to execute the above test code as a separate Thread or to convert the ServiceMyEvent Class into a Thread (call it ServiceMyEventThread for simplicity). The purpose in doing this is to create a program that can service custom events as well as client I / O requests. For example a simple Web Application that has a back end program servicing commands and events for a robotic system.

  1. Go ahead now and create the ServiceMyEventThread class. This is should be relatively straight forward since you should have already created the ServiceMyEvent class.
  2. Now modify the test program you created to combine the functionality of the MyGUI and the ServiceMyEventThread classes. If you have done this properly the user GUI interface will service the user I / O and every 10 seconds you will get a pop window that comes up telling you that the event triggered.
  3. Draw a class diagram of this application as well as sequence diagrams for the event.
  4. Service the event through the GUI so that you can display the event in the same window as the GUI you developed instead of the pop up window. You will need to change the code so that the GUI now implements MyEventListener Class. Presentation to the TA: Show your results to the TA.

In the next lab you will extend this code into an RMI distributed application for a robotic application where you can service robot commands as well as capture custom events from the robot.

D. Food for Thought The Listener pattern is very similar to the Observer pattern (publish / subscribe). (http://en.wikipedia.org/wiki/Observer_pattern) but not exactly. Describe the Observer pattern and comment on the difference between the Listener and Observer pattern. The special Java synchronized appears in several method definitions of MyEventSource (Code 5). Explain the use and importance of the synchronized key word in Java. You will also notice the use of the synchronized (…) method call in code 7. How is this different than the synchronized statement used for the methods? Why is it used at this point in the code? The wait() method that was used in the driver program (code 7) to test the custom event causes a thread to release the lock it is holding on an object, allowing another thread to use that object. What other thread would use this object? What would happen if the wait() statement was not there? Explain the difference between a wait() and sleep() Java methods. To what Classes do these 2 methods belong to?