iRUI - The Rich Client and i - IBM€¦ · iRUI - The Rich Client and i Pluta Brothers Design, Inc....

Preview:

Citation preview

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 2joepluta@plutabrothers.com

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 3joepluta@plutabrothers.com

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 4joepluta@plutabrothers.com

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 5joepluta@plutabrothers.com

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 6joepluta@plutabrothers.com

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 7joepluta@plutabrothers.com

Multi-Tiered Applications

UserInterface

BusinessLogic

Pluta Brothers Design, Inc.http://www.plutabrothers.com

Page 8joepluta@plutabrothers.com

Thick Client Applications

PC Host

Pluta Brothers Design, Inc.http://www.plutabrothers.com

Page 9joepluta@plutabrothers.com

5250-Based Applications

PC

5250Emulation

i

Business Logic /Database

Pluta Brothers Design, Inc.http://www.plutabrothers.com

Page 10joepluta@plutabrothers.com

Thin Client Applications (Browser-Based)

PC

Browser

i

WebApplication

Server

Business Logic /Database

Pluta Brothers Design, Inc.http://www.plutabrothers.com

Page 11joepluta@plutabrothers.com

Thin Client (JSF) in EGL

EGLPageHandler

JSFPage

EGLLibraryFunction

ILEBusinessLogic

Pluta Brothers Design, Inc.http://www.plutabrothers.com

Page 12joepluta@plutabrothers.com

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 13joepluta@plutabrothers.com

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 14joepluta@plutabrothers.com

Tiers of a Rich Client

Business LogicService LayerRich UI TierBetween these, you have messages

Pluta Brothers Design, Inc.http://www.plutabrothers.com

Page 15joepluta@plutabrothers.com

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 16joepluta@plutabrothers.com

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 17joepluta@plutabrothers.com

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 18joepluta@plutabrothers.com

Business Logic Messaging

RESTService

EGLLibraryFunction

ILEBusinessLogic

WebService

EGLRich UIApplication

SOAP/REST Flexible Records Fixed Records

Pluta Brothers Design, Inc.http://www.plutabrothers.com

Page 19joepluta@plutabrothers.com

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 20joepluta@plutabrothers.com

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 21joepluta@plutabrothers.com

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 22joepluta@plutabrothers.com

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 23joepluta@plutabrothers.com

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 24joepluta@plutabrothers.com

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 25joepluta@plutabrothers.com

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 26joepluta@plutabrothers.com

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 27joepluta@plutabrothers.com

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 28joepluta@plutabrothers.com

And Now We Generate a Service

That's all it takes.

Done.

Pluta Brothers Design, Inc.http://www.plutabrothers.com

Page 29joepluta@plutabrothers.com

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 30joepluta@plutabrothers.com

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 31joepluta@plutabrothers.com

The Order Widget

Pluta Brothers Design, Inc.http://www.plutabrothers.com

Page 32joepluta@plutabrothers.com

The Order Widget

Three Boxes:

Header Box

Lines Box

Totals Box

Pluta Brothers Design, Inc.http://www.plutabrothers.com

Page 33joepluta@plutabrothers.com

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 34joepluta@plutabrothers.com

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 35joepluta@plutabrothers.com

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 36joepluta@plutabrothers.com

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 37joepluta@plutabrothers.com

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 38joepluta@plutabrothers.com

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 39joepluta@plutabrothers.com

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 40joepluta@plutabrothers.com

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 41joepluta@plutabrothers.com

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 42joepluta@plutabrothers.com

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 43joepluta@plutabrothers.com

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 44joepluta@plutabrothers.com

Advanced Concepts

EncapsulationREST vs SOAPExtensionsDebugging

Pluta Brothers Design, Inc.http://www.plutabrothers.com

Page 45joepluta@plutabrothers.com

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 46joepluta@plutabrothers.com

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 47joepluta@plutabrothers.com

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 48joepluta@plutabrothers.com

Debugging

EGL-level debuggingJava debuggingConsole loggingWeb service explorerChris Laffra's service monitorService Entry Points (SEPs)

Pluta Brothers Design, Inc.http://www.plutabrothers.com

Page 49joepluta@plutabrothers.com

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

Recommended