Skip to Content
0
Former Member
Sep 14, 2011 at 12:10 PM

Experiences around the nCo 3.0 RfcDestinationManager

1373 Views

Hello everyone,

I'm very interested in your application architecture around the .NET connector 3.0.

For example I just don't manage to be friends with the RfcDestinationManager 😕

Example 1:

Okay so there's this MAX_POOL_SIZE and POOL_SIZE setting. According to the developers manual it's exactly the same(?). Whatever. And some piece of documentation I found (some SAP blog) says we cannot grab and manage a connection ourselves and we have to rely on the RfcDestinationManager to return one. That's a good thing. In theory. Indeed this is where it gets complicated.

I wrote a small multi threaded console application to simulate parallel connections. All the console application does is to Ping() the target SAP system. With MAX_POOL_SIZE set to 5 (default value?) I sooner or later run into a SAP.Middleware.Connector.RfcResourceException: Unable to allocate client in pool [NAME=xxx USER=xxx CLIENT=xxx LANG=xxx ASHOST=xxx ASHOST=xxx SYSNR=xxx SYSID=xxx]. MAX_POOL_SIZE [5] exceeded

at SAP.Middleware.Connector.RfcConnectionPool.GetClient()

at SAP.Middleware.Connector.RfcDestination.GetClient(Boolean forRepository)

at SAP.Middleware.Connector.RfcDestination.Ping()

at CA4MultiThread.SapClient.Ping() in D:\workspace\xxx\SapDotNetConnector\CA4MultiThread\SapClient.cs:line 104

at CA4MultiThread.Program.SapPing() in D:\workspace\xxx\SapDotNetConnector\CA4MultiThread\Program.cs:line 98

at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

at System.Threading.ThreadHelper.ThreadStart()

Bad. On one hand I cannot manage the connections myself (because the connector takes care of the connection pool) and on the other hand there's no way to check whether it's safe to submit a request to SAP. Either the connector should implement a queue to handle those scenarios or offer a possibility to check if a connection is present or can be opened.

Of course I can set the MAX_POOL_SIZE to 100 - but what's the point of MAX_POOL_SIZE then?

Example 2:

Another thing that bugs me is the registration of destination configurations.

SAP.Middleware.Connector.RfcInvalidStateException: destination configuration already initialized

at SAP.Middleware.Connector.RfcDestinationManager.RegisterDestinationConfiguration(IDestinationConfiguration config)

at CA4MultiThread.SapClient..ctor() in D:\workspace\rsom\SapDotNetConnector\CA4MultiThread\SapClient.cs:line 81

at CA4MultiThread.SapClient.get_Instance() in D:\workspace\rsom\SapDotNetConnector\CA4MultiThread\SapClient.cs:line 57

at CA4MultiThread.Program.SapPing() in D:\workspace\xxx\SapDotNetConnector\CA4MultiThread\Program.cs:line 96

at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

at System.Threading.ThreadHelper.ThreadStart()

Typically you register your destinations only once. Okay. But in multi threaded scenarios you might very well run into situations where two threads are trying to register their destinations at just the same time and there's your exception. First of all I think the RfcDestinationManager should be aware of its state and know whether it has already a configuration present or not. And the worst thing is... you cannot even check for the RfcDestinationmanager's state yourself. The only public method which comes somewhat close to that purpose is RfcDestinationManager.GetDestination()... but that throws an exception if the destination doesn't exist - so it's not exactly a solution.

So I'm tracking RfcDestinationManager's state - thread safe - in my own application now (which is not a good thing, but I prefer this approach to having some startup code in global.asax or something like that). What's your approach here?