View
224
Download
0
Category
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