JavaBlog.fr / Java.lu DEVELOPMENT,Documentum,Java,powershell,Tools Documentum : Execution CMD/PowerShell Via Job/Method

Documentum : Execution CMD/PowerShell Via Job/Method

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

Leave a Reply

Your email address will not be published.

Time limit is exhausted. Please reload CAPTCHA.

Related Post