Update 2: Made the code compatible with Domino 8.5.2
Update 3: Added methods to display message/exception on page
Update 4: Modified to send to current user. If on localhost, the exception/message is thrown -> xpage shows stack trace.
Since there are no good tools for debugging XPages, I created a couple of helper-methods (Server Side Javascript) of my own.
Debug.message sends a (MIME/HTML) mail with the specified message
Debug.exception sends a stack trace of an exception (used in a try/catch). This is useful because not all exceptions crash the application (for instance AfterRenderResponse code).
// Helper-class for debugging
var Debug = {
// Send a stack trace of an exception
exception: function( exception ){
// If on localhost/public db - throw exception
if( this.getUserName() === 'Anonymous' ){ throw exception; }
this.message( this.getExceptionString( exception ), 'Exception!' );
},
// Add exception to page
exceptionToPage: function( exception ){
this.setPageDebugMessage( 'Exception: ' + this.getExceptionString( exception ) );
},
getExceptionString: function( exception ){
var errorMessage = exception.message;
if( typeof exception.printStackTrace !== 'undefined' ){
var stringWriter = new java.io.StringWriter();
exception.printStackTrace( new java.io.PrintWriter( stringWriter ) );
errorMessage = stringWriter.toString();
}
if( typeof exception === 'com.ibm.jscript.InterpretException' ){
errorMessage = exception.getNode().getTraceString() + '\n\n' + errorMessage;
}
return errorMessage;
},
getUserName: function(){
return @Name( '[CN]', @UserName() );
},
// Send a message (supports HTML)
message: function( message, subject ){
// If on localhost/public db - throw exception
if( this.getUserName() === 'Anonymous' ){ throw 'Not logged in. Could not send message: ' + message; }
session.setConvertMime( false );
var doc:NotesDocument = database.createDocument();
doc.replaceItemValue( 'Form', 'Memo' );
doc.replaceItemValue( 'Subject', subject || 'Debug..' );
doc.replaceItemValue( 'SendTo', this.getUserName() );
var body:NotesMIMEEntity = doc.createMIMEEntity();
var contentStream = session.createStream();
// Set preferred styling
contentStream.writeText( '' );
// Convert linefeeds to <br>s
contentStream.writeText( message.replace( '\n', '<br />' ) );
body.setContentFromText( contentStream, 'text/html;charset=ISO-8859-1',
lotus.domino.MIMEEntity.ENC_NONE );
doc.send();
session.setConvertMime( true );
},
// Add message to page
messageToPage: function( message ){
this.setPageDebugMessage( message );
},
// Adds message to the bottom of the page in a dynamically created xp:text
setPageDebugMessage: function( message ){
var messageControl = getComponent( 'global-debug-messages' );
if( !messageControl ){
messageControl = new com.ibm.xsp.component.xp.XspOutputText();
messageControl.setId( 'global-debug-messages' );
messageControl.setEscape( false );
messageControl.setStyleClass( 'xspMessage' );
var valueBinding = facesContext.getApplication().createValueBinding( '#{requestScope.debugMessages}' );
messageControl.setValueBinding( 'value', valueBinding );
view.getChildren().add( messageControl );
}
var currentMessages = requestScope.debugMessages;
if( typeof currentMessages !== 'string' ){ currentMessages = ''; }
requestScope.put( 'debugMessages', message + '<br />' + currentMessages );
}
}
7 comments:
Nice,
another way is to use a print statement which write to the server console - and create an event handler in events4.nsf which will send you a mail ;-)
http://xpages.notessidan.se/blogg.nsf/xstart.xsp?post=718BA0FD3D9D08A7C1257673002BBDDE
- Thomas
What do I do with this code?
Put it inside a SSJS library.
In your functions, add try/catch. When an error occurs, you'll get a mail.
Example:
function someFunction(){
try {
/*the code*/
} catch(e){ Debug.exception(e); }
}
Or, if you're curious about a value or something..
/*code*/
Debug.message( param.get( 'some_parameter' ) );
/*code*/
The script library containing Debug have to be added to the page you're using it in.
Hope this helps. :)
In our production environment, we use a customized Java script/an extended Debug "class", so that the stack traces go to an OpenLog db. This is better when putting applications into production, so that the user/you won't get hammered by error messages
Pretty cool stuff. I really like how you create an additional control on the page if it doesnt already exist and then bind it to a requestScope variable, then add it to the Xpage.
Very neat.
Thanks :)
I always try to make my "APIs" as simple to use as possible.
When I am calling Debug.messageToPage in beforePageLoad event it is throwing an exception
com.ibm.xsp.component.xp.XspOutputText incompatible with com.ibm.xsp.component.UIScriptCollector
If I remember correctly, the XSP Component tree isn't created until afterPageLoad, so that might be why it fails.
Post a Comment