在xPages中处理文档锁定的最佳方法?

时间:2012-06-04 14:22:44

标签: xpages

在xPages中处理文档锁定的最佳方法是什么?目前我们使用标准的软锁定,它似乎在Notes客户端中运行得相当好。

在xPages中,我考虑使用“允许文档锁定”功能,但我担心人们会在不使用关闭或保存按钮的情况下关闭浏览器,然后永远不会清除锁定。

当用户关闭会话时,有没有办法清除锁定?我没有看到这样的事件。

或者有更简单的文件锁定方法吗?

我意识到我可以使用代理清除锁,但何时运行它?我会想到一个晚上的某个时候,我相当肯定锁不再真正活跃。

5 个答案:

答案 0 :(得分:1)

以下是我正在使用的代码:

/* DOCUMENT LOCKING */
/*

    use the global object "documentLocking" with:
    .lock(doc) -> locks a document
    .unlock(doc) -> unlocks a document
    .isLocked(doc) -> returns true/false
    .lockedBy(doc) -> returns name of lock holder
    .lockedDT(doc) -> returns datetime stamp of lock

*/ 
function ynDocumentLocking() {

    /*

        a lock is an entry in the application scope

        with key = "$ynlock_"+UNID

        containing an array with
        (0) = username of lock holder
        (1) = timestamp of lock


    */

    var lockMaxAge = 60 * 120; // in seconds, default 120 min

    this.getUNID = function(v) {
        if (!v) return null;
        if (typeof v == "NotesXspDocument") return v.getDocument().getUniversalID();
        if (typeof v == "string") return v;
        return v.getUniversalID();
    }

    /* puts a lock into application scope */
    this.lock = function(doc:NotesDocument) {
        var a = new Array(1);
        a[0] = @UserName();
        a[1] = @Now();
        applicationScope.put("$ynlock_"+this.getUNID(doc), a);  
        // print("SET LOCK "+"$ynlock_"+doc.getUniversalID()+" / "+a[0]+" / "+a[1]);
    }   

    /* removes a lock from the application scope */
    this.unlock = function(doc:NotesDocument) {
        applicationScope.put("$ynlock_"+this.getUNID(doc), null);
        //print("REMOVED LOCK for "+"$ynlock_"+doc.getUniversalID());
    }

    this.isLocked = function(doc:NotesDocument) {
        try {
            //print("ISLOCKED for "+"$ynlock_"+doc.getUniversalID());       

            // check how old the lock is
            var v = applicationScope.get("$ynlock_"+this.getUNID(doc));
            if (!v) {
                //print("no lock found -> return false");
                return false;   
            }

            // if lock holder is the current user, treat as not locked
            if (v[0] == @UserName()) {
                //print("lock holder = user -> not locked");
                return false;
            }


            var dLock:NotesDateTime = session.createDateTime(v[1]);
            var dNow:NotesDateTime = session.createDateTime(@Now());
            // diff is in seconds
            //print("time diff="+dNow.timeDifference(dLock)+" dLock="+v[1]+" now="+@Now());
            // if diff > x seconds then remove lock, it not locked
            if (dNow.timeDifference(dLock) > lockMaxAge) {
                // print("LOCK is older than maxAge "+lockMaxAge+" -> returning false");
                return false;
            }
            //print("return true");
            return true;
        // TODO: check how old the lock is
        } catch (e) {
            print("ynDocumentLocking.isLocked: "+e);
        }

    }

    this.lockedBy = function(doc:NotesDocument) {
        try {
        var v = applicationScope.get("$ynlock_"+this.getUNID(doc));
        if (!v) return "";
        //print("ISLOCKEDBY "+"$ynlock_"+doc.getUniversalID()+" = "+v[0]);
        return v[0];

        } catch (e) {
            print("ynDocumentLocking.isLockedBy: "+e);
        }
    }

    this.lockedDT = function(doc:NotesDocument) {
        try {
        var v = applicationScope.get("$ynlock_"+this.getUNID(doc));
        if (!v) return "";
        return v[1];

        } catch (e) {
            print("ynDocumentLocking.isLockedBy: "+e);
        }
    }

}

var documentLocking = new ynDocumentLocking();

答案 1 :(得分:0)

您可以从webDAV的工作方式中获取一个页面。有一个servlet管理锁定文件的“锁定列表”。锁定会在10分钟后自动失效。通过呼叫可以更新或终止锁。因此,当您编辑文档时,您将请求锁定,然后启动CSJS计时器,每8分钟调用一次重新锁定函数(因此您有一些错误的余地),并且postSave调用解锁(除非您保持编辑模式)。 如果用户在10分钟后关闭浏览器,文档将自动解锁。由于您可以自由地实现锁定功能,因此您可以捕获用户/位置并在“锁定失败”显示中使用该信息(您的事件可以进一步推动并让原作者了解它或执行一些“重试”选项。 实现起来并不简单,但一旦实现简单易用

答案 2 :(得分:0)

ApplicationScope可能是捕获“锁定”文档的好地方。毕竟,要使applicationScope过期,所有用户的会话都必须已过期,因此打开页面的任何人都无法保存。

当有人编辑文档时,可能会捕获UNID,用户和时间。保存文档时清除值。请记住,用户可能会关闭浏览器等。我一直在内部讨论这种方法,如果我们最终建立这个,我会把它添加到OpenNTF。但我们不太可能在下个月内加入它。

答案 3 :(得分:0)

我更喜欢使用类似于Withers先生的答案的解决方案。主要问题是如何处理不需要的和可怕的后退按钮。打开时很容易锁定文档,但是有很多方法可以关闭XPage,用户不仅限于你提供的导航,而且正如他所说,也可以完全关闭浏览器,使用后面的因此,我能想到的最好的方法是创建一些我们将在应用程序和会话范围中使用的java对象。

第一步是创建一个“LockedDocument”类。我们知道,文档不可序列化,我们不希望将文档本身保存在此对象中,我们希望保存UNID及其保存时间。我们希望这样做,以便我们可以设法在给定时间(例如30分钟到一小时)之后清除对象。此类还应实现类似的接口,以便此时对集合进行排序,以便最早的文档是最先进的,最新的文档是最后的。

接下来,我们创建另一个包含这些LockedDocuments的列表或地图的类。这个类还必须有一个线程(实现Runnable),它将每五分钟左右检查一次所有文档,我还没有测试过,但它应该工作)。任何在30到60分钟前锁定的文档(预定义)将被解锁(从列表中删除)。重要的是如上所述对列表进行分类,并且当达到小于锁定时间的时间时,循环被“破坏”以防止不希望的处理。

下一步是在sessionScope中包含用户特定列表。此列表是当前用户拥有的LockedDocuments。当用户将文档的状态更改为可编辑时设置,并在将文档设置为可编辑之前进行检查,以防止同一用户在多个选项卡中打开一个文档。锁定再次检查onquerysave()。打开主页面后,锁定会自动释放。 onquerysave()还必须检查以确保文档UNID在sessionScope列表中,或者在允许保存之前文档是否为新文件。

快速回顾
除非它存在于自己的sessionScope列表中,否则任何人都无法编辑保存在applicationScope LockedDocumentList中的任何UNID。 可以警告用户他们的锁定时间正在接近并重置计时器 包含带锁定文档的列表的类必须是单例
可能有办法改善这个答案,我相信我错过了一些东西。这只是一个想法。

可能有更好的方法来解决这个问题,但这是我找到的最好方法。

答案 4 :(得分:0)

您可以删除window.onunload事件中的Domino锁:

window.onunload = function(){
    dojo.xhrGet(...
}

无需重新发明轮子。