SSJS equivalent of LSI_Info from LotusScript - xpages

Most of my code is error handled with try/catch and OpenLog (modified to handle SSJS exceptions). Unfortunately, exception in SSJS gives hard to read stack trace.
So I need to pass more info - at least event/method where is the error handler. I can simply put "method XY" argument to every OpenLog.logError call, but this makes every handler unique and prone to errors (programmers love copypasta). It would be nice to have LSI_Info equivalent, what makes error handlers constant (so you can define them as template in Eclipse).
Is there any call, which returns "where I am" info of method/event for SSJS code (including libraries)?

Have a look at the code in the Message class of my debug toolbar (found here on GitHub). I contains a way to 'pretty print' errors and also captures a com.ibm.jscript.InterpretException. I use that to send a formatted error message to an OpenLog event document. It (sort of) mimics the information you get in the default XPage error page.
To see what the formatted error looks like go to my toolbar's demo page and hit the Test 1 or Test 2 button. That will throw a SSJS error that is captured by a custom error form. That form writes a message to the toolbar which is configured to also store error messages in a separate OpenLog database.
(toolbar download can be found here on OpenNTF)

Related

Runtime error on Partial refresh

I need to do a partial refresh of multiple components as found here:
http://xpageswiki.com/web/youatnotes/wiki-xpages.nsf/dx/Work_with_events_and_partial_or_full_refresh
So I figured I would start small with just one component and placed the code:
XSP.partialRefreshPost("#{txtProductType}");
In the on client side click event of a radio button group. When the page is displayed, I get:
The runtime has encountered an unexpected error.
Any idea what I am doing wrong?
The XSP.partialRefreshPost method requires a client side id and an optional argument. So in your case the correct syntax is:
XSP.partialRefreshPost("#{id:txtProductType}", {});

Custom Control datasource use in Xpage

How can I use a custom control datasource (named doc) in XPage Application layout?
I need to control read mode and edit mode through the basic node of the place bar.
When I put the code doc.isEditable() in the rendered property, the following error is display in the browser:
Error while executing JavaScript computed expression
Script interpreter error, line=1, col=6: [ReferenceError] 'doc' not found
JavaScript code
doc.isEditable();
I am new to Xpage.
Can you post some code? not entirely sure what you mean.
Generally the best place to define a data source is at the top of the XPage so that every control beneath it has access to it. If your defining a data source after your trying to query it you would get an error like this

XPages sometimes refresh and lose content

I hope someone can help me solve a very serious problem we face at the moment with a business critical application losing data when a user works in it.
This happens randomly - I have never reproduced this but the users are in the system a lot more than me.
A document is created with a load of fields on it, and there are 2 rich text fields. We're using Domino 8.5.3 - there are no extension lib controls in use. The document has workflow built in, and all validation is done by a SSJS function called from the data query save event. There is an insane amount of logging to the sessionscope.log and also this is (now) captured for each user in a notes document so I can review what they are doing.
Sometimes, a user gets to a workflow step where they have to fill in a Rich Text field and make a choice in a dropdown field, then they submit the document with a workflow button. When the workflow button is pressed (does a Full Update) some client side JS runs first
// Process any autogenerated submit listeners
if( XSP._processListeners ){ // Not sure if this is valid in all versions of XPages
XSP._processListeners( XSP.querySubmitListeners, document.forms[0].id );
}
(I added this to try and prevent the RTF fields losing their values after reading a blog but so far it's not working)
then the Server-side event runs and calls view.save() to trigger QS code (for validation) and PS code to run the workflow agent on the server.
95% of the time, this works fine.
5% of the time however, the page refreshes all the changes made, both to the RFT field (CKEditor) and the dropdown field are reloaded as they were previously, with no content. It's like the save hasn't happened, and the Full Update button has decided to work like a page refresh instead of a submit.
Under normal circumstances, the log shows that when a workflow button is pressed, the QuerySave code starts and returns True. Then the ID of the workflow button pressed is logged (so I can see which ones are being used when I am reviewing problems), then the PostSave code starts and finally returns true.
When there is a problem, The QuerySave event runs, returns true if the validation has passed, or false if it's failed, and then it stops. The ID of the workflow button is also logged. But the code should continue by calling the PostSave function if the QuerySave returns true - it doesn't even log that it's starting the PostSave function.
And to make matters worse, after the failure to call the PostSave code, the next thing that is logged is the beforePageLoad event running and this apparently reloads the page, which hasn't got the recent edits on it, and so the users loses all the information they have typed!
This has to be the most annoying problem I've ever encountered with XPages as I can find no reason why a successful QuerySave (or even a failure because mandatory fields weren't filled in) would cause the page to refresh like this and lose the content. Please please can someone help point me in the right direction??
It sounds as if in the 5% use cases, the document open for > 30mins and the XSP session is timing out - the submit causes the component tree to be re-created, and the now empty page returned back to the user. Try increasing the time out for the application to see if the issue goes away.
I would design the flow slightly different. In JSF/XPages validation belongs into validators, not into a QuerySave event. Also I'd rather use a submit for the buttons, so you don't need to trigger a view.save() in code. This does not interfere with JSF's sequence of things - but that's style not necessarily source of your problem.... idea about that:
As Jeremy I would as a first stop suspect a timeout, then the next stop is a fatal issue in your QuerySave event, that derails the runtime (for whatever reason). You can try something like this:
var qsResult = false;
// your code goes here, no return statements
// please and if you are happy
qsResult = true;
return qsResult;
The pessimistic approach would eventually tell you if something is wrong. Also: if there is an abort and your querySave just returns, then you might run in this trap
function noReturn() {return; } //nothing comes back!
noReturn() == true; --> false
noReturn() == false; --> false
noReturn() != false; --> true!!!!
What you need to check: what is your performance setting: serialize to disk, keep in memory or keep latest in memory? It could be you running foul of the way JavaScript libraries work.
A SSJS library is loaded whenever it is needed. Variables inside are initialized. A library is unloaded when memory conditions require it and all related variables are discarded. so if you rely on any variable in a JS Function that sits inside a SSJS library between calls you might or might not get the value back, which could describe your error condition. Stuff you want to keep should go into a scope (viewScope seems right here).
To make it a little more trickier:
When you use closures and first class functions these functions have access to the variables from the parent function, unless the library had been unloaded. Also functions (you could park them in a scope too) don't serialize (open flaw) so you need to be careful when putting them into a scope.
If your stuff is really complex you might be better off with a backing bean.
Did that help?
To create a managed bean (or more) check Per's article. Your validator would sit in a application bean:
<faces-config>
<managed-bean>
<managed-bean-name>workflowvalidator</managed-bean-name>
<managed-bean-class>com.company.WfValidator</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
</faces-config>
Inside you would use a map for the error messages
public Map<String,String> getErrorMessages() {
if (this.errorStrings == null) { // errorStrings implements the MAP interface
this.loadErrorDefinitions(); //Private method, loads from Domino
}
return this.errorStrings;
}
then you can use EL in the Error message string of your validators:
workflowvalidator.errorMessage("some-id");
this allows XPages to pick the right one directly in EL, which is faster than SSJS. You could then go and implement your own custom Java validator that talks to that bean (this would allow you bypass SSJS here). Other than the example I wouldn't put the notes code in it, but talk to your WfValidator class. To do that you need to get a handle to it in Java:
private WfValidator getValidatorBean() {
FacesContext fc = FacesContext.getCurrentInstance();
return (WfValidator) fc.getApplication()
.getVariableResolver()
.resolveVariable(fc, "workflowvalidator");
}
Using the resolver you get access to the loaded bean. Hope that helps!
My experience is that this problem is due to keeping page in memory. Sometimes for some reason the page gets wiped out of memory. I'm seeing this when there is a lot of partial refreshes with rather complex backend Java processing. This processing somehow seems to take the space from memory that is used by the XPage.
The problem might have been fixed in later releases but I'm seeing it at least in 8.5.2.
In your case I would figure out some other workaround for the CKEditor bug and use "Keep pages on disk" option. Or if you can upgrade to 9.0.1 it might fix both problems.

How to set the order of validation messages?

We're using the "Error Messages" XPages (native) control to show the validation errors to user. It works. The validation is done by setting the field as required and entering the field error message. Nothing special.
Now the requirement is to set the error messages in to the same order as they appear in the form. Is this possible?
I guess I could create a custom validator (Java) and doing all the form validations there in certain order (just tested the Validation interface... but not really used id, yet).
There's the old (unresolved) argument: should the errors appear next to the control that failed the validation, on top of the form or next to the button you pressed for submission. I tend to put them next to the failed control and have ONE message next to the button reading: "Sorry I couldn't process the input, help me and fix the fields that have error messages next to them". Then sequence isn't an issue any more. If you want to be 100% sure you could instead of the summary control use the individual controls next to each other.
What anyway would be a nice exercise: let the error message control alter the css of the failed control, so it becomes clearer what to look out for.
The Validations are fired one by one in order they are in the component tree. Depending on how you are wanting them to display you could move the components around and then style them with css. Or if you are really just wanting to move the order of the summary statements around in the Messages Box, I would just use some JS to move them around I believe they just render as a UL. Only having one Validator won't really work as the same validator will get fired for every component in the order of the component tree.

How to add link to error message within ItemDeleting event receiver method?

I have an SPList event receiver method like:
ItemDeleting(ByVal voHttpContex As HttpContext, ByVal voProperties As Microsoft.SharePoint.SPItemEventProperties)
To block unwanted operation i uset this code:
voProperties.Cancel = True
voProperties.ErrorMessage="This is my error message."
After executing above code error message within error page is shown.
Is there a way to add to this error message html link to another page?
I was tying to use "a" html tag but it was displayed explicitly on page and wasn't recognized as a Html code to be transformed and parsed.
Do anybody knows how to add this link to the message? Link should have of course some name like "click here" instead of "http://blablabla.bla" format.
Unlikely by using ErrorMessage - whatever code in SharePoint is outputing this message is useing HTMLEncode and you're not going to be able to stop that.
With SP2010 .Cancel is depreciated and you could use Status = CancelWithRedirectUrl
voProperties.Status = CancelWithRedirectUrl;
// Redirect to some page that shows your error and provides link.
voProperties.RedirectUrl = "someurl.htm";

Resources