Hello,

Sometimes, the execution of a job/method Documentum via Java Method Server (JMS) can generate a Core dump error for various reasons : content file protected, document corrupted, …etc…especially when using IRM protection which produces the stopping of DCTM job.

Here, an example of error:

	EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000000111b9d09, pid=3684, tid=7584
	#
	# JRE version: 7.0_17-b02
	# Java VM: Java HotSpot(TM) 64-Bit Server VM (23.7-b01 mixed mode windows-amd64 compressed oops)
	# Problematic frame:
	# C  [libemcdctmirm.dll+0x1f9d09]  PVS_TemplateListFree+0x7069
	#
	# Core dump written. Default location: D:\App\Workspaces\....\hs_err_pid3684.mdmp

So, I will try to expose a simple solution in order to avoid the stopping of JMS by by-passing the use of JMS:
DCTM JOB => DCTM METHOD => Script BATCH CMD => Script POWERSHELL => JAVA DFC/JVM

  • Creation of a DCTM job My_Method_PowershellScript :
    In Documentum Administrator, in the section Administration/Job Management/Methods, create a method My_Method_PowershellScript:

    ***** in tab "Method Info" 
    * Name = My_Method_PowershellScript
    * Verb = D:\App\MyFolder4DCTM\My_ScriptProcess.cmd
    * Method Type = program
    * Timeout Minimum = 30
    * Timeout Default = 172800
    * Timeout Maximum = 345600
    * Launch Direct	= [X] Use the exec call to execute the procedure
    * Launch Asynchronously	= [X] Launch as a separate process	 
    * Run As Owner = [X] Run as the installation owner
    

  • Creation of a DCTM method My_Job_BatchScript :
    In Documentum Administrator, in the section Administration/Job Management/Jobs, create a method My_Job_BatchScript:

    ***** in tab "Info"
    * Name = My_Job_BatchScript
    * Trace Level = 0 (no trace)
    * Designated Server = Any Running Server
    * State = "Inactive"
    
    ***** in tab "Method"
    * Method Name = My_Method_PowershellScript
    
    ***** in tab "SysObject Info"
    * Title = My_Job_BatchScript
    

  • Creation of folder containing the scripts and librairies D:\App\MyFolder4DCTM on DCTM server

  • Creation of BATCH CMD script My_ScriptProcess.cmd in the folder D:\App\MyFolder4DCTM calling the POWERSHELL script:
    @echo off
    SET "DOCUMENTIDS="
    :parse
    IF "%~1"=="" GOTO endparse
    if "%DOCUMENTIDS%"=="" (
    	SET DOCUMENTIDS=-DocumentIds %~1
    ) ELSE (
    	SET DOCUMENTIDS=%DOCUMENTIDS%,%~1
    )
    SHIFT
    GOTO parse
    
    :endparse
    
    CD "D:\App\MyFolder4DCTM"
    D:
    
    SET CurrentDirectory=%CD%
    SET JavaHome=D:\Documentum\java64\1.7.0_17
    SET DctmDirectory=D:\Documentum
    SET DctmConfigDirectory=%DctmDirectory%\config
    SET DctmIrmDirectory=%DctmDirectory%\irm
    
    powershell .\My_ScriptProcess.ps1 "%DOCUMENTIDS%" -DctmEnv ALL -CurrentDirectory "%CurrentDirectory%" -JavaHome "%JavaHome%" -DctmConfigDirectory "%DctmConfigDirectory%" -DctmIrmDirectory "%DctmIrmDirectory%"
    

  • Creation of POWERSHELL script My_ScriptProcess.ps1 in the folder D:\App\MyFolder4DCTM calling the JAVA com.java.lu.business.service.ecm.utils.main.CreateListToProcess:
    param(
    	[Int32[]] $DocumentIds,
    	[String] $CurrentDirectory,
    	[String] $JavaHome,
    	[String] $DctmConfigDirectory,
    	[String] $DctmIrmDirectory,
    	[String] $DctmEnv
    )
    
    
    
    
    function CreateIdList
    {
    	param(
    		[String] $DocumentIds,
    		[String] $CurrentDirectory,
    		[String] $JavaHome,
    		[String] $DctmConfigDirectory,
    		[String] $DctmIrmDirectory,
    		[String] $DctmEnv,
    		[String] $IdsToProcessFile
    	)
    	
    	Write-Host "Calling CreateIdList with parameters:"
    	Write-Host " * DocumentIds: $DocumentIds"
    	Write-Host " * CurrentDirectory: $CurrentDirectory"
    	Write-Host " * JavaHome: $JavaHome"
    	Write-Host " * DctmConfigDirectory: $DctmConfigDirectory"
    	Write-Host " * DctmIrmDirectory: $DctmIrmDirectory"
    	Write-Host " * DctmEnv: $DctmEnv"
    	Write-Host " * IdsToProcessFile: $IdsToProcessFile"
    
    	$ClassPath = $DctmConfigDirectory;
    	
    	foreach($Jar IN Get-ChildItem "$CurrentDirectory\dfc" -filter "*.jar" -Name){
    		$ClassPath += ";$CurrentDirectory\dfc\$Jar"
    	}
    	
    	foreach($Jar IN Get-ChildItem "$CurrentDirectory\lib" -filter "*.jar" -Name){
    		$ClassPath += ";$CurrentDirectory\lib\$Jar"
    	}
    	
    	$ClassPath += ";$DctmIrmDirectory\emcdctmirm.jar"
    	$ClassPath += ";$CurrentDirectory\IRMisationDocs4ArchivedDeliverable.jar"
    	
    	$JavaLibraryPath = "$DctmIrmDirectory"
    	$JavaLibraryPath += ";$DctmIrmDirectory\Common"
    	$JavaLibraryPath += ";$env:path"
    	$JavaLibraryPath = $JavaLibraryPath -replace "\\", "/"
    	
    	$pInfo = New-Object System.Diagnostics.ProcessStartInfo
    	$pInfo.FileName = "$JavaHome\bin\java.exe"
    
    	$LogFile = "$CurrentDirectory\log\My_ScriptProcess_log_$((Get-Date).ToString("yyyyMMdd_HHmmss")).log"
    	$pInfo.Arguments = @(
    		#"-Xrunjdwp:transport=dt_socket,address=9797,server=y,suspend=y",
    		#"-XX:-DumpOnCrash",
    		#"-XX:-CoreOnCrash",
    		"-Xmx1g",
    		"-Doracle.net.tns_admin=""$env:TNS_ADMIN""",
    		"-Djava.library.path=""$JavaLibraryPath""",
    		"-cp", """$ClassPath""",
    		"com.java.lu.business.service.ecm.utils.main.CreateListToProcess",
    		$DctmEnv,
    		"""$LogFile""",
    		"""$IdsToProcessFile""",
    		$DocumentIds)
    
    	$p = New-Object System.Diagnostics.Process
    	$p.StartInfo = $pInfo
    	
    	$p.Start() | Out-Null
    	
    	$p.WaitForExit()
    	
    	Write-Host "Content of $($IdsToProcessFile):"
    	Get-Content -Path $IdsToProcessFile | Foreach-Object { Write-Host $_ }
    	Write-Host "End of Content"
    }
    
    
    
    
    function LaunchSensitiveProcess 
    {
    	param(
    		[String] $ObjectIds,
    		[String] $CurrentDirectory,
    		[String] $JavaHome,
    		[String] $DctmConfigDirectory,
    		[String] $DctmIrmDirectory,
    		[String] $DctmEnv
    	)
    	
    # ....
    # ....
    # ....
    # ....
    # ....
    
    }
    
    function MyProcess{
    	param(
    		[Int32[]] $DocumentIds,
    		[String] $CurrentDirectory,
    		[String] $JavaHome,
    		[String] $DctmConfigDirectory,
    		[String] $DctmIrmDirectory,
    		[String] $DctmEnv
    	)
    	$DocumentIdsToProcess=$DocumentIds -join ','
    
    	$IdsToProcessFile = "$CurrentDirectory\My_ScriptProcess_$((Get-Date).ToString("yyyyMMdd_HHmmss")).txt"
    
    	CreateIdList -DocumentIds $DocumentIdsToProcess -CurrentDirectory $CurrentDirectory -JavaHome $JavaHome -DctmConfigDirectory $DctmConfigDirectory -DctmIrmDirectory $DctmIrmDirectory -DctmEnv $DctmEnv -IdsToProcessFile $IdsToProcessFile
    
    	foreach ($IdsToProcess in Get-Content -Path $IdsToProcessFile) {
    		LaunchSensitiveProcess -ObjectIds $IdsToProcess -CurrentDirectory $CurrentDirectory -JavaHome $JavaHome -DctmConfigDirectory $DctmConfigDirectory -DctmIrmDirectory $DctmIrmDirectory -DctmEnv $DctmEnv
    	}
    
    	#Remove-Item -Path $IdsToProcessFile
    }
    
    
    
    
    $MaxNbOfDocumentIds = 150
    
    if ($DocumentIds.Count -gt $MaxNbOfDocumentIds){
    	while($DocumentIds.Count -gt 0){
    		$NewDocumentIds = New-Object System.Collections.ArrayList
    		while(($NewDocumentIds.Count -le $MaxNbOfDocumentIds) -and ($DocumentIds.Count -gt 0)){
    			$DocumentId = $DocumentIds[0]
    			if ($DocumentIds.Count -gt 1){
    				$DocumentIds = $DocumentIds[1..($DocumentIds.Count -1)]
    			}else{
    				$DocumentIds = @()
    			}
    			$NewDocumentIds.Add($DocumentId) > $null
    		}
    		
    		MyProcess -DocumentIds $NewDocumentIds -CurrentDirectory $CurrentDirectory -JavaHome $JavaHome -DctmConfigDirectory $DctmConfigDirectory -DctmIrmDirectory $DctmIrmDirectory -DctmEnv $DctmEnv
    	}
    }else{
    	MyProcess -DocumentIds $DocumentIds -CurrentDirectory $CurrentDirectory -JavaHome $JavaHome -DctmConfigDirectory $DctmConfigDirectory -DctmIrmDirectory $DctmIrmDirectory -DctmEnv $DctmEnv
    }
    

  • Creation of java class com.java.lu.business.service.ecm.utils.main.CreateListToProcess:
    package com.java.lu.business.service.ecm.utils.main;
    
    import java.io.File;
    import java.io.PrintWriter;
    import java.text.MessageFormat;
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Properties;
    import java.util.Set;
    
    import javax.naming.spi.NamingManager;
    import javax.sql.DataSource;
    
    import org.apache.commons.configuration.PropertiesConfiguration;
    import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
    import org.apache.commons.lang.StringUtils;
    
    import com.documentum.com.DfClientX;
    import com.documentum.com.IDfClientX;
    import com.documentum.fc.client.DfQuery;
    import com.documentum.fc.client.IDfClient;
    import com.documentum.fc.client.IDfCollection;
    import com.documentum.fc.client.IDfQuery;
    import com.documentum.fc.client.IDfSession;
    import com.documentum.fc.client.IDfSessionManager;
    import com.documentum.fc.client.IDfUser;
    import com.documentum.fc.common.DfException;
    import com.documentum.fc.common.DfLoginInfo;
    import com.documentum.fc.common.IDfId;
    
    
    public class CreateListToProcess {
    	public static void main(String[] args) {
    		try {
    			String myRepository = "MY_DOCBASE";
    			String adminLogin = "adminuser";
    			String adminPassword = "pwd4adminuser";
    			
    			IDfClientX clientx = new DfClientX();
    			IDfClient client = clientx.getLocalClient();
    			final IDfSessionManager sMgr = client.newSessionManager();
    			sMgr.setIdentity(IDfSessionManager.ALL_DOCBASES, new DfLoginInfo(adminLogin, adminPassword));
    			IDfSession dfSession = sMgr.getSession(myRepository);
    			
    			try {
    				if (dfSession.getUser(null).getUserPrivileges() != IDfUser.DF_PRIVILEGE_SUPERUSER) {
    					throw new DfException(MessageFormat.format("{0} is not a superuser.", dfSession.getUser(null).getUserName()));
    				}
    
    				PrintWriter printWriterLog = new PrintWriter(new File(args[1])) {
    					@Override
    					public void println(String x) {
    						super.println(x);
    						super.flush();
    						System.out.println(x);
    					}
    				};
    				
    				HashSet<String> docsIdsSet = new HashSet<String>();
    				File fileToCreate = null;
    
    				for (int i = 2; i < args.length; i++) {
    					if (i == 2) {
    						fileToCreate = new File(args[i]);
    					} else {
    						docsIdsSet.add(args[i]);
    					}
    				}
    
    				int cpt = 0;
    
    				PrintWriter printWriterIdsFile = new PrintWriter(fileToCreate);
    				try {
    					final int lineSize = 100;
    
    					IDfCollection dfCollection = getDocumentIdsToProcess(dfSession);
    					try {
    						List<String> list = new ArrayList<String>();
    						while (dfCollection.next()) {
    							cpt++;
    							IDfId dfId = dfCollection.getId("r_object_id");
    							list.add(dfId.getId());
    							if (list.size() == lineSize) {
    								printWriterIdsFile.println(StringUtils.join(list, ','));
    								printWriterIdsFile.flush();
    								list.clear();
    							}
    						}
    						if (list.size() > 0) {
    							printWriterIdsFile.println(StringUtils.join(list, ','));
    							printWriterIdsFile.flush();
    							list.clear();
    						}
    					} finally {
    						dfCollection.close();
    					}
    
    				} finally {
    					printWriterLog.write(MessageFormat.format("There {0,choice,0#are no documents|1#is one document|1<are {0,number,integer} documents} to process.", cpt));
    					printWriterLog.close();
    				}
    
    			} finally {
    				sMgr.release(dfSession);
    			}
    		} catch (Throwable e) {
    			e.printStackTrace();
    		}
    	}
    	
    	
    	/**
    	 * Get the documents for the scope's current execution
    	 * @param session
    	 * @return
    	 * @throws Throwable
    	 */
    	public static IDfCollection getDocumentIdsToProcess(IDfSession session) throws Throwable {
    		IDfCollection collection = null;
    		
    		StringBuilder sb = new StringBuilder();
    		sb.append(" SELECT DISTINCT docsall.r_object_id FROM my_document (ALL) docsall WHERE docsall.i_chronicle_id  ");
    		sb.append(" 	IN ( SELECT docs.i_chronicle_id  from my_document docs ");
    		sb.append(" 		WHERE ANY docs.r_aspect_name = 'my_aspect' and docs.my_aspect.is_ok=1  ");
    		sb.append(" 		AND docs.r_content_size>0 ");
    		//....
    		sb.append(" 	) ");
    
    		System.out.println(MessageFormat.format("Building and execution of query: {0}", sb.toString()));
    		IDfQuery dfQuery = new DfQuery(sb.toString());
    		collection = dfQuery.execute(session, IDfQuery.DF_READ_QUERY);					
    		return collection;
    	}
    	
    }
    

  • So, on the DCTM server, in the folder D:\App\MyFolder4DCTM, there will be:
    o My_ScriptProcess.cmd
    o My_ScriptProcess.ps1
    o MyJavaLuLib.jar : containing all needed classes
    o \lib : commons-collections-3.2.jar + commons-configuration-1.5.jar + commons-io-1.2.jar + commons-logging-1.1.1.jar + ojdbc6.jar + commons-csv-1.1.jar …etc.
    o \dfc : all JARs and DLLs of DFC (dfc.jar,Dfc.dll, …etc).
    o \log : log files

Just a last point, in the POWERSHELL script the below command allows debugging of remote server execution from local IDE (Composer) via the port 9797:
“-Xrunjdwp:transport=dt_socket,address=9797,server=y,suspend=y”
however, if this instruction is uncommented, the execution is put on hold until the launch of the IDE on the port.

Best regards,

Huseyin OZVEREN