iRUI - The Rich Client and iiRUI - The Rich Client and i
Pluta Brothers Design, Inc.Joe Pluta
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Agenda
Who is PBD?Multi-Tiered Application DesignThe Tiers of a Rich ClientThe MessagesCreating a Business Logic Library FunctionCreating a ClientConnecting to ILE CodeAdvanced Concepts
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Who is PBD?
In business since 1998 Devoted to application modernization through industry standards
using IBM tooling
Products CPYSPLFPDF - The first commercial Java-based product for the i
family PSC/400 - The first tool to completely replace the display file with
servlets and JSPs
Services Training, mentoring, consulting Specializing in proofs of concept
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Who is PBD?
Started building open source and commercial solutions for Java-based modernization in 1999
Early adopter of Visual Age for Java, Eclipse, and WDSC ("wrote the book" on the latter two)
Started writing about EGL in 2005 Began pushing the multi-tiered EGL/RPG concept in
2006 Advocate EGL as the primary interface to the i Gave the first hands-on lab for EGL at an i-related
conference
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Who is PBD?
Articles, sessions, labs Wrote the business logic for the first public EGL
application, the scheduling application for the Rational Software Developer Conference This was a unique accomplishment, since it used the
Rich UI in conjunction with an i back end Working with a large i ISV to web enable their product
line using thin client EGL to access their existing back end logic
Blog - "EGL and i" on EGL Cafe Rich UI book coming out Real Soon Now
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Multi-Tiered Application Design
Multi-Tiered ApplicationsThick Client5250 - The original multi-tierThin Client (Browser Based)Multi-Tiered Rich Internet Applications
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Multi-Tiered Applications
UserInterface
BusinessLogic
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Thick Client Applications
PC Host
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
5250-Based Applications
PC
5250Emulation
i
Business Logic /Database
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Thin Client Applications (Browser-Based)
PC
Browser
i
WebApplication
Server
Business Logic /Database
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Thin Client (JSF) in EGL
EGLPageHandler
JSFPage
EGLLibraryFunction
ILEBusinessLogic
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Multi-Tiered Rich Internet Applications
Browser
JavaScriptInterpreter
i
WebApplication
Server
DOM(Web Page)
Business Logic /Database
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Rich Client with EGL
RESTService
EGLLibraryFunction
ILEBusinessLogic
The point here is that regardless of the interface, the business logic stays the same. And with the concept of a dynamic array of records, even the EGL library function can remain the same, leaving only the interface to change, which is the ultimate goal of a UI independent application development environment.
WebService
EGLRich UIApplication
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Tiers of a Rich Client
Business LogicService LayerRich UI TierBetween these, you have messages
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Business Logic
Two componentsFirst is the library function within EGL
Note: not necessarily a call to ILE!It could be a call to SQLIt could be a call to another service
In the iRUI architecture, it is a call to an ILE programThe other component of the business logic for iRUI is the code in the ILE program
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Service Layer
Written entirely in EGLRuns in a web application server
WebSphere or TomcatThe web application server provides the infrastructure to support REST or SOAP services
The web application server can run on the i or notNOTE: The EGL portion of the business logic interface also runs in the web application server
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Rich UI Tier
JavaScriptRuns in the browser on the end user PCResponds to events from the user (keystrokes, button clicks, mouse movement)Calls logic on the host via services (REST or SOAP)
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Business Logic Messaging
RESTService
EGLLibraryFunction
ILEBusinessLogic
WebService
EGLRich UIApplication
SOAP/REST Flexible Records Fixed Records
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Fixed vs. Flexible
Not a whole lot of differencesFixed records have fixed length fields
Used when calling ILEMap directly to data structures
Flexible records do not (especially character fields)Better between EGL layers
Used to hide the complexities of service call formattingCan be translated easily to either XML or JSON
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Simple vs. Composite
When talking to the host, use simple fixed recordsThese are interchangeable with data structuresWhen passing data between layers, however, you can use more complex data structuresLet's take a look how this would map out
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
record DSOrderHeader{} 10 OrderNumber string(10); 10 CustomerNumber decimal(6,0); 10 CustomerName string(50); 10 ShippingAddr string(50); 10 Tax money(9,2); 10 Freight money(9,2); 10 Total money(9,2);endrecord DSOrderLine{} 10 ItemNumber string(15); 10 Description string(30); 10 Quantity decimal(9,2); 10 Price money(9,2); 10 Extended money(11,2);end
I use the prefix DS on these records to indicate clearly that they are data structures (fixed), not flexible records.
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
record OrderHeader{} OrderNumber string; CustomerNumber decimal(6,0); CustomerName string; ShippingAddr string; Tax money(9,2); Freight money(9,2); Total money(9,2);endrecord OrderLine{} ItemNumber string; Description string; Quantity decimal(9,2); Price money(9,2); Extended money(11,2);endrecord Order{} Header OrderHeader; Lines OrderLine[];end
Note that in the flexible records strings have no lengths. Also, we see the concept of the Order, which is a composite.
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Messaging Design Points
The primary message format is flexibleComposite flexible records are used between EGL functionsFixed is used only in the lowest level of the library functions to interface with the ILE programs
The functions that call ILE are responsible for reformatting and packaging the simple records into composites
Support may be added for "simplified" flexible records
Flexible records are directly supported by the service generation pieces (SOAP and REST)
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Creating the Business Logic Function
Now that we've got the architecture in place, it's time to start cooking with gasFirst, create a dummy library function
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Creating the Business Logic Function
Add some logic to create a dummy recordfunction getOrderLocal(orderNumber string in, order Order out) returns (Error)
order = new Order { Header = new OrderHeader {OrderNumber = orderNumber,CustomerNumber = 789,CustomerName = "Pluta Brothers Design, Inc.",ShippingAddr = "542 E. Cunningham, Palatine, IL, 60074",Tax = 17.19,Freight = 14.95,Total = (17.19 + 14.95 + 4.32 + 23.95 + 9.45)
},Lines = [
new OrderLine {ItemNumber = "AS-1445", Description = "Squirt Guns",Quantity = 36, Price = .12, Extended = 4.32 },
new OrderLine {ItemNumber = "IIR-7728", Description = "Wading Pool",Quantity = 1, Price = 23.95, Extended = 23.95 },
new OrderLine {ItemNumber = "IIR-7243", Description = "Metal Ladder",Quantity = 1, Price = 9.45, Extended = 9.45 }
]};return (null);
end
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Thin Client is Now Enabled
From this point forward, you can start developing thin client (JSF) applicationsThe flexible record definitions can be used to build the screenBy creating a library function (and not a service), the business logic is now available to the thin client
At this point, it takes just a few minutes to throw together a JSF interfaceA few minutes more, you add AJAX support
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Create a Service
But we're here for the SOA piece, so let's get thereFirst, create a service partservice OrderServicefunction getOrder(orderNumber string in, order Order out) returns (Error)
return ((OrderLib.getOrder(orderNumber, order)));endend
This is a proxy. Its purpose is to surface the library function as a service.
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
And Now We Generate a Service
That's all it takes.
Done.
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Creating the Rich UI
Rich UI is different than JSFFor green screen veterans like me, it's different than just about anything we've ever doneBut it's not that bad; you build boxes
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Creating the Rich UI
Boxes are like grids - you specify the number of columns, and then put components in the box and they get laid out in the columns
Components can be simple things like labels and text fieldsComplex things like gridsEven other boxes
You can also create custom widgets that have their own layout, and embed them
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
The Order Widget
Three Boxes:
Header Box
Lines Box
Totals Box
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Crafting the UI
orderBox Box { columns = 1, paddingtop = 20,children = [ header, lines, totals] };
header Box = new Box { columns = 2, class = "header",children = [ new TextLabel { text = "Order Number", class = "prompt" }, new TextLabel { class = "value" },
new TextLabel { text = "Customer Number", class = "prompt" }, new TextLabel { class = "value" }, new TextLabel { text = "Customer Name", class = "prompt" }, new TextLabel { class = "value" }]
};
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Crafting the UI (cont'd)lines Grid { behaviors = [ GridBehaviors.alternatingColor, formatCells ], headerBehaviors = [ GridBehaviors.grayCells ], columns = [ new GridColumn{name = "ItemNumber", width = 90, displayName = "Item Number"}, new GridColumn{name = "Description", width = 170 }, new GridColumn{name = "Quantity", width = 70 }, new GridColumn{name = "Price", width = 80 }, new GridColumn{name = "Extended", width = 80 } ],
data = (new any[])};
totals Box = new Box { columns = 2, class = "totals",children = [ new TextLabel { text = "Tax", class = "prompt", width = 430 }, new TextLabel { class = "rvalue", width=80 }, new TextLabel { text = "Shipping and Handling", class = "prompt" }, new TextLabel { class = "rvalue" }, new TextLabel { text = "Order Total", class = "prompt" }, new TextLabel { class = "rvalue" }] };
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
A Little Stylin'
<style type="text/css">
/* Standard overrides */body { font-family: "Verdana"; }
.prompt, .value, .rvalue { padding: 3px 10px 2px 10px }
.header .prompt { text-align: left; background-color: blue; color: white; }
.totals .prompt { text-align: right; }
.rvalue, .right { text-align: right; }
</style>
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
And a Little Gridwork
// Handle column formattingfunction formatCells(
grid Grid in, cell Widget in, row any in,rowNumber int in, column GridColumn in)// Set attributes based on column namecase
when (column.name == "Quantity")html HTML = cell.children[1];cell.class = "EglRuiGridCell right";tf TextField = new TextField {
text = html.text, width = 50, class = "right",onChange ::= updateQuantity };
tf.setAttribute("row", rowNumber);cell.children = [ tf ];
when (column.name == "Price" or column.name == "Extended")cell.class = "EglRuiGridCell right";
endend
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
The Magic (Info)Bus
function setId(ibmSrc string in)id = ibmSrc;InfoBus.subscribe(id, listener);
endfunction listener(eventName String in, eventData any in)
ibm = eventData;case
when (ibm.action == "SHOW")showOrder(ibm.data);
endendfunction sendResponse(action string in, data any in)
InfoBus.publish(ibm.src,new InfobusMessage {
src = id, action = action, data = data });end
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
More on the Bus
MC Press Online just published an article today(Great timing, eh?)http://tinyurl.com/8jddd6That's short for this:http://www.mcpressonline.com/programming/web-languages/rich-ui-unleashed.html
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Install the Service
Generate a WSDL in the EGL projectCopy the WSDL into the RUI projectRight-click on the WSDL and generate the client interface
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Invoking the Service
function showOrder(order string)InfoBus.publish(ibm.src, new InfobusMessage
{ action = "*STATUS", data = "Reading Order " :: order } );OrderLib.getOrder(order, orderNotify);
end
// Remote functionsfunction getOrderRemote(orderNumber string, orderNotify OrderNotify in)
oncb = orderNotify;orderService OrderService { @WebBinding {
wsdlLocation="wsdl/OrderService.wsdl",wsdlPort = "OrderService",wsdlService = "OrderServiceService"}};
wOrder order;wError error;call orderService.getOrder(orderNumber, wOrder, wError
returning to gORCallback;endfunction gORCallback(order Order in, error Error in)
oncb(order, error);end
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Getting the Results
function orderNotify(orderIn Order in, error Error in)if (error != null and error.severity != 0)
sendResponse("*STATUS","Order Read Error[" :: error.severity :: "]:" :: error.message);
else;(header.children[2] as TextLabel).text = order.Header.OrderNumber;(header.children[4] as TextLabel).text = order.Header.CustomerNumber;(header.children[6] as TextLabel).text = order.Header.CustomerName;orderLines.data = order.Lines as any[]; (totals.children[2] as TextLabel).text = order.Header.Tax;(totals.children[4] as TextLabel).text = order.Header.Freight;(totals.children[6] as TextLabel).text = order.Header.Total;(shipping.children[2] as TextLabel).text = order.Header.ShippingAddr;(shipping.children[2] as TextLabel).text = MyAddress;sendResponse("SHOW", orderBox);
endend
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Connecting Back to the i
function getOrderPgmCall(orderNumber string in, order Order out) returns (Error)control Control;line OrderLine;control.opcode = "H";order.Header.OrderNumber = orderNumber;call "ORDSVR" (control, order.Header, line); // Fill headercontrol.opcode = "D";call "ORDSVR" (control, order.Header, line); // First linewhile (control.retcode == "0")
order.Lines.appendElement(line);call "ORDSVR" (control, order.Header, line); // Next line
endend
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
The RPG Code FORDHDR IF E K DISK FORDDTL IF E K DISK
DdsCONTROL E DS QUALIFIED DdsORDHDR E DS QUALIFIED DdsORDDTL E DS QUALIFIED
DORDSVR PR D P1 likeds(dsCONTROL) D P2 likeds(dsORDHDR) D P3 likeds(dsORDDTL)
DORDSVR PI D P1 likeds(dsCONTROL) D P2 likeds(sdORDHDR) D P3 likeds(dsORDDTL)
/free select; when P1.opcode = 'H'; chain P2.OHNUM ORDHDR dsORDHDR; P1.retcode = %found(ORDHDR); setll P2.OHNUM ORDDTL; when P1.opcode = 'D'; reade P2.OHNUM ORDDTL dsORDDTL; P1.retcode = %eof(ORDDTL); endsl; /end-free
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Advanced Concepts
EncapsulationREST vs SOAPExtensionsDebugging
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Encapsulation
function getOrder(orderNumber string in, order Order out) returns (Error)case (access)
when (Utility.ACCESS_LOCAL)return (getOrderLocal(orderNumber, order));
when (Utility.ACCESS_SQL)return (getOrderSql(orderNumber, order));
when (Utility.ACCESS_PGMCALL)return (getOrderPgmCall(orderNumber, order));
otherwisereturn (Utility.Fatal("Invalid access " :: access));
endend
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
REST vs. SOAP
ios com.pbd.svc.IOrderService { @RESTBinding{baseURI = "http://localhost:9081/iEGL/restservices/OrderService"}};
order com.pbd.data.Order;call ios.getOrder(orderNumber, order)
returning to gORCallBackonException ServiceLib.serviceExceptionHandler;
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
ExtensionsExternalType Fmt type JavaScriptObject {
relativePath = "com/pbd/util",javaScriptName = "Fmt"
} function getNow() returns (string);
end
egl.defineClass('com.pbd.util', 'Fmt', // this class{"constructor" : function() {
this.ms = new Date().getTime(); },"getNow" : function( ) {
function two(x) {return ((x>9)?"":"0")+x}function three(x) {return ((x>99)?"":"0")+((x>9)?"":"0")+x}var sec = Math.floor(this.ms/1000);var msec = this.ms % 1000;var min = Math.floor(sec/60);sec = sec % 60;var hr = Math.floor(min/60);min = min % 60;hr = (hr + 18) % 24;return (two(hr) + ":" + two(min) + ":" +
two(sec) + "." + three(msec));}});
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Debugging
EGL-level debuggingJava debuggingConsole loggingWeb service explorerChris Laffra's service monitorService Entry Points (SEPs)
Pluta Brothers Design, Inc.http://www.plutabrothers.com
Page [email protected]
Summary
Multi-tiered applications are complex beasts, usually requiring multiple languages and skill sets, not to mention toolsEGL provides a consistent syntax, both in data representation and in program flowAll components, both EGL and non-EGL, can be developed within the RDi-SOA workbenchBy providing end-to-end development capabilities, EGL is the only tool that can leverage the i out of the box to build powerful rich Internet applications