|
From: <jas...@ma...> - 2004-10-29 07:28:53
|
On 28 Oct 2004, at 21:14, j=FCrgen h=F6ller [werk3AT] wrote: > James, > > I've looked at the JmsClientInterceptor in some more detail, and found=20= > that it uses the JMS QueueRequestor class (which I haven't seen in=20 > action before). Its a JMS helper class. Its possible to implement in a slightly more=20 efficient way with timeouts and re-try support; but its a suitable=20 first implementation. We could get more advanced later on. > I've noticed that QueueRequestor takes a Session and a Queue,=20 > internally creating a temporary queue for responses. However, in the=20= > current usage style, it would use the same Session for the entire=20 > lifetime of the JmsClientInterceptor bean (i.e. the entire=20 > application), and isn't properly closed on shutdown. Good catch. I've just patched the code to support DisposableBean to=20 close down the session & queueRequestor. > While that might not cause any issues in a standalone client=20 > environment, what about usage of JmsClientInterceptor in a J2EE=20 > environment, for example a web app invoking some external process? And=20= > what about the JMS Session used by the QueueRequestor becoming stale,=20= > for example through a restart of the JMS server? Most decent JMS providers can handle auto-reconnection to the JMS=20 server if it goes down and full HA. > It seems to me that we should get a Session via a given=20 > ConnectionFactory for each request here. In the J2EE case, this will=20= > usually be a pooled Session from a pooled Connection. In the=20 > standalone case, it can be from a single Connection, via Spring's=20 > SingleConnectionFactory. Grabbing a session from a pool is a reasonable idea (though there's=20 also the MessageProducer, MessageConsumer and temporary Queue to=20 consider). Though creating JMS resources like session, consumer,=20 producer, each time you need to perform some kind of remote invocation=20= is a very bad idea - its really slow, since creating a=20 session/consumer/producer requires an RPC with the JMS server anyway :) Sessions are pretty lightweight to keep around though; its Connections=20= that need to be pooled as they are the expensive resource; sessions are=20= much cheaper, though they are intended to be long lived objects. In terms of pooling, the best idea is to pool the QueueRequestor; i.e.=20= pool the Session + temporary Queue + MessageProducer + MessageConsumer.=20= Then when you grab one from the pool its complete ready to be used -=20 you don't have to wait for a session or producer or consumer to be=20 created - all of which are pretty expensive operations, requiring an=20 RPC with the JMS server. If further down the road we write a more complex kind of QueueRequestor=20= object, we could pool that too as a single unit since it'll always have=20= a Session, MessageProducer, MessageConsumer and temporary Queue. > The problem with the ConnectionFactory approach is that we'd need to=20= > recreate a QueueRequestor instance for each request, with a freshly=20 > fetched Session. Does this mean that the QueueRequestor would create a=20= > new temporary Queue for each request in such a scenario? Yes - which is a bad idea too, as creating a temporary queue requires=20 an RPC with the JMS server. > I wonder if that's feasible... However, what's the alternative, given=20= > that we shouldn't keep using the same Session forever? Well we could use the same session forever. Or we could pool the=20 QueueRequestor instances. How about we use the same trick we just used on the JCAContainer - we=20 create an interface to represent some kind of JMS based QueueRequestor;=20= then we could use a single one for the duration of the client stub, or=20= we could introduce a pool using TargetSource? > We could also add QueueRequestor/TopicRequestor support to=20 > JmsTemplate, offering "request" methods that throw unchecked=20 > JmsExceptions, fetching a fresh Session from the configured=20 > ConnectionFactory underneath. We could also offer a=20 > "requestAndConvert" method that takes Object as input message and also=20= > returns Object, analogous to "convertAndSend"/"receiveAndConvert". Sounds great. I'd be nice to use the same JMS implementation code=20 underneath. > Already touching 1.2 RC1 work here, I guess :-) :) > P.S.: I'd like to rename JmsClientInterceptor, JmsServiceExporter etc=20= > to JmsInvokerClientInterceptor respectively JmsInvokerServiceExporter.=20= > It's about serializing Spring's remote invocations through JMS, not=20 > about native remoting support in JMS, and I feel that we should=20 > reflect this in the name. We use the terms "HTTP invoker" and "RMI=20 > invoker" too, when serializing RemoteInvocations via HTTP or RMI. Sounds good with me. Shouldn't we rename BurlapClientInterceptor and=20 HessianClientInterceptor too? James ------- http://radio.weblogs.com/0112098/ |