You are completely correct, powerEXT Core is built on top of a special
version of CGIDEV2 and shares I/O buffers with CGIDEV2.
The reason for that is historical. I have used CGIDEV2 since 2002 and have
a lot of systems running based on CGIDEV2 that had to be rewritten if
powerEXT Core hasn’t been built on CGIDEV2.
So the goal was to be able to run in a mixed environment so powerEXT Core
could be used either as a standalone service program on top of CGIDEV2 or
side by side as an enhancement to the existing CGIDEV2 environment.
You may ask why I didn’t just made a new CGIDEV2 XXX….. service program for
my own stuff but my version of CGIDEV2 isn’t compatible without
recompilation of all related CGIDEV2 programs since all 32K fields has been
changed to 64K and thereby many procedure interfaces. For this reason my
CGIDEV2 service program has been rename so it doesn’t interfere with any
existing CGIDEV2 installation. Besides that powerEXT Core has over 100
subprocedures compared with CGIDEV2 that has 72 where many are obsolete in
a WEB 2.0 perspective.
powerEXT Core has therefore the same capability to use templates as CGIDEV2
since it is some of the about 15 subprocedures that is used and shared with
However time studies (LEAN) showed that inline XML and JSON node support is
much more efficient than templates. I don’t remember the factor but it is
more than twice.
The reason for that is first of all the reduction of number of source
members (the template and the program) to only one (the program). The
second is the lack of redundancy and need to synchronize the code (section
and field tags). The third is the lack of need to encode special characters
(<> etc.) in the variables since the node support will do that
automatically. The fourth is the ability to build nodes or sections based
on business rules in complex XML (I’m not saying this can’t be done using
templates but it is much harder/inefficient because you may have to chop up
the XML template in very small sections). The fifth is that node support is
much more suited for program generators. The sixth is that the generated
XML from node support is automatically indented correct which makes the
generated XML very readable in plain text editors.
You write in another post that the template can be based on a XML example
and that is truly correct however powerEXT has a command that can generated
the RPG node skeleton based on the same XML example so the use of XML
skeleton is also used in powerEXT.
You ask if I can make generic code (using the same RPG code to connect to
either a XML or JSON template or a HTML template) and the answer is no when
using node support. But this has no practical use when we are talking about
XML business documents since different business logic always will be
connected to different formats or counter wise.
However, even this is off topic, I do use templates in the service program
that generates highly specialized EXT JS JSON grid and form UI objects in
powerEXT Framework. The entire UI is based on approx. 15 field type JSON
templates (approx. 600 line of code) that have sections (components) for
various ways to display a field based on simple attributes in a simple XML
template that, mixed with metadata, defines the grid or form. Here I am
talking about reading XML and metadata from the data dictionary while
generating JSON objects in the same process.
And I also use templates when generating HTML page section even though I
use a mix of templates and node support which is necessary since my HTML
pages doesn’t have any <BODY> section but have a lot of generated JSON
then generates the <BODY> on the fly. Here I’m talking about a two tier
generation, the server generates JSON UI component object definitions and
the client generates the HTML <BODY> based on the JSON definitions using
the EXT JS component library. Since all this is done at the fly a powerEXT
Framework program such as a File Maintenance program doesn’t really exist
as an entity other than as on the fly assembled code (View) by standardized
the moment the program is closed. The communication with the server and
thereby business logic and DB (Model) is done in separated REST services
that doesn’t have a clue of what client is using them. This represents the
ultimate separation of UI and BL/DB access since the UI (View and
Controller) is device depended and the BL/DB access (Model) is device
independed and thereby generic.
Back to the subject. You claim that you only have to use 5 subprocedures
where I have to use 6 so I will walk you through my subprocedures.
ClearSrvPgm() – clears and reset all global fields, settings and buffers in
my service program. This is necessary because there is not any guaranty of
the state the last user left the service program in and since powerEXT
Core, unlike CGIDEV2 that only have one output buffer, can have up to 1000
2TB data stores it is a good idea.
SetContent() – actually start with a CGIDEV2 clrHtmlBuffer() but if you
pass anything else that ‘*none’ to this procedure it will build the MIME
header followed by two CRLF in the buffer. If you pass nothing it will put
’Content-Type: text/html’ – this is an example of how a CGIDEV2
subprocedure is enhanced in powerEXT.
Echo() – writes any data string to the buffer followed by a CRLF unless you
supersede this function global or in optional parameters. It actually calls
wrtNoSection() in CGIDEV2.
xmlNode(element:[attributes]:[data]) – creates a XML parent, child or
sibling node. The element doesn’t have to be enclosed in <> and the </> is
automatically generated saving keystrokes and spelling errors. Attributes
are passed as is and special characters (<> etc.) in the data is
automatically encoded unless you want <!CDATA[[…]]> encapsulation and
thereby no encoding (this a just an optional parameter). Is it a parent
node (no data) the node is registered in the tree as an open node and the
depth are increased by 1. The depth is used to TAB the offset of the
generated XML element.
xmlEndNode() – creates a </> element with the same element name as the
previous opened parent node. The depth is first decreased with 1 for
echoToStmf() – does more or less the same as CGIDEV2 wrtHtmlToStmf() but it
doesn’t clear the output buffer and it has the ability to append data to an
existing stream file. So you are able to store even a client response to a
stmf before sending it to the client (browser) with my echoToClient() that
is the same as wrtSection(‘*fini’). I have also a echoBinToClient() that
sends any IFS stmf to the client in binary mode.
In regards to other ‘common’ CGIDEV2 subprocedures there are a lot of other
small enhancements …
getExtVar() – Is similar to CGIDEV2 zhbGetvar() but you can pass data to
not found parameters that is very usefull if you don’t know if the
parameter is in the input – FIELDA = getExtVar(‘ABC’:FIELDA); if ABC is not
in the input FIELDA will have the same value.
getExtVarJson() – will search for a CGIDEV2 variable in the input that
contains a JSON response and then search the JSON string for a variable
within the JSON string. For more complex JSON I use the input buffer
echoAsp(), echoCgi() and echoCgiDev2() combines a getMultHtmlIfs() and a
wrtSection() – the file is the first parameter, the section is the second
and the service program keeps track of if it is already loaded.
The bottom line is that while CGIDEV2 ‘core’ development more or less since
2005 (where Mel retired and IBM official took over) has come to a
standstill. Small enhancements have been made by Giovanni mostly driven by
the needs of development of his amazing tools, but no major changes have
been made to support a more modern approach and environment.
CGIDEV2 was originally developed as a RPG based middleware between the RPG
environment and the Apache server, powerEXT Core has isolated the current
needed parts from CGIDEV2 but that is only 10 % of powerEXT Core since it
has 90 new subprocedures that handles a number of needs in WEB 2.0
development and at the same time has a strong focus of handling data
formats such as XML and JSON and handling IFS files in an integrated
service program where subprocedures works together by sharing global fields
as well as allocated storage among them when needed.
Most subprocedures in powerEXT Core is developed because I needed them in
developing powerEXT Framework and in my daily need for handling EDI, XML
and JSON and data from/to IFS files others has been developed based of the
needs people has expressed in various forums that just seemed to fit into
the concept and not to forget - I found interesting and educational.
When all this is said, I find it strange that nobody points Debbie to the
newly released ‘IBM Modernization Guide’ where Jon has made a section on
how to make XML in various ways in RPG.
On Wed, Aug 13, 2014 at 8:29 PM, Vernon Hamberg <vhamberg@xxxxxxxxxxxxxxx>
I like the look of this code - and I think it is a toss of a coin, whether
Henrik's or mine is easier - 5 function calls in mine, 6 in Henrik's.
I think one thing about Henrik's is this - you may be able to see the
actual structure of the XML more easily, more directly - with the CGIDEV2
version, it depends to a degree on how you name things (a person could use
the XML tag names as variable names, for example) - and with CGIDEV2, we
use sections, which are not necessarily related directly to XML elements
and attributes and all.
Now CGIDEV2 can do this kind of thing to any text output - Henrik, I
believe powerEXT uses CGIDEV2, for some of its functions - I assume there
are functions for writing to other formats, such as HTML and maybe RTF and
whatever. A question - can you use powerEXT in a more generic fashion, so
that I could write to a format you have not included? Just curious.
I've put a much-abridged version of my program here - the variables are
declared above this, and there is a READ loop that updates the variables
and writes the activity section. In addition, date and time and history are
built from several fields in the file being read.
IfsMultIndicators = getHtmlIfsMult('/XML/activities.tpl' :
'<!-- $' : '$ -->' : '<!-- %' : '% -->');
updHtmlVar('CustomerNumber' : custno);
updHtmlVar('ActivationDate' : %char(actdate));
updHtmlVar('ActivationTime' : %char(acttime));
updHtmlVar('HistoryEntry' : history);
rc = wrtHtmlToStmf('report.xml' : 1208);
*inlr = *on;
On 8/13/2014 11:07 AM, Henrik Rützou wrote:
It may be easier for you to make XML with inline code/subprocedures like
used in powerEXT Core,
to make Vernons example here is the complete code (Vernon is missing the
echo('<?xml version="1.0" encoding="UTF-8"?>');
echo('<!DOCTYPE activity_import_file SYSTEM "activity.dtd">');
xmlEndNode(); // ends activity
xmlEndNode(); // ends activity_import_file
*inlr = *on;
This is the Midrange Systems Technical Discussion (MIDRANGE-L) mailing list
To post a message email: MIDRANGE-L@xxxxxxxxxxxx
To subscribe, unsubscribe, or change list options,
or email: MIDRANGE-L-request@xxxxxxxxxxxx
Before posting, please take a moment to review the archives