Menu

DCOM Server

christian
2007-02-08
2012-11-29
  • christian

    christian - 2007-02-08

    Hi,

    Can j-interop be used to implement a DCOM server? There's a lot of information on the site about how to create a DCOM client with the j-interop classes, but I'm not sure if you can create a service.

    Thanks,

    Christian

     
    • Vikram Roopchand

      Hi Christian,
                   The library is currently not fully bi-directional (I am working on that). What this means is that if you have a COM interface which has APIs accepting references(pointers) to other COM interfaces, you can use j-Interop to replace a COM interface reference with it's Java implementation. That way an existing Java class can be passed around to COM servers as if it was a COM interface itself. It will support automation and direct calls as well. The COMCallingJava sample in the example tries to depict it.

      Full Bi-directional(which allows the COM runtime to "wake" up the Java server, register it's bindings etc., and then use it as if it was talking to a COM server) is on the cards, but not in yet.

      I hope this answer's your question,
      thanks,
      best regards,
      Vikram

       
    • christian

      christian - 2007-02-08

      Thanks Vikram - that does answer my question. Good luck!

      Christian

       
    • Tylka

      Tylka - 2007-06-28

      I'm having a hard time understanding the flow of the example that is included in the current distribution.  It is simply a consequence of my dunderheadedness,  this library is an amazing addition to the java community. Would anyone be willing to help me, and hopefully others, by walking through the Test_ITestServer2_Impl.java source file step by step.  Any help would be greatly appreciated.

       
      • Vikram Roopchand

        Hi Tylka,
                I will help ...firstly , the source which you have has some extra QIs which I forgot to remove while I was debugging another issue, so sorry about that :)...

        As you are already aware (I hope) that j-Interop is not fully bi-directional i.e a Java class cannot be "woken" up like we can to the COM servers. Though what is possible is that you can mimic an existing COM interface by providing it's implementation in Java and passing a reference of such implementation to any standard COM call (which is expecting it ofcourse).

        Now to specifics:-

        <code>

        JIComServer testServer1 = new JIComServer(JIProgId.valueOf(session1,"TestJavaServer.TestServer1"),args[0],session1);
                    JIComServer _testServer4 = new JIComServer(JIProgId.valueOf(session3,"TestJavaServer.ITestServer4"),args[0],session3);
                    IJIUnknown unkTestServer1 = testServer1.createInstance();
                    IJIUnknown unkTestServer4 = _testServer4.createInstance();
        IJIComObject testServer4 = (IJIComObject)unkTestServer4.queryInterface("477D6886-95BF-4E9D-BB71-EF3CABEF1DBD");

        </code>

        The above creates instances of two interfaces.

        <code>

        //Now for the Java Implementation of ITestServer2 interface (from the type library or IDL) 
                    //IID of ITestServer2 interface
                    //JIInterfaceDefinition interfaceDefinition = new JIInterfaceDefinition("9CCC5120-457D-49F3-8113-90F7E97B54A7");
                    JIInterfaceDefinition interfaceDefinition = new JIInterfaceDefinition("D4CF4091-79A8-4926-A071-97BD0232A0AC",false);
                    //lets define the method "Execute" now. Please note that either this should be in the same order as defined in IDL
                    //or use the addInParamAsObject with opnum parameter function.
                    JIParameterObject parameterObject = new JIParameterObject();
                    parameterObject.addInParamAsObject(new JIString(JIFlags.FLAG_REPRESENTATION_STRING_BSTR),JIFlags.FLAG_REPRESENTATION_STRING_BSTR);
                    JIMethodDescriptor methodDescriptor = new JIMethodDescriptor("Execute",parameterObject);
                    interfaceDefinition.addMethodDescriptor(methodDescriptor);

        </code>

        If you would look at the IDL or the TLB of the TestServer class, you would see this ITestServer2 interface there. In the above steps, we are trying "mimic" the IDL as a Java class.

        <code>

        //Create the Java Server class. This contains the instance to be called by the COM Server ITestServer1.
                    JIJavaCoClass _testServer2 = new JIJavaCoClass(interfaceDefinition,new Test_ITestServer2_Impl());
                    //Get a interface pointer to the Java CO Class. The template could be any IJIComObject since only the session is reused.
                    IJIComObject __testServer2 = ComFactory.createCOMInstance((IJIComObject)testServer4,JIInterfacePointer.getInterfacePointer(session1,_testServer2));

        </code>

        Now that we have a Java mimic, we will link that to it's implementation. Consider it as a link similar to the Class(interface) and it's instance.

        The next step in the above code, defines the reference which will shuttle between COM servers. As they (COM) only work on interface pointer, it became natural to morph the java mimic as a JIInterfacePointer as well.

        <code>

        //Call our Java server. The same message should be printed on the Java console.
                    JICallObject callObject = new JICallObject(testServer4.getIpid(),true);
                    callObject.setOpnum(0);
                    callObject.addInParamAsInterfacePointer(__testServer2.getInterfacePointer(), JIFlags.FLAG_NULL);
                    testServer4.call(callObject);

        </code>

        And above we make the actual call.

        Then we wait for about 20 secs to make sure that the call back completes and the main thread is kept alive till this completes.

        Hope this helps,
        thanks,
        warm regards,
        Vikram

         
        • Tylka

          Tylka - 2007-06-28

          Thank you very much, it will take me a little bit to absorb this, but it will help.  I'm fairly new to this whole COM concept, I was forced to start looking into it due to OPC Requirements with one of my clients.  Thank you again for your help, and the addition of this project. 

           
          • Vikram Roopchand

            no problem, anytime...

             
        • Tylka

          Tylka - 2007-07-17

          Ok, per this thread I've managed to understand this much better. I am however at a stand still.  I have compiled and registered a dll stub using VC++ 6.  When connecting to this com object, instead of the Not Registered error, I get this message instead, "No such interface supported".  I am not sure what this means.  Any help would be appreciated.

           
          • Vikram Roopchand

            You may need to create a proxy DLL in this case. I have a sample project available to create that (one can be used for all). Please mail me at vikram.roopchand@gmail.com and I will send you that. (sourceforge attachments don't work).

            Thanks,
            best regards,
            Vikram

             
    • Anonymous

      Anonymous - 2007-07-10

      Hi Vikram,

      I tried to run the Test_ITestServer2_Impl file, but it would not run.  It looks to me like j-Interop is unable to access the system registry, but I'm not sure why.  I'm running Windows XP in Parallels Desktop on my Macbook Pro.  Can you please shed some light on this?

      Runtime arguments are:
      localhost localhost Administrator admin_password

      Here is the output from System.out:
      Log file will be created in System's tmp directory, which in the current case is (java.io.tmpdir): C:\DOCUME~1\SUMMIT~1.GRU\LOCALS~1\Temp\ progIdVsClsidDB: {}

      org.jinterop.dcom.common.JIException: Message not found for errorCode: 0xC0000034
              at org.jinterop.winreg.smb.JIWinRegStub.winreg_OpenHKLM(JIWinRegStub.java:87)
              at org.jinterop.dcom.core.JIProgId.getIdFromWinReg(JIProgId.java:114)
              at org.jinterop.dcom.core.JIProgId.getCorrespondingCLSID(JIProgId.java:147)
              at org.jinterop.dcom.core.JIComServer.<init>(JIComServer.java:180)
              at javaapplication1.Main.main(Main.java:39)
      Caused by: jcifs.smb.SmbException: The system cannot find the file specified.
              at jcifs.smb.SmbTransport.checkStatus(SmbTransport.java:510)
              at jcifs.smb.SmbTransport.send(SmbTransport.java:610)
              at jcifs.smb.SmbSession.send(SmbSession.java:231)
              at jcifs.smb.SmbTree.send(SmbTree.java:102)
              at jcifs.smb.SmbFile.send(SmbFile.java:687)
              at jcifs.smb.SmbFile.open0(SmbFile.java:827)
              at jcifs.smb.SmbFile.open(SmbFile.java:845)
              at jcifs.smb.TransactNamedPipeOutputStream.write(TransactNamedPipeOutputStream.java:60)
              at jcifs.smb.RpcTransport.send(RpcTransport.java:108)
              at rpc.DefaultConnection.transmitFragment(DefaultConnection.java:127)
              at rpc.DefaultConnection.transmit(DefaultConnection.java:57)
              at rpc.ConnectionOrientedEndpoint.send(ConnectionOrientedEndpoint.java:173)
              at rpc.ConnectionOrientedEndpoint.connect(ConnectionOrientedEndpoint.java:193)
              at rpc.ConnectionOrientedEndpoint.bind(ConnectionOrientedEndpoint.java:167)
              at rpc.ConnectionOrientedEndpoint.call(ConnectionOrientedEndpoint.java:74)
              at rpc.Stub.call(Stub.java:113)
              at org.jinterop.winreg.smb.JIWinRegStub.winreg_OpenHKLM(JIWinRegStub.java:85)
              ... 4 more

      Here is the output from the j-Interop0.log file:
      Jul 10, 2007 11:26:19 AM  Thread: main
      FINEST: java.runtime.name = Java(TM) SE Runtime Environment
      sun.boot.library.path = C:\Program Files\Java\jdk1.6.0_01\jre\bin
      java.vm.version = 1.6.0_01-b06
      java.vm.vendor = Sun Microsystems Inc.
      java.vendor.url = http://java.sun.com/
      path.separator = ;
      java.vm.name = Java HotSpot(TM) Client VM
      file.encoding.pkg = sun.io
      sun.java.launcher = SUN_STANDARD
      user.country = US
      sun.os.patch.level = Service Pack 2
      java.vm.specification.name = Java Virtual Machine Specification
      user.dir = C:\Documents and Settings\MYUSER\My Documents\CVSCheckouts\JavaApplication1
      java.runtime.version = 1.6.0_01-b06
      java.awt.graphicsenv = sun.awt.Win32GraphicsEnvironment
      java.endorsed.dirs = C:\Program Files\Java\jdk1.6.0_01\jre\lib\endorsed
      os.arch = x86
      java.io.tmpdir = C:\DOCUME~1\MYUSER\LOCALS~1\Temp\ line.separator =

      java.vm.specification.vendor = Sun Microsystems Inc.
      user.variant =
      os.name = Windows XP
      sun.jnu.encoding = Cp1252
      java.library.path = C:\Program Files\Java\jdk1.6.0_01\jre\bin;.;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\Program Files\Microsoft Visual Studio\Common\Tools;C:\Program Files\Rockwell Software\RSCommon;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\MSSQL7\BINN;C:\Program Files\Microsoft SQL Server\80\Tools\BINN;C:\Program Files\QuickTime\QTSystem\;C:\Program Files\VoiceAge\Common;C:\program files\GnuWin32\bin;C:\Program Files\Microsoft Visual Studio\VIntDev98\bin
      java.specification.name = Java Platform API Specification
      java.class.version = 50.0
      sun.management.compiler = HotSpot Client Compiler
      os.version = 5.1
      user.home = C:\Documents and Settings\MYUSER
      user.timezone =
      java.awt.printerjob = sun.awt.windows.WPrinterJob
      file.encoding = Cp1252
      java.specification.version = 1.6
      java.class.path = Z:\j-Interop\lib\iwombat.jar;Z:\j-Interop\lib\j-interop.jar;Z:\j-Interop\lib\jarapac.jar;Z:\j-Interop\lib\jcifs-1.2.9.jar;Z:\j-Interop\lib\jcifs-ntlm-auth.jar;Z:\j-Interop\lib\ncacn_ip_tcp.jar;Z:\j-Interop\lib\ncacn_np.jar;Z:\j-Interop\lib\ntlm-security.jar;C:\Documents and Settings\MYUSER\My Documents\CVSCheckouts\JavaApplication1\build\classes
      user.name = summit
      java.vm.specification.version = 1.0
      java.home = C:\Program Files\Java\jdk1.6.0_01\jre
      sun.arch.data.model = 32
      user.language = en
      java.specification.vendor = Sun Microsystems Inc.
      awt.toolkit = sun.awt.windows.WToolkit
      java.vm.info = mixed mode, sharing
      java.version = 1.6.0_01
      java.ext.dirs = C:\Program Files\Java\jdk1.6.0_01\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
      sun.boot.class.path = C:\Program Files\Java\jdk1.6.0_01\jre\lib\resources.jar;C:\Program Files\Java\jdk1.6.0_01\jre\lib\rt.jar;C:\Program Files\Java\jdk1.6.0_01\jre\lib\sunrsasign.jar;C:\Program Files\Java\jdk1.6.0_01\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.6.0_01\jre\lib\jce.jar;C:\Program Files\Java\jdk1.6.0_01\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.6.0_01\jre\classes
      java.vendor = Sun Microsystems Inc.
      file.separator = \ java.vendor.url.bug = http://java.sun.com/cgi-bin/bugreport.cgi
      sun.io.unicode.encoding = UnicodeLittle
      sun.cpu.endian = little
      sun.desktop = windows
      sun.cpu.isalist = pentium_pro+mmx pentium_pro pentium+mmx pentium i486 i386 i86

      Jul 10, 2007 11:26:20 AM  Thread: Timer-1
      INFO: Running ClientPingTimerTask !
      Jul 10, 2007 11:26:20 AM  Thread: Timer-2
      INFO: Running ServerPingTimerTask !
      Jul 10, 2007 11:26:20 AM  Thread: main
      INFO: Created Session: -1359211370
      Jul 10, 2007 11:26:20 AM  Thread: main
      INFO: Created Session: -1665373038
      Jul 10, 2007 11:26:20 AM  Thread: main
      INFO: Created Session: 107346096
      Jul 10, 2007 11:26:28 AM  Thread: main
      INFO:
      Sending BIND
      Jul 10, 2007 11:26:28 AM  Thread: main
      FINEST: [TRANSMIT BUFFER]:-
      00000: 05 00 0B 03 10 00 00 00 48 00 00 00 01 00 00 00  |........H.......|
      00010: B8 10 B8 10 00 00 00 00 01 CC CC CC 00 00 01 00  |¸.¸......ÌÌÌ....|
      00020: 01 D0 8C 33 44 22 F1 31 AA AA 90 00 38 00 10 03  |.Ð.3D"ñ1ªª..8...|
      00030: 01 00 00 00 04 5D 88 8A EB 1C C9 11 9F E8 08 00  |.....]..ë.É..è..|
      00040: 2B 10 48 60 02 00 00 00                          |+.H`....        |

       
      • Anonymous

        Anonymous - 2007-07-10

        Nevermind.  I found the problem.  The Remote Registry service was stopped, so even though I was running on the local machine, setAutoRegisteration(true) would not actually register the components.

         
        • Anonymous

          Anonymous - 2007-07-10

          Okay, now I am getting a different error.  It looks as if the self-registration still does not work properly.  I think it's just something I've overlooked, but I can't figure out what.  Any help would be greatly appreciated.

          The line it's failing on is:
          JIComServer testServer1 = new JIComServer(JIProgId.valueOf(session1,"TestJavaServer.TestServer1"),args[0],session1);

          Again, I'm logging in with the system administrator username and password.  I've made sure that the local security policy matches what you have in your readme.htm but it still is not working.

          Here's my System.out:

          Log file will be created in System's tmp directory, which in the current case is (java.io.tmpdir): C:\DOCUME~1\MYUSER\LOCALS~1\Temp\ progIdVsClsidDB: {}

          org.jinterop.dcom.common.JIException: The system cannot find the file specified. Please check the path provided as parameter. If this exception is being thrown from the WinReg package, please check if the library is registered properly or do so using regsvr32. [0x00000002]
                  at org.jinterop.winreg.smb.JIWinRegStub.winreg_OpenKey(JIWinRegStub.java:169)
                  at org.jinterop.dcom.core.JIProgId.getIdFromWinReg(JIProgId.java:115)
                  at org.jinterop.dcom.core.JIProgId.getCorrespondingCLSID(JIProgId.java:147)
                  at org.jinterop.dcom.core.JIComServer.<init>(JIComServer.java:180)
                  at javaapplication1.Main.main(Main.java:39)
          Caused by: org.jinterop.dcom.common.JIRuntimeException: The system cannot find the file specified. Please check the path provided as parameter. If this exception is being thrown from the WinReg package, please check if the library is registered properly or do so using regsvr32. [0x00000002]
                  at org.jinterop.winreg.IJIWinReg$openKey.read(IJIWinReg.java:939)
                  at ndr.NdrObject.decode(NdrObject.java:19)
                  at rpc.ConnectionOrientedEndpoint.call(ConnectionOrientedEndpoint.java:127)
                  at rpc.Stub.call(Stub.java:113)
                  at org.jinterop.winreg.smb.JIWinRegStub.winreg_OpenKey(JIWinRegStub.java:163)
                  ... 4 more

           
          • Vikram Roopchand

            Hi there,
                     Two things here:-

            1. FYI, setAutoRegistration just sets up the COM server (if it is a inproc server like a DLL or OCX) to use a surrogate host. In our case the COM server is an EXE.

            2. FYA, Please try to do this :- at the "exe location of TestJavaServer":\&gt;TestJavaServer  -RegServer

            for e.g. D:\TestCodes\TestJavaServer\Debug>TestJavaServer.exe -RegServer

            And then re-run the example.

            Thanks,
            best regards,
            Vikram

             
            • Anonymous

              Anonymous - 2007-07-11

              Thanks, but it didn't completely fix my problem.  Now I get the same failure on the very next line:

              JIComServer _testServer4 = new JIComServer(JIProgId.valueOf(session3,"TestJavaServer.ITestServer4"),args[0],session3);

              I've tried it on both the source file and with Execute.bat and I get the same error on both.

              Also, if I'm reading this correctly, you're saying that if I were to write my own DCOM server with J-Interop, I would also need to write a DLL or EXE to host it?  What exactly does this host do?

              Please forgive my ignorance.  COM is relatively new to me, and although I've read up on the documentation, most of it was COM theory and there was little explanation of how to actually implement a COM server.

               
              • Vikram Roopchand

                hmm, that's strange, the registration should have registered all interfaces. To answer your question:- The library is partially bi-directional , i.e. you can only have a Java implementation of those interfaces which are already exposed by a COM server. In our case I think it is one of the ITestServerXs. DCOM is done either by DLLs or by EXEs (since it is Windows based only), what this feature of j-Interop provides is a way to morph Java Code as a COM interface, where by allowing the COM servers to use this interface and replace there implementations.  Consider it similar to Map implementation, where HashMap and MyHashMap both implement Map and are interchageable. So to conclude, you will "currently" need an existing COM server to replace one of it's interfaces. Going forward (if some one pays me :)... or there is a massive requirement for it) I will provide a full bi-directional access.

                Thanks,
                best regards,
                Vikram

                 
    • AndyMan2007

      AndyMan2007 - 2007-07-18

      Hi Christian,

      Reading through your post, especially the sentence "although I've read up on the documentation, most of it was COM theory and there was little explanation of how to actually implement a COM server", I can only recommend a book that I bought a few weeks ago from Amazon...well actually via them from the USA...it took a few weeks to get to me...but it was worth the wait. So the book is "Developer's Workshop to COM and ATL 3.0" by Andrew W. Troelsen, ISBN 1-55622-704-3

      He takes you from the ground up and in a week or two gets you building your own ATL-based COM servers with advanced stuff like callbacks. I don't know Andrew, and I don't get paid commission, but I do recommend it, even though it is 7 years old.

      Good luck.

      Andy

       

Log in to post a comment.