Connecting Out of Process Servers via COM+
|
|
Thread rating:  |
Lance Wynn - 20 Jul 2005 22:13 GMT Hi, It's been a long time since I have done anything with Out-of Process servers, but I have a project that is going to require one.
Basically, I have a Java Application that makes a connection to a Java RMI service. I have managed to create a nice little COM wrapper for it so that I can communicate with it from VB6. However, this application can only have on instance connected, and the process to create a connection is around 15 seconds. I need to load up one instance of this app, and then connect to it from multiple clients.
I am thinking of creating an ActiveX.exe, that will run as a service, and then allow COM+ Components to do a getObject on it, execute the functions, and retrieve the data.
I think that if I match the User that the service logs in under, and the User that the Com+ components log in as, I can pull this off, otherwise I will need to write a Socket interface, or something else which will be alot harder.
Has anyone done anything similar to this, and if so can you give me some pointers, or potential risks associated with this?
Thanks Lance
Ralph - 21 Jul 2005 06:03 GMT > Hi, > It's been a long time since I have done anything with Out-of Process [quoted text clipped - 21 lines] > Thanks > Lance First a bit of heresy (as this is a classic vb newsgroup) - Do you know C++? If so, you will be better off creating an ActiveX Server using ATL. (It just runs leaner and provides more options and control.)
However, you can easily create one in VB, just open 'new' and select the ActiveX Exe wizard. You can then use it to manage the RMI service. (Just curious - do you have to use RMI? Whats the database? Nevermind, non of my business. <g>)
Using COM+ is an excellent strategy as it is directly supported by the OS, and will provide a well-known (documented), secure (authentication and authorization services), easily managed, consistent interface. It can appear daunting at first, but once you learn it - it will quickly become the tool of choice for a host of other solutions.
Roll 'ur owns are for people who like to receive calls at 3am.
hth -ralph
Lance Wynn - 21 Jul 2005 17:35 GMT Hi Ralph, Thanks for the reply.
My question isn't really one of how to build/use COM+, or Activex.exe My question is more along the lines of how they work together.
I am using RMI because it is an external Company that we need to connect to, and they only offer an RMI interface to their application.
Unfortunately, the time it takes to connect to the RMI server (15 - 30 Seconds) makes it so I must keep the connection open, and flow messages from many different clients through the one connection.
The connection is made through a Java component that I have wrapped in a Activex.DLL.
My question then is (I guess). Is it feasible to have a single ActiveX out-of-process server running on the machine, and maintaining the connection, and then connect to that server from many COM+ Components running on the same machine?
I think this would allow me to easily maintain the single connection, and manage messages to/from the individual clients.
Ideally, I would like for each client to create it's own connection, pass the data, receive responses, and close the connection. However, the 30 second connection time makes this method implausible.
What do you think? Does a single instance ActiveX server play nicely when being called from multiple COM+ objects? I know COM+ is the ideal solution, because of the easy of use, and security. What security issues, memory issues, etc.. can I expect to run into going the COM+ route versus writing a service that maintains the connection, and passes messages through a protocol such as TCP/IP, or even MSMQ, or FileQueue?
> Hi, > It's been a long time since I have done anything with Out-of Process > servers, but I have a project that is going to require one. > > Basically, I have a Java Application that makes a connection to a Java RMI > service. I have managed to create a nice little COM wrapper for it so that
> I can communicate with it from VB6. However, this application can only have
> on instance connected, and the process to create a connection is around 15 > seconds. I need to load up one instance of this app, and then connect to it
> from multiple clients. > [quoted text clipped - 5 lines] > User that the Com+ components log in as, I can pull this off, otherwise I > will need to write a Socket interface, or something else which will be alot
> harder. > [quoted text clipped - 3 lines] > Thanks > Lance First a bit of heresy (as this is a classic vb newsgroup) - Do you know C++? If so, you will be better off creating an ActiveX Server using ATL. (It just runs leaner and provides more options and control.)
However, you can easily create one in VB, just open 'new' and select the ActiveX Exe wizard. You can then use it to manage the RMI service. (Just curious - do you have to use RMI? Whats the database? Nevermind, non of my business. <g>)
Using COM+ is an excellent strategy as it is directly supported by the OS, and will provide a well-known (documented), secure (authentication and authorization services), easily managed, consistent interface. It can appear daunting at first, but once you learn it - it will quickly become the tool of choice for a host of other solutions.
Roll 'ur owns are for people who like to receive calls at 3am.
hth -ralph
Ralph - 21 Jul 2005 20:07 GMT < managled a bit to manage top posting >
> > Hi, > > It's been a long time since I have done anything with Out-of Process [quoted text clipped - 45 lines] > hth > -ralph
> Hi Ralph, Thanks for the reply. > [quoted text clipped - 27 lines] > because of the easy of use, and security. What security issues, memory > issues, etc.. can I expect to run into going the COM+ route versus writing a
> service that maintains the connection, and passes messages through a > protocol such as TCP/IP, or even MSMQ, or FileQueue? First let's get some definitions straight. This will help you find articles and books for more explanation and examples.
COM+, through one of those amazing acronym-re-use-processes that MS does so well, is not just 'COM' as we generally think of it. [COM itself is a specification. "OLE" is the internal MS propriatory implementation of 'COM'.]
"COM+" is an advanced COM run-time environment that provides prefabricated solutions for distributed architectures. It is fully integrated (using OLE implementation services) into Windows platforms starting with Win2k. Look at it as a 'ToolKit' or an "API" for additional standard system services. [ie, you don't have "multiple COM+ components" - you have muliple components that use the platform's intrinsic COM+ services.]
COM+ provides the following services: Transaction Services (MTS) Security Services Synchronization Services Queued Components (Messaging) Event Services In-Memory Database (a bit clunky) Load Balancing (you will likely use other services)
So you see if you write a component/client/service/exe to use COM+ you get a lot of functionality that you don't have to write - only configure. Also these services are implemented using algorithms that are more efficient than anything you could write on your own.
[Sidebar: Often you can write a raw sockets process that is 'faster'. However, it is just that a naked raw process. By the time you add security, synchronization, logging, error handling, blah, blah - you will have essentially re-invented the wheel. It will also be at the mercy of each new MS security patch or platform change. COM+ will port.]
A "Connection" as you describe is expensive and represents the complexities of opening up a channel of communication between a database and an app. As you described it, you are dependent on using a Dll that wraps a Java RMI to supply a connection. However, from that point on you don't have to maintain that 'connection'. From there on down through the VB/Windows world you can do pretty much what you want.
Imagine the following stack. Java RMI thingy (TheThingFromAnotherWorld, aka thingy) <wrapper> Your Wrapper Dll (Wrap.dll) <COM Component> ActiveX Server / Exe (Bob.exe) <Interface to VB clients> VB Client/Server Dlls (Msg.dll or Trans.dlls) <Interface to Application> VB Application (VBApp.exe) You have a number of choices - here is perhaps one scenario...
Bob fires up on the server and instantiates a couple of Wraps and puts them into a pool. Bob waits for somebody to call. VBApp fires up on the client machine and loads up 'Msg' to send something interesting and safe (guaranteed delivery) to Thingy. Bob catches the message from msg, selects a Wrap and passes the information on.
Same basic process with 'transactions' except of course how robust and how much work you have to do depends on what the Thingy supports.
hth -ralph
Lance Wynn - 21 Jul 2005 20:46 GMT Ralph, You make some interesting points, the example you provide is along the lines of what I was invisioning. I wonder though if I can simplify it, and do it all in the COM+ environment...
I have mainly used COM+ for remoting objects, and security in the past, Is there a setting where I can have COM+ instantiate only one instance of the object (In this case, my connection wrapper) and allow client applications to "share" this one instance of the COM+ object? If this is possible, how would I instantiate the teh object at the client? GetObject? CreateObject? When one client sent a command, it would have to wait until the command had finished completely before allowing the next client's command through.
What do you think?
Ralph - 21 Jul 2005 21:33 GMT > Ralph, > You make some interesting points, the example you provide is along the lines [quoted text clipped - 10 lines] > > What do you think? Whoa!
You missed my point. [Warning: a few rather snide pedantic comments follows... <g>]
[First pedantic remark:] Get a book.
Can you have COM+ instantiate only one instance? Yes - but this might not be what you want. COM+ also provides object pooling. Can multiple clients share one instance of a component? Yes - but this might not be what you want. Can I use GetObject? CreateObject? Yes - but this might not be what you want.
"> When one client sent a command, it would have to wait until the command had finished completely before allowing the next client's command through." - Not necessarily. Depends on what you want to do. COM+ provides asynchronous and synchronous opportunities.
[Pedantic Remark:] Browse, read, and play with sample code...
Here is just the first couple of sites from a Google search of 27,900 ... http://www.idevresource.com/com/library/articles/com+firstapp.asp http://www.idevresource.com/com/library/articles/com+objpool.asp http://msdn.microsoft.com/library/en-us/dncomser/html/complusguide.asp?
[Last pedantic remark: ] Don't try optimizing or 'implementing' until you get a better grasp of the tools and all the system services available to you. Write out "what you want to do" - forget "how to do it". The coding comes later. "Code" what you need to do, don't "Code" what you know how to write.
Forget about the apparent complexities. Of course it looks complex - you haven't done it before - its new. However, I guarantee there is an easier way to implement your solution using COM+ services, than to go about rolling 'ur own.
[I lied. A very last pedantic remark: <g>] Bruce McKinney re-quoted in his book a very important rule that is useful to always keep in mind when attempting to 'pre-optimize' or 'pre-implement' a solution -
"It doesn't matter how fast it is, if it doesn't work."
hth -ralph
Schmidt - 21 Jul 2005 22:55 GMT > Is there a setting where I can have COM+ instantiate only one instance > of the object (In this case, my connection wrapper) and allow client > applications to "share" this one instance of the COM+ object? I wouldn't try to find a setting for COM+ itself, to restrict the PoolSize of a specific COM+-object to 1. I would allow your clients, to access a "normal" configured COM+ Object (name it ComPlusRMIWrap). This ComPlusRMIWrap-Object (if requested) then accesses the RunningObjectsTable (ROT) on the serverside per GetObject(, "COMRMI.cServerDispatcher"), to get a (marshaled) Reference to your own ServerApplication (running as a sessionwide Singleton-Object on the COM+-Host). If you want to implement such a "Singleton-Server" in VB, you can use a Standard-Exe, that loads your RMI-DLL-Instance once, makes the connect to the Java-Environment and registers this Object in the ROT. Another (better, but more complicated) approach is, not to use a VB-Standard-Exe, but an ActiveX-Exe instead. With an ActiveX-Exe you can write a Server-Application, that can create more than one instance of your RMI-Connection-Wrapper on different threads. If the AX-Exe starts, it would create a Dispatcher-Object first and registers that in the ROT (cServerDispatcher). This Dispatcher-Object is the Singleton-Object, that the COM+Objects can reference per GetObject. Inside the Dispatcher is a Thread-Pool-Collection (created at Startup) of (for example 10) RMIWrapper-Objects (cRMIWrapper). Those Wrappers are the (threaded) COM-Objects, wich create and hold a separate RMI-Connection (from your Dll) inside.
> If this is possible, how would I instantiate the teh object at the client? > GetObject? CreateObject? When one client sent a command, it would > have to wait until the command had finished completely before > allowing the next client's command through. If two Clients at the same time are requesting the COM+-Server, the requests are processed in parallel up to the point, where the Interface of the ROT-Singleton (the Proxy) is used. Interface-Calls of a marshaled ROT-Object are queued automatically (the call, wich is a moment later will be blocked until the first request against the interface of the ROT-Singleton is finished). This means, altough COM+ would allow parallel requests, the calls would be serialized regarding the internal ROT-Object-Requests. In case of the VB-Standard-Exe, wich could place your RMIWrapper-Object directly in the ROT, your Clients would block each other during parallel RMI-Calls against the same ROT-Instance (I don't write a Code-Example for the COM+WrapperClasses - that case would be easy)
In Case of the VB-AxtiveX-Exe, the ROT-Object is not the RMIWrapper itself, it's a Dispatcher-Object, wich allows 'ThreadpoolCollection.Count' parallel and async requests. Your COM+ Objects would then have some Code like this (Aircode, no error+timeout handling):
Private RMIDispatcher as COMRMI.cServerDispatcher
Public Function DoRMIRequest(Params) Set RMIDispatcher = GetObject(, "COMRMI.cServerDispatcher")
'The Dispatcher takes the Params, chooses a free RMI-Pool-Object internally 'and creates an EventObject, calls the PoolObject async and returns immediately hEvt = RMIDispatcher.GetFreePoolObjectAndCallAsyncWith(Params)
'The Dispatcher will raise a SystemWide-Event, if the threaded RMI-Pool '-Object has finished the request and informed the ROT-Dispatcher WaitForSingleObject hEvt, TimeOut DoRMIRequest = RMIDispatcher.GetResult(hEvt) End Function
Olaf
Lance Wynn - 22 Jul 2005 00:25 GMT This is what I was thinking of doing.
Have you ever done anything like this before, and if so did it work well, did you get any difficult to track errors? I have never tried using a singleton server in this way, and so I am unaware of the many pitfalls that could arise out of implementing it like this.
"Lance Wynn" <lance_wynn@N.O.S.P.A.M.hotmail.com> schrieb im Newsbeitrag news:eW0UczijFHA.2152@TK2MSFTNGP14.phx.gbl...
> Is there a setting where I can have COM+ instantiate only one instance > of the object (In this case, my connection wrapper) and allow client > applications to "share" this one instance of the COM+ object? I wouldn't try to find a setting for COM+ itself, to restrict the PoolSize of a specific COM+-object to 1. I would allow your clients, to access a "normal" configured COM+ Object (name it ComPlusRMIWrap). This ComPlusRMIWrap-Object (if requested) then accesses the RunningObjectsTable (ROT) on the serverside per GetObject(, "COMRMI.cServerDispatcher"), to get a (marshaled) Reference to your own ServerApplication (running as a sessionwide Singleton-Object on the COM+-Host). If you want to implement such a "Singleton-Server" in VB, you can use a Standard-Exe, that loads your RMI-DLL-Instance once, makes the connect to the Java-Environment and registers this Object in the ROT. Another (better, but more complicated) approach is, not to use a VB-Standard-Exe, but an ActiveX-Exe instead. With an ActiveX-Exe you can write a Server-Application, that can create more than one instance of your RMI-Connection-Wrapper on different threads. If the AX-Exe starts, it would create a Dispatcher-Object first and registers that in the ROT (cServerDispatcher). This Dispatcher-Object is the Singleton-Object, that the COM+Objects can reference per GetObject. Inside the Dispatcher is a Thread-Pool-Collection (created at Startup) of (for example 10) RMIWrapper-Objects (cRMIWrapper). Those Wrappers are the (threaded) COM-Objects, wich create and hold a separate RMI-Connection (from your Dll) inside.
> If this is possible, how would I instantiate the teh object at the client? > GetObject? CreateObject? When one client sent a command, it would > have to wait until the command had finished completely before > allowing the next client's command through. If two Clients at the same time are requesting the COM+-Server, the requests are processed in parallel up to the point, where the Interface of the ROT-Singleton (the Proxy) is used. Interface-Calls of a marshaled ROT-Object are queued automatically (the call, wich is a moment later will be blocked until the first request against the interface of the ROT-Singleton is finished). This means, altough COM+ would allow parallel requests, the calls would be serialized regarding the internal ROT-Object-Requests. In case of the VB-Standard-Exe, wich could place your RMIWrapper-Object directly in the ROT, your Clients would block each other during parallel RMI-Calls against the same ROT-Instance (I don't write a Code-Example for the COM+WrapperClasses - that case would be easy)
In Case of the VB-AxtiveX-Exe, the ROT-Object is not the RMIWrapper itself, it's a Dispatcher-Object, wich allows 'ThreadpoolCollection.Count' parallel and async requests. Your COM+ Objects would then have some Code like this (Aircode, no error+timeout handling):
Private RMIDispatcher as COMRMI.cServerDispatcher
Public Function DoRMIRequest(Params) Set RMIDispatcher = GetObject(, "COMRMI.cServerDispatcher")
'The Dispatcher takes the Params, chooses a free RMI-Pool-Object internally 'and creates an EventObject, calls the PoolObject async and returns immediately hEvt = RMIDispatcher.GetFreePoolObjectAndCallAsyncWith(Params)
'The Dispatcher will raise a SystemWide-Event, if the threaded RMI-Pool '-Object has finished the request and informed the ROT-Dispatcher WaitForSingleObject hEvt, TimeOut DoRMIRequest = RMIDispatcher.GetResult(hEvt) End Function
Olaf
Schmidt - 22 Jul 2005 01:02 GMT > This is what I was thinking of doing. > > Have you ever done anything like this before, Yes, both approaches (singlethreaded ROT-Singletons with direct access to the worker-class and ROT-Dispatchers with indirekt access to multithreaded worker-pools). But always behind our own (socketbased) Appserver-Environment and not in combination with COM+.
> and if so did it work well, did you > get any difficult to track errors? I have never tried using a > singleton server in this way, and so I am unaware of the many > pitfalls that could arise out of implementing it like this. It works well, but you have to ensure a very clean timing/timeout-handling (over the entire roundtrip) - especially, if you want to use the singlethreaded approach - so that the ROT-Objects are never blocked for more than 1-3 seconds.
Olaf
P.S. Here are a few ROT-VB-examples:
www.datenhaus.de/Downloads/ROT Server.zip www.datenhaus.de/Downloads/ROT _Threading.zip
Ralph - 22 Jul 2005 02:40 GMT > This is what I was thinking of doing. > > Have you ever done anything like this before, and if so did it work well, > did you get any difficult to track errors? I have never tried using a > singleton server in this way, and so I am unaware of the many pitfalls that > could arise out of implementing it like this. Yes, quite often. Every situation is different.
As you no doubt know - COM+ transcends just one language development environment. Although VB has some unique builit-in properties to make it easier to provide the working elements, COM+ itself is a different world, its own quirks, its own rules, and don't take shortcuts.
The only real pitfall that might await you - is if you piss off your admin. Then it can get ugly. Buy him beer, or her flowers, but get to know them, keep them on your side.
<g> -ralph
> "Lance Wynn" <lance_wynn@N.O.S.P.A.M.hotmail.com> schrieb im Newsbeitrag > news:eW0UczijFHA.2152@TK2MSFTNGP14.phx.gbl... [quoted text clipped - 68 lines] > > Olaf Lance Wynn - 22 Jul 2005 05:35 GMT Unfortunately, this project was dropped in my lap at the last minute, and I don't have a lot of time to get it out. (We're talking several weeks.)
I have 90% of it done (or it was already 90% done with our existing system), I am using a number of COM+ registered components, and Transaction aware components to handle our internal business logic, and workflow, it's just this last connection to the external company's RMI app that is the weak link. The fact that the java app is limited to only allowing one connection, and in fact we can only use one connection because of the way they are handling logins means that all internal clients have to share that one connection.
Definitely not ideal, and certainly not the way I would choose to do it, but unfortunately that's the way it is. I wrote some stuff similar to this years ago when I needed a number of clients to share a single serial connection into a phone switch, and it worked fine, but I used TCP/IP and a custom broker to manage the connections. hopefully I'll get this to work with a singleton server, and COM so I don't need to reinvent the wheel. (Of course the singleton design is foreign to me, so we'll see how it goes!)
Thanks for all your help! It is much appreciated!
Lance
> This is what I was thinking of doing. > > Have you ever done anything like this before, and if so did it work well, > did you get any difficult to track errors? I have never tried using a > singleton server in this way, and so I am unaware of the many pitfalls that
> could arise out of implementing it like this. Yes, quite often. Every situation is different.
As you no doubt know - COM+ transcends just one language development environment. Although VB has some unique builit-in properties to make it easier to provide the working elements, COM+ itself is a different world, its own quirks, its own rules, and don't take shortcuts.
The only real pitfall that might await you - is if you piss off your admin. Then it can get ugly. Buy him beer, or her flowers, but get to know them, keep them on your side.
<g> -ralph
> "Lance Wynn" <lance_wynn@N.O.S.P.A.M.hotmail.com> schrieb im Newsbeitrag > news:eW0UczijFHA.2152@TK2MSFTNGP14.phx.gbl... [quoted text clipped - 17 lines] > VB-Standard-Exe, but an ActiveX-Exe instead. > With an ActiveX-Exe you can write a Server-Application, that can create more
> than one instance of your RMI-Connection-Wrapper on different threads. If > the AX-Exe starts, it would create a Dispatcher-Object first and registers [quoted text clipped - 3 lines] > example 10) RMIWrapper-Objects (cRMIWrapper). Those Wrappers are the > (threaded) COM-Objects, wich create and hold a separate RMI-Connection (from
> your Dll) inside. > > > If this is possible, how would I instantiate the teh object at the client?
> > GetObject? CreateObject? When one client sent a command, it would > > have to wait until the command had finished completely before > > allowing the next client's command through. > > If two Clients at the same time are requesting the COM+-Server, the requests
> are processed in parallel up to the point, where the Interface of the > ROT-Singleton (the Proxy) is used. Interface-Calls of a marshaled ROT-Object
> are queued automatically (the call, wich is a moment later will be blocked > until the first request against the interface of the ROT-Singleton is [quoted text clipped - 7 lines] > > In Case of the VB-AxtiveX-Exe, the ROT-Object is not the RMIWrapper itself,
> it's a Dispatcher-Object, wich allows 'ThreadpoolCollection.Count' parallel
> and async requests. > Your COM+ Objects would then have some Code like this (Aircode, no [quoted text clipped - 12 lines] > > 'The Dispatcher will raise a SystemWide-Event, if the threaded RMI-Pool
> '-Object has finished the request and informed the ROT-Dispatcher > WaitForSingleObject hEvt, TimeOut > DoRMIRequest = RMIDispatcher.GetResult(hEvt) > End Function > > Olaf
|
|
|