SSJS global variable seems not working - xpages

I had declared and used a global variable in ssjs library as below:
var backendDoc:NotesDocument = null;
function savedata () {
print (backendDoc.getItemValueString("fieldname")); // crash here
}
I assigned a document object to it in the Edit button just after changing docuemnt mode from read to edit:
backendDoc = document1.getDocument(); // get backend document from datasource called document1
The code in above function return error NotesDocument.getItemValueString("string")) null. Apparently, the backendDoc is null.
Any ideas how to assign value and use global variable in ssjs library? Thanks in advance

There are 2 problems with your code:
as Michael pointed out: you should use a scoped variable. Global variables in script libraries are actually application global (think applicationScope) and might be unloaded any time if memory gets tight (behavior of them depends on the XPages version)
You can't use NotesObjects here. Between the calls the C Object that backs the JS object is released and your object becomes invalid.
You can either store the NoteId in a scoped variable and retrieve the NotesDocument every time or actually use a JSON structure to keep the values you are interested in and only read/write when actually needed (load/save event). Hope this helps

I think you have to use a scoped variable in which you store the universalid of the document. This can then be used at any script to initialize the backend document.
From a ssjs you can set a scoped variable using the put method and the get method to read the variable. Example to set and read a scoped variable in session scope :
sessionScope.put(“myvar“,“myvalue“)
sessionScope.get(“myvar“)
To learn more about scoped variables watch this
http://notesin9.com/index.php/2009/11/07/episode-4-intro-to-scoped-variables/

Related

Node - look up the value of an arbitrary variable

Take this code for an example:
(() => {
const data = []
const ws = new WebSocket('ws:/localhost:5555');
ws.onmessage = (frame) => data.push(frame.data);
})();
Is it possible to look up the value of data without stopping the application, or breakpointing onmessage and waiting for it to occur? Is it possible to just look up the value of any variable that I know to be stored persistently somewhere?
Variables inside a function are private to within that function scope. Only code inside that function scope can examine them.
If you're in the debugger, you will need to be at a breakpoint inside that function scope in order to see that variable.
Sometimes it's appropriate to move the declaration of a variable to a higher scope so that after it is modified inside some local scope, it's value will persist and can be accessed from a higher scope. I don't know what real problem you're trying to solve here to know whether that makes sense for your situation or not.
More likely, since variables like your data variable get modified at some unknown time, the only way some outside code can know when to look at an updated value is by participating in some sort of event system or callback system that notifies outside that it now has a new value. In that case, it's common to just pass the new value to the callback or along with the event. Then the outside code gets the value that way, rather than having to declare it in some parent scope.

Pass String Variable to different forms within Access Database

I have a string variable assigned a value in Form1, but wish to use this variable (and the same value) in another form within the database (e.g. Form2).
How can this be achieved?
You could create a global variable.
Declare it outside any procedures at the top of Form1, like this:
Public strYourVariable as String
Now, once you have assigned a value to strYourVariable, it will be available in other modules and forms.
The global variables will be reset if you:
Use "End"
Get an unhandled error
Edit your VBA code
Close Access

Node.js Garbage Collection

Node.js will do auto garbage collections ?
var objUser = new Object ();
objUser.userName = objReq.userName;
userDB.registerUser (objUser , callback) ;
In the above code I have "objUser" which will be passed as an argument to another class and it is no longer required in the present class. Still, should I have to forcefully collect it or will it do automatically.
To do it manually, Will NULL help or is there any other mechanism given by Node Framework?
objUser = null;
Node does garbage collection, but if userDb.registerUser() retains a reference to it, your objUser will not be collected. Only when no references to an object remain it will be collected. You usually don't need to explicitly release local references by assigning null to the variable — when your function returns, all local references are released automatically. You need to worry only about global references to your object.
Also worth noting on this subject: It's been my experience that objects of the same type will reuse instances. So, if you truly want a "new Instance()" of an object make sure you nullify or reset any attributes in your constructors

mongoose and lazy initialize attributes not executing in correct scope

I'm using mongoose for my data access layer, and I really like the different
features it offers to create document models (Attributes, Methods, Static Methods..)
I use the virtual attribute feature of mongoose to create attributes that will not be persisted to MongoDB. However, these attributes are computationaly expensive (and using them many times is not helping me).
Lets take for example the same example on mongoose virtual
it persists person.name.first and person.name.last, and uses virtual attribute for person.name.full
Let's say I want to compute person.name.full only one time per the lifetime of the document
(and if I allow to set the attribute or its dependent fields like in the example, then also for every get after a dirty set).
I need an extra variable in the document scope, so naturally I used closures for this
but the 'this' scope in the function that computes the attribute, is of the global object, and not of the document I'm working on.
Code:
var makeLazyAttribute = function(computeAttribute) {
var attribute = null;
return function() {
if(!attribute) {
attribute = computeAttribute();
}
return attribute;
}
};
MySchema.virtual('myAttribute').get(makeLazyAttribute(function () {
// some code that uses this, this should be the document I'm working on
// error: first is not defined, inspecting what is this gives me the global object
return this.first + this.last
}));
Please help!
Well, ok, I've made some progress makeLazyAttribute does execute in the document scope
so I only needed to change attribute = computeAttribute(); to
attribute = computeAttribute.call(this); .
However, now Im only remembering the first ever computeAttribute() invocation instead of remembering
the first function invocation per each document.
Must have a way to mitigate this.

How can I add a JSON object to a scoped variable in Java?

I have used many JSON object in applicationScope, sessionScope, and viewScope to track related data. Writing and reading these in SSJS is very simple:`
//Create a app scope variable
applicationScope.put("myvarname", {p1:"part 1", p2:"part2"});
// read and use the app scope variable ...
var myvar = applicationScope.get("myvarname");
//Work with parts as myvar.p1, myvar.p2, etc...
In the Java code I have been writing I have learned to read these variables which were written using SSJS using the com.ibm.jscript.std.ObjectObject package with code like this:
ObjectObject myvar = (ObjectObject) ExtLibUtil
.getApplicationScope().get(dbkey);
FBSValue localFBS = myvar.get("p1");
String myp1 = localFBS.stringValue();
localFBS = myvar.get("p2");
String myp2 = localFBS.stringValue();
Now, of course, I want to write a new entry using the Java Bean that can then be read by SSJS and other Java Beans in the same manner. I managed to write to the scope using a Map and a Hashtable, but these crash the logic when trying to read using the ObjectObject.
So, how would I go about building a new entry in the scope using the ObjectObject and/or FBSValue packages? I cannot find how to create a new FBSValue that can then be added to an ObjectObject. I am sure it is a simple thing a Newbs like me has missed.
/Newbs
You can construct an empty ObjectObject, populate it with FBSValues, and just put it directly into the scope Map:
ObjectObject myvar = new ObjectObject();
try {
myvar.put("p1", FBSUtility.wrap("part 1"));
myvar.put("p2", FBSUtility.wrap("part 2"));
} catch (InterpretException e) {
e.printStackTrace();
}
Map<String, Object> applicationScope = ExtLibUtil.getApplicationScope();
applicationScope.put("myvarname", myvar);
When retrieving it later (as in the examples you provided), SSJS will see it as JSON, Java will see it exactly as it was stored.
If you need to store deeper hierarchies, you can put instances of ArrayObject and ObjectObject inside an ObjectObject in addition to primitives, so, just like JSON itself, you can nest these as deep as you need.
Just be sure to only include true JSON (strings, numbers, booleans, arrays, objects) if you'll be storing it anywhere higher than the requestScope; specifically, FunctionObject does not implement Serializable, so JSON is safe to store, JavaScript is not. Strictly speaking, this only becomes toxic when stored in the viewScope in 8.5.2 and 8.5.3 (and even then, only when the application's persistence option is not set to keep all pages in memory). But if IBM ever implements cluster support, then all objects stored in sessionScope and applicationScope will need to be serializable to allow for inter-server state transport... so, in the interest of future-proofing the design, it's wise to hold to this principle for anything stored longer than the duration of a single request.

Resources