Java 7: COM-API does not work with Quality Center (OTAClient.dll), but works with Java 6
Asked Answered
C

1

8

We are running on Windows 7 Enterprise, SP1, 64bit. We just installed Java 7 on all our machines, which causes the following problem:

When my program tries to communicate with the OpenTestArchitecture-API from Quality Center it fails to create the ActiveX-Component. I use JACOB as my Java-COM library. Upgrading to the latest version of JACOB does not change anything.

The following test works with jdk1.6.0_24 (32 bit) but fails with jdk1.7.0_04 (32 bit):

import java.io.File;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.LibraryLoader;

public class JacobTest {
    static {
        File lib = new File("lib/" + LibraryLoader.getPreferredDLLName() + ".dll");
        System.setProperty(LibraryLoader.JACOB_DLL_PATH, lib.getAbsolutePath());

        System.out.println("JACOB_DLL_PATH = " + lib.getAbsolutePath());
        LibraryLoader.loadJacobLibrary();
    }

    public static void main(String[] args) {
        try {
            // Excel: Works with jdk1.6.0_24 AND jdk1.7.0_04
            System.out.println("new ActiveXComponent(\"Excel.Application\");");
            new ActiveXComponent("Excel.Application");

            // Quality Center OTAClient: Only works with jdk1.6.0_24
            System.out.println("ActiveXComponent component = new ActiveXComponent(\"TDApiOle80.TDConnection\");");
            ActiveXComponent component = new ActiveXComponent("TDApiOle80.TDConnection");

            System.out.println("ComThread.InitSTA();");
            ComThread.InitSTA();

            System.out.println("Dispatch.call(component, \"InitConnectionEx\", \"http://intranet/qcbin\");");
            Dispatch.call(component, "InitConnectionEx", "http://intranet/qcbin");
        }
        catch (Exception exception) {
            exception.printStackTrace();
        }
    }
}

jdk1.6.0_24 output:

JACOB_DLL_PATH = C:\Development\Java\Test\JacobTest\lib\jacob-1.17-M2-x86.dll

new ActiveXComponent("Excel.Application");
ActiveXComponent component = new ActiveXComponent("TDApiOle80.TDConnection");
ComThread.InitSTA();
Dispatch.call(component, "InitConnectionEx", "http://intranet/qcbin");

jdk1.7.0_04 output:

JACOB_DLL_PATH = C:\Development\Java\Test\JacobTest\lib\jacob-1.17-M2-x86.dll

new ActiveXComponent("Excel.Application");
ActiveXComponent component = new ActiveXComponent("TDApiOle80.TDConnection");
com.jacob.com.ComFailException: Invalid access to memory location.
    at com.jacob.com.Dispatch.createInstanceNative(Native Method)
    at com.jacob.com.Dispatch.<init>(Dispatch.java:99)
    at com.jacob.activeX.ActiveXComponent.<init>(ActiveXComponent.java:58)
    at JacobTest.main(JacobTest.java:26)

The original ComFailException-Message is "Can't co-create object" but I've edited the following Code in the jacob Dispatch.cpp: (I didn't touch CoCreateInstance, I just wanted to know what the HRESULT was)

  // standard creation
  hr = CoCreateInstance(clsid,NULL,CLSCTX_LOCAL_SERVER|CLSCTX_INPROC_SERVER,IID_IUnknown, (void **)&punk);
  if (!SUCCEEDED(hr)) {
     if (hr == REGDB_E_CLASSNOTREG)
        ThrowComFail(env, "Can't co-create object: REGDB_E_CLASSNOTREG", hr);
     if (hr == CLASS_E_NOAGGREGATION)
        ThrowComFail(env, "Can't co-create object: CLASS_E_NOAGGREGATION", hr);
     if (hr == E_NOINTERFACE)
        ThrowComFail(env, "Can't co-create object: E_NOINTERFACE", hr);
     if (hr == E_POINTER)
        ThrowComFail(env, "Can't co-create object: E_POINTER", hr);

     _com_error error(hr);
     LPCTSTR errorText = error.ErrorMessage();

     ThrowComFail(env, errorText, hr);
     return;
  }

Does anyone have a clue what the problem could be? The only difference is that I switch between the Java 6 and Java 7 runtime.

Thanks very much for your help!

PS: Excel works with both versions and a switch to the com4j-Library does not change anything. (I have a com4j-Test, but I didn't post it because I've already posted enough code)

Edit: The same test works with Windows XP, SP3 and Java 7.

Chaffee answered 11/5, 2012 at 8:28 Comment(8)
It's not clear whether the exception you are getting from original jacob code is a "memory access violation" or an HRESULT ?Aquarist
And if you can clarify whether same behavior reproduces using com4j and java 7.Aquarist
The original Jacob-Exception is "Can't co-create object". Because this does not tell very much I tried to figure out what the result of the CoCreateInstance function in the Native-Part was. The error-message from this method is "Invalid access to memory location". When I use com4j instead of Jacob i get the same results: "Excel.Application" and "TDApiOle80.TDConnection" works with Java 6, with Java 7 "Excel.Application" works but "TDApiOle80.TDConnection" does not.Chaffee
Shouldn't the COM threading model (ComThread.InitSTA()) be set before creating the component that may require a particular one?Brunhilda
@cynic: Don't know. It works like it is with java 6. Calling ComThread.InitSTA() before creating the ActiveXComponent does not change the behavior with java 7. I just tried it.Chaffee
Is it possible it comes from an "assembly" stuff ? For instance Java 6 runs with some version of DLLs but Java 7 runs with other versions... And finally the OTAClient.dll is not linked with expected DLL versions.Grubb
InitSTA should be applied before any operations, including creation of TDConnection, else in most cases it does fail with abscure errors like access violation. But if this has checked and did not help we are in bad luck.Aquarist
You should try to debug with debugger configured to stop on memory access violation and see where the exception originates. If it originates inside OTAClient.dll or inside Webclient.dll then most likely it's an edge case bug exposed by java 7. In which case you need to open a support ticket with QC support.Aquarist
G
2

Jacob DLL is linked with jvm.dll (methods and structures) from the JRE. So my guess is that the Jacob DLL should be compiled from sources with Java 7 to load properly into Java 7 JRE.

You are not alone but I guess too few people are already running Java 7...

Update: I propose you investigate first with Process Monitor if there are some library or system calls failing in your Java process, before running the process itself in a debugger... Maybe OpenJDK 7 may be an option to try too, it should be easier to debug then, at least to diagnose what the problem is.

Grubb answered 15/5, 2012 at 10:18 Comment(1)
I've already built jacob with java 7, but that did not change anything... Anyway, thanks for your answer!Chaffee

© 2022 - 2024 — McMap. All rights reserved.