Pros & cons bean vs SSJS?

I was trying to build a bean that always retrieves the same document ( a counter document), gets the current value, increment it and save the document with the new value. Finally it should return the value to the calling method and that would get me a new sequential number in my Xpage.

Since the Domino objects cannot be serialized or singleton'ed what's the benefit creating a bean doing this, over creating a SSJS function doing the exact same thing?

My bean must have calls to session, database, view and document, which then will be called every time.

The same within the SSJS-function except for session and database.

Bean:

public double getTransNo() {
        try {
            Session session = ExtLibUtil.getCurrentSession();
            Database db = session.getCurrentDatabase();
            View view = db.getView("vCount");
            view.refresh();
            doc = view.getFirstDocument();
            transNo = doc.getItemValueDouble("count");
            doc.replaceItemValue("count", ++transNo);

            doc.save();
            doc.recycle();
            view.recycle();
        } catch (NotesException e) {
            e.printStackTrace();
        }

        return transNo;
    }

SSJS:

function getTransNo() {
    var view:NotesView = database.getView("vCount");
    var doc:NotesDocument = view.getFirstDocument();
    var transNo = doc.getItemValueDouble("count");
    doc.replaceItemValue("count", ++transNo);
    doc.save();
    doc.recycle();
    view.recycle();
    return transNo;     
}

Thank you

Upvotes: 0

Views: 661

Answers (1)

stwissel
stwissel

Reputation: 20394

Both pieces of code are not good (sorry to be blunt).
If you have one document in your view, you don't need a view refresh which might be queued behind a refresh on another view and be very slow. Presumably you are talking about a single sever solution (since replication of the counter document would for sure lead to conflicts).

What you do in XPages is to create a Java class and declare it as application bean:

  public class SequenceGenerator {
    // Error handling is missing in this class
    private double sequence = 0;
    private String docID;

    public SequenceGenerator() {
      // Here you load from the document
      Session session = ExtLibUtil.getCurrentSession();
      Database db = session.getCurrentDatabase();
      View view = db.getView("vCount");
      doc = view.getFirstDocument();
      this.sequence = doc.getItemValueDouble("count");
      this.docID = doc.getUniversalId();
      Utils.shred(doc, view); //Shred currenDatabase isn't a good idea
    }   

    public synchronized double getNextSequence() {
      return this.updateSequence();
    }

    private double updateSequence() {
       this.sequence++;
       // If speed if of essence I would spin out a new thread here
       Session session = ExtLibUtil.getCurrentSession();
       Database db = session.getCurrentDatabase();        
       doc = db.getDocumentByUnid(this.docID);
       doc.ReplaceItemValue("count", this.sequence);
       doc.save(true,true);
       Utils.shred(doc);
       // End of the candidate for a thread
       return this.sequence;
     }
 }

The problem for the SSJS code: what happens if 2 users hit that together? At least you need to use synchronized there too. Using a bean makes it accessible in EL too (you need to watch out not to call it too often). Also in Java you can defer the writing back to a different thread - or not write it back at all and in your class initialization code read the view with the actual documents and pick the value from there.

Update: Utils is a class with static methods:

 /**
 * Get rid of all Notes objects
 * 
 * @param morituri = the one designated to die, read your Caesar!
 */
public static void shred(Base... morituri) {

    for (Base obsoleteObject : morituri) {
        if (obsoleteObject != null) {
            try {
                obsoleteObject.recycle();
            } catch (NotesException e) {
                // We don't care we want go get
                // rid of it anyway
            } finally {
                obsoleteObject = null;
            }
        }
    }

}

Upvotes: 3

Related Questions