22.07.2010

2 SSJS libs, one XPage and a Mystery

>>Author:  Thomas Bahn
>>Ort:     Schwentinental (Kiel)
        
URL: http://www.assono.de/blog/d6plinks/2-SSJS-libs-one-XPage-and-a-Mystery

Category: Lotus Domino, Entwicklung, XPages, SSJS

At times, I spend waste a lot of time due to my stubbornness, when something that should work, doesn't work.

This time, the problem - at its core - involved only two server-side JavaScript script libraries and one XPage.


First I wrote a SSJS library
commonUtils.jss, which creates the object de.assono.commonUtils. Then I developed a second library myViewUtils.jss, which in turn creates the object de.assono.myViewUtils. In order to use the first library, I import it into the second one.

After that, I implemented a simple XPage, which uses both objects, and therefore I included both SSJS libraries as resources into the XPage.


The result:

A picture named M2

For some reason, the object
de.assono.myViewUtils seems to be undefined?!

Here are the SSJS libraries and the XPage:

SSJS library commonUtils.jss:
if (!de) {var de = {};}
if (!de.assono) {de.assono = {};}

if (de.assono.commonUtils) {return;}

de.assono.commonUtils = (function() {
       return {
               className : "de.assono.commonUtils",
               uses :

               getView : function (db : NotesDatabase, viewName : String) {
                       
                       var dbToBeUsed : NotesDatabase = (typeof(db) == "undefined" ? database : db);
                       if (!dbToBeUsed.isOpen() && !dbToBeUsed.Open("", "")) {
                               throw { message : "Could not open database" }
                       }

                       var view : NotesView = dbToBeUsed.getView(viewName);
                       if (typeof(view) == "undefined") {
                               throw { message : "Could not open view" }
                       }

                       return view;
               }
       };
})();



SSJS library myViewUtils.jss:
import commonUtils;

if (de.assono.myViewUtils) {return;}

de.assono.myViewUtils = (function () {
       return {
               className : "de.assono.myViewUtils",
               uses : e.assono.commonUtils

               getDocCount : function (viewName : String) {
                       var view : NotesView = de.assono.commonUtils.getView(database, viewName);
                       return view.getAllEntries().getCount();
               }
       }
})();



XPage commonUtilsTest_not_working.xsp:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
       <xp:this.resources>
               <xp:script src="/commonUtils.jss" clientSide="false" />
               <xp:script src="/myViewUtils.jss" clientSide="false" />
       </xp:this.resources>

       <xp:label value="NotesURL of the view:" id="label1" />
       <xp:link escape="true" id="link1">
               <xp:this.value><!DATA#{javascript:var view : NotesView = de.assono.commonUtils.getView(database, "Help"); return view.getNotesURL()}></xp:this.value>
               <xp:this.text><!DATA[#{javascript:var view : NotesView = de.assono.commonUtils.getView(database, "Help"); return view.getNotesURL()}></xp:this.text>
       </xp:link>
       <xp:br />

       <xp:br />

       <xp:label value="Number of documents in the view: " id="label2" />
       <xp:inputText id="inputText1" readonly="true">
               <xp:this.value><!DATA[#{javascript:return de.assono.myViewUtils.getDocCount("Help")}></xp:this.value>
       </xp:inputText>
       <xp:br />
</xp:view>



It tried a lot, moved code between the libraries and the XPage, imported more or less, etc.

In the end, a very, very little change got the XPage working:

XPage commonUtilsTest_working.xsp:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
       <xp:this.resources>
               <xp:script src="/myViewUtils.jss" clientSide="false"/>
               <xp:script src="/commonUtils.jss" clientSide="false"/>
       </xp:this.resources>

       <!-- ... -->
</xp:view>


Do you spot the difference? It's the order I import the SSJS libraries as resources!

But I still don't understand, why the object cannot be found, if commonUtils.jss is imported first. Is there anyone, who could explain this behavior and solve the mystery?

For your own experiments:

Comments

#1 I'm not exactly sure why the error gets thrown about the object not existing, however, the problem stems from some techniques you've employed that are problematic.

First, in your SSJS libraries, the lines

if (de.assono.<<OBJECTNAME>>) {return;}

are actually useless ... return is only like this within a function block. Inside the SSJS library, it does not cease execution of the SSJS. I would avoid object checking like that in this case, since you are directly including the script libraries, as a designer you must make sure your object hierarchy is built, or employ a more robust object extension model.

Also, since you import the main library from the myViewUtils library, including it in the XPage is redundant. I believe this redundancy is what is causing your error, although with the limited time i've looked at the code, I can not discern exactly why that particular error is being thrown ...

In any case, either remove the import, and make sure to include both libraries, commonUtils first, then myViewUtils next, OR use the import, and only include myViewUtils ... but don't do both.
Gravatar Image
#2 Thank you, Jeremy.

if (...) {return;}
is obviously (now at least I see it, too Emoticon ) an oversimplification. It should be
if (!...) {
// object creation here
}

For the subject import in JS vs. resource inclusion in XPage:
In my point of view, if the second library uses something of the first library, it must import it.
If the XPage uses something of the first and something of the second library, it should include both as resources.

The developer of the XPage shouldn't need to be aware of the "inner" dependencies of the libraries he uses.

Thus I would expect the commonUtilsTest_not_working.xsp to work, even if myViewUtils.jss imports commonUtils.jss (and indepently of the import).
Gravatar Image
#3 After changing the
if (...) { return; }
to
if (!...) { ... }
commonUtilsTest_not_working.xsp still doesn't work.
Gravatar Image
#4 It seems to be impossible to change an object of another library (in XPages).

So e.g. you have library A and B and both "exports" an object O. You will have the O of that library you add first to a XPage. Therefore in commonUtilsTest_working.xsp you get the de object of myViewUtils.jss and commonUtils.jss is not able to add something to it, which is no problem since it has already added it inside the script library. But in commonUtilsTest_not_working.xsp you get the de object of commonUtils.jss and myViewUtils.jss is not able to add/change something. Therefore de.assono.myViewUtils is not present.

I don't know if it is changeable but I think it is wanted as default because it would be terrible if to libraries shares a variable name incidentally.

Maybe there is a way to access the variable by a full qualifying name e.g. libname#var? I would like to know it is ;)

You could bypass the problem via a *Scope variable e.g. applicationScope.de.assono
Gravatar Image
#5 Sry, I was a bit confused...

I meant "if two libraries share a variable name incidentally" and "I would like to know if it is".

Furthermore most likely you just want to omit "de.assono." since the libraries have separated namespaces.
Gravatar Image

Post A Comment

Comments

:-D:-o:-p:-x:-(:-):-\:angry::cool::cry::emb::grin::huh::laugh::lips::rolleyes:;-)

Tags

Deutsche RSS-Feeds (German)

Custom Button Custom Button

English RSS feeds

Custom Button Custom Button