使用相同多米诺骨牌对象的不同DOTS Tasklet => "对象已被删除或回收"

时间:2014-03-17 12:28:28

标签: lotus-domino

我正在使用一个带有四个DOTS Tasklet的DOTS配置文件。所有tasklet都由domino目录程序文档“tell profileName run XYZ”启动,因为计划的tasklet不能与IBM SBT一起使用。

所有tasklet都使用相同的配置视图和文档。同时运行任务(例如每60分钟),我经常会收到错误“NotesException:Object已被删除或回收”。

如何防止这种情况?

它影响不同的代码行,并且只有当两个Tasklet同时运行时(在程序文档中同时运行,例如60分钟)。

每个DOTS tasklet在单个DOTS配置文件上运行时没有问题。

示例1:

NotesException: Object has been removed or recycled
    at lotus.domino.local.NotesBase.CheckObject(Unknown Source)
    at lotus.domino.local.Document.getSize(Unknown Source)
    at de.gish.gisdots.utils.DominoUtils.isValidDocument(DominoUtils.java:54)


public static boolean isValidDocument( Document doc ) {
    boolean isValid = false;
    try {
        if ( null == doc )
            return false;
        if ( doc.getSize() <= 0 ) //line 54
            return false;
        if( doc.isValid() == false )
            return false;
        if( !doc.hasItem( "Form" ))
            return false;
        if ( doc.hasItem( "$Conflict" ) )
            return false;
        isValid = true;
    } catch ( NotesException ne ) {
        isValid = false;
        LOG.error( ne.getMessage(), ne );
    } catch ( Exception e ) {
        isValid = false;
        LOG.error( e.getMessage(), e );
    }
    return isValid;
}

示例2:

NotesException: Object has been removed or recycled
    at lotus.domino.local.NotesBase.CheckObject(Unknown Source)
    at lotus.domino.local.View.getNextDocument(Unknown Source)
    at de.gish.gisdots.adap.db.config.ConfigurationDBInformation.readConnections(ConfigurationDBInformation.java:182)


    public Map<String, ConnectionsConfiguration> readConnections( Database configDB ) throws Exception {
        View viewConnections = null;
        Document docTmp = null;
        Document docConnections = null;
        Map<String, ConnectionsConfiguration> connections = new HashMap<String, ConnectionsConfiguration>();
        try {
            LOG.trace( ">>> Start reading configuration database Connections information" );
            // Ansicht der Connections Dokumente ermitteln
            viewConnections = DominoUtils.getView( configDB, Constants.CONFIGDB_VIEW_CONNECTIONS );
            viewConnections.setAutoUpdate( false );
            // Alle Connections Dokumente durchlaufen
            docConnections = viewConnections.getFirstDocument();
            while ( docConnections != null ) {
                docTmp = viewConnections.getNextDocument( docConnections );  //line 182
                ConnectionsConfigurationReader reader = new ConnectionsConfigurationReader();
                ConnectionsConfiguration connectionsConfig = reader.readFromDominoDocument( docConnections );
                if ( connectionsConfig != null && connectionsConfig.isValid() ) {
                    connections.put( connectionsConfig.getID(), connectionsConfig );
                    LOG.debug( "Connections configuration read: {}", connectionsConfig.toString() );
                }
                DominoUtils.recycleSilent( docConnections );
                docConnections = docTmp;
            }
            return connections;
        } finally {
            DominoUtils.recycleSilent( docTmp );
            DominoUtils.recycleSilent( docConnections );
            DominoUtils.recycleSilent( viewConnections );
            LOG.trace( "<<< End reading configuration database Connections information" );
        }
    }

示例3:

NotesException: Object has been removed or recycled
    at lotus.domino.local.NotesBase.CheckObject(Unknown Source)
    at lotus.domino.local.Document.getItemValueString(Unknown Source)
    at de.gish.gisdots.adap.db.config.DatabaseAssignmentReader.readFromDominoDocument(DatabaseAssignmentReader.java:20)

    public DatabaseAssignment readFromDominoDocument( Document docDBAssignment) throws Exception{
        if ( DominoUtils.isValidDocument( docDBAssignment ) ) {
            DatabaseAssignment dbAssignment = new DatabaseAssignment( );
            dbAssignment.setId( docDBAssignment.getItemValueString( "id" ) );
            dbAssignment.setTitle( docDBAssignment.getItemValueString( "titel" ) );
            dbAssignment.setServer( docDBAssignment.getItemValueString( "hauptServer" ) );
            dbAssignment.setReplicaID( docDBAssignment.getItemValueString( "replikID" ) );
            dbAssignment.setCode( docDBAssignment.getItemValueString( "verwendetesKuerzel" ) ); //line 20
            dbAssignment.setType( docDBAssignment.getItemValueString( "art" ) );
            dbAssignment.setEnvironment( docDBAssignment.getItemValueString( "f_Mandant" ) );
            return dbAssignment;
        } else {
            LOG.warn( "Invalid database assignment document skiped");
        }
        return null;
    }

1 个答案:

答案 0 :(得分:1)

免责声明:我没有使用过DOTS tasklet,但我相信以下内容适用于它们,就像应用于多线程代理一样。这是因为我的理解是DOTS tasklet都在同一个JVM中运行,因此它们共享一个加载的LSXBE实例。 (LSXBE是在Java类的Java场景后面运行的C API逻辑。

在同一个JVM中,LSXBE会对事物进行排列,以便对同一文档的所有引用共享NotesDocument对象的单个后端表示。这同样适用于视图等.LSXBE代码跟踪所有引用相同物理NSF结构并通过公共C API结构路由它们的对象实例。因此,如果两个线程在同一个文档上运行,并且您在一个线程中回收了Document对象,那么您已经从第二个线程中回收它,并且您将得到此错误。为了防止这种情况,您必须确保只有一个线程拥有该文档并对其进行回收。

通常,您需要某种代理或某种锁定机制来防止两个tasklet使用和回收引用同一底层物理对象的Java对象。通常,在多线程代理中,可以通过使用将一个数据库分配给每个工作线程的调度程序线程来实现此目的。这确保没有重叠。如果通过为每个线程分配文件夹或视图来执行此操作并不是很干净,因为可以从多个文件夹或视图引用同一文档,但您可以使用Java的同步机制来锁定文档。

对于您的常见配置视图和文档,您可能要做的是创建一个同步的包装类TaskletConfig(或类似的东西),它打开视图,将文档读入成员变量,并回收所有内容。有关如何设置整个类的信息,请参阅here,以便使用它创建的所有对象同步方法。