Submitted by itp on Wed, 12/13/2006 - 00:00
Forums

How is Icebreak different from Profound Logic RPGsp, BDC WebSmart and IBM's CGIDEV2 freeware? They all seem to allow you to develop with a combination of RPG and HTML. How does Icebreak differentiate itself in the iSeries CGI market?

Here are a few questions I have based on work with similar products.

Can you use Icebreak to write stream files to disk? If so, is there a practical memory limit to the size of stream files created? (eg: A 2 GIG XML or flat EDI file)
Can I append to Stream file.

Can I maintain a custom HTML template for different customers. Eg: One RPG program that generates 25 diferent order confirmation emails based on customer type? Can I modify templates on the fly or use another program to generate templates used by Icebreak.

Can one RPG program drive both 5250 and HTML screens?

Does Icebreak come with built-in or recommented complementary email program. Are there tools for bulk email and mail merge applications?

some references:
http://www.profoundlogic.com/product...martpages.html
http://www.bcdsoftware.com/iseries40...mart/index.htm
http://en.wikipedia.org/wiki/Cgidev2

John Foldager

Thu, 12/14/2006 - 00:00

Hi!

A lot of questions, but I might be able to answer or clarify a few of them. Please keep in mind that I am in no way part of the IceBreak Development Team.


 Originally Posted by itp: 
"How is Icebreak different from Profound Logic RPGsp, BDC WebSmart and IBM's CGIDEV2 freeware? They all seem to allow you to develop with a combination of RPG and HTML. How does Icebreak differentiate itself in the iSeries CGI market?"

First of all IceBreak does not have anything in common with these tools in relation to the CGI market! Profound Logic RPGsp and BCD WebSmart both run your applications as CGI programs. When a program is called it is loaded into memory, run the business logic and then removed from memory again. This is inefficient and even though RPGsp says that it has "lightening fast CGI code" it has its limits because of the CGI approach. I know that you can buy a product called "WebSmart JSE" that can actually produce Java Servlets which is smarter than CGI because applications are loaded into memory either when the application server (Apache Tomcat or WebSphere) or the first time the business logic is called. And it stays in memory until the application server is shutdown, keeping it efficient and fast.

Another alternative is SoftDesign's Websydian (not the "Express" edition!) which can do some of the same as IceBreak and also create Java Servlets like the WebSmart JSE edition. This product is great if you want to build business processes easy. IceBreak can do this too and - at the same time - provide you with really low-level programming which you - in my world at least - needs to create the applications of tomorrow.

The sales people at System & Metode would probably tell you that IceBreak is so much faster than the other alternatives because it has its own build in HTTP/application server that compiles and generates real native AS/400 program code. You can have persistent settings on the server side even though the page is sent back to the client etc. They might also tell you that everything in Java is slower than their RPG/Cobol approach... which I will actually agree with(!!). That said, I do not agree with their sales presentation slides that shows the different kind of "layers" that the Java world needs in contrast to the IceBreak world.

In my oppinion IceBreak is the greatest product of them all to create lightning fast applications for the low-end market. If you want fail-overs, clustering etc. you need the Java world and the WebSphere application server. I do them both... for what ever is best for the job.


 Originally Posted by itp: 
"Here are a few questions I have based on work with similar products.

Can you use Icebreak to write stream files to disk? If so, is there a practical memory limit to the size of stream files created? (eg: A 2 GIG XML or flat EDI file)
Can I append to Stream file."

Yes you can read and write stream files.
I don't know the limit of stream files... we need IceBreak Development Team to answer this one; but... IceBreak has build in functions called ILOB (Internal Large Objects) which you can use for string, XML and other kinds of manipulation. You probably know of the 32K limit of strings in RPG. ILOB is one of the coolest functionalities in IceBreak and I will dare to say that I'm the "father" of this functionality... even though it was Niels that implemented it 


 Originally Posted by itp: 
"Can I maintain a custom HTML template for different customers. Eg: One RPG program that generates 25 diferent order confirmation emails based on customer type? Can I modify templates on the fly or use another program to generate templates used by Icebreak."
 

Yes you can! But you will either have to use the IBM supplied API's for sending emails, integrate to a WebService on a Lotus Domino server or buy a BlueSeries product (from System & Metode) that can do the sending of emails. I keep hoping that this functionality is implemented into core IceBreak as it is a crucial part of applications today... but you know... someone has to decide which functions go into which product ... they'll want to sell you both 


 Originally Posted by itp: 
"Can one RPG program drive both 5250 and HTML screens?"

I'm not a 5250 application developer so I don't know the exact and precise answer to this question, but I do know that you can create a WebService that can be called from the web and at the same time called from another 5250 application! So I guess my answer would be "Yes"... with a twist. Hopefully Niels might be able to answer this in more details.


 Originally Posted by itp: 
"Does Icebreak come with built-in or recommented complementary email program. Are there tools for bulk email and mail merge applications?"

As stated above you will currently have to buy the BlueSeries Email product, write your own interfaces to the IBM API's, integrate to a Lotus Domino WebService or call a Java application to send it.

If you have any further questions for me just ask... otherwise, lets wait until IceBreak Development Team will respond to "the rest" or provide other details of the answers I have given above.

Best regards,

John Foldager
www.izone.dk

Thank you for your prompt replies.

"...IceBreak is so much faster than the other alternatives because it has its own build in HTTP/application server that compiles and generates real native AS/400 program code."
 
XTools, CGIDEV2 (and believe the two other mentioned) also generate compiled RPG objects. Also with IBM Apache server, from what I have seen, once a program is run, it seems to stay in memory for very fast access the second time run, even if run by a different user. If you don't seton LR at the end of the program, even the files are already opened and ready for you next time. The only problem is that the first time run after a delay response time can be slower.

Looking at Icebreak web page, Icebreak seems to compile HTML into executable, which may give it a speed edge over other solutions. However the downside of this approach is that a programmer would have to recompile every time any change is made on the web page. Maybe Icebreak gives you a choice.


"If you want fail-overs, clustering etc. you need the Java world and the WebSphere application server. I do them both... for what ever is best for the job."

I agree with you here, despite the claims of many competing products I think Java has a good claim here.

No problem there! IceBreak uses JIT (Just In Time) compile. Every time the programmer make changes to a program it will be re-compiled next time used.

This technique is used for all IceBreak servers in “Development” mode. So there will be absolute NO overhead for this technique when a server is set to “Production” mode.

Bent

Gents;

Thanks John for you support of IceBreak - it sounds like it is your baby ;-)

Just some short follow ups:

Buffers are implemented with "teraspaces" - and 128 byte pointers - so the limit for streams is terabytes ...

JIT - Is when a ULR referred program object has a older change date than the corresponding source ( and soon also other dependencies ) it will triggers a recompile, if the server instance is in "development" - this check is bypassed in "production" mode

Mails: It is done in BlueMail ( BlueSeries) but is integrated to IceBreak so an ASP program (an IceBreak Program ) can create the mailbody .. with all the templates you got ...
The Responseobject is directly mapped to the mailbody so you can design the mail in e.g. Frontpage or DreamWeaver or whatever.
e.g. we are having a daily mail containing a download report from the IceBreak.org site


Thanks

Niels 

"Buffers are implemented with "teraspaces" - and 128 byte pointers - so the limit for streams is terabytes ..."
 
That should meet most requirements!!!

"JIT - Is when a ULR referred program object has a older change date than the corresponding source ( and soon also other dependencies ) it will triggers a recompile, if the server instance is in "development" - this check is bypassed in "production" mode"

That should ensure good performance and fewer versioning issues.

Can I maintain a custom HTML template for different customers. Eg: One RPG program that generates 25 diferent order confirmation emails based on customer type? Can I modify templates on the fly or use another program to generate templates used by Icebreak.

How does Icebreak deal with html and html templates? A long time ago I did some work on Perl, and it drove me crazy when management wanted changes and I had to wade through hundreds of lines of business logic to change logos or phone number. I had to write custom template routines, but it was not standard or very efficient. Now I have cases where each customer has to have a custom form. (Sort of like custom shipping labels). Also I might want to hand off screen design and layout to a “real” web designer, without having to hand over all my code and business logic. CGIDEV2 (as well as Cozzi’s xTools, and Stone’s eRPG as well) allows one to handle this very easily because all HTML is externalized (unless you are really insistant on business and screen logic).

Again, can one Icebreak program drive both 5250 and HTML screens? This is important for companies in endless process of modernization. With CGIDEV2 I have been able to do this (although I admit not very gracefully)

Itp

 Originally Posted by itp: 
"Now I have cases where each customer has to have a custom form. (Sort of like custom shipping labels). Also I might want to hand off screen design and layout to a “real” web designer, without having to hand over all my code and business logic."

You can... tell a designer that he has 5 fields (or whatever) to show in the header, some master information and a table with detail records of field a, b, c etc.

What you - or the designer - then do is to split-up the HTML source (or XML if you like) with some boundaries with a unique name; it could be "start", "master", "detail-record", "end" and then use an "import" section in your code. You will use an import of "detail-record" within a loop that shows all the detail records. I'm sorry I do not have an example right here, but I hope you get the point. Inside a section you will have a syntax like <%$ ColumnValue1 %> and in you RPG you will - inside your loop - have a SetMarker('ColumnValue1' : %char(SomeRpgValue)) and a call to a function that puts the value inside the "marker" in the HTML and then proceed to the next record doing the exact same.

Even though I talked about splitting up the source with the boundaries the source HTML is still one single file  ... or multiple if you like.

Best regards,

John Foldager
www.izone.dk

Gents;

5250 / HTML is actually a question about model-view-control (MVC)

see http://ootips.org/mvc-pattern.html

So if you isolate you business logic into service programs then IceBreak has this strength above others semlilar solutions - that any service program (of you choice) becomes ALSO a WebService.

I real life that is a super feature since for 5250 don't have the SOAP overhead, and your C#.net application is accesing the exact same business logic.

IceBreak even creates the prototype file for your service programs procedures...

take a look at this small sample:

 
  <%@ language="RPGLE" pgmtype="webservice" %>
  <%   
 h nomain     

  p*name++++++++++..b...................keywords++++++++++++++++++++++++++comments++++++++++++
  p Calculator      B                   export

 d Calculator      pi
 d    x                          10i 0 Input        
 d    y                          10i 0 Input
 d    z                          10i 0 Output

  /free

   z = x + y; 

 /end-free  
 p Calculator      E 

The only difference is that you have to save this RPG as an .ASMX file (just like in Microsoft Development studio) and the you have a webservice with WSDL and all the bells and wistles.

Read tutorial 21.

Niels

Interesting. CGIDEV2 uses boundaries as well, conceptually similar to record DDS formats, but the code is always kept separate from design elements. I think that this is the way most web development is moving these days.
See example below or at
http://tinyurl.com/jf4jf

 
  <AS400>top
  Content-type: text/html

 <HTML>
  <BODY>

  <AS400>Header1
  <h2>Sample Sales Report</h2> 

  <AS400>TopOfTable 
 <table border=1>
  <tr><td>
  <center> Region 
 </td><td> 
 <center> Sales
  </td></tr>

  <AS400>TableDetail
  <tr><td>
  <center> /%Region%/ </td><td > /%Sales%/
  </td></tr>

  <AS400>BottomOfTable 
  </table>

  <AS400>endhtml
  <br><br><br>

  <a href="/cgidev2p/dspsrc.pgm?cgiinp01=cgidev2&cgiinp02=qrpglesrc&cgiinp03=cookie2"
  target="_blank"><b>Display the external HTML source</b></a></td>
 <br>
  </BODY>
 </HTML> 

 Originally Posted by itp: 
"Interesting. CGIDEV2 uses boundaries as well, conceptually similar to record DDS formats, but the code is always kept separate from design elements. I think that this is the way most web development is moving these days."


Exactly... but IceBreaks uses <!-- ... --> syntax which makes it possible to include it whereever you want inside XML syntax (and HTML etc.). This means that it is possible to syntax highlight etc. in modern "source-code-collapsible-editors" and have it validated without problems. In your example the <AS400> is never terminated with a </AS400>

Best regards,

John Foldager
www.izone.dk

The <AS400> tag is user defined. You could terminate it if you want to validate against an XML style sheet or editor. I could probably have used <!-- just as easily. But with CGIDEV2, there is nothing to hide in comments. Code and markup is clearly separated. Here is a bit more on the subject from the easy400 web site. The product comes with full source code, so if you don't like the way it works, you can fix it.

ref: http://www.easy400.net/cgidev2o/exhibit4.htm

"How to provide HTML responses using externally defined HTML
this means Version 2
power search
blue line

This page shows how to

1. define the variables needed for these operations
2. read into memory an externally defined html script
3. assign values to variables of this external html
4. write html sections and send the output buffer
5. use special output procedures

1. Variables

We recommend you use

1. command cgidev2/setcgilib to setup the development and execution environments in your source library and object (production) library
2. command cgidev2/crtcgisrc to create a sample source for a new CGI program. You can compile an run such program.

If you do so, you'll find out that the variables are already defined by copying in other source members:

/copy mysrclib/qrpglesrc,hspecs
/copy mysrclib/qrpglesrc,hspecsbnd
... etc. ...
/copy mysrclib/qrpglesrc,prototypeb
/copy mysrclib/qrpglesrc,usec
/copy mysrclib/qrpglesrc,variables(1, or 2, or 3)
... etc. ...

 

2. Read skeleton html member into memory

Use subprocedure

* getHtml to load into memory a single externally defined html source member
* getHtmlifs to load into memory a single externally defined html IFS (stream) file
* getHtmlifsMult to load into memory in one shot multiple externally defined html IFS (stream) files

Examples for default section and variables delimiters

* section name start delimiter: /$
* variable name start delimiter: /%
* variable name end delimiter: %/


1) getHtml

C eval HtmlSrcLib = 'CGIDEV2'
C eval HtmlSrcFil = 'DEMOHTML'
C eval HtmlSrcMbr = 'EXERCISE'
C callp gethtml(HtmlSrcFil:HtmlSrcLib:HtmlSrcMbr)


C callp gethtml('DEMOHTML':'CGIDEV2':'EXERCISE')


2) getHtmlifs

C callp gethtmlifs('/CgidevExtHtml/talk2ifs.html')

See the example in CGI TEMPLATE4.
Note that the directory to be specified as a parameter of the gethtmlifs procedure is the real directory path, not the alias mentioned in a HTTP pass directive.
The recommendation is -in any case- not to use for the IFS html code directories accessed also by the HTTP server.

3) getHtmlifsMult
This subprocedures allows to load into memory multiple externally defined html files. All the sections and records in all the files are read into dynamic storage as though they resided in a single file. If a section name appears more than once, only the first occurrence is used.
This feature allows to maintain as separate HTML files frequently used pieces of HTML code, such as headers, footers, navigation bars, etc.. In several cases, breaking html code into separate modules may greatly reduce both development and maintenance times.

* Indicators for GetHtmlIfsMult subprocedure
D IfsMultIndicators...
D ds
D NoErrors n
D NameTooLong n
D NotAccessible n
D NoFilesUsable n
D DupSections n
D FileIsEmpty n
... etc. ...
* Read externally defined output html files
C eval IfsMultIndicators = gethtmlifsmult(
C '/CgiDevExtHtml/StdTop.Html +
C /CgidevExtHtml/StdRunTime.Html +
C /CgidevExtHtml/StdMsg.Html +
C /CgidevExtHtml/StdPssr.Html +
C /CgidevExtHtml/Talk2Stuff.Html +
C /CgidevExtHtml/StdEnd.Html')


See the example in CGI TEMPLATE5.

Note 1. Subprocedures getHtmlifs and getHtmlifsMult can also load HTML source members as part of the /QSYS.LIB/... directory.
See the following example:

* Read externally defined output html files
C eval IfsMultIndicators = gethtmlifsmult(
C '/CgiDevExtHtml/StdTop.Html +
C /QSYS.LIB/MYLIB.LIB/HTMLSRC.FILE/X.MBR')

 

Note 2. When using getHtmlifs or getHtmlifsMult subprocedure, make sure that the IFS files containing the external HTML code can be read from the HTTP server user profile QTMHHTP1 (the one adopted when running CGI). This can be done in one of the following ways (in the examples below, we assume that QPGMR owns the files, but this is not relevant at all):
Data --Object Authorities--
User Authority Exist Mgt Alter Ref
*PUBLIC *RX
QPGMR *RWX X X X X
or
Data --Object Authorities--
User Authority Exist Mgt Alter Ref
*PUBLIC *EXCLUDE
QPGMR *RWX X X X X
QTMHHTP1 *RX


Examples for user-defined delimiters (see also this page).

First example:

* section name start delimiter: "<!-- Sec_"
* section name end delimiter (optional): " -->"
* variable name start delimiter: "<var400>"
* variable name end delimiter: "</var400>"

C eval HtmlSrcLib = 'CGIDEV2'
C eval HtmlSrcFil = 'HTMLSRC'
C eval HtmlSrcMbr = 'TALK2'
C callp gethtml(HtmlSrcFil:HtmlSrcLib:HtmlSrcMbr:
C '<!-- Sec_':
C ' -->':
C '<var400>':
C '</var400>')

Second example:

* section name start delimiter: "<as400>"

C callp gethtmlifs('/CgidevExtHtml/talk2ifs.html':
C '<as400>')


* Indicators for GetHtmlIfsMult subprocedure
D IfsMultIndicators...
D ds
D NoErrors n
D NameTooLong n
D NotAccessible n
D NoFilesUsable n
D DupSections n
D FileIsEmpty n
... etc. ...
* Read externally defined output html files
C eval IfsMultIndicators = gethtmlifsmult(
C '/CgiDevExtHtml/StdTop.Html -
C /CgidevExtHtml/StdRunTime.Html -
C /CgidevExtHtml/StdMsg.Html -
C /CgidevExtHtml/StdPssr.Html -
C /CgidevExtHtml/Talk2Stuff.Html -
C /CgidevExtHtml/StdEnd.Html':
C '<as400>')

 

3. Assign values to html variables

This must be done using subprocedure updHtmlVar.
This subprocedure assigns a value to all the instances of a given html variable name.
Note 3. The value to be assigned must be a character string (numeric fields must be converted or edited to character strings, see examples number 4 and 5).

Inputs

* variable name
* variable value
* action (optional)
o '1' = replace this variable if it exists, otherwise add it (default)
o '0' = clear arrays and write this one as the first
* trim instructions (optional)
o %trim - trim left and right (default)
o %triml - trim left only
o %trimr - trim right only
o %trim0 - don't trim


Examples:

1. Clear all html variables and assign to html variable custname the value contained in character field CusNam:

C callp updHTMLvar('custname':CusNam:'0')


2. Assign to html variable custaddr the value contained in character field CusAdr:

C callp updHTMLvar('custaddr':CusAdr)


3. Assign to html variable custaddr the value contained in character field CusAdr without trimmimg it:

C callp updHTMLvar('custaddr':CusAdr:'1':'%trim0')


4. Assign to html variable ordertotal the value contained in numeric field (9 2) TotThisOrd using an edit code:

C callp updHTMLvar('ordertotal':
C %editc(TotThisOrd:'J'))

About edit codes

5. Assign to html variable ordertotal the value contained in numeric field (9 2) TotThisOrd using an edit word:

C callp updHTMLvar('ordertotal':
C %editw(TotThisOrd:' , , 0. '))

See this living example.

For vary large output variables (max 16 Mb) you may use subprocedure updHtmlVar2.
In this subprocedure, instead of passing the name or the value of the substituting variable, you will pass a pointer to it and its length.
Inputs

* variable name
* pointer to the substituting string
* length of the substituting string
* action (optional)
o '1' = replace this variable if it exists, otherwise add it (default)
o '0' = clear arrays and write this one as the first
* trim instructions (optional)
o %trim - trim left and right (default)
o %triml - trim left only
o %trimr - trim right only
o %trim0 - don't trim

Example:

D varPointer s *
D varLength s 10i 0
C callp updHtmlVar2('longdata':
C varPointer:varLength)

 

4. Write html sections and send the output buffer

This must be done using subprocedure wrtsection.
One can write one or multiple sections in a single call.
Important.
Once all sections have been written, do not forget to send the output buffer to the client. This must be done by writing a pseudo section named *fini.

Example:

* Write a single section
C callp wrtsection('start')
* Write two sections
C callp wrtsection('part1 part2')
* Send the output html to the remote browser
C callp wrtsection('*fini')

Note 4. Section names are not case sensitive. A section name is a 50 char max alfanumeric string. Only english letters are supported.

Note 5. Subprocedure wrtSection supports two optional parameters:

* NoNewLine indicator.
Set it to *on to tell wrtsection NOT to insert a newline character x'15' at the end of each HTML output line. This may be useful when binary data are being sent to the browser.
* NoDataString value.
What to do when a substitution variable is encountered and no value has been set up with UpdHtmlVar.
If not specified, output variables left without substitutions display the default "**Missing Data**".

Examples:

D NoDataString c '<b>*** no substitution! ***</b>'
* Write a section without newline characters
C callp wrtsection('mysection':*on)
* Write a section with non-default warning for
* missing substitution variables
C callp wrtsection('mysection':*off:
C NoDataString)

 

5. Special output procedures

Subprocedure wrtNoSection
writes data for the browser without using substitution variables or sections.
This subprocedure can be used when a large block of data is to written. This is more likely to happen when writing non-textual data such as images.
The following example shows how to read an external IFS file (an HTML page, an image, or what you need) and how to insert it into the CGI output buffer:

D IfsInpBuff s 10000a varying
D InpBuffLen s 10i 0
D IfsObj s 255a
D FileHandle s 10i 0
D ReturnInt s 10i 0
D BytesIn s 10i 0
* ... ... ...
* Read an IFS object into "IfsInpBuff"
C eval IfsObj = '/mypath/mysubpath/myobj.xxx'
* 1-Open the IFS file
C eval FileHandle = open(%trim(IfsObj)
C : O_RDONLY + O_TEXTDATA)
* 2-Read the IFS file
C eval BytesIn = read(FileHandle
C : %addr(IfsInpBuff)
C : %size(IfsInpBuff))
* 3-Close the IFS file
C eval ReturnInt = close(FileHandle)
C eval IfsInpBuff = %trim(IfsInpBuff)
* Insert the string read into the CGI output buffer
C ' ' checkr IfsInpBuff InpBuffLen
C callp WrtNoSection(%addr(IfsInpBuff):
C InpBuffLen)


Subprocedure clrHtmlBuffer
clears any HTML output that has been buffered but has neither been sent to the browser nor written into a stream file. This is useful when program logic dictates you need to output something other than what has already been buffered.

C callp clrHtmlBuffer


# Subprocedure getHtmlBytesBuffered Returns the number of bytes in the output HTML buffer.
# This number is incremented each time output is written with WrtSection or WrtNoSection.
# It is reset to 0 when either WrtSection('*fini') or WrtHtmlToStmf is run.
# If this number is allowed to grow to more than 16 MB, the CGI program will fail.
Could be useful to stop creating an output page when its size exceeds a reasonable limit.

D buffsize s 10i 0
C eval buffsize = getHtmlBytesBuffered"