Frequently Asked Questions
- What is the JRE version compatibility of j-Interop ?
- How do I install it ?
- What threading model do the COM servers adhere to while in use from j-Interop ?
- What threading model does j-Interop follow ?
- How do I configure my COM server for DCOM access ?
- My COM Server is a DLL\OCX control, how do I make it work with j-Interop ?
- Why could the library not do step 6 for me automatically?
- What all COM Interfaces are directly supported ?
- What data types are supported by j-Interop ?
- Do I have to do any reference counting,memory management etc. ?
- Any configuration to be done before using j-Interop ?
- Is there any logging done ?
Answers
(A1) Tested with JRE 1.4 and 1.6 on Windows XP(SP2),Windows Vista(SP1),Windows 2K3(SP2) and Ubuntu 8.4(desktop). Compatible with JRE version 1.4 and above.
(A2) Please see the installation section.
(A3) From MSDN:-
On Windows side, Local servers (EXEs) are in full control of the kind of apartment(threading model) that COM is
using for their objects. The local server calls CoInitializeEx on one or more threads and registers the class factory
(or multiple class factories) from the appropriate thread with the appropriate threading model.
The In-process servers (DLLs), however run in the context of their client i.e they run in the apartment the client gives them. By client, I don't mean j-Interop here, but a Windows COM Client. In-process components indicate the threading model they are ready to satisfy by placing a named value (ThreadingModel) under their InprocServer32 key in the registry:
[HKEY_CLASSES_ROOT\CLSID\{clsid}\InprocServer32]
"ThreadingModel"="Both"
or
"ThreadingModel"="Apartment"
or
"ThreadingModel"="Free"
If ThreadingModel is not specified, the component is assumed to follow the assumptions for "STA-Main" and can only be loaded into the main STA in a process. A value of "Both" indicates that the component can be loaded in both MTAs and STAs. A value of "Apartment" indicates that the component can be loaded into any STA. A value of "Free" indicates that the component can be loaded into an MTA, but not into an STA.
(A4) j-Interop follows the "Apartment" model i.e regardless of threading model or the component type(Local or Inproc)
used by the COM Server, j-Interop synchronizes all calls to the COM Server per org.jinterop.dcom.core.JIComServer
instance (which is the starting point for each COM Server).
JISession session = JISession.createSession("DOMAIN","USERNAME","PASSWORD");
JIComServer comServer = new JIComServer(JIProgId.valueOf("Excel.Application"),"127.0.0.1",session);
IJIComObject comObject = comServer.createInstance();
IJIDispatch dispatch = (IJIDispatch)JIObjectFactory.narrowObject(comObject.queryInterface(IJIDispatch.IID));
IJITypeInfo typeInfo = dispatch.getTypeInfo(0);
FuncDesc funcDesc = typeInfo.getFuncDesc(0);
int dispId = dispatch.getIDsOfNames("Visible");
JIVariant variant = new JIVariant(Boolean.TRUE);
dispatch.put(dispId,variant);
Calls from all interfaces ("dispatch
" and "typeInfo
"), even if they are running on different threads, are
synchronized at the JIComServer
("comServer
") level. That said, within an application, there can be more
than one JIComServer
s running at the same time and they run independent of each other.
Ideally if your COM server is actively being used for remote access , then it is perhaps already configured for DCOM. If not you can configure it by following steps mentioned here or here.
For Windows XP (SP2) , this is a good link. Alternatively, this is also a good article.
(A6)Ideally if your COM server is actively being used for remote access , then it is perhaps already configured for DCOM. If not, you have 2 ways to do this. Both ways are recommended by Microsoft. I personally prefer the Easiest way.
- Easiest Way:-
Let the j-Interop library do this for you. You can set the "autoRegistration" flag in the JISystem class. When the library encounters a "Class not registered" exception, it will perform all the registry changes if the autoRegistration flag is set. And then re-attempt loading the COM Server. Please have a look at MSSysInfo,MSWMI examples.
- Easy Way:-
From MSDN , here (skip to the section titled below):-
Modify registry to force remoting of the object
- Use the OLE/COM Object viewer (Oleview.exe) that is shipped with Microsoft Visual C++ and locate the ProgID in the form of OLEComponent.Object under All Objects.
- Select the COM object, and then from the Object menu, select CoCreateInstance Flags. Make sure that only CLSCTX_LOCAL_SERVER is selected.
- Next, under the Implementation and Inproc Server tabs select Use Surrogate Process and leave the "Path to Custom Surrogate" blank, which allows the Dllhost.exe file to be loaded and the COM DLL brought within it's process space.
If you do not have Microsoft Visual C++, the OLE/COM Object Viewer utility is also available for download from the following Microsoft Web site here
- Hard Way:-
- For each CLSID encountered in the DLL component, create an AppID value under HKCR\CLSID\{clsid} which contains the
same value as the CLSID.
HKCR\CLSID\{clsid}
AppID = {appid value}
- Using the same AppID value, then create an AppID key under HKCR\AppID.
HKCR\AppID\{appid}
- Under HKCR\AppID\{appid}, then create the following values:
(Default) =
DllSurrogate =
For example, let's say YourDll.dll contains one class called MyClass with CLSID {6A048AAA-7DDD-4CCC-BE59-9BBB746E5C6E}. To host YourDll.dll using dllhost, you will need to create the following entries in the registry:
HKCR\CLSID\{6A048AAA-7DDD-4CCC-BE59-9BBB746E5C6E}
AppID = {6A048AAA-7DDD-4CCC-BE59-9BBB746E5C6E}
HKCR\AppID\{6A048AAA-7DDD-4CCC-BE59-9BBB746E5C6E}
(Default) = "Your DLL Surrogate"
DllSurrogate =You would then be able to configure this surrogate by running DCOMCNFG and looking for the Application entry called "Your DLL Surrogate".
- For each CLSID encountered in the DLL component, create an AppID value under HKCR\CLSID\{clsid} which contains the
same value as the CLSID.
Please note that the use of surrogates for accessing DLLs is not a j-Interop specification, but a COM specification. In any DCOM case for accessing a DLL\OCX you would need the DLLHOST. It is a Microsoft DCOM DLL Host Process. If the COM server being accessed is an Exe, like MSWord or MSExcel or IE then this is not required. But for DLLs , it is required. This is how the DCOM clients talk to In-Process Servers. You can obtain more info from here (please open in IE for proper viewing).
Also, it would be best to view j-Interop as a DCOM client when accessing COM from Java. It would be much easier to work with it then. Whatever configurations are required for a DCOM client, will be required for j-Interop also.
(A7)j-Interop behaves as a COM client to the COM Server, changes in step 6 have to be done at the server machine's registry. It is best that the user initiate those actions instead of the library doing these silently.
(A8)All automation interfaces like IDispatch, ITypeInfo, ITypeLib, IEnumVariant
are directly supported. You can start
using them right away.
All DCOM datatypes including VARIANTs are supported by j-Interop. The only limitation in the present version is that Arrays upto Maximum 2 dimensions are accepted currently.
(A10)No, the library does all this on it's own (including pinging the COM server for keeping it alive).
(A11)Yes, please make sure that the Server service and the Remote Registry Service is running on the target workstation (where the COM Server is hosted). This is required for reading the registry to map the ProgIds to their CLSIDs. If you can't have this , then please use CLSID instead of ProgId. The progIdVsClsidDB.properties maintains a mapping of ProgId Vs there CLSIDs, if this file is present in the classpath. This file is consulted before the registry for the ProgId.
Also, if you are working with GUI components and would like to make them visible\interactive, then make sure that you read up (A5) and setup the COM Server for "Interactive User". By default, it is the "Launching User". If this option is set, then the COM Server will not present it's GUI. It is best to use this for all silient operations like working with DBs , or using Excel formulas etc.
(A12) Yes, j-Interop uses java logging by default (and to the console), but you can configure a handler for this logger to redirect output to logger mechanisms of your own choice.
There is also a method in JISystem.setInBuiltLogHandler
which creates a handler to store the logs to a file in the user's temp directory as j-Interop.log . (e.g. for Windows systems it should be "C:\Documents and Settings\your_username\Local Settings\Temp")