iSeries EGL

All things EGL for the iSeries / i5 / Power System

Archive for July 2012

A Multi-Select Widget

leave a comment »

Introduction

This post illustrates how to create a new widget so that it can be included into a new project or existing project.

The Widget

The widget will present a list of items from which the user may select one, some or all to be included into a working list. As they are select from the original list to be added to the working list they are removed from the list on the left.

Shown here is the widget as it appears in the designer.

The Mulit-Select widget consists of 2 ListMulti widgets and a couple of buttons.

The widget includes several functions that allow the developer to establish short descriptions that appear above each list and to populate each ListMulti widget with values. The buttons are left as they appear and let the user move the selected items from one list to another.

Here is an example of the widget as it is used by the main application after it has been fully initialized.

A fully initialized Multi-Select widget running in an application.

Below is the source code for this very short web-page. The start function does all the work of initializing. In this case the list is filled with different types of aircraft. The user may select one or more from the list at the left and then select the button with the “>” arrow which moves the selected item(s) to the list shown on the right. Modifying the list of selected items (at right) is performed the same way; select the desired items from the list at right and select the button marked as “<" and the items are placed back into the list on the left.

package com.mig.selectwidget.client;

// RUI Handler

import org.eclipse.edt.rui.widgets.GridLayout;
import org.eclipse.edt.rui.widgets.GridLayoutData;

//
//

handler Test type RUIhandler{initialUI =[ui
            ], onConstructionFunction = start, cssFile = "css/SelectIncludeWidget.css", title = "Test"}

    ui GridLayout{columns = 3, rows = 3, cellPadding = 4, children = [ selectincludewidget]};
    selectIncludeWidget SelectIncludeWidget{ layoutData = new GridLayoutData{ row = 2, column = 2 }};

    function start()
    	
    	includeItems String[] = new String[8];
    	
     	includeItems[1] = "Piper Cub";       	
     	includeItems[2] = "North American T-6G";       
     	includeItems[3] = "North American T-28";     
     	includeItems[4] = "Lockheed T-33A";       
     	includeItems[5] = "Douglas C-47D";          	
    	includeItems[6] = "Cessna 152";
    	includeItems[7] = "Cessna 172";    	
     	includeItems[8] = "Piper Archer PA-28-181";  
      	     	
     	this.selectIncludeWidget.setSelectList(includeItems);
 
 		this.selectIncludeWidget.setSelectTextLabel("Selectable Aircraft");
 		this.selectIncludeWidget.setIncludeTextLabel("Included Aircraft");
		this.selectIncludeWidget.setListWidths(180);
		this.selectIncludeWidget.setListSizes(15);
		 
    end
    
end

Fig.1 – An example of an application using the widget.

Note the start function’s use of the widget’s functions that let the developer initialize the list entries, the short descriptions that appear above each in addition to the length and width of each list. The widget’s functions are listed here.

  • setSelectList(stringArray String[]) Sets the list of selectable items shown on the left side of the widget.
  • setSelectTextLabel(labelText String) Sets the text label appearing over the selection list shown at the left of the widget.
  • setIncludeTextLabel(stringArray String[]) Sets the text label appearing over the include list shown at the right of the widget.
  • setListWidths(widths int) Sets the widths of the list windows.
  • setListSizes(sizes int) Sets the sizes of the list windows in terms of the number of entries that are visible before a scroll bar is made visible.

Below is the full source listing for the widget. To use it, simply add the code to your project and then drag-n-drop it into your page.

package com.mig.selectwidget.client;

// RUI Widget

import org.eclipse.edt.rui.widgets.GridLayout;
import dojo.widgets.DojoComboBox;
import org.eclipse.edt.rui.widgets.GridLayoutData;
import dojo.widgets.DojoButton;
import org.eclipse.edt.rui.widgets.GridLayoutLib;
import org.eclipse.edt.rui.widgets.ListMulti;
import org.eclipse.edt.rui.widgets.TextLabel;

//
//

handler SelectIncludeWidget type RUIWidget{targetWidget = ui, onConstructionFunction = start, cssFile = "css/SelectIncludeProject.css", @VEWidget{category = "Custom"}}
    ui GridLayout{columns = 3, rows = 6, cellPadding = 0, children = [ excludeSelectedButton, selectSelectedButton, includeTextLabel, selectTextLabel, selectListMulti, includeListMulti],
    	padding = 0,
    	marginLeft = 0};
    selectSelectedButton DojoButton{ layoutData = new GridLayoutData{ row = 3, column = 2,
    	horizontalAlignment = GridLayoutLib.ALIGN_CENTER,
    	verticalAlignment = GridLayoutLib.VALIGN_MIDDLE }, text = ">", onClick ::= selectSelectedButton_onClick };
    excludeSelectedButton DojoButton{ layoutData = new GridLayoutData{ row = 5, column = 2,
    	horizontalAlignment = GridLayoutLib.ALIGN_CENTER,
    	cellPadding = 0 }, text = "<", onClick ::= exludeSelectedButton_onClick };
    	
    selectListMulti ListMulti{ layoutData = new GridLayoutData{ row = 2, column = 1,
    	verticalSpan = 5 }, values = ["selectListMulti"], size = 10,
    	width = "120"  };
    includeListMulti ListMulti{ layoutData = new GridLayoutData{ row = 2, column = 3,
    	verticalSpan = 5 }, values = ["includeListMulti1"], size = 10,
    	width = "120" };


	//This will be used to preserve the developer-defined list of initial values from which
	//the user selects entries to be included in the list seen at the right of the widget.
	preserveSelectValues String[] ;
	selectTextLabel TextLabel{ layoutData = new GridLayoutData{ row = 1, column = 1 }, text="TextLabel" };
	includeTextLabel TextLabel{ layoutData = new GridLayoutData{ row = 1, column = 3 }, text="TextLabel" };
	
	
    function start()
    	includeListMulti.values = new String[];
    end
    
    function setListWidths(value int in)
    	selectListMulti.width = value;
    	includeListMulti.width = value;
    end	
    
    function setListSizes(value int in)
    	selectListMulti.size = value;
        includeListMulti.size = value;
    end
    
    function setSelectTextLabel(value String)
    	selectTextLabel.text = value;
    end
    
    function setSelectList(values String[])
    	selectListMulti.values = values;
    	
    	size int = values.getSize();
    	preserveSelectValues = new String[ ];
    	preserveSelectValues.appendAll(values);
    	
    end
     
    function setIncludeTextLabel(value String)
    	includeTextLabel.text = value;
    end   
    
    
    function getIncudedList() returns(String[])
    	return(includeListMulti.values);
    end
    
    //**********************************************************************
    //
    //
    function selectSelectedButton_onClick(event Event in)
    	    	
        //Isolate the values which are remaining in the selectListMulto to update the list.
        workSelectableValues String[]  = selectListMulti.values;
        

    	//Isolate the values which may already be in includeListMulti to preserve the list.
    	workIncludedValues String[]  = includeListMulti.values;
    	
  	
    	//Get the number of selections available in selectListMulti.
    	numberOfSelections int = selectListMulti.selection.getSize();
 
    	if (numberOfSelections > 0)
    		
    		//Iterate through the item numbers 
    		for(idx int from 1 to numberOfSelections)
    			selectEntryIndex int = selectListMulti.selection[idx];
    			selectedEntryValue string = selectListMulti.values[selectEntryIndex];
    			workIncludedValues.appendElement( selectedEntryValue );  	 
    		end
    		
    		//Process in reverse order to properly remove the entries
    		for(idx int from numberOfSelections to 1 decrement by 1)
    		  selectEntryIndex int = selectListMulti.selection[idx];	
    		  workSelectableValues.removeElement(selectEntryIndex);	
    		end
    		
    		//Update the ListMulti widgets
    		selectListMulti.values = workSelectableValues;
 			includeListMulti.values = workIncludedValues;
 			
 
 			
    	end
    end
    


    //**********************************************************************
    //
    //    
    function exludeSelectedButton_onClick(event Event in)
                
        //Isolate the values which are remaining in the selectListMulto to update the list.
        workSelectableValues String[]  = selectListMulti.values;
 
        //Isolate the values which may already be in includeListMulti to preserve the list.
        workIncludedValues String[]  = includeListMulti.values;
        
    
        //Get the number of entries available in includeListMulti.
        numberOfIncluded int = includeListMulti.selection.getSize();
 
        if (numberOfIncluded > 0)
            
            //Iterate through the item numbers 
            for(idx int from 1 to numberOfIncluded)
                includedEntryIndex int = includeListMulti.selection[idx];
                includedEntryValue string = includeListMulti.values[includedEntryIndex];
                workSelectableValues.appendElement( includedEntryValue );      
            end
            
            // Process in reverse order to properly remove the entries
            for(idx int from numberOfIncluded to 1 decrement by 1)
              selectEntryIndex int = includeListMulti.selection[idx];    
              workIncludedValues.removeElement(selectEntryIndex); 
            end
            
            //Update the ListMulti widgets
            selectListMulti.values = workSelectableValues;
            includeListMulti.values = workIncludedValues;
            
        end    	
    end
   
end

Fig.2 – The full source for the widget.

Summary

This post showed how custom widgets can be used and re-used across difference applications. Designing EGL applications in this manner can result in productivity gains by reducing development and testing times.
 
 

Advertisements

Written by iseriesadmin

July 29, 2012 at 5:13 pm

Posted in EGL Widgets, Rich UI

Tagged with ,

A Multi-page RichUI Web Architecture Using EGL

with one comment

Introduction

This post presents a simple multi-page web architecture using EGL and RichUI components. The architecture provides the means to manage navigation between pages while also providing a simple method of allowing the pages to share data using a central storage mechanism.

Be aware that these pages were developed using the open source version of EGL as opposed to using the Community Edition or RDi’s RBD plug in. Therefore, when importing the source into RDi the imports will have to be updated to reflect the libraries provided by the RBD product.

The following EGL handlers and widgets are presented and are described below.

  • HomePage.egl (RUIhandler)
  • This is the home page of the web application . The final html file generated from this EGL part and which is deployed onto the web application server will be the page referenced in the URL (i.e. http://server:port/applicationName/HomePage.html) that was supplied to the browser.

    While it is referenced as the home page for the application it has nothing within to display as would be expected by a normal RUIHander part. It is simply an empty container which holds the current page as requested by the user. It handles user requests for a new page by swapping the current page with the requested page.

  • Page01.egl (RUIWidget)
  • This represents the first page of the web application. Using menu items provided it may navigate to page 2 and page 3.

  • Page02.egl (RUIWidget)
  • This represents the second page of the web application. Using menu items provided it may navigate to page 1 and page 3.

  • Page03.egl (RUIWidget)
  • This represents the third page of the web application. Using menu items provided it may navigate to page 2 and page 1.

 

The files presented above are designed to work together. In the IDE’s project space, they will appear as shown below.

The EGL source files as seen in the EGL project.


You may have noticed a few extra files i.e. Splash.egl and Test.egl. While the first represents a simple screen that presents the name of the application, it can be omitted from your project as it is not an integral part of the architecture. The second file is simply a development artifact and should be ignored.

 

Operation and Behavior

When running the applicatin the first screen to be presented is of course, page 1. To navigate to any other page in the series the user may select the menu option “Go to” from which the appropriate page can be selected. The navigation manager then presents the page selected by the user.

For demonstration purposes, a text message is presented to indicate the page from which navigation occured which was passed by the logic of that page so that it could be presented on the new page. The more important aspect of this message is that it serves to demonstrate how information can be passed from one page to the next during the navigation process.

EGL’s InfoBus is used to pass data from one page to the next as needed. The InfoBus is also used by each web page to communicate to the page navigation manager the page to which the user wishes to navigate. Prior to page navigation each page places data into an EGL Library part which acts as the session data object seen in normal web page development using languages such as Java.

Persisting Session Variables

The SessionLibrary part is presented here. It is used to persist session values so they may be made available to the new page presented by the navigation manager. Just before leaving the page, the logic within that page uses the provided functions to persist the values required for each page.
 

package com.mig.testnav.libraries;

// basic library
library SessionLibrary
	
	// Use Declarations
	//use usePartReference;
	
	// Variable Declarations

        //This is the runtimeEnvironment ("localhost", "TEST" or "PROD")
	private runtimeEnvironment string;	

        //These contain the current screen being displayed and the screen 
        //that will be displayed.  
	private screenName string;
	private toScreenName string;	
	

	function setRuntimeEnvironment(value string in)
		this.runtimeEnvironment = value;
	end
	
	function getRuntimeEnvironment() returns(string)
		return(this.runtimeEnvironment );
	end
	

	function setFromScreen(value string in)
		this.screenName = value;
	end
	
	function getFromScreen() returns(string)
		return(this.screenName);
	end

	
	function setToScreen(value string in)
		this.toScreenName = value;
	end
	
	function getToScreen() returns(string)
		return(this.toScreenName);
	end
	
end

Source code for the SessionLibrary part

 

When using the SessionLibrary in a real project, you can omit the variables for screenName and toScreenName in addition to their functions. They are present simply to demonstrate how variable values can be shared by every screen within the application thereby simulating session variables used by Java servlets.

Storing Constants for a Project

Constants are stored in a separate EGL Library part. Libraries provide a way to make values and functions available across the application.

The ProjectLibrary part that contains constants (which follow standard naming conventions) is presented here.

package com.mig.testnav.libraries;

// basic library
library ProjectLibrary
	
  	// Constant Declarations
	const CONST_APPLICATION_NAME string = "Test Page Navigation";

	const CONST_NAVIGATION_DATA_CALLBACK string = "navigationDataCallBack";	

	const CONST_SESSION_DATA string = "sessionData";

	
	// Variable Declarations
	variableName string;
	
end

Source code for the ProjectLibrary which contains constants

Note how the constant fields are in all uppercase with each word separated by an underscore, which follows the standard for constants. With the fact that each is prefixed with “CONST_” (CONSTant), it ensures that the code completion feature of the IDE will sort the constants together in the list, making it easier to visually isolate a constant from the entries presented.
 
 

The Page Navigation Manager

As previously described this EGL part manages page navigation. It contains an array of widgets ( Widgets[] ) that will hold the pages of the web application.

The EGL program is almost ready to use and has plenty of comments explaining where to make changes before it is ready to be used in your application. There are only 2 places that require modification. The first is the size of the array that holds each page or widget. The second is the function performLazyLoad() which must be modified as indicated in its comment section preceding the function.

package com.mig.testnav.client;

// RUI Handler

//************************************************
//*  Imports for Open Source Version of EGL
//************************************************
import org.eclipse.edt.rui.infobus.infobus;
import org.eclipse.edt.rui.widgets.Box;
import org.eclipse.edt.rui.widgets.Div;
import org.eclipse.edt.rui.widgets.GridLayout;
import org.eclipse.edt.rui.widgets.HTML;
import com.mig.testnav.libraries.ProjectLibrary;
import com.mig.testnav.libraries.SessionLibrary;


//************************************************
//*  Imports for EGL / RBD for RDi
//************************************************
import com.ibm.egl.rui.infobus.infobus;
import com.ibm.egl.rui.widgets.Div;
import com.mig.testnav.libraries.ProjectLibrary;
import egl.javascript.job;
import egl.ui.rui.widget;


//************************************************************
// This is the Navigation Manager (NavMan) for the EGL web site.
// The only responsibility of the developer is to add a new instance
// to the array Widget[].  
//
// No other modifications to the NavMan should be made so that it
// remains as agnostic as possible about the application.
//  

handler HomePage type RUIhandler{initialUI =[ui
            ], onConstructionFunction = start, cssFile = "css/TestNavProject.css", title = "HomePage"}

    ui Div{position = "relative", x = 10, y = 10, width = "1410", height = "2000", borderColor = "LightGray", borderWidth = 1, borderStyle = "solid", children =[splash
            ]};

    //    ui Box{ padding=8,columns = 1,  
    //     	padding=8, columns = 1, 
    //    	x = 10,
    //    	y = 10,   	
    //    	borderColor = "LightGray",
    //    	borderWidth = 1,
    //    	borderStyle = "solid",  
    //    	children = [ splash ] };
    
    splash Div{children =[ new Splash{}
            ], borderWidth = 1, borderColor = "Black"};

    //**********************************************************************
    //*TO DEVELOPER : Change the size of Widget to match the number of pages
    //              : in the application.  Make no other modifications to 
    //              : this section
    //**********************************************************************
    pages Widget[3];
 	
 	
    pageStack int[100];

    fromPage string;

	

    //**********************************************************************
    //* TO DEVELOPER : DO NOT MODIFY THIS FUNCTION *
    //
    function start()

        Infobus.subscribe(ProjectLibrary.CONST_NAVIGATION_DATA_CALLBACK, navigationInfoBusCallBack);
        new Job{runFunction = start2}.schedule(3000);
		
    end

    function start2()
        addPage(1);
    end

    //**********************************************************************
    // This function is called from any of the web application screens.
    // The call is executed via the following construct:
    //	"InfoBus.publish(ProjectLibrary.CONST_APPLICATION_NAME, newPage);"
    //
    // *TO DEVELOPER : DO NOT MODIFY THIS FUNCTION *
    function navigationInfoBusCallBack(event string in, data any in)

        newPage int = data as int;
        if(newPage == -1)
            if(pageStack.getSize() > 1)
                ;
                pageStack.removeElement(pageStack.getSize());
            end
            showPage(pageStack[pageStack.getSize()]);
        else
            addPage(newPage);
        end
    end

	
    //**********************************************************************
    // Performs a lazy load of the web page being requested.   It does this
    // by interrogating the pages array for entries.  The scheme rests upon
    // the idea that each entry of the array corresponds to a page within
    // the navigation sequence. When the page requested is not found one
    // is instantiated and added to the array, thus the lazy load.
    //
    // *TO DEVELOPER : MODIFY THIS FUNCTION TO PERFORM THE FOLLOWING -
    //	    o INCLUDE THE SAME NUMBER OF BOOLEANS AS THERE ARE PAGES
    //      o INCLUDE THE SAME NUMBER OF if (pages[idx] isa Page01) 
    //      o INCLUDE THE SAME NUMBER OF if (newPage == 1 && !page01Found)
    //      Of course, for the last 2 above, modify Page01 and page01Found
    //      to properly reflect the page ID required.
    //
    function performLazyLoad( newPage int )
		
	page01Found boolean   = false;
	page02Found boolean   = false;
	page03Found boolean   = false;

	//Iterate through the array of web pages to determine if the
	//page being requested has already been loaded				
	for (idx int from 1 to pages.getSize())
			
	    //If page is already in the page array then exit
            if (pages[idx] isa Page01) 
		page01Found = true;
	    end
	    //If page is already in the page array then exit
	    if (pages[idx] isa Page02) 
		page02Found = true;
	    end
	    //If page is already in the page array then exit
	    if (pages[idx] isa Page03) 
		page03Found = true;
	    end			
        end

        //If the page requested is not found in the pages[] array 
        //add a new instance of the page.
        if (newPage == 1 && !page01Found)
	    pages[newPage] = new Page01;
        end
        if (newPage == 2 && !page02Found)
	    pages[newPage] =new Page02;
        end
        if (newPage == 3 && !page03Found)
 	    pages[newPage] = new Page03;
        end

        //Now when navigation proceedes it will find the page in 
        //the array.
		 		
    end
	
	
    //**********************************************************************
    // Add the new page to the page stack and show it.
    // *TO DEVELOPER : DO NOT MODIFY THIS FUNCTION *
    function addPage(newPage int in)
    	
    	performLazyLoad(newPage);
    	
        pageStack ::= newPage;
        showPage(newPage);
    end


    //**********************************************************************
    // Show the page requested.
    // *TO DEVELOPER : DO NOT MODIFY THIS FUNCTION *
    function showPage(newPage int in)
        ui.children =[pages[newPage]];

        //This was added to communicate to the destination page information 
        //about page navigation which can be obtained from the Session Library
        //which was placed there by the screen making the navigation request.
        InfoBus.publish(ProjectLibrary.CONST_SESSION_DATA, "GetDataFromSessionLibrary");
        //End of Modification.
        
    end

end

This version of the page navigation manager is for RDi with RBD plug-in

 

How It Performs Navigation

The page navigation manager uses an important feature in EGL, the InfoBus, which is used to communicate information from one RichUI Handler to another. The use of the InfoBus can be seen with these lines;

  • Infobus.subscribe([subscribed name], [function-to-be-called]);
  • function [function-to-be-called](event string in, data any in).

These entries are placed into the RichUI Handler that desires to expose a function (the second entry) through the InfoBus so that other RichUI handlers or widgets may call that function. For those handlers or widgets wishing to call the function, the following is placed inside each.
InfoBus.publish([subscribed name], [value required for the function]);

I’m going to digress a bit. Personally, I wish the designers had instead named the InfoBus functions subscribe and publish as register and evoke so that it better reflects what is actually happening. We’ll see the use of the publish function shortly. Ok, digression over.

Below is a diagram that illustrates how all this works together. The subscribe function has two parameters. (See Item 1 at the bottom of the diagram.) The first provides the name or handle being assigned to the function name provided by the second parameter. The navigationInfoBusCallBack function which was supplied by the subscribe function is registered with the InfoBus. The second argument – the function name to be called – is then made available, i.e. publicized, and can therefore be called by any other program by way of the InfoBus. This is illustrated by the line of code indicated by Item 3 which resides in each of the Rich UI Widget programs represented by Page 1 and Page 2. Item 2 represents the function being called which resides in the navigation manager which receives the page identifier as a parameter value passed by the caller (Item 3).

The InfoBus allows the project’s pages to communicate with the Page Navigation Manager which presents the desired page as requested.

How Screens Pass Data

In a similar manner, each screen of the application also register functions to be evoked, however, they are doing it for a different reason which is to pass data from the current screen to the destination screen. Each screen’s start() function registers the SessionDataInfoBusCallBack function using the InfoBus’s subscribe function as shown;
Infobus.subscribe(ProjectLibrary.CONST_SESSION_DATA, SessionDataInfoBusCallBack);
Remember, the first parameter is simply the name being assigned to the function name supplied by the second parameter. It will be up to the page navigation handler to evoke it.

 

Pages 1, 2 and 3

This section presents screen shots for each page and the source code for each.

 

Page 1

Presented below is a screen shot for page 1. The source code for this page follows.

Page 1


 

Depending upon the version of the IDE you are using, (the open source version of EGL using Eclipse or IBM’s RDi with RDB) you will need to delete the appropriate set of imports. Both sets have been provided for convenience. You just need to decide which set needs to be deleted. No other modifications are required.

package com.mig.testnav.client;

// RUI Widget

//************************************************
//*  Imports for Open Source Verion of EGL
//************************************************
import org.eclipse.edt.rui.infobus.infobus;
import org.eclipse.edt.rui.widgets.Box;
import org.eclipse.edt.rui.widgets.Div;
import org.eclipse.edt.rui.widgets.GridLayout;
import org.eclipse.edt.rui.widgets.GridLayoutData;
import org.eclipse.edt.rui.widgets.GridLayoutLib;
import org.eclipse.edt.rui.widgets.Image;
import org.eclipse.edt.rui.widgets.Menu;
import org.eclipse.edt.rui.widgets.MenuItem;
import org.eclipse.edt.rui.widgets.TextLabel;
import com.mig.testnav.libraries.ProjectLibrary;
import com.mig.testnav.libraries.SessionLibrary;
import dojo.widgets.DojoMenu;
import dojo.widgets.DojoMenuItem;
import dojo.widgets.DojoTitlePane;


//************************************************
//*  Imports for RBD plug-in for RDi 
//************************************************
import com.ibm.egl.rui.infobus.infobus;
import com.ibm.egl.rui.widgets.Div;
import com.ibm.egl.rui.widgets.GridLayout;
import com.ibm.egl.rui.widgets.GridLayoutData;
import com.ibm.egl.rui.widgets.GridLayoutLib;
import com.ibm.egl.rui.widgets.Image;
import com.ibm.egl.rui.widgets.TextLabel;
import com.mig.testnav.libraries.ProjectLibrary;
import com.mig.testnav.libraries.SessionLibrary;
import dojo.widgets.DojoMenu;
import dojo.widgets.DojoMenuItem;
import dojo.widgets.DojoTitlePane;

//
//

handler Page01 type RUIWidget{targetWidget = ui, onConstructionFunction = start, cssFile = "css/TestNavProject.css", @VEWidget{category = "Custom"}}



    ui GridLayout{columns = 2, rows = 5, cellPadding = 4, children = [ BodyPane, ControlPane, MenuBar, GridLayout],
    	width = "1400",
    	position = "relative",
    	x = 20,
    	y = 10,
    	borderColor = "Black",
    	borderWidth = 0,
    	borderStyle = "solid"};
    GridLayout GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 1 }, cellPadding = 4, rows = 1, columns = 2,
    	children = [ Image, GridLayout1],
    	borderColor = "LightGrey",
    	borderStyle = "solid",
    	borderWidth = 1,
    	width = "1350" };
    MigDepartmentName TextLabel{ layoutData = new GridLayoutData{ row = 1, column = 1 }, text = "Department Name",
    	fontSize = "26",
    	fontWeight = "bold",
    	color = "SteelBlue" };
    MigApplicationName TextLabel{ layoutData = new GridLayoutData{ row = 2, column = 1 }, text = "The Application Name",
    	fontSize = "18",
    	color = "SteelBlue" };
    GridLayout1 GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 1 }, cellPadding = 4, rows = 2, columns = 3,
    	children = [ MigApplicationName, MigDepartmentName] };
    Image Image{ layoutData = new GridLayoutData{ row = 1, column = 2,
    	horizontalAlignment = GridLayoutLib.ALIGN_RIGHT },
    	src = "MigLogo03.png"};
    MenuBar GridLayout{ layoutData = new GridLayoutData{ row = 2, column = 1,
    	cellPadding = 0 }, cellPadding = 4, rows = 1, columns = 3,
    	backgroundColor = "RGB(245,245,245)",
    	width = "1350",
    	children = [ InnerMenuLayout ],
    	padding = 0,
    	margin = 0,
    	height = "40" 
    	  };
    HelpMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 4 }, text = "Help", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    FileMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 1 }, text = "File", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    EditMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 2 }, text = "Edit", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    InnerMenuLayout GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 1,
    	verticalAlignment = GridLayoutLib.VALIGN_MIDDLE,
    	horizontalAlignment = GridLayoutLib.ALIGN_LEFT }, cellPadding = 4, rows = 1, columns = 5,
    	children = [ gotoMenu, HelpMenu, EditMenu, FileMenu],
    	height = "32" };
    ControlPane DojoTitlePane{ layoutData = new GridLayoutData{ row = 3, column = 1 }, title = "Control Pane", isOpen=true, duration=1000, width = "1350", children = [ new Div {
    	children = [ ControlPaneGridLayout ]
    } ] };
    ControlPaneGridLayout GridLayout{ cellPadding = 4, rows = 3, columns = 3,
    	children = [ TextLabel ] };
    BodyPane DojoTitlePane{ layoutData = new GridLayoutData{ row = 4, column = 1 }, title = "Main Data Pane", isOpen=true, duration=1000, width = "1350", children = [ new Div {
    	children = [ BodyPaneGridLayout ]
    } ] };
    BodyPaneGridLayout GridLayout{ cellPadding = 4, rows = 3, columns = 3 };
    gotoMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 3 }, text = "Go to", children = [
 
		new DojoMenuItem {
			text = "Page2", iconClass = "dijitEditorIcon dijitEditorIconCut", onClick ::= onPage2
		},
		new DojoMenuItem {
			text = "Page3", iconClass = "dijitEditorIcon dijitEditorIconCut", onClick ::= onPage3
		},		
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	]};
    TextLabel TextLabel{ layoutData = new GridLayoutData{ row = 2, column = 1 }, text="TextLabel" };
 


    function start()
    	
    	//Register a callback function to process communication requests made through the InfoBus.
        Infobus.subscribe(ProjectLibrary.CONST_SESSION_DATA, SessionDataInfoBusCallBack);   	
        
        //Set Page Titles as required
    	MigDepartmentName.text = "Information Technology";
       	MigApplicationName.text = "Application Name - Page 01";
       	ControlPane.title = "Control Pane Title";
       	BodyPane.title = "Body Pane Title";
       	
       	//Startup Processing to get Runtime Environment and to read properties from XML file.
       	
       	//Get the screen name from which we came.
       	this.TextLabel.text = SessionLibrary.getFromScreen();
      	    
      	       	
    end
 
	function SessionDataInfoBusCallBack(event string in, data any in)
		this.TextLabel.text = "Navigation occurred from " + SessionLibrary.getFromScreen();
	end    
    
    function onPage2(e Event in)
     	toPage(2); 
    end
    
    function onPage3(e Event in)
    	toPage(3); 
    end
    
	//**********************************************************************
	// This function navigates to the requested screen. If the page's design
	// requires certain data elements to be passed to the destination page
	// place the elements into the Session Library established for this purpose 
	// before publishing the navigation request.
	//
    function toPage(newPage int in)
    	;
    	//Set this page as the page from which and to which we are navigating
    	SessionLibrary.setFromScreen("Page01");
    	SessionLibrary.setToScreen("Page0"+newPage);
    	    	
    	//SessionLibrary.setFromScreen("From Page 01");
    	InfoBus.publish(ProjectLibrary.CONST_NAVIGATION_DATA_CALLBACK, newPage);    	
    end
    
     
end

Source code for Page 1

 

Page 2

Presented below is a screen shot for page 2. The source code for this page follows.

Page 2


 

Depending upon the version of the IDE you are using, (the open source version of EGL using Eclipse or IBM’s RDi with RDB) you will need to delete the appropriate set of imports. Both sets have been provided for convenience. You just need to decide which set needs to be deleted. No other modifications are required.

package com.mig.testnav.client;

// RUI Widget

//************************************************
//*  Imports for Open Source Verion of EGL
//************************************************
import org.eclipse.edt.rui.infobus.infobus;
import org.eclipse.edt.rui.widgets.Box;
import org.eclipse.edt.rui.widgets.Div;
import org.eclipse.edt.rui.widgets.GridLayout;
import org.eclipse.edt.rui.widgets.GridLayoutData;
import org.eclipse.edt.rui.widgets.GridLayoutLib;
import org.eclipse.edt.rui.widgets.Image;
import org.eclipse.edt.rui.widgets.TextLabel;
import com.mig.testnav.libraries.ProjectLibrary;
import com.mig.testnav.libraries.SessionLibrary;
import dojo.widgets.DojoMenu;
import dojo.widgets.DojoMenuItem;
import dojo.widgets.DojoTitlePane;



//************************************************
//*  Imports for RBD plug-in for RDi 
//************************************************
import com.ibm.egl.rui.infobus.infobus;
import com.ibm.egl.rui.widgets.Div;
import com.ibm.egl.rui.widgets.GridLayout;
import com.ibm.egl.rui.widgets.GridLayoutData;
import com.ibm.egl.rui.widgets.GridLayoutLib;
import com.ibm.egl.rui.widgets.Image;
import com.ibm.egl.rui.widgets.TextLabel;
import com.mig.testnav.libraries.ProjectLibrary;
import com.mig.testnav.libraries.SessionLibrary;
import dojo.widgets.DojoMenu;
import dojo.widgets.DojoMenuItem;
import dojo.widgets.DojoTitlePane;


//
//

handler Page02 type RUIWidget{targetWidget = ui, onConstructionFunction = start, cssFile = "css/TestNavProject.css", @VEWidget{category = "Custom"}}



    ui GridLayout{columns = 2, rows = 5, cellPadding = 4, children = [ BodyPane, ControlPane, MenuBar, GridLayout],
    	width = "1400",
    	position = "relative",
    	x = 20,
    	y = 10,
    	borderColor = "Black",
    	borderWidth = 0,
    	borderStyle = "solid" };
    GridLayout GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 1 }, cellPadding = 4, rows = 1, columns = 2,
    	children = [ Image, GridLayout1],
    	borderColor = "LightGrey",
    	borderStyle = "solid",
    	borderWidth = 1,
    	width = "1350" , backgroundColor = "RGB(40,95,175)"};
    MigDepartmentName TextLabel{ layoutData = new GridLayoutData{ row = 1, column = 1 }, text = "Department Name",
    	fontSize = "26",
    	fontWeight = "bold",
    	color = "White" };
    MigApplicationName TextLabel{ layoutData = new GridLayoutData{ row = 2, column = 1 }, text = "The Application Name",
    	fontSize = "18",
    	color = "White" };
    GridLayout1 GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 1 }, cellPadding = 4, rows = 2, columns = 3,
    	children = [ MigApplicationName, MigDepartmentName] };
    Image Image{ layoutData = new GridLayoutData{ row = 1, column = 2,
    	horizontalAlignment = GridLayoutLib.ALIGN_RIGHT },
    	src = "MigLogo00.png"};
    MenuBar GridLayout{ layoutData = new GridLayoutData{ row = 2, column = 1,
    	cellPadding = 0 }, cellPadding = 4, rows = 1, columns = 3,
    	backgroundColor = "RGB(245,245,245)",
    	width = "1350",
    	children = [ InnerMenuLayout ],
    	padding = 0,
    	margin = 0,
    	height = "40" 
    	  };
    HelpMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 4 }, text = "Help", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		} 
	],
    	height = "22"};
    FileMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 1 }, text = "File", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    EditMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 2 }, text = "Edit", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    InnerMenuLayout GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 1,
    	verticalAlignment = GridLayoutLib.VALIGN_MIDDLE,
    	horizontalAlignment = GridLayoutLib.ALIGN_LEFT }, cellPadding = 4, rows = 1, columns = 4,
    	children = [ HelpMenu, EditMenu, FileMenu, gotoMenu],
    	height = "32" };
    ControlPane DojoTitlePane{ layoutData = new GridLayoutData{ row = 3, column = 1 }, title = "Control Pane", isOpen=true, duration=1000, width = "1350", children = [ new Div {
    	children = [ ControlPaneGridLayout ]
    } ] };
    ControlPaneGridLayout GridLayout{ cellPadding = 4, rows = 3, columns = 3,
    	children = [ TextLabel ] };
    BodyPane DojoTitlePane{ layoutData = new GridLayoutData{ row = 4, column = 1 }, title = "Main Data Pane", isOpen=true, duration=1000, width = "1350", children = [ new Div {
    	children = [ BodyPaneGridLayout ]
    } ] };
    BodyPaneGridLayout GridLayout{ cellPadding = 4, rows = 3, columns = 3 };

    gotoMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 3 }, text = "Go to", children = [
		new DojoMenuItem {
			text = "Back", iconClass = "dijitEditorIcon dijitEditorIconCut", onClick ::= onBack
		},
		new DojoMenuItem {
			text = "Page1", iconClass = "dijitEditorIcon dijitEditorIconCut", onClick ::= onPage1
		}, 
		new DojoMenuItem {
			text = "Page3", iconClass = "dijitEditorIcon dijitEditorIconCut", onClick ::= onPage3
		},		
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	]};
    TextLabel TextLabel{ layoutData = new GridLayoutData{ row = 2, column = 2 }, text="TextLabel" };
	
    function start()
    	
    	//Register a callback function to process communication requests made through the InfoBus.
        Infobus.subscribe(ProjectLibrary.CONST_SESSION_DATA, SessionDataInfoBusCallBack);   	
        
        //Set Page Titles as required      	
    	MigDepartmentName.text = "Information Technology";
       	MigApplicationName.text = "Application Name - Page 02";
       	ControlPane.title = "Control Pane Title";
       	BodyPane.title = "Body Pane Title";
       	
       	//Startup Processing to get Runtime Environment and to read properties from XML file.
       	
       	//Get the screen name from which we came.
       	this.TextLabel.text = SessionLibrary.getFromScreen();
    end
    
 
	function SessionDataInfoBusCallBack(event string in, data any in)
		this.TextLabel.text = "Navigation occurred from " + SessionLibrary.getFromScreen();
	end   
    
    function onBack(e Event in)
    	toPage(-1); 
    end
    
     
    function onPage1(e Event in)
    	toPage(1); 
    end   
    function onPage3(e Event in)
    	toPage(3); 
    end
    
    
	//**********************************************************************
	// This function navigates to the requested screen. If the page's design
	// requires certain data elements to be passed to the destination page
	// place the elements into the Session Library established for this purpose 
	// before publishing the navigation request.
	//    
    function toPage(newPage int in)
    	
    	//Set this page as the page from which and to which we are navigating
    	SessionLibrary.setFromScreen("Page02");
    	SessionLibrary.setToScreen("Page0"+newPage);
    	 
     	//SessionLibrary.setFromScreen("From Page 02");
		InfoBus.publish(ProjectLibrary.CONST_NAVIGATION_DATA_CALLBACK, newPage);    	
    end

    
end

Source code for Page 2

 

Page 3

Presented below is a screen shot for page 3. The source code for this page follows.

Page 3


 

Depending upon the version of the IDE you are using, (the open source version of EGL using Eclipse or IBM’s RDi with RDB) you will need to delete the appropriate set of imports. Both sets have been provided for convenience. You just need to decide which set needs to be deleted. No other modifications are required.

package com.mig.testnav.client;

// RUI Widget

//************************************************
//*  Imports for Open Source Verion of EGL
//************************************************
import org.eclipse.edt.rui.infobus.infobus;
import org.eclipse.edt.rui.widgets.Box;
import org.eclipse.edt.rui.widgets.Div;
import org.eclipse.edt.rui.widgets.GridLayout;
import org.eclipse.edt.rui.widgets.GridLayoutData;
import org.eclipse.edt.rui.widgets.GridLayoutLib;
import org.eclipse.edt.rui.widgets.Image;
import org.eclipse.edt.rui.widgets.TextLabel;
import com.mig.testnav.libraries.ProjectLibrary;
import com.mig.testnav.libraries.SessionLibrary;
import dojo.widgets.DojoMenu;
import dojo.widgets.DojoMenuItem;
import dojo.widgets.DojoTitlePane;

 
//************************************************
//*  Imports for RBD plug-in for RDi 
//************************************************
import com.ibm.egl.rui.infobus.infobus;
import com.ibm.egl.rui.widgets.Div;
import com.ibm.egl.rui.widgets.GridLayout;
import com.ibm.egl.rui.widgets.GridLayoutData;
import com.ibm.egl.rui.widgets.GridLayoutLib;
import com.ibm.egl.rui.widgets.Image;
import com.ibm.egl.rui.widgets.TextLabel;
import com.mig.testnav.libraries.ProjectLibrary;
import com.mig.testnav.libraries.SessionLibrary;
import dojo.widgets.DojoMenu;
import dojo.widgets.DojoMenuItem;
import dojo.widgets.DojoTitlePane;

//
//

handler Page03 type RUIWidget{targetWidget = ui, onConstructionFunction = start, cssFile = "css/TestNavProject.css", @VEWidget{category = "Custom"}}



    ui GridLayout{columns = 2, rows = 5, cellPadding = 4, children = [ BodyPane, ControlPane, MenuBar, GridLayout],
    	width = "1400",
    	position = "relative",
    	x = 20,
    	y = 10,
    	borderColor = "Black",
    	borderWidth = 0,
    	borderStyle = "solid" };
    GridLayout GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 1 }, cellPadding = 4, rows = 1, columns = 2,
    	children = [ Image, GridLayout1],
    	borderColor = "LightGrey",
    	borderStyle = "solid",
    	borderWidth = 1,
    	width = "1350",  backgroundColor = "DarkCyan" };
    MigDepartmentName TextLabel{ layoutData = new GridLayoutData{ row = 1, column = 1 }, text = "Department Name",
    	fontSize = "26",
    	fontWeight = "bold",
    	color = "White" };
    MigApplicationName TextLabel{ layoutData = new GridLayoutData{ row = 2, column = 1 }, text = "The Application Name",
    	fontSize = "18",
    	color = "White" };
    GridLayout1 GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 1 }, cellPadding = 4, rows = 2, columns = 3,
    	children = [ MigApplicationName, MigDepartmentName] };
    Image Image{ layoutData = new GridLayoutData{ row = 1, column = 2,
    	horizontalAlignment = GridLayoutLib.ALIGN_RIGHT },
    	src = "MigLogo00.png"};
    MenuBar GridLayout{ layoutData = new GridLayoutData{ row = 2, column = 1,
    	cellPadding = 0 }, cellPadding = 4, rows = 1, columns = 3,
    	backgroundColor = "RGB(245,245,245)",
    	width = "1350",
    	children = [ InnerMenuLayout ],
    	padding = 0,
    	margin = 0,
    	height = "40" 
    	  };
    HelpMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 4 }, text = "Help", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    FileMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 1 }, text = "File", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    EditMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 2 }, text = "Edit", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    InnerMenuLayout GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 1,
    	verticalAlignment = GridLayoutLib.VALIGN_MIDDLE,
    	horizontalAlignment = GridLayoutLib.ALIGN_LEFT }, cellPadding = 4, rows = 1, columns = 4,
    	children = [ HelpMenu, EditMenu, FileMenu, gotoMenu],
    	height = "32" };
    ControlPane DojoTitlePane{ layoutData = new GridLayoutData{ row = 3, column = 1 }, title = "Control Pane", isOpen=true, duration=1000, width = "1350", children = [ new Div {
    	children = [ ControlPaneGridLayout ]
    } ] };
    ControlPaneGridLayout GridLayout{ cellPadding = 4, rows = 3, columns = 3,
    	children = [ TextLabel ] };
    BodyPane DojoTitlePane{ layoutData = new GridLayoutData{ row = 4, column = 1 }, title = "Main Data Pane", isOpen=true, duration=1000, width = "1350", children = [ new Div {
    	children = [ BodyPaneGridLayout ]
    } ] };
    BodyPaneGridLayout GridLayout{ cellPadding = 4, rows = 3, columns = 3 };

    gotoMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 3 }, text = "Go to", children = [
		new DojoMenuItem {
			text = "Back", iconClass = "dijitEditorIcon dijitEditorIconCut", onClick ::= onBack
		},
		new DojoMenuItem {
			text = "Page1", iconClass = "dijitEditorIcon dijitEditorIconCut", onClick ::= onPage1
		},
		new DojoMenuItem {
			text = "Page2", iconClass = "dijitEditorIcon dijitEditorIconCut", onClick ::= onPage2
		}, 		
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	]};
    TextLabel TextLabel{ layoutData = new GridLayoutData{ row = 2, column = 2 }, text="TextLabel" };
	
    function start()
    	
    	//Register a callback function to process communication requests made through the InfoBus.
        Infobus.subscribe(ProjectLibrary.CONST_SESSION_DATA, SessionDataInfoBusCallBack);   	
        
        //Set Page Titles as required	
    	MigDepartmentName.text = "Information Technology";
       	MigApplicationName.text = "Application Name - Page 03";
       	ControlPane.title = "Control Pane Title";
       	BodyPane.title = "Body Pane Title";
       	
       	//Startup Processing to get Runtime Environment and to read properties from XML file.
       	
       	//Get the screen name from which we came.
       	this.TextLabel.text = SessionLibrary.getFromScreen();
       	    	
       	       	
    end

 
	function SessionDataInfoBusCallBack(event string in, data any in)
		this.TextLabel.text = "Navigation occurred from " + SessionLibrary.getFromScreen();
	end  
	
    function onBack(e Event in)
    	toPage(-1); 
    end
    
    function onPage1(e Event in)
    	toPage(1); 
    end

    function onPage2(e Event in)
    	toPage(2); 
    end  
 
 
 	//**********************************************************************
	// This function navigates to the requested screen. If the page's design
	// requires certain data elements to be passed to the destination page
	// place the elements into the Session Library established for this purpose 
	// before publishing the navigation request.
	//   
    function toPage(newPage int in)

    	//Set this page as the page from which and to which we are navigating
    	SessionLibrary.setFromScreen("Page03");
    	SessionLibrary.setToScreen("Page0"+newPage);
    	 
    	//SessionLibrary.setFromScreen("From Page 03");
		InfoBus.publish(ProjectLibrary.CONST_NAVIGATION_DATA_CALLBACK, newPage);    	
    end

        
end

Source code for Page 3

 

 

Credit

The source code for the page navigator was presented by Joe Pluta at the Eclipse Community Forum for the EDT project supporting the open source version of EGL and is the basis for the navigation scheme presented. It was augmented to demonstrate parameter passing between pages supported by employing EGL’s InfoBus.
 
 

Written by iseriesadmin

July 22, 2012 at 5:37 pm

Naming Conventions

leave a comment »

Introduction

This post presents a number of important and useful programming conventions. If you follow them your EGL code will be self-documenting and easier to read and maintain.

Naming and Capitalization Conventions

The standards that follow are derived from David Flanagan’s book, “Java In A Nutshell”, third edition. Since EGL development is similar to Java development these standards can apply to EGL as well. EGL development can often include Java code to help with tasks that EGL cannot perform and so adopting these standards will naturally apply to any Java source members included into the EGL project. Later, when the EGL developer endeavours to embark upon developing web applications using Java alone, they can apply the same standards they have been using all along for EGL and will serve to make that transition much easier.

The naming conventions refer to packages, EGL parts (programs, services, records, libraries, external types, etc.), functions, fields and constants in EGL. Because these conventions are universally followed in the Java development community and to some degree by the .NET community they are very well suited for the EGL development community. The naming standards for fields and functions can also be applied to RPG-Free.

  • Packages
    EGL source files, whether they are for RichUI Handers, Services, External Types or Records, are organized into related groups known as packages and should be made unique by prefixing them with the inverted name of an internet name, such as “com.mig.application”.

    Whether for Java or EGL, packages should follow the convention as shown.

      com.mig.[project name].[package name].  

    Naming in this way will ensure they are unique enough to avoid name collision if packages encapsulated within a .jar file are included in the project. All package names should be lowercase.
     

  • EGL Parts
    All EGL parts are files used to create EGL applications. These are Logic parts including Program parts and Library parts, which are general-use parts, as well as Service parts, External-Type parts, and Handler parts, which have more specialized uses.

    EGL part names should be nouns as they represent “things” or “objects”. (e.g. Customer, Invoice, Policy, etc.) The names for these parts should begin with a capital letter and be written in mixed case. If a part name consists of more than one word, each word should begin with a capital letter (e.g. CancerPolicyService, CustomerEntryHandler, ClaimsService etc.). If an EGL part, or one of the words in the part name is an acronym, the acronym can be written using capital letters (e.g. URL, HTMLParser).
     

  • Interfaces
    Interface names follow the same capitalization conventions as EGL Parts. When an interface is used to provide additional information about the par that implements it, it is common to choose an interface name that is an adjective (e.g. Runnable, Cloneable, Serializable, DataInput). When an interface works more like an abstract representation of the part, use nouns (e.g. Document, FileName, Collection).
     

  • Functions
    Function names should contain a verb as they are used to make an EGL Handler, Service or Program perform an action. Adjectives and nouns can be included in its name.

      function showPage(newPage int in)
      function toPage(newPage int in)

    A function name always begins with a lowercase letter. If the name contains more than one word, every word after the first begins with a capital letter (e.g. insert(), addPolicy(), updateClaim(), etc.). Function names are typically chosen so that the first word is a verb. Function names can be as long as needed to make their purpose clear, but choose succinct names where possible.
     

  • Variables and Constants
    Nonconstant variable names should be nouns and should follow the same capitalization conventions as function names. If a field is a constant it should be written in uppercase. If the name of the constant includes more than one word, the words should be separated with underscores (e.g. MAX_VALUE, EMAIL_ADDRESS, MACHINE_ID, USER_PASSWORD, etc.) A field name should be chosen to best describe the purpose of the field or the value it holds.
     

  • Parameters
    The names of function parameters appear in the documentation for a function as presented by the IDE’s code assist facility. Therefore, you should choose names that make the purpose of the parameters as clear as possible. Try to keep parameter names to a single word and use them consistently. For example, if a CancerClaimService service-part defines many functions that accept a claim number as the first parameter, name this parameter claimNumber in each function.
     

  • Local Variables
    Local variable names are an implementation detail and never visible outside of the EGL Part. Nevertheless, choosing good names makes your code easier to read, understand, and maintain. Variables are typically named following the same conventions as functions and fields.
     

Written by iseriesadmin

July 14, 2012 at 2:53 pm

A Starting Template for a RichUI Handler

leave a comment »

Introduction

This post presents source code to be used as a starting point for coding a Rich UI handler. Presented are two variations giving a “minimalist” appearance based on the philosophy of “less is more”. The screens are not exposed to an internet based audience where flashy presentations designed to capture and keep the attention of the user is not a requirement. On the contrary, the screens are deliberately austere in appearance allowing the user to focus on the task at hand which is to enter and/or maintain information as it relates to the business where distractions impacting accuracy must be minimized.

Design Features

The source creates a header for a title and an area below it for a collection of menu items. The menu items are just place holders to indicate this is the area where they should reside and until logic is added they essentially do nothing. If the page design does not require menu options the developer should delete them but leave the bar in which they would normally reside.

Adding a menu option begins by right-clicking on the grid layout component and adding a new column within which the option will reside. (Click to enlarge.)


What remains below the menu bar constitutes the main body of the web page which is further divided into two sections. The first section is intended to contain widgets allowing for input of data to be provided by the user. The user data supplied is then used to retrieve information from the database to be presented in the second section that is presented below the first. If there are no business requirements that must allow the user to enter such data (i.e. part number, customer account number, policy number, etc.) then the first section should be deleted.

As mentioned above, the second section constitutes the main area where data is presented. More often than not the data presented here is retrieved using user-supplied data provided in widgets contained in the first section described above. If the application is a browse/select type where the user is allowed to see a list of data then a data grid would be presented in this section. As another example, if the first section allows for information to be entered for a new inventory item number, a customer account number or policy number, the second section would then be filled with the appropriate widgets or components to display the related data for the purpose of inquiry or maintenance.

Because the two sections are contained in a title pane the user can collapse them by selecting the downward pointing arrow at the left of each of the pane’s titles. The user may select the arrow after supplying select criteria or a policy number to retrieve the information related to minimize its space on the browser screen.

The Source Code

Presented below is source code for a Rich UI handler that acts as a template or starting point for all web applications. Using a template such as this will serve to ensure all web pages are presented with a uniform appearance and behavior. This in turn will minimize training time and expense and ensure the user’s understanding of screen behavior can be applied to the next application in the system without having to rely upon guessing.

Source Template for a Rich UI Handler – Variation 1

Presented below is the source code for the first variation of the overall look which can be best described as having a “minimalist” appearance.

package com.app.pagetemplate.client;

// RUI Handler

//Remove one of the following sets of imports as needed.

//************************************************
//*  Imports for Open Source Verion of EGL
//************************************************
import org.eclipse.edt.rui.widgets.GridLayout;
import org.eclipse.edt.rui.widgets.GridLayoutData;
import org.eclipse.edt.rui.widgets.TextLabel;
import org.eclipse.edt.rui.widgets.Image;
import org.eclipse.edt.rui.widgets.GridLayoutLib;
import org.eclipse.edt.rui.widgets.Box;
import dojo.widgets.DojoMenu;
import dojo.widgets.DojoMenuItem;
import dojo.widgets.DojoTitlePane;
import org.eclipse.edt.rui.widgets.Div;

//************************************************
//*  Imports for EGL RBD (RDi plugin)
//************************************************
import com.ibm.egl.rui.widgets.Div;
import com.ibm.egl.rui.widgets.GridLayout;
import com.ibm.egl.rui.widgets.GridLayoutData;
import com.ibm.egl.rui.widgets.GridLayoutLib;
import com.ibm.egl.rui.widgets.Image;
import com.ibm.egl.rui.widgets.TextLabel;
import egl.io.sql.column;
import egl.ui.color;
import dojo.widgets.DojoMenu;
import dojo.widgets.DojoMenuItem;
import dojo.widgets.DojoTitlePane;


//
//

handler WebPageTemplate type RUIhandler{ initialUI =[ui
            ], onConstructionFunction = start, cssFile = "css/WebPageTemplateProject.css", title = "WebPageTemplate"}

    ui GridLayout{columns = 3, rows = 5, cellPadding = 4, children = [ BodyPane, ControlPane, MenuBar, GridLayout],
    	width = "1400",
    	position = "relative",
    	x = 50,
    	y = 10,
    	borderColor = "LightGrey",
    	borderWidth = 1,
    	borderStyle = "solid"};
    GridLayout GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 2 }, cellPadding = 4, rows = 1, columns = 3,
    	children = [ Image, GridLayout1],
    	borderColor = "LightGrey",
    	borderStyle = "solid",
    	borderWidth = 1,
    	width = "1350" };
    MigDepartmentName TextLabel{ layoutData = new GridLayoutData{ row = 1, column = 1 }, text = "Department Name",
    	fontSize = "26",
    	fontWeight = "bold" };
    MigApplicationName TextLabel{ layoutData = new GridLayoutData{ row = 2, column = 1 }, text = "The Application Name",
    	fontSize = "18" };
    GridLayout1 GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 2 }, cellPadding = 4, rows = 2, columns = 3,
    	children = [ MigApplicationName, MigDepartmentName] };
    Image Image{ layoutData = new GridLayoutData{ row = 1, column = 3,
    	horizontalAlignment = GridLayoutLib.ALIGN_RIGHT },
    	src = "MigLogo03.png"};
    MenuBar GridLayout{ layoutData = new GridLayoutData{ row = 2, column = 2,
    	cellPadding = 0 }, cellPadding = 4, rows = 1, columns = 3,
    	backgroundColor = "RGB(245,245,245)",
    	width = "1350",
    	children = [ InnerMenuLayout ],
    	padding = 0,
    	margin = 0,
    	height = "40" 
    	  };
    HelpMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 3 }, text = "Help", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    FileMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 1 }, text = "File", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    EditMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 2 }, text = "Edit", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    InnerMenuLayout GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 1,
    	verticalAlignment = GridLayoutLib.VALIGN_MIDDLE,
    	horizontalAlignment = GridLayoutLib.ALIGN_LEFT }, cellPadding = 4, rows = 1, columns = 3,
    	children = [ HelpMenu, EditMenu, FileMenu],
    	height = "32" };
    ControlPane DojoTitlePane{ layoutData = new GridLayoutData{ row = 3, column = 2 }, title = "Control Pane", isOpen=true, duration=1000, width = "1350", children = [ new Div {
    	children = [ ControlPaneGridLayout ]
    } ] };
    ControlPaneGridLayout GridLayout{ cellPadding = 4, rows = 3, columns = 3 };
    BodyPane DojoTitlePane{ layoutData = new GridLayoutData{ row = 4, column = 2 }, title = "Main Data Pane", isOpen=true, duration=1000, width = "1350", children = [ new Div {
    	children = [ BodyPaneGridLayout ]
    } ] };
    BodyPaneGridLayout GridLayout{ cellPadding = 4, rows = 3, columns = 3 };


    function start()
    	
    	MigDepartmentName.text = "Information Technology";
       	MigApplicationName.text = "Application Name";
       	ControlPane.title = "Control Pane Title";
       	BodyPane.title = "Body Pane Title";
       	
       	//Startup Processing to get Runtime Environment and to read properties from XML file.
       	
       	
    end
end

Fig.1 – Source template for a Rich UI handler

 

Shown below is a screen shot for the above source code.

 
 

Source Template for a Rich UI Handler – Variation 2

Presented below is the source code for the second variation of the overall look. The only difference is the header section containing the title which has been filled with a blue color ( backgroundColor = “RGB(40,95,175)” ) with a white color for the title font.

package com.app.pagetemplate.client;

// RUI Handler

//Remove one of the following sets of imports as needed.

//************************************************
//*  Imports for EGL CE
//************************************************
import org.eclipse.edt.rui.widgets.GridLayout;
import org.eclipse.edt.rui.widgets.GridLayoutData;
import org.eclipse.edt.rui.widgets.TextLabel;
import org.eclipse.edt.rui.widgets.Image;
import org.eclipse.edt.rui.widgets.GridLayoutLib;
import org.eclipse.edt.rui.widgets.Box;
import dojo.widgets.DojoMenu;
import dojo.widgets.DojoMenuItem;
import dojo.widgets.DojoTitlePane;
import org.eclipse.edt.rui.widgets.Div;

//************************************************
//*  Imports for EGL RBD (RDi plugin)
//************************************************
import com.ibm.egl.rui.widgets.Div;
import com.ibm.egl.rui.widgets.GridLayout;
import com.ibm.egl.rui.widgets.GridLayoutData;
import com.ibm.egl.rui.widgets.GridLayoutLib;
import com.ibm.egl.rui.widgets.Image;
import com.ibm.egl.rui.widgets.TextLabel;
import egl.io.sql.column;
import egl.ui.color;
import dojo.widgets.DojoMenu;
import dojo.widgets.DojoMenuItem;
import dojo.widgets.DojoTitlePane;
//
//

handler WebPageTemplate type RUIhandler{ initialUI =[ui
            ], onConstructionFunction = start, cssFile = "css/WebPageTemplateProject.css", title = "WebPageTemplate"}

    ui GridLayout{columns = 3, rows = 5, cellPadding = 4, children = [ BodyPane, ControlPane, MenuBar, GridLayout],
    	width = "1400",
    	position = "relative",
    	x = 50,
    	y = 10,
    	borderColor = "LightGrey",
    	borderWidth = 1,
    	borderStyle = "solid"};
    GridLayout GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 2 }, cellPadding = 4, rows = 1, columns = 3,
    	children = [ Image, GridLayout1],
    	borderColor = "LightGrey",
    	borderStyle = "solid",
    	borderWidth = 1,
    	width = "1350",
    	backgroundColor = "RGB(40,95,175)" };
    MigDepartmentName TextLabel{ layoutData = new GridLayoutData{ row = 1, column = 1 }, text = "Department Name",
    	fontSize = "26",
    	fontWeight = "bold",
    	color = "White" };
    MigApplicationName TextLabel{ layoutData = new GridLayoutData{ row = 2, column = 1 }, text = "The Application Name",
    	fontSize = "18",
    	color = "White" };
    GridLayout1 GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 2 }, cellPadding = 4, rows = 2, columns = 3,
    	children = [ MigApplicationName, MigDepartmentName] };
    Image Image{ layoutData = new GridLayoutData{ row = 1, column = 3,
    	horizontalAlignment = GridLayoutLib.ALIGN_RIGHT },
    	src = "MigLogo04.png"};
    MenuBar GridLayout{ layoutData = new GridLayoutData{ row = 2, column = 2,
    	cellPadding = 0 }, cellPadding = 4, rows = 1, columns = 3,
    	backgroundColor = "RGB(245,245,245)",
    	width = "1350",
    	children = [ InnerMenuLayout ],
    	padding = 0,
    	margin = 0,
    	height = "40" 
    	  };
    HelpMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 3 }, text = "Help", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    FileMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 1 }, text = "File", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    EditMenu DojoMenu{ layoutData = new GridLayoutData{ row = 1, column = 2 }, text = "Edit", children = [
		new DojoMenuItem {
			text = "Item 1, please set onClick", iconClass = "dijitEditorIcon dijitEditorIconCut"
		},
		new DojoMenuItem {
			text = "Item 2, please set iconClass", iconClass = "dijitEditorIcon dijitEditorIconCopy"
		},
		new DojoMenuItem {
			text = "The next item is a separator"
		},
		new DojoMenuItem { },
		new DojoMenuItem {
			text = "Item 3, this one is disabled", disabled = true
		}
	],
    	height = "22"};
    InnerMenuLayout GridLayout{ layoutData = new GridLayoutData{ row = 1, column = 1,
    	verticalAlignment = GridLayoutLib.VALIGN_MIDDLE,
    	horizontalAlignment = GridLayoutLib.ALIGN_LEFT }, cellPadding = 4, rows = 1, columns = 3,
    	children = [ HelpMenu, EditMenu, FileMenu],
    	height = "32" };
    ControlPane DojoTitlePane{ layoutData = new GridLayoutData{ row = 3, column = 2 }, title = "Control Pane", isOpen=true, duration=1000, width = "1350", children = [ new Div {
    	children = [ ControlPaneGridLayout ]
    } ] };
    ControlPaneGridLayout GridLayout{ cellPadding = 4, rows = 3, columns = 3 };
    BodyPane DojoTitlePane{ layoutData = new GridLayoutData{ row = 4, column = 2 }, title = "Main Data Pane", isOpen=true, duration=1000, width = "1350", children = [ new Div {
    	children = [ BodyPaneGridLayout ]
    } ] };
    BodyPaneGridLayout GridLayout{ cellPadding = 4, rows = 3, columns = 3 };


    function start()
    	
    	MigDepartmentName.text = "Information Technology";
       	MigApplicationName.text = "Application Name";
       	ControlPane.title = "Control Pane Title";
       	BodyPane.title = "Body Pane Title";
       	
       	//Startup Processing to get Runtime Environment and to read properties from XML file.
       	
       	
    end
end



Fig.2 – Source template for a Rich UI handler

 

Shown below is a screen shot for the above source code.

Variation 2

 
 

Written by iseriesadmin

July 13, 2012 at 9:45 pm

Application Startup Processing

leave a comment »

Introduction

This post illustrates the start-up processing phase of an arbitrary EGL based web application. The focus will be about how to incorporate some of the building blocks already presented which are used to help initialize the application.

The code to acquire the runtime environment variable is contained within runtimeEnvironment.jar. The code used to read the XML file is contained within appUtilities.jar.

Ask a member of the development team for these files so they can be included into your project.

Application Properties

Most web applications will have configurable program values stored in a file external to the application. The values are usually contained within an XML file. Shown below is an XML containing values for a comment, a version number and three values for an email address.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">

<properties> 

    <comment>Configuration File</comment>

    <entry key="version">20120710.01.00</entry >

    <entry key="localhost.emailAddress">theDeveloper@theCorporateNetwork.com</entry >

    <entry key="TEST.emailAddress">theDeveloper@theCorporateNetwork.com</entry >

    <entry key="PROD.emailAddress">realDistributionList@theCorporateNetwork.com</entry >

</properties>

Fig.1 – A simple set of property values in an XML file.

 
The entries for <comment> and <entry key=”version”> is pretty much self-explanatory. The first is to hold a simple comment for the developer while the second contains a version number for the application.

The entries for <entry key=”localhost.emailAddress”>, <entry key=”TEST.emailAddress”> and <entry key=”PROD.emailAddress”> hold values reserved for one of the 3 possible servers in which the application will run. Each entry for email address is preceded with either ‘localhost’, ‘TEST’ or ‘PROD’ which represent the server running on the developer’s machine (i.e. 127.0.0.1, a.k.a ‘localhost’) the server assigned to the role of application testing (“TEST’) and the server assigned to the production role (‘PROD’).

In this situation, this approach of assigning application property values allows the developer to test the email application so that during the development-testing phase, emails will only be sent to the developer rather than a community of users. The same holds true for the TEST server. When the application is finally deployed to the production server the correct production-oriented email address is used.

By prefixing each property value with a server identifier, a unique value can be established for each server. This allows the application to pick up the correct value that has been assigned for the server in which the application is running. The only trick now is to get the application to determine which server it happens to be running on.
 

Placement of the Property File Within the EGL Project

As previously stated, the code used to read the XML file is contained within appUtilities.jar. As a consequence the XML file must be placed into a directory known to it, as shown below.

The ‘src/config’ folder must be placed as shown.


In addition, the XML file must be named ‘applicationConfig.xml’.
 

Determining The Server’s Role During Startup

Getting the right value during run-time rests upon the application’s ability to determine which server it happens to be running on. This is done by assigning an externally-defined value to each of the servers. To see how this is accomplished please refer to this post.

Once this value (‘TEST’ or ‘PROD’) has been established the application can read it which usually occurs at the very beginning when the application is first started.

The idea here is to read this value (‘TEST’ or ‘PROD’) and use it to append to the property name so that the retrieval process picks up the correct value which is then cached inside the application so that it can refer to it when needed. In this case, that would be when the application needs to send an email.

This post illustrates how to create EGL code to read the environment variable (EV) assigned to Tomcat’s JVM.
 

Reading Application Properties From The XML File

This section will illustrate how to create an External Type that is the interface to an external Java application.

The first thing to do is to create an EGL External Type so that the Java methods that are used to read the XML file can be called from the EGL Service program

Two functions have been crossed out from the list as they will not be discussed here.

package com.mig.jobmessages.externaltypes;

externalType ConfigurationCache type JavaObject{PackageName = "com.app.utilities.configuration"}
    
    static function getInstance() returns(ConfigurationCache);

    function setRuntimeEnvironment(runtimeEnvironment String in);    
    function getBaseProperties();
    function setPropertyTableEntry(propertyName String in, propertyValue String in );
    function cacheAppPropertyValues(listOfPropertyNames String[] in);
    function getPropertyTableEntry(propertyName String in )  returns (String);
    
end

Fig.2 – An EGL External Type used to read property values in an XML file.

 

Each entry following the ‘externalType’ entry represents methods to be used in this process. Each of these are described below.

  • static function getInstance() returns(ConfigurationCache);
    This function is used to get an instance of the Java class called ConfigurationCache. It is the program that handles all of the I/O to the XML file holding the application’s configuration values.
  •  

  • function setRuntimeEnvironment(runtimeEnvironment String in);
    Once an instance of ConfigurationCache is obtained use this method to inform it about the runtime environment in which it is running. This value is used to enable ConfigurationCache to read the correct set of values assigned for each server role.
  •  

  • function getBaseProperties();
    This function gets properties that have been identified as basic properties common to all applications. Examples of these are shown here:

    <entry key=”localhost.log4jConfigFileLocation”>C:\Desk\AppDevEGL\JobMessages\JobMessagesProject\src\config\log4j.xml</entry>
     

    <entry key=”localhost.log4jLogFileDirectory”>C:\Desk\AppDevEGL\JobMessages\JobMessagesProject\WebContent\logs\</entry>
     

    <entry key=”localhost.daysBeforeLogFilesDeleted”>10</entry>
     
  •  

  • function setPropertyTableEntry(propertyName String in, propertyValue String in );
    This function allows the developer to set an arbitrary name-value pair into the cache, however this function makes no sense in an EGL setting.
  •  

  • function cacheAppPropertyValues(listOfPropertyNames String[] in);
    This function is best explained with by the set of code that appears below. It shows the creation of a dynamic array that is used to hold 5 entries, each of which is a named property. In this case, the dynamic array of names will be used to hold just two values i.e. ‘version’ and ’emailAddress’ which are referenced using constants defined elsewhere in the program. (See the XML at the beginning of this post to see the entries for ‘version’ and ’emailAddress’.)
     
    The idea is to ‘push’ the names of each property into the array and then pass the array of values to the function cacheAppPropertyValues(listOfPropertyNames String[] in); that reads and caches them. When control is returned to the caller, calls to the next function (presented below) will retrieve each individual value for the name specified on the function’s parameter.

        //Get the runtime environment value from the server using RuntimeEnvironment 
        rte RuntimeEnvironment = new RuntimeEnvironment();
        runtimeEnvironment string  = rte.getRuntimeEnvironment();
    
        //Initialize the dynamic list of property names and the size. Set index 'p' to zero.
        listOfPropertyNames string[5] {maxsize = 5} ;
        p int = 0;
        
        //Increment index and add the property name to the list.
        p=p+1; listOfPropertyNames[p] = CommonLibrary.CONST_VERSION;
        p=p+1; listOfPropertyNames[p] = runtimeEnvironment+"."+CommonLibrary.CONST_EMAIL_ADDRESS;
           //... add more here when needed. 
     
        //Get an instance of the Configuration Cache and pass the runtimeEnvironment variable.
        configCache ConfigurationCache = ConfigurationCache.getInstance();
        configCache.setRuntimeEnvironment(runtimeEnvironment);
    
        //Read the properties in the list into the Cache. The values of each will be retrieved next.
        configCache.cacheAppPropertyValues(listOfPropertyNames);
    

    Fig.3 – This code goes into the Service program called on startup.

     

  • function getPropertyTableEntry(propertyName String in ) returns (String);
    This function retrieves the value of the property specified by the passed parameter. Retrieval is dependent upon the preceding step that caches the property value. See the function cacheAppPropertyValues(listOfPropertyNames String[] in);, above.

        //Retrieve and store the value into EGL program variables. 
        configDataRecord.version         = configCache.getPropertyTableEntry(CommonLibrary.CONST_VERSION ); 
        configDataRecord.emailAddress    = configCache.getPropertyTableEntry(CommonLibrary.CONST_EMAIL_ADDRESS);
    

    Fig.4 –

     

Summary

This post showed how to set up an EGL External Type to describe the interface to Java methods that allows access to discrete data elements residing in an external XML file. The nature of the values contained within the XML file are used to control program behavior that must differ across multiple server environments. The solution presented prevents the need for the program to be modified each time it is deployed to a new environment.

Written by iseriesadmin

July 12, 2012 at 2:41 pm

EGL and Subversion

leave a comment »

Introduction

Attached to his post is a .PDF document that illustrates how to use Subversion (SVN), which is a version control tool that has been integrated with “Rational Developer for i” (RDi) so that EGL project source can be safe guarded.

The document presents three main topics the first of which covers the installation of Tortoise, a graphical application that provides tools to be used by Subversion administrators to manipulate source code repositories. The tool is not often used once a repository has been created. Although Tortoise is intended for use only by administrators, the topic showing installation and use is presented as background information and for reference purposes. For this reason the developer can skip this topic if they choose. The topics that follow are intended for developers.

After RDi has been installed on the developer’s machine, the document’s second topic shows how to install a plug-in for RDi so that it sees the source code repository. Once installed, the third topic presented provides the ability to enroll projects into the SVN repository, commit changes and manage conflicts with other developers.

Rather than create a somewhat long web-page chock full of images to upload the document can be downloaded by clicking this link.

On some browsers the download may not present the first page. If this occurs simply scroll down using the mouse’s scroll wheel and the first page should appear.
 
 
 
 

Written by iseriesadmin

July 6, 2012 at 6:54 am