Exploring Eclipse RCP

A "Rich" Alternative for System i GUI Development

May 2007

May 31, 2007 7:40 PM

Java data queues 311 -- add a logon dialog to RCP DtaQ Demo

Elena Lower wrote an article published this month in System iNEWS, ProVip (May 2007), "5 Tips for Integrating Java with System i Resources". RCP DtaQ Demo project will benefit from the first tip, Connection to the System i. Lets apply it:

logonDialog.jpg

These changes give RCP DtaQ Demo a logon dialog consistent with the graphical appearance of the application and is more functional. The user can cancel the logon without ending the application and later call for the logon dialog through the file menu.

This is how it is done.

RCP DtaQ Demo violates Elena's advice by using the AS400 default sign-in dialog. Worse the user is forced to either sign in or cancel and abort the program. In something simple like this, something that needs a System i connection to work, requiring a successful logon before allowing the application to continue is reasonable. This would not work well if the user had to do something, say set some preferences (that is a hint about future development), before logging on.

Three classes will be added to the dataqueue package and other classes will be changed in base package.


LogonDialog

Eclipse defines a Dialog as " … specialized window used for narrow-focused communication with the user. Dialogs are usually modal…" In this case the focus is to get the logon information from the user. The logon dialog is shown.

There is no wizard to build a dialog in Eclipse. This is the code for LogonDialog.java.

When the OK button is pressed the logon information is validated. Errors are shown in the error status line. The OK button won't exit the Dialog unless the information is validated. The CANCEL button function isn't changed.


ListenForModelOutput

The guts of this class were taken from the Activator.start() method. The Activator class, startup() method is an excellent place to create application wide objects, like the AS400 and data queue objects. The problem is that the User Interface isn't running. Without the user interface the program can't get the logon information from the user.

This is the code for ListenForModelOutput.java.

This class
- activates the Dialog to get the user information
- if the Dialog information is validated then
-- start the model output data queue listener
-- prevent the user from executing the logon dialog again

The AS400 object is created in Activator.startup(). That made it easy to use the default dialog to get the logon information right there.

After the change the AS400 object is created in Activator's constructor. However it can't be used until the system, user and password are provided. The system, user and password can't be provided until the UI is running. So the AS400 object is created without a system, user or password.

The run() method of ListenForModelOutput first calls LogonDialog to get the system, user and password. LogonDialog will only return OK if the system, user and password are validated. To do this is sets these values in the AS400 object. With the validated information then it creates and starts the data queues, work that was previously done in Activator.startup().

Comment out this line of code in ListenForModelOutput.run() which prevents the user from trying to log one once the data queue is running.

	LogonAction.getDefault().setEnabled(false);

ListenForModelOutput will be ready to test before the LogonAction class is ready. You will have an error until that class is available, that is why this line is commented out.


Modify ApplicationWorkbenchWindowAdvisor to call ListenForModelOutput

Override the ApplicationWorkbenchWindowAdvisor.postWindowOpen() method to call ListenForModelOutput.

The postWindowOpen() method is called after the UI is stared and the application window is created or restored, but before the application starts. At this point the UI is up and running but the application hasn't done anything. Here is the place to get the system, user and password and then start the model output data queues and its listeners.

Put the cursor in the body of the class between methods, press Ctrl-space, and select postWindowOpen(). This code, except for the last line, will be added:

@Override
public void postWindowOpen() {
// TODO Auto-generated method stub
super.postWindowOpen();
// you add the following line
ListenForModelOutput.run();
}

Add the call to the run() method of ListenForModelOutput.


Modify the Activator class to remove the code now in ListenForModelOutput

Comment out everything in the start() method except the call to the super method. It will look like this:

	public void start(BundleContext context) throws Exception {
super.start(context);
}

Remove the method isAs400Connected().

To prevent the AS400 default logon dialog add this snippet to the constructor after instantiating the AS400 object:

	try {
as400.setGuiAvailable(false);
} catch( PropertyVetoException e) {}

See Elena Lowery's explanation.

Remove the method isAs400Connected().

Activator.java is creating the AS400 object but other classes are validating it and using it to create the Thread or KeyedDataQueue objects. So the AS400 object needs to be accessable from outside Activator and Activator needs methods to set the Thread and KeyedDataQueue objects since they are used in the stop() method.

Add these methods to Activator.java.

	/**
* Return AS400 object.
* @return AS400 object created during startup.
*/
public AS400 getAS400() {
return as400;
}

/**
* Thread to listen to model output data queue is create outside
* Activator class however Activator needs access in order to end
* the thread in a controlled way. Use this method to call back
* into Activator to set the Thread after it is created.
*
* @param Thread which has been started to listen to model output
* data queue.
*/
public void setMdloDqThread( Thread _mdloDqThread ) {
mdloDqThread = _mdloDqThread;
}

/**
* Model output data queue is create outside
* Activator class however Activator needs access in order to end
* the thread in a controlled way. Use this method to call back
* into Activator to set the data queue after it is created.
*
* @param Model output data queue to which Thread listens.
*/
public void setModelOutputDataQueue( ModelOutputDataQueue _mdloDq ) {
mdloDq = _mdloDq;
}

Well, that is quite a bit of hacking to the Activator which was first generated by the wizard. This is Activator.java with most of the original code commented out.

Now test RCP DtaQ Demo

It will work as before except
1. the log on dialog is handled by the applications UI, not the AS400 object, and
2. the cancel button does not end the application.

Messages from the sign on process, like "invalid user id" or "invalid password" appear in the message box of the dialog.


What about the Cancel button?

The cancel button of LogonDialog does not end the application. The Thread which listens to the model output data queue can't be started until the signon information is validated. If Cancel is allowed, does not terminate the application, then the application needs to provide the user a means to log on and start the data queue Thread.

To meet this need an action named "Logon" will be added to the File menu.

LogonAction.jpg

Basically the Logon action will do the same thing as postWindowOpen() method in the class ApplicationWorkbenchWindowAdvisor. The Logon action lets the user execute the method


ListenForModelOutput.run()

on demand. This method is called after the application window is opened. The action provides the means to re-execute this code if the user cancels the log on.


Create the Action

The Action is LogonAction.java, it is very short. The XML edited by PDE does the heavy lifting.

The run() method checks to see if the application is already listening to the model output data queue by calling

	ListenForModelOutput.isListening()

If the application is connected then run() will not execute

The method getDefault() returns the instance of LogonAction to the caller. This is specifically for the line that was commented out in ListenForModelOutput.run() so that it could be tested.

	LogonAction.getDefault().setEnabled(false);

This line of code calls back into LogonAction from ListenForModelOutput and disables the Action at the end of the run() method, when the connection is made and the Thread has been started to listen to the model output data queues.

Go back to ListenForModelOutput.run() and remove the comment, that is enable the code.


Use PDE to add an ActionSet extension point and define the logon action

- Open PDE (one way is to double click MANIFEST.MF in the META-INF folder.
- Go to the extention tab.
- Press the Add button.
- In the "Extension Point filter area" start typing "org.eclipse.ui.actionSets". When you see this on the list select it and press Finish. Don't select the template "Hello World" action.

pde1.jpg

- right click the new extension (...actionSets)
- select New
- select ActionSet, accept the default name actionSet1


pde2.jpg


These are the Extention Element Details.


pde3.jpg


You will need to add
- the icon (don't skip this, the Action won't work without something here)
- the tool tip
- the Action class, LogonAction.java


Add the Logon Action to the File menu

Edit ApplicationActionBarAdvisor.java to add the Logon action to the File menu.

Copy

	private IWorkbenchAction aboutAction;

then change the copied line to
	private IWorkbenchAction logonAction;

Instantiate logonAction, add a tooltip and register it.
	logonAction = new LogonAction(window);
logonAction.setToolTipText(
"Log onto System i and start listenting to model output data queue.");
register(logonAction);

The tooltip seems to be required. Sometimes the Action won't work if one is not provided.

Add logonAction to the File menu. Add this line:

	fileMenu.add(logonAction);

just above
	fileMenu.add(exitAction);.

That is it!

When RCP DtaQ Demo starts the connection dialog is displayed. If the login data is entered and OK is pressed the connection is made and the Thread to read the model output data queue starts.

The File menu has a new option, Logon. If the connection was made Logon is disabled (grayed out). If the connection was not made, the user pressed Cancel, then Logon is enabled and the user can connect the application to the System i.

The final source for the project to date is in the CVS, see

info.billblalock.eclipsercp.dtaqdemo2_311

Posted by Bill Blalock on May 31, 2007 at 7:40 PM | Comments (0)

May 13, 2007 11:00 PM

Java data queues 302 -- remove console output from RCP DtaQ Demo

Typically a rich client does not have console output. The classes brought over from Java data queue 211 write their output to stdout. They were designed for a Java command line or console application. RCP DtaQ Demo will be modified to eliminate the console output and use the rich client user interface (UI) and log file. When finished the application would look like this:

RCP%20with%203%20messages.jpg

- No console output
- The messages are written to the View (think subfile).
- The status line is used to alert the user (no alerts yet).
- Errors are written to the log file.

Notice the scroll bars at the bottom and the top. Those are automatically generated, they would disappear is the window were just a little larger.

The status line was used to display messages sent by the model in the initial version of RCP DtaQ Demo for the sake of brevity, to postpone the work described here. Those messages should be displayed in the UI. In this version the message will be moved to the View, replacing the constants "One", "Two" and "Three." Alerts will be displayed in the status line. Errors will be logged. The console output will be removed.

You should continue to develop on the project that you created in Java data queues 301.

The source is in the CVS. The project is info.billblalock.eclipsercp.dtaqdemo2_302. I renamed the project so that this version would remain as it is, and be seperate from the code of the prior and future versions. The completed source code for each step in RCP DtaQ Demo can be accessed by version.

Changes to the View class.

Define an ArrayList, a type of Collection, as a class variable. Think of it as a dynamic array. It will hold the lines that are displayed on the view.

 
private ArrayList tableArray;

Change the getElements() method to return an array of the contents of the ArrayList instead of a String[] of "One", "Two", "Three".

public Object[] getElements(Object parent) {
// return new String[] { "One", "Two", "Three" };
return tableArray.toArray();
}

Instantiate the ArrayList variable in the constructor and add the value of the data queue key to the list.

/**
* The constructor.
*/
public View() {
plugin = this;
tableArray = new ArrayList();
addTableEntry("The key generated for this client is: " +
IpDtaQKey.getDqKey()); }

Create a method to add an entry to the ArrayList. Think of this object as a dynamically allocated array. The parameter passed to the method will add the String as the next element of the array.

/**
* Add a String to ArrayList to be displayed in View.
* @param entry String to add to ArrayList which is displayed in View.
*/
public void addTableEntry( String entry ) {
tableArray.add( entry );
view.refresh();
}

This method is called by a class that adds an element to the View, passing the method a String of what is to be added to the view. After adding the String to the array that is display, the View is refreshed or reconstructed.

A new classes, Messages:

Every class in the dataqueue package which writes to the console, System.out.print() or Exception.printStackTrace(), has to be changed. We could add methods like setStatusLine() plus a logging method to each class. A lot of cut and paste.

setStatusLine() doesn't use anything from ModelDemoOutputDqListener so it can be moved to someplace that makes it easier to reuse. This is similar to putting a RPG procedure into a separate program or a service program instead of cut and pasting it as a sub-routine or sub-proceedure..

Create Messages class in the dataqueue package.

Messages.java is a convenience class to make it easy to write messages to the status line and log. It is set up so the methods can be accessed statically. For example


Messages.setStatusline("Hello, I am the status line.");

from any class in the project. It is the first new class that has been created for RCP DtaQ Demo, that is why the link.

Move setStatusline() method from ModelDemoOutputDqListener into Messages class and change from private to static public. The message method can be called anywhere by Messages.setStatusline(message). This eliminates cut and pasting the same method into each class which uses it.

The Messages class needs two more methods. One method writes an error message to the status line. The other writes a log entry.

This writes an error status to the status line. An error status will stay on the status line until it is removed by another setErrorStatus().


/**
* Set error status line of RCP with this message.
* @param message String to be placed on status line, set to
* null to clear status message.
*/
public static void setErrorStatusline(final String message) {
Activator.getDefault().getWorkbench().getDisplay().asyncExec(new Runnable() {
public void run() {
View.getDefault().getViewSite().getActionBars()
.getStatusLineManager().setErrorMessage(message);
}
});
}

The RCP wizard generate code to log errors. Right now the program uses it to record its start up data and any fatal errors. Think of it as a job log. This method enables your classes to write to it.

/**
* Write message to log.
* @param severity
* IStatus.OK
* IStatus.INFO
* IStatus.WARNING
* IStatus.ERROR
* IStatus.CANCEL
* @param pluginId Identify plugin or class which wrote the log entry.
* @param message Message to log.
* @param exception Thowable if applicable otherwise null
*/
public static void logEntry(int severity, String pluginId, String message,
Throwable exception) {
Activator.getDefault().getLog().log((IStatus)new Status(severity,
pluginId, 0, message, exception));
}

The About action in the File menu will display the log, at least if anything has been written to it. Press the Configuration Details button. View Error Log button is on the bottom left, it will be grayed out if there are no log entries. The log, if present, will be openned by an OS application you choose, for Windows that would usually be Notepad.

configuration%20details.jpg

ModelDemoOutputDqListener

Comment out System.out.println() output of the data queue entry read.

Add method to call View.addTableEntry with the message received from the data queue.


/**
* Add this message to the ArrayList which is displayed by the
* View and refresh the TableViewer.
* @param message String to be added to the table in View.
*/
private void addTableEntry(final String message) {
Activator.getDefault().getWorkbench().getDisplay().
asyncExec(new Runnable() {
public void run() {
View.getDefault().addTableEntry(message);
}
});
}

Comment out the line to set the status line with the message read from the data queue and replace it with call to addTableEntry(). The message read from the data queue will now appear in the view and not the status line.

// send output message to status line
// setStatusline( mdloMessage.trim());
// add output message to View
addTableEntry(mdloMessage.trim());

Define a constant to identify this class for the error log.

static final String classId =
"info.billblalock.eclipsercp.dtaqdemo2.dataqueue.ModelDemoOutputDqListener";

In the exception handler replace the stack trace with calls to Messages.logEntry() and setErrorStatusline(). The log will have the trace information and indicate what plugin or class wrote the log entry. The status line indicates to the user that a handled error occurred.

} catch (Exception e) {
// e.printStackTrace();
Messages.logEntry(IStatus.ERROR, classId,
"Error converting DataQueueEntry to model " +
"output dtaq record format", e );
Messages.setErrorStatusline(
"See log -- Error converting DataQueueEntry " +
"to model output dtaq record format");
}

Remove console output from ModelOutputDataQueue

The View class puts the data queue key as the first line of the table it displays. ModelOutputDataQueue no longer needs to write the data queue to the console.

Comment out


// System.out.println("Key used is: " + dqKey);

Remove the console output from the other classes in the dataqueue package. Have some fun and make your own output to the View, Statusline and/or Log.

Replace printStackTrace() with logEntry() and errorStatusline()

The ModelInputDataQueue.java and ModelOutputDataQueue.java classes report errors with printStackTrace() in one method. Modify the reportException() method of these two classes to write a log entry and set the error Statusline. Hint: This is a general reporting method, use e.getMessage() to get the description of the Exception for the log message and status line. Don't forget to add a constant to identify the class for the logEntry().

The method Activator uses both System.out.print() and Exception.printStackTrace(). This class can only write to the log because the UI is not established. In the start() method, where this error reporting is found, the UI has not yet been started. In the end() method the UI is probably closed. Replace this console output with Messages.logEntry().

Get creative.

You can clear the status line or error status line by calling the corresponding method in Messages with a null parameter.

You can write anything you want to the log. It is frequently used for debugging information. To separate your entries set the severity to OK, INFO or WARN.

Posted by Bill Blalock on May 13, 2007 at 11:00 PM | Comments (0)

May 6, 2007 7:00 PM

Java data queues 301 -- an RCP application to monitor the System i demonstration model output

This exercise builds an RCP application which monitor's the output data queue of the demonstration model. Eclipse RCP wizards are used to create an RCP application with a view that contains a table, the table shows a String[] with the values "One", "Two" and "Three." This blog entry shows how to run the wizards and modify the code generated by the wizards, and how to use the data queue classes created in Java data queues 211 blog entry.

The RCP application looks like when it first starts and determines the data queue key.

Startup%20and%20key%202.jpg

The console output of the key is a legacy of reusing classes from Java data queues 211. Future refinements will move this output to the user inferface and/or log file.

The is the RCP application after the CL view-controller on the System i puts the
- key "A80008",
- instruction "HELLO" and
- message "Bill Blalock"
in the demo model input data queue, the demo model has processed it and written to the output data queue.

showing%20message%20in%20status%20line%202.jpg

Do you want to give it a try?

These are the pre-requisites

You worked through the RCP tutorial by Ed Burnette on the Eclipse web site or had some other basic introduction to Eclipse RCP. This blog tutorial exercise modifies an example RCP application produced by Eclipse wizards. The different parts of the RCP produced by the wizards are explained in Ed's tutorial. This blog tutorial tells you what to modify but not why unless it is specific to data queues.

You built the System i demonstration model and view-controller. The RCP works with the demonstration model. By itself the RCP doesn't do anything. The demonstration view-controller on the System i will be used to provide input to the demonstration model. Without that there won't be anything for the model to read and display.

If you don't have access to a System i but you want to work through the Java parts of these exercises please write me. If there is need I will see what I can do to get you access to the demonstration model and view-controller on the system which I time share on. No promises except that I will try if there are requests.

You built the console data queue examples in the previous set blog entries (Java data queues 101-211), particularly the last one (Java data queues 211). The classes developed in Example3d, that is 211, will be used in this RCP application.

Where is the java source?

Links to html of each class referenced are not provided. If you want to see the modified source use the CVS web access to this project, info.billblalock.eclipsercp.dtaqdemo2_301 .

Eclipse RCP wizards will generate the code to be modified. The changes are simple and documented in this entry. The RCP Eclipse tutorial explains the code generated by the wizards.

You already have the dataqueue code from the Java data queues 211 blog entry.

Step 1 -- Use wizards to create a skeleton RCP to build upon

New > Project > Plug-in Project

Give it a name, my project name is

info.billblalock.eclipsercp.dtaqdemo2

Press Next

Change radio button to Yes for "Would you like to create a rich client application?" Press Next

Make sure "Create a plug-in using one of the templates" is checked. Choose "RCP application with a view." Press Next. This creates a view with a JFace table, the table data provider is a String[] statically loaded with the values shown.

Change "Application widow title:" from "RCP Application" to "RCP DtaQ Demo" or whatever you like. Press Finish

You should now have a skeleton RCP application. Try it and make sure it runs. For now run it from within Eclipse so output to stdout with System.out.println is shown in the console at the bottom of the IDE.

Step 2 -- Add JT Open archive to your project

Create a folder within your project named "lib". To do this right click your project,

New > Folder.

Import jt400.jar into lib. Right click the lib folder,

Import > General > File System and press Next.

Find the folder with jt400.jar on your system, check jt400.jar and press Finish.

If PDE is not open double click MANIFEST.MF in the META-INF folder to open it. Choose Runtime tab at the bottom. Press Add to the right of the Classpath box. You will see a list of folders in the project. Expand lib and select jt400.jar. Press Finish.

In the Java and Plug-in Development perspectives you will see that jt400.jar now appears in the root of the project, not in the lib folder.

How to add the JT Open archive to a project was explained in more detail earlier in the blog. If you need a more complete explanation see the modified RCP Tutorial blog entries.

An optional touch is to add javadocs to jt400.jar so the javadocs will be available from the Java editor. Right click jt400.jar,

Properties > Javadoc location

and put in the folder with the JT Open javadocs.

Try the application to make sure nothing was broken. Fix any errors before proceeding to the next step.


Step 3 -- Add or enable standard Eclipse RCP features

3a. Modify ApplicationActionBarAdvisor class to add About top level action to File menu. About will provide access to the log file. See the "Branding" section in Part 3 of the Eclipse RCP Tutorial for more information about the About feature.

Make a copy of

private IWorkbenchAction exitAction;

and change the copied statement to

private IWorkbenchAction aboutAction;

Make a copy of

exitAction = ActionFactory.QUIT.create(window);
register(exitAction);

and change the copied statement to

aboutAction = ActionFactory.ABOUT.create(window);
register(aboutAction);

Make a copy of

fileMenu.add(exitAction);

and change the copied statement to

fileMenu.add(aboutAction);

Try the application to make sure nothing was broken. Fix any errors before proceeding to the next step.


3b. Modify ApplicationWorkbenchWindowAdvisor to show status line.

A standard RCP feature not mentioned in the tutorial is the status line, at the bottom of the main window. In this application the status line will show the message received from the demo model. Later it will also show the user errors and alerts.

Change the line of code

configurer.setShowStatusLine(false);

to

configurer.setShowStatusLine(true);


3c. Modify ApplicationWorkbenchAdvisor to save window size and location. Override the WorkbenchAdvisor.initialize() method by adding this method:


@Override
public void initialize(IWorkbenchConfigurer configurer) {
configurer.setSaveAndRestore(true);
}

Change the launch configuration (Main tab) to give you the choice to clear workspace data before launching and to ask for confirmation before clearing. Select both of these check buttons. Each time the application is launched is you will be asked whether to clear the workspace. Clearing the workspace returns the application to its initial size, location and space allocation.


3d Modify Perspective class to show an editor area for future use.

The editor area is to be displayed so comment out

layout.setEditorAreaVisible(false);

Change the line of code

layout.addStandaloneView(View.ID, false, IPageLayout.LEFT, 1.0f, editorArea);

to

layout.addStandaloneView(View.ID, false, IPageLayout.TOP, 0.50f, editorArea);

this puts the view on the top half of the window and saves the bottom half for the future editor.

Try the application to make sure nothing was broken. Fix any errors before proceeding to the next step.


3e View class needs a means for other classes to reference it.

Do this the same way that the Activator class provides a means for other classes to reference Activator through the getDefault() method.

Add a static View object


// The shared instance
private static View plugin;

Override the default constructor to initialize the View object which will be the reference

/**
* The constructor.
*/
public View() {
plugin = this;
}

Add a method to return the reference.

/**
* Returns the shared instance
*
* @return the shared instance
*/
public static View getDefault() {
return plugin;
}

Step 4 -- Create a dataqueue package and import classes created in DtaQExample3d

4a Create the package. The package is the same root name of the package which contains the source generated by the wizard plug ".dataqueue". For example the package created for my project is

info.billblalock.eclipsercp.dtaqdemo2

The dataqueue package I will create will be named

info.billblalock.eclipsercp.dtaqdemo2.dataqueue

Your package name is based on the project name you choose.

Right click the project,

New > Package.

Put in the name of the package.


4b Import classes from the Java data queue examples into the new package. My project name, and the name in the CVS is:

info.billblalock.mvcintro.java_apps

Import all the classes in the common package into the new package.

Import only these classes from the dataqueue package into the new package.
- DtaQExample3dListener.java
- ModelInputDataQueue.java
- ModelOutputDataQueue.java

Right click the package,

Import > File system press Next

Find the common package, select all the classes and import them

Right click the package,

Import > File system press Next

Find the dataqueue package, select the three classes named above and import them


4c Fix the errors now in the imported classes.

All the imported packages will indicate errors. The first step to fixing these errors is to change the package from
package common;
or
package dataqueue;

to (for my case)
package info.billblalock.eclipsercp.dtaqdemo2.dataqueue;

Use the package name you specified in step 4a.

The only error remaining should be in DtaQExample3dListener. Edit this class. The remaining error should be this import statement

import common.MDLOFMFormat;

Remove or comment it out. The common package doesn't exist in this project and the MDLOFMFormat class is now in the same package so it doesn't need an import statement.

The dataqueue package should now have no errors. If there still errors you are on your own to track them down and fix them. Some classes in this package will have to be tweaked to work with the RCP GUI instead of the console (stdout) but most of the work is done and tested. How about that, reuse of classes!

Try the application to make sure nothing was broken. If there are still errors in the new dataqueue package you will get a warning that errors exist in the project. Since these classes aren't referenced yet the project will still run so press Proceed. Fix any errors before proceeding to the next step.


4d Use DtaQExample3dListener as the property change listener for this project.

Refactor > rename

DtaQExample3dListener.java

to

ModelDemoOutputDqListener.java


4e Add a method to the renamed listener class to update the status line of the RCP window. This is one means the listener will communicate what happens when a model output data queue entry is read, or attempted to be read.


/**
* Set status line of RCP with this message.
* @param message String to be placed on status line.
*/
private void setStatusline(final String message) {
Activator.getDefault().getWorkbench().getDisplay().syncExec(new Runnable() {
public void run() {
View.getDefault().getViewSite().getActionBars()
.getStatusLineManager().setMessage(message);
}
});
}

The wizard created the Activator.getDefault() method to allow other classes to get an instance of the running Activator.. You added View.getDefault() to the View class created by the wizard in step 3e to do the same thing.

The listener is running of in its own thread, totally disconnected from the thread in which the RCP is running. This is going to grab a reference to the thread in with the RCP UI is running and call the UI method to write the status line.


4f The listener now writes the data received from the data queue to the console. Also send the message received from the data queue to the status line.

Find this code:


// Get two values out of the record and display them.
String mdloInstruction = (String) mdloData.getField("OINSTRTN");
String mdloMessage = (String) mdloData.getField("OMESSAGE");
System.out.println(" * The model received instruction: "
+ mdloInstruction.trim()
+ "\n * and returned data: "
+ mdloMessage.trim());
System.out.println(" *********************************************");

Then add this line of code:

setStatusline( mdloMessage.trim());

This class uses the method just added (4e) to send the message to the status line.

Try the application to make sure nothing was broken. You will get a warning that errors exist in the project. Since these classes aren't referenced yet the project will still run so press Proceed. Fix any errors before proceeding to the next step.

The next step makes RCP DtaQ Demo a partner with your System i so it needs to be working at this point. This is the last chance you have to test the RCP without needing to be connected to a System i and have the demonstration model running.


Step 5 -- Connect RCP DtaQ Demo to the AS400 through the Activator class.

Now the project is ready to connect to the AS400.

The pseudo code logic of Java data queues 201 Example3d, the main() method, is:
i. set up the System i connection
ii. instantiated the Runnable, attached the listener, created the Thread that listens to the model output data queue and started the Thread.
iii. instantiated the object to write to the model input data queue
iv. looped accepting input to send to the model input data queue
v. looked for the end signal, *STOPITNOW, to break the loop
vi. closed down the Thread and disconnected from the System i.

Activator will be modified to do steps i, ii, iii and vi. The UI nature of the RCP replaces the need to loop waiting for input (iv). The exit action in the File menu or upper right X takes the place of the end signal (v).


5a. Add these class global variables to Activator


private static AS400 as400;
private static Thread mdloDqThread;
private static ModelOutputDataQueue mdloDq;

5b Instantiate the AS400 object in the constructor


as400 = new AS400();

This is done in the constructor because as400 is a class level object, available to all methods.


5c Add this code from DtaQExample3d (see previous blog entries) to the start() method
after the call to the base start() method:


super.start(context); // base start() method

// added code
try {
as400.connectService(AS400.CENTRAL);
// create instance of Runnable for Thread which reads data queue
mdloDq = new ModelOutputDataQueue(as400, Me.getMDLO_DTAQ(),
IpDtaQKey.getDqKey() );
// execute the run() method of the thread
mdloDqThread = new Thread(mdloDq);
// register a separate class as the listener for
// property change events
mdloDq.addPropertyChangeListener(new ModelDemoOutputDqListener() );
// execute the run() method of the thread
mdloDqThread.start();
if ( !as400.isConnected() ) {
System.out.println("... unable to connect to System i");
System.exit(0);
}
} catch(AS400SecurityException se) {
System.out.println("... signon cancelled");
System.exit(0);
} catch(Exception e) {
e.printStackTrace();
throw e;
}


The start method() now implements part i, ii and iii of Example3d. It is done before the UI gets going.


5d. Modify the stop() method to shut down the Thread which reads the model's output data queue. After the call to the base stopt() method add this code:


super.stop(context); // base stop method

// added code
mdloDq.stopReadingDq();
try {
mdloDqThread.join(5000);
} catch (InterruptedException e) {
// do nothing
}
as400.disconnectAllServices();
as400 = null;


See the previous blog entries for explanation of how this shuts down the Thread.

The stop() method now implements part vi of Example 3d. The stop() method is called when the UI shuts down.


Interlude --

At this point RCP DtaQ Demo can read the demonstration model's output data queue and display the message in the status line. You have to run it within Eclispe so that you can see the console output (System.out.println … we haven't eliminated it yet). This is a good place to take a break.

Here is how to test it.

1. Start the demonstration model on the System i. Use the demonstration CL view-controller on the System i to make sure it is running properly.

2. Start RCP DtaQ Demo in Eclipse so the stdout output goes to the console window.

3. You will be prompted for the AS400 connection information. After the connection is established the key that is generated from the IP address is displayed in the console.

4. Note the key generated -- in my case it is A80008. See the image at the introduction of this entry.

5. Use the demonstration view-client CL program on the System i to cause the model to write a data queue entry to the model's output data queue.

CL%20view-controller.jpg

Use the key that the RCP is listening for. Use the CL option for the view-controller to only write the model output data queue (last parameter is *YES), we want RCP Dtaq Demo to read it … not to have the CL view-controller read it first.

6. Shortly after the Enter is pressed the message from the demonstration model will show up in the status line and the console will show the stdout output. showing message in status line and console.jpg

showing%20message%20in%20status%20line%20and%20console.jpg


The source is in the CVS. The project is info.billblalock.eclipsercp.dtaqdemo2_301. I renamed the project so that this version would remain as it is, at version _301, and futher development would be posted under other versions.

RCP DtaQ Demo will later be enhanced to
- remove the console output, use the UI and log errors
- display the data queue messages in the view
- accept demonstration model input from the user.
I'll try to go a little more slowly, make the entries smaller and have more explanation since the new materials aren't covered by the RCP Tutorial (Ed Burnette) and Java data queues 101-211. This one turned out rather long because this is what it took to go from nothing to an RCP application which did something.

Posted by Bill Blalock on May 6, 2007 at 7:00 PM | Comments (0)

Bill Blalock
October 2008
Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Blog Policy

We welcome your comments and opinions and encourage lively debate on the issues. However, Penton Media reserves the right to delete or move any content that it may determine, in its sole discretion, violates or may violate its Terms of Use or is otherwise unacceptable. For more information, see Penton Media's Terms of Use.

ProVIP Sponsors