Hello,
it's not clear to me how to create custom COM types in a java COM server app.
I need to have a COM Server that works as a Protocol translator between to systems.
One is a VB6 application. Then I want to have custom objects, which I can send to VB6 app.
I'd tried this:
public OlaCOMAgent(CoClassMetaInfo coClassMetaInfo) {
super(coClassMetaInfo);
IClassFactoryServer classFactoryServer = new IClassFactoryServer(OlaCOMAgent.class);
classFactoryServer.registerInterface(IDispatch.class, new IDispatchVTBL(classFactoryServer));
classFactoryServer.registerInterface(IOlaCOMAgent.class, new IDispatchVTBL(classFactoryServer));
classFactoryServer.registerInterface(IWorkcycle.class, new IDispatchVTBL(classFactoryServer));
}
OlaCOMAgent implements IOlaCOMAgent
Then I have a custom interface IWorkcycle. But I get this error when calling the COM server:
16:05:16,015 INFO IClassFactoryServer The ola.IOlaCOMAgent interface was not registered for ola.OlaCOMAgent, because ola.server.IOlaCOMAgentVTBL class was not found. 16:05:16,125 INFO IClassFactoryServer The ola.IOlaCOMAgent interface was not registered for ola.OlaCOMAgent, because ola.server.IOlaCOMAgentVTBL class was not found. 16:05:16,140 ERROR IClassFactoryServer java.lang.NoSuchFieldException: INTERFACE_IDENTIFIER at java.lang.Class.getDeclaredField(Unknown Source) at com.jniwrapper.win32.com.server.IClassFactoryServer.b(SourceFile:262) at com.jniwrapper.win32.com.server.IClassFactoryServer.registerInterface(SourceFile:177) at ola.OlaCOMAgent.<init>(OlaCOMAgent.java:46)
Do I have to create a VTBL class? Can I have custom interfaces and send them to clients?
Thanks in advanced,
Frank Senn
Additional information:
I want to have beans that I can provide to programs that use this COM-Server
Like this:
package ola.records; import com.jniwrapper.win32.automation.types.BStr; import com.jniwrapper.win32.automation.types.Variant; import com.jniwrapper.win32.com.server.CoClassMetaInfo; import com.jniwrapper.win32.com.server.IDispatchServer; public class WorkcycleRecord extends IDispatchServer implements IWorkcycle{ private Variant recordName; public WorkcycleRecord(CoClassMetaInfo co) { super(co); } public Variant getRecordName() { return recordName; } public void setRecordName(Variant recordName) { this.recordName = recordName; } }
Hello Frank,
Please try to use the following code:
public class OlaCOMAgent extends IDispatchServer implements IOlaCOMAgent, IWorkcycle
{
public OlaCOMAgent(CoClassMetaInfo classImpl)
{
super(classImpl);
}
public void registerInterfaces()
{
IClassFactoryServer server = new IClassFactoryServer(OlaCOMAgent.class);
server.registerInterface(IDispatch.class, new IDispatchVTBL(server));
server.registerInterface(IOlaCOMAgent.class, new IOlaCOMAgentVTBL(server));
server.registerInterface(IWorkcycle.class, new IWorkcycleVTBL(server));
}
}
Also please note that you should provide appropriate VTBL class for each your custom interface. If you have TLB or DLL with compiled interfaces description then you can use our ComfyJ Code Generator to create required VTBL classes (IWorkcycleVTBL and IOlaCOMAgentVTBL).
Regards,
Vladimir Ikryanov
hello Vladimir,
thanks for responding!
So there is no way to create tbl file with ComfyJ ?
Hi Frank,
Actually creating TLB files is not the responsibility of ComfyJ. It just parse TLB files to provide Java proxies and stubs.
Way to obtain right TLB files depends on how your custom COM interfaces were created:
1. In case COM interfaces are provided by third-party library, TLB (it can also be named OLB) is always provided by library creator. This file can be provided standalone, or can be attached (as a Windows resource) to Dll file.
2. In case COM interfaces are written on your side, they are usually created as an IDL files. In this case, they can be compiled into TLB file by Microsoft's midl compiler.
In both cases, you can use Dll, TLB or OLB as an input file to ComfyJ's Code Generator to create right VTBL classes.
Regards,
Vladimir Ikryanov
What I've done, is to create an ActiveX Project in VB6, creating all necessary objects and then create a DLL.
Then I generate java code with CodegenForComfyJ.
Hi Vladimir,
sorry, I didn't wrote it explicit.
The CodeGenerator generated all necessary classes, also the VTBL Classes.
VB6 registrated the DLL automatically, so I use this types, but work with the JavaCOMServer which have of course the same types.
So this works. Even the Event Handling. I notify a VB6 object about an event.
Thanks for helping.
Tomorrow (Friday) I will present this to the management and I think we will order then two licences
Kind regards,
Frank Senn
I'm having another question.
I have this type TestOrder. I have genereated classes: the interface, the coclass, the vtbl class and the impl class.
I have my own class COMTestOrder (derived from DispatchComServer)that implements the interface _TestOrder (the generated interface)
Registration is in the constructor of COMTestOrder.
With IClassFactoryServer and IClassFactory I want to have an instance of COMTestOrder
IClassFactoryServer classFactoryServer = new IClassFactoryServer( COMTestOrder.class);
classFactoryServer.registerInterface(COMTestOrder.class, new _TestOrderVTBL(classFactoryServer));
IClassFactory classFactory = classFactoryServer.createIClassFactory();
IDispatchImpl handler = new IDispatchImpl();
classFactory.createInstance(null, handler.getIID(), handler);
COMTestOrder to = (COMTestOrder) classFactoryServer.getInstances().pop();
This COMTestOrder instance I give as parameter to another COMServer object (an observer, which VB6 was registrating)
Then I get the following error:
07:48:45,750 DEBUG OlaCOMAgent setting now testorder to RecordObserver...
java.lang.ClassCastException: de.olympus.olre.ola.records.COMTestOrder cannot be cast to com.jniwrapper.Parameter
at de.olympus.olre.ola.gen.comcustomtypes.impl._RecordObserverImpl.setTransferTestOrder(_RecordObserverImpl.java:46)
at de.olympus.olre.ola.OlaCOMAgent.notifyRecordObservers(OlaCOMAgent.java:109)
at de.olympus.olre.ola.OlaCOMAgent.notifyRecordObservers(OlaCOMAgent.java:100)
at de.olympus.olre.ola.agent.LISAgent.onTestOrder(LISAgent.java:46)
at de.olympus.olre.ola.agent.TestOrderWorkerThread.handleRequest(TestOrderWorkerThread.java:187)
at de.olympus.olre.ola.agent.BaseReactorThread$RequestHandler.onMessageRead(BaseReactorThread.java:291)
at de.olympus.odl.proton.dtp.astm.BaseASTMReader.callInterceptors(BaseASTMReader.java:364)
at de.olympus.odl.proton.dtp.astm.BaseASTMReader.readMessage(BaseASTMReader.java:98)
at de.olympus.olre.ola.agent.BaseReactorThread.onRun(BaseReactorThread.java:130)
at de.olympus.odl.daemonbase.AbstractAgentThread.run(AbstractAgentThread.java:133)
at java.lang.Thread.run(Unknown Source)
07:48:45,828 ERROR OlaCOMAgent java.lang.ClassCastException: de.olympus.olre.ola.records.COMTestOrder cannot be cast to com.jniwrapper.Parameter
So, COMTestOrder is type DispatchCOMServer and not Parameter. How can I send Parameter?
Hello Frank,
When you pass pointer to your COM object to another COM method, you should pass it as IUnknownImpl-derived object (in your case, this should be IDispatchImpl object). Try to pass "handler" variable instead of "to".
If this won't help (it's possible if your VB6 method expects exactly _TestOrder interface instead of IDispatch), you can obtain ITestOrderImpl interface through the following line: to.queryInterface(IID.create(TestOrder.INTERFACE_IDENTIFIER), resultingTestOrder);
Regards,
Vadim Ridosh