Friday, July 27, 2007

Working around the 64k print limit in web-agents

In LS, there seems to be a 64k limit per Print statement

If you have agents that print a large amount of HTML/XML (concatenating into a string), one workaround is to check the string-length frequently:

If Len(yourString) > safeNumber Then
Print yourString
yourString = ""
End If

Where yourString is the string containing the HTML/XML/etc., and safeNumber is a number that is smaller than the 64k - the maximum amount of characters you can imagine is added per concatenation.

If there is A LOT (5000+) of string concatenation in the agent, I suggest using Julian Robichaux' StringBuffer class. You would have to add a getLength-method, to check the length of the buffer.

Something like this:

'in stringbuffer class
Public Function getLength() As Long
getLength = Len(buffer)
End Function

'in the printing agent
If bufferObject.getLength > safeNumber Then
Print bufferObject.toString()
bufferObject.erase()
End If


The above If-statements .. > safeNumber .. should be put inside the loop that you use to concatenate the string. Thanks for making me aware of the bad "documentation", Thomas.


If you have a lot of different content you want to print, I'd suggest having one agent per content-type, and that the agents only contains method calls to their respective script libraries (which in turn can use other scriptlibs). Having 20+ agents in an application quickly gets messy (at least from my point of view).

Example:
..xml?OpenAgent&action=report&type=wages&employeenum=2134212

In agent (untested code):

Use "PrintXML"
Dim s As New NotesSession
Dim action As Variant

action = Evaluate( |@UrlQueryString("action")|,_
s.DocumentContext)
'the evaluate above returns a text-list with one item
Select Case( action(0) )
Case "report"
Call report( s.DocumentContext )
End Select

5 comments:

The Rotary Club of Tanglin said...

Why not directly use a modified Stringbuffer Class? Call it WebAgentStringBuffer. Whenever you append a string you check the length *inside* the class and write it out if needed. Then just add one method e.g. flush that writes out on command. Makes your code much shorter.

Tommy Valand said...

Yes, that should work just fine.

One could also just expand the StringBuffer class (no need to split it into two classes), and add web-specific methods that do what you suggest.

Miguel said...

Hi Tommy,
Another option could be to create a new method to print just in time..

Public Sub safePrint()
Dim i As Integer
For i = 0 To Ubound(Me.tempArray)
Print tempArray(i)
Next
End Sub

Miguel Angel

Rob Mellinger said...

Hi, have you ever heard of a 4K limit on print statements? I'm encountering a weird problem when trying to print xml in agent as web service, and it stops at random places in the print process with no discernible pattern (sometimes it writes 3915, others 3881, but always short of 4k). Works the same if I concatenate string or print every bit of xml as I gather it.

Tommy Valand said...

Sounds similar to what happened when I tested the limits of the print statements a while back.

The result of the Print was random when there were more than 65 534 characters per Print statement. What I did to work around the issue was to print in chunks smaller than the limit (in your case, 4k).