Hi, We are running OpenEdge 11.4, and for this particular question the client is a prowin32 session and the appserver is a state-free appserver. If we connect to the appserver and run code in the server program that creates a client-principal, we can access that client-principal from the appserver on subsequent calls by using the SESSION:CURRENT-REQUEST-INFO object. That consistently works fine as long as the client is making synchronous calls. However, if the client makes an asynchronous call, SESSION:CURRENT-REQUEST-INFO in the server program comes up NULL. We can add code to the client program to set a specific client-principal to the client-side REQUEST-INFO object before each asynchronous call and the server program will see that OK, but it will not automatically see the client-principal that was originally assigned unless we change the calls to be synchronous. The documentation of the CURRENT-REQUEST-INFO doesn't give any indication that an asynchronous call would be handled differently than a synchronous call. The documentation of the client-side REQUEST-INFO object does seem to infer that synchronous calls and asynchronous calls might be handled differently. Should we expect to be able to access the client-principal that was assigned to an appserver session during a synchronous call when we are executing an asynchronous request on the same connection (the same SERVER handle from the client perspective)? Or must we code to specifically assign a client-principal to the REQUEST-INFO on the client-side for every asynchronous call we make, even if the client-principal object to use and the server handle are the same on every call? Thanks for any advice, Mark Opfer DMSi Software
This issue was caused by a bug in the ABL client, and was fixed in OE11.6 in early June. The fix should be included in the recent ESAP drop.
Hi Mark,
The functionality should work as you expect. But obviously something is not happening correctly. If I understand the process correctly:
1) The client connects to the AppServer state-free
2) The client runs a synchronous request [to login]
3) The server creates, seals, and returns a Client-Princpal via the SESSION:CURRENT-RESPONSE-INFO:SetClientPrincipal()
4) The client runs a synchronous request and the server obtains a valid Client-Principal via SESSION:CURRENT-REQUEST-INFO:GetClientPrincipal()
5) The client runs an asynchronous request and the server obtains an UNKNOWN from SESSION:CURRENT-REQUEST-INFO:GetClientPrincipal() {ERROR: expect a valid Client-Principal}
When the client is calling asynchronous requests, are there multiple requests happening at the same time?
Is more than one AppServer serving the one client server connection?
Sorry for the questions, but there are many things happening at the same time internally and this would help us understand where to focus.
Mike Jacobs
Hi Mark,
The functionality should work as you expect. But obviously something is not happening correctly. If I understand the process correctly:
1) The client connects to the AppServer state-free
2) The client runs a synchronous request [to login]
3) The server creates, seals, and returns a Client-Princpal via the SESSION:CURRENT-RESPONSE-INFO:SetClientPrincipal()
4) The client runs a synchronous request and the server obtains a valid Client-Principal via SESSION:CURRENT-REQUEST-INFO:GetClientPrincipal()
5) The client runs an asynchronous request and the server obtains an UNKNOWN from SESSION:CURRENT-REQUEST-INFO:GetClientPrincipal() {ERROR: expect a valid Client-Principal}
When the client is calling asynchronous requests, are there multiple requests happening at the same time?
Is more than one AppServer serving the one client server connection?
Sorry for the questions, but there are many things happening at the same time internally and this would help us understand where to focus.
Mike Jacobs
Flag this post as spam/abuse.
Hi Mark,
The functionality should work as you expect. But obviously something is not happening correctly. If I understand the process correctly:
1) The client connects to the AppServer state-free
2) The client runs a synchronous request [to login]
3) The server creates, seals, and returns a Client-Princpal via the SESSION:CURRENT-RESPONSE-INFO:SetClientPrincipal()
4) The client runs a synchronous request and the server obtains a valid Client-Principal via SESSION:CURRENT-REQUEST-INFO:GetClientPrincipal()
5) The client runs an asynchronous request and the server obtains an UNKNOWN from SESSION:CURRENT-REQUEST-INFO:GetClientPrincipal() {ERROR: expect a valid Client-Principal}
When the client is calling asynchronous requests, are there multiple requests happening at the same time?
Is more than one AppServer serving the one client server connection?
Sorry for the questions, but there are many things happening at the same time internally and this would help us understand where to focus.
Mike Jacobs
Flag this post as spam/abuse.
Flag this post as spam/abuse.
Hi Mark,
The functionality should work as you expect. But obviously something is not happening correctly. If I understand the process correctly:
1) The client connects to the AppServer state-free
2) The client runs a synchronous request [to login]
3) The server creates, seals, and returns a Client-Princpal via the SESSION:CURRENT-RESPONSE-INFO:SetClientPrincipal()
4) The client runs a synchronous request and the server obtains a valid Client-Principal via SESSION:CURRENT-REQUEST-INFO:GetClientPrincipal()
5) The client runs an asynchronous request and the server obtains an UNKNOWN from SESSION:CURRENT-REQUEST-INFO:GetClientPrincipal() {ERROR: expect a valid Client-Principal}
When the client is calling asynchronous requests, are there multiple requests happening at the same time?
Is more than one AppServer serving the one client server connection?
Sorry for the questions, but there are many things happening at the same time internally and this would help us understand where to focus.
Mike Jacobs
Flag this post as spam/abuse.
Flag this post as spam/abuse.
Flag this post as spam/abuse.
Hi Mark,
Attaching files, I find, is a bit obscure. Click on the "Use rich formatting" link in the reply box. This will take you to a new page with three tabs "compose", "options", "<I forget>". In the "options" tab I can add files. At the bottom is a simple RTF editor box in which I can enter the text reply.
Slightly off topic - but why manually manage multiple connections to a state-free appserver in your ABL code rather than use a single appserver connection and let the connection manage multiple physical appserver connections and simultaneous asynchronous request executions?
Anyway... we'll look at the code, see if we can see the same behavior, and get back to you.
Have a good day,
Mike Jacobs
[quote user="Michael Jacobs"]
Slightly off topic - but why manually manage multiple connections to a state-free appserver in your ABL code rather than use a single appserver connection and let the connection manage multiple physical appserver connections and simultaneous asynchronous request executions?
[/quote]
I am not the OP, but we have two reasons for managing multiple connections from the client:
1. synchronous and asynchronous calls cannot be mixed on the fly
2. one asynchronous connection will handle requests in queued order - if the user decides to start something else it should not wait in the queue of the application that is still handling async requests for the previous application that is still busy.
Regards,
Stefan
Hi Mike,
Thanks for the information about attaching files.
Our main reason for wanting to have multiple connections is that the processes that run asynchronously sometimes change properties in the application's session context while they are running, and we don't want the various processes to be sharing the same application context while they are running. So the idea is that each connection has its own context.
With that said, it may be that we don't really want to have more than one process running asynchronously on a particular connection on a state-free appserver. We've been stacking asynchronous calls on a state-reset appserver for years, trusting them to run in the order that we put them on the stack, but maybe state-free asynchronous calls don't work that way.
If I make three asynchronous calls to a state-free appserver connection, will they get run one after another, or will each request be handed to a separate appserver session immediately and all three will be running at the same time? I may have to adjust what I'm trying to do.
Thanks,
Mark
Hi Mark,
Attaching files, I find, is a bit obscure. Click on the "Use rich formatting" link in the reply box. This will take you to a new page with three tabs "compose", "options", "<I forget>". In the "options" tab I can add files. At the bottom is a simple RTF editor box in which I can enter the text reply.
Slightly off topic - but why manually manage multiple connections to a state-free appserver in your ABL code rather than use a single appserver connection and let the connection manage multiple physical appserver connections and simultaneous asynchronous request executions?
Anyway... we'll look at the code, see if we can see the same behavior, and get back to you.
Have a good day,
Mike Jacobs
Flag this post as spam/abuse.
My thanks to both Mark and Stefan for adding some background for using multiple connections. I'll be adding these to my store of use cases.
Mike J.
There is a fundamental difference in the way that asynchronous requests from an ABL client are handled for session-managed (i.e. state-reset, state-aware, stateless) appservers than for session-free (i.e. state-free) appservers.
In session-managed mode, when a client application connects a server handle, a single physical connection is made between the client and appserver, and all requests from that server handle are run on that connection. Only one request can be active on that request at a time. When requests are run asynchronously, they are run serially on that single connection in the order that the RUN statements were executed. The developer is assured of a FIFO behavior and can depend on the order the requests will run.
In session-free mode, when a client application connects a server handle, a pool of physical connections is established between the client and appserver. This pool can contain multiple physical connections to one or more appservers (when using load balancing). As asynch requests are run, connections are temporarily reserved from the connection pool and used for the duration of the request; when the request is over, the connection goes back into the pool, and can be used for a different request. If an asynch request is made and there are no available connections in the pool (i.e. all existing connections are currently being used by running asynch requests) a new connection is established to run the request. Once the request is over, that connection is returned to the pool. In this way, the pool can grow in size, depending on the maximum number of concurrent asynch requests run on that server handle.
The initial size and upper size limit of this pool can be determined by optional connection parameters specified in the first parameter to hSrv:CONNECT(). The default behavior is to establish one connection when the hSrv:CONNECT() is run, and create an unrestricted number of additional connections "on demand".
The key thing to note from this behavior is that, when multiple asynch requests are run, they can each run immediately on separate connections, in parallel (provided that sufficient connections can be reserved and/or created). That is, they are NOT serialized on a single connection. As a result, the order that they execute cannot be predicted. Also, depending on how long each request runs, the responses can return in a different order than they were executed.
There is a fundamental difference in the way that asynchronous requests from an ABL client are handled for session-managed (i.e. state-reset, state-aware, stateless) appservers than for session-free (i.e. state-free) appservers.
In session-managed mode, when a client application connects a server handle, a single physical connection is made between the client and appserver, and all requests from that server handle are run on that connection. Only one request can be active on that request at a time. When requests are run asynchronously, they are run serially on that single connection in the order that the RUN statements were executed. The developer is assured of a FIFO behavior and can depend on the order the requests will run.
In session-free mode, when a client application connects a server handle, a pool of physical connections is established between the client and appserver. This pool can contain multiple physical connections to one or more appservers (when using load balancing). As asynch requests are run, connections are temporarily reserved from the connection pool and used for the duration of the request; when the request is over, the connection goes back into the pool, and can be used for a different request. If an asynch request is made and there are no available connections in the pool (i.e. all existing connections are currently being used by running asynch requests) a new connection is established to run the request. Once the request is over, that connection is returned to the pool. In this way, the pool can grow in size, depending on the maximum number of concurrent asynch requests run on that server handle.
The initial size and upper size limit of this pool can be determined by optional connection parameters specified in the first parameter to hSrv:CONNECT(). The default behavior is to establish one connection when the hSrv:CONNECT() is run, and create an unrestricted number of additional connections "on demand".
The key thing to note from this behavior is that, when multiple asynch requests are run, they can each run immediately on separate connections, in parallel (provided that sufficient connections can be reserved and/or created). That is, they are NOT serialized on a single connection. As a result, the order that they execute cannot be predicted. Also, depending on how long each request runs, the responses can return in a different order than they were executed.
Flag this post as spam/abuse.
Hi Mark,
I took your sample code and ran it in a state-free AppServer this morning.
It did not work correctly - at least not to my expectations.
Adding some 'message' debug statements I've found that the first async call to a server handle passes correctly the ClientContextId and ClientPrincipal to the AppServer that was received from the first sync call. Thereafter, the 2nd, 3rd, etc async calls to the AppServer passed unknown for both the ClientContextId and the ClientPrincipal. It is like the first async call clears the server handle's ClientContextId and ClientPrincipal.
I'll next consult Peter and take a closer look to see what options are available. I'll be back...
Mike J.
Did this get solved? Ive only just come across this thread but am having this exact same issue, only with PAS. Im connecting to a session-free appserver for async requests only and using a state-reset appserver for sync requests. We only use our async process for fetching data for the user interface so it works well.
On my first request I create a context record using clientcontextid for session data etc. The contextid is perfectly returned and valid. An activate procedure shows the contextid as valid on the first async request. As soon as I launch the second async request (the first request is completed at this time) it has ? as the value for contextid and is unable to retrieve the context data.
Any ideas?
-Darren
Did this get solved? Ive only just come across this thread but am having this exact same issue, only with PAS. Im connecting to a session-free appserver for async requests only and using a state-reset appserver for sync requests. We only use our async process for fetching data for the user interface so it works well.
On my first request I create a context record using clientcontextid for session data etc. The contextid is perfectly returned and valid. An activate procedure shows the contextid as valid on the first async request. As soon as I launch the second async request (the first request is completed at this time) it has ? as the value for contextid and is unable to retrieve the context data.
Any ideas?
-Darren
Flag this post as spam/abuse.
This issue was caused by a bug in the ABL client, and was fixed in OE11.6 in early June. The fix should be included in the recent ESAP drop.
This issue was caused by a bug in the ABL client, and was fixed in OE11.6 in early June. The fix should be included in the recent ESAP drop.
Flag this post as spam/abuse.
I was about to say it was still broken in 11.5.1. I've gotten around it by resetting clientcontextid and the clientprincipal on return. I'll have a look at 11.6 when it comes out. I don't believe 11.6 is due until the fall.
Any idea if this will make its was to 11.5.2 and do we have a date for this SP.
-Darren