Source Code Cross Referenced for JmsInvokerClientInterceptor.java in  » J2EE » spring-framework-2.5 » org » springframework » jms » remoting » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.5 » org.springframework.jms.remoting 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2007 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.springframework.jms.remoting;
018:
019:        import javax.jms.JMSException;
020:        import javax.jms.Message;
021:        import javax.jms.MessageFormatException;
022:        import javax.jms.Queue;
023:        import javax.jms.QueueConnection;
024:        import javax.jms.QueueConnectionFactory;
025:        import javax.jms.QueueReceiver;
026:        import javax.jms.QueueSender;
027:        import javax.jms.QueueSession;
028:        import javax.jms.Session;
029:        import javax.jms.TemporaryQueue;
030:
031:        import org.aopalliance.intercept.MethodInterceptor;
032:        import org.aopalliance.intercept.MethodInvocation;
033:
034:        import org.springframework.aop.support.AopUtils;
035:        import org.springframework.beans.factory.InitializingBean;
036:        import org.springframework.jms.connection.ConnectionFactoryUtils;
037:        import org.springframework.jms.support.JmsUtils;
038:        import org.springframework.jms.support.converter.MessageConverter;
039:        import org.springframework.jms.support.converter.SimpleMessageConverter;
040:        import org.springframework.jms.support.destination.DestinationResolver;
041:        import org.springframework.jms.support.destination.DynamicDestinationResolver;
042:        import org.springframework.remoting.RemoteAccessException;
043:        import org.springframework.remoting.RemoteInvocationFailureException;
044:        import org.springframework.remoting.support.DefaultRemoteInvocationFactory;
045:        import org.springframework.remoting.support.RemoteInvocation;
046:        import org.springframework.remoting.support.RemoteInvocationFactory;
047:        import org.springframework.remoting.support.RemoteInvocationResult;
048:
049:        /**
050:         * {@link org.aopalliance.intercept.MethodInterceptor} for accessing a
051:         * JMS-based remote service.
052:         *
053:         * <p>Serializes remote invocation objects and deserializes remote invocation
054:         * result objects. Uses Java serialization just like RMI, but with the JMS
055:         * provider as communication infrastructure.
056:         *
057:         * <p>To be configured with a {@link javax.jms.QueueConnectionFactory} and a
058:         * target queue (either as {@link javax.jms.Queue} reference or as queue name).
059:         *
060:         * <p>Thanks to James Strachan for the original prototype that this
061:         * JMS invoker mechanism was inspired by!
062:         *
063:         * @author Juergen Hoeller
064:         * @author James Strachan
065:         * @since 2.0
066:         * @see #setConnectionFactory
067:         * @see #setQueue
068:         * @see #setQueueName
069:         * @see org.springframework.jms.remoting.JmsInvokerServiceExporter
070:         * @see org.springframework.jms.remoting.JmsInvokerProxyFactoryBean
071:         */
072:        public class JmsInvokerClientInterceptor implements  MethodInterceptor,
073:                InitializingBean {
074:
075:            private QueueConnectionFactory connectionFactory;
076:
077:            private Object queue;
078:
079:            private DestinationResolver destinationResolver = new DynamicDestinationResolver();
080:
081:            private RemoteInvocationFactory remoteInvocationFactory = new DefaultRemoteInvocationFactory();
082:
083:            private MessageConverter messageConverter = new SimpleMessageConverter();
084:
085:            private long receiveTimeout = 0;
086:
087:            /**
088:             * Set the QueueConnectionFactory to use for obtaining JMS QueueConnections.
089:             */
090:            public void setConnectionFactory(
091:                    QueueConnectionFactory connectionFactory) {
092:                this .connectionFactory = connectionFactory;
093:            }
094:
095:            /**
096:             * Return the QueueConnectionFactory to use for obtaining JMS QueueConnections.
097:             */
098:            protected QueueConnectionFactory getConnectionFactory() {
099:                return this .connectionFactory;
100:            }
101:
102:            /**
103:             * Set the target Queue to send invoker requests to.
104:             */
105:            public void setQueue(Queue queue) {
106:                this .queue = queue;
107:            }
108:
109:            /**
110:             * Set the name of target queue to send invoker requests to.
111:             * The specified name will be dynamically resolved via the
112:             * {@link #setDestinationResolver DestinationResolver}.
113:             */
114:            public void setQueueName(String queueName) {
115:                this .queue = queueName;
116:            }
117:
118:            /**
119:             * Set the DestinationResolver that is to be used to resolve Queue
120:             * references for this accessor.
121:             * <p>The default resolver is a DynamicDestinationResolver. Specify a
122:             * JndiDestinationResolver for resolving destination names as JNDI locations.
123:             * @see org.springframework.jms.support.destination.DynamicDestinationResolver
124:             * @see org.springframework.jms.support.destination.JndiDestinationResolver
125:             */
126:            public void setDestinationResolver(
127:                    DestinationResolver destinationResolver) {
128:                this .destinationResolver = (destinationResolver != null ? destinationResolver
129:                        : new DynamicDestinationResolver());
130:            }
131:
132:            /**
133:             * Set the RemoteInvocationFactory to use for this accessor.
134:             * Default is a {@link org.springframework.remoting.support.DefaultRemoteInvocationFactory}.
135:             * <p>A custom invocation factory can add further context information
136:             * to the invocation, for example user credentials.
137:             */
138:            public void setRemoteInvocationFactory(
139:                    RemoteInvocationFactory remoteInvocationFactory) {
140:                this .remoteInvocationFactory = (remoteInvocationFactory != null ? remoteInvocationFactory
141:                        : new DefaultRemoteInvocationFactory());
142:            }
143:
144:            /**
145:             * Specify the MessageConverter to use for turning
146:             * {@link org.springframework.remoting.support.RemoteInvocation}
147:             * objects into request messages, as well as response messages into
148:             * {@link org.springframework.remoting.support.RemoteInvocationResult} objects.
149:             * <p>Default is a {@link org.springframework.jms.support.converter.SimpleMessageConverter},
150:             * using a standard JMS {@link javax.jms.ObjectMessage} for each invocation /
151:             * invocation result object.
152:             * <p>Custom implementations may generally adapt Serializables into
153:             * special kinds of messages, or might be specifically tailored for
154:             * translating RemoteInvocation(Result)s into specific kinds of messages.
155:             */
156:            public void setMessageConverter(MessageConverter messageConverter) {
157:                this .messageConverter = (messageConverter != null ? messageConverter
158:                        : new SimpleMessageConverter());
159:            }
160:
161:            /**
162:             * Set the timeout to use for receiving the response message for a request
163:             * (in milliseconds).
164:             * <p>The default is 0, which indicates a blocking receive without timeout.
165:             * @see javax.jms.MessageConsumer#receive(long)
166:             * @see javax.jms.MessageConsumer#receive()
167:             */
168:            public void setReceiveTimeout(long receiveTimeout) {
169:                this .receiveTimeout = receiveTimeout;
170:            }
171:
172:            /**
173:             * Return the timeout to use for receiving the response message for a request
174:             * (in milliseconds).
175:             */
176:            protected long getReceiveTimeout() {
177:                return this .receiveTimeout;
178:            }
179:
180:            public void afterPropertiesSet() {
181:                if (getConnectionFactory() == null) {
182:                    throw new IllegalArgumentException(
183:                            "Property 'connectionFactory' is required");
184:                }
185:                if (this .queue == null) {
186:                    throw new IllegalArgumentException(
187:                            "'queue' or 'queueName' is required");
188:                }
189:            }
190:
191:            public Object invoke(MethodInvocation methodInvocation)
192:                    throws Throwable {
193:                if (AopUtils.isToStringMethod(methodInvocation.getMethod())) {
194:                    return "JMS invoker proxy for queue [" + this .queue + "]";
195:                }
196:
197:                RemoteInvocation invocation = createRemoteInvocation(methodInvocation);
198:                RemoteInvocationResult result = null;
199:                try {
200:                    result = executeRequest(invocation);
201:                } catch (JMSException ex) {
202:                    throw convertJmsInvokerAccessException(ex);
203:                }
204:                try {
205:                    return recreateRemoteInvocationResult(result);
206:                } catch (Throwable ex) {
207:                    if (result.hasInvocationTargetException()) {
208:                        throw ex;
209:                    } else {
210:                        throw new RemoteInvocationFailureException(
211:                                "Invocation of method ["
212:                                        + methodInvocation.getMethod()
213:                                        + "] failed in JMS invoker remote service at queue ["
214:                                        + this .queue + "]", ex);
215:                    }
216:                }
217:            }
218:
219:            /**
220:             * Create a new RemoteInvocation object for the given AOP method invocation.
221:             * The default implementation delegates to the RemoteInvocationFactory.
222:             * <p>Can be overridden in subclasses to provide custom RemoteInvocation
223:             * subclasses, containing additional invocation parameters like user credentials.
224:             * Note that it is preferable to use a custom RemoteInvocationFactory which
225:             * is a reusable strategy.
226:             * @param methodInvocation the current AOP method invocation
227:             * @return the RemoteInvocation object
228:             * @see RemoteInvocationFactory#createRemoteInvocation
229:             */
230:            protected RemoteInvocation createRemoteInvocation(
231:                    MethodInvocation methodInvocation) {
232:                return this .remoteInvocationFactory
233:                        .createRemoteInvocation(methodInvocation);
234:            }
235:
236:            /**
237:             * Execute the given remote invocation, sending an invoker request message
238:             * to this accessor's target queue and waiting for a corresponding response.
239:             * @param invocation the RemoteInvocation to execute
240:             * @return the RemoteInvocationResult object
241:             * @throws JMSException in case of JMS failure
242:             * @see #doExecuteRequest
243:             */
244:            protected RemoteInvocationResult executeRequest(
245:                    RemoteInvocation invocation) throws JMSException {
246:                QueueConnection con = getConnectionFactory()
247:                        .createQueueConnection();
248:                QueueSession session = null;
249:                try {
250:                    session = con.createQueueSession(false,
251:                            Session.AUTO_ACKNOWLEDGE);
252:                    Queue queueToUse = resolveQueue(session);
253:                    Message requestMessage = createRequestMessage(session,
254:                            invocation);
255:                    con.start();
256:                    Message responseMessage = doExecuteRequest(session,
257:                            queueToUse, requestMessage);
258:                    return extractInvocationResult(responseMessage);
259:                } finally {
260:                    JmsUtils.closeSession(session);
261:                    ConnectionFactoryUtils.releaseConnection(con,
262:                            getConnectionFactory(), true);
263:                }
264:            }
265:
266:            /**
267:             * Resolve this accessor's target queue.
268:             * @param session the current JMS Session
269:             * @return the resolved target Queue
270:             * @throws JMSException if resolution failed
271:             */
272:            protected Queue resolveQueue(Session session) throws JMSException {
273:                if (this .queue instanceof  Queue) {
274:                    return (Queue) this .queue;
275:                } else if (this .queue instanceof  String) {
276:                    return resolveQueueName(session, (String) this .queue);
277:                } else {
278:                    throw new javax.jms.IllegalStateException(
279:                            "Queue object ["
280:                                    + this .queue
281:                                    + "] is neither a [javax.jms.Queue] nor a queue name String");
282:                }
283:            }
284:
285:            /**
286:             * Resolve the given queue name into a JMS {@link javax.jms.Queue},
287:             * via this accessor's {@link DestinationResolver}.
288:             * @param session the current JMS Session
289:             * @param queueName the name of the queue
290:             * @return the located Queue
291:             * @throws JMSException if resolution failed
292:             * @see #setDestinationResolver
293:             */
294:            protected Queue resolveQueueName(Session session, String queueName)
295:                    throws JMSException {
296:                return (Queue) this .destinationResolver.resolveDestinationName(
297:                        session, queueName, false);
298:            }
299:
300:            /**
301:             * Create the invoker request message.
302:             * <p>The default implementation creates a JMS ObjectMessage
303:             * for the given RemoteInvocation object.
304:             * @param session the current JMS Session
305:             * @param invocation the remote invocation to send
306:             * @return the JMS Message to send
307:             * @throws JMSException if the message could not be created
308:             */
309:            protected Message createRequestMessage(Session session,
310:                    RemoteInvocation invocation) throws JMSException {
311:                return this .messageConverter.toMessage(invocation, session);
312:            }
313:
314:            /**
315:             * Actually execute the given request, sending the invoker request message
316:             * to the specified target queue and waiting for a corresponding response.
317:             * <p>The default implementation is based on standard JMS send/receive,
318:             * using a {@link javax.jms.TemporaryQueue} for receiving the response.
319:             * @param session the JMS Session to use
320:             * @param queue the resolved target Queue to send to
321:             * @param requestMessage the JMS Message to send
322:             * @return the RemoteInvocationResult object
323:             * @throws JMSException in case of JMS failure
324:             */
325:            protected Message doExecuteRequest(QueueSession session,
326:                    Queue queue, Message requestMessage) throws JMSException {
327:
328:                TemporaryQueue responseQueue = null;
329:                QueueSender sender = null;
330:                QueueReceiver receiver = null;
331:                try {
332:                    responseQueue = session.createTemporaryQueue();
333:                    sender = session.createSender(queue);
334:                    receiver = session.createReceiver(responseQueue);
335:                    requestMessage.setJMSReplyTo(responseQueue);
336:                    sender.send(requestMessage);
337:                    long timeout = getReceiveTimeout();
338:                    return (timeout > 0 ? receiver.receive(timeout) : receiver
339:                            .receive());
340:                } finally {
341:                    JmsUtils.closeMessageConsumer(receiver);
342:                    JmsUtils.closeMessageProducer(sender);
343:                    if (responseQueue != null) {
344:                        responseQueue.delete();
345:                    }
346:                }
347:            }
348:
349:            /**
350:             * Extract the invocation result from the response message.
351:             * <p>The default implementation expects a JMS ObjectMessage carrying
352:             * a RemoteInvocationResult object. If an invalid response message is
353:             * encountered, the <code>onInvalidResponse</code> callback gets invoked.
354:             * @param responseMessage the response message
355:             * @return the invocation result
356:             * @throws JMSException is thrown if a JMS exception occurs
357:             * @see #onInvalidResponse
358:             */
359:            protected RemoteInvocationResult extractInvocationResult(
360:                    Message responseMessage) throws JMSException {
361:                Object content = this .messageConverter
362:                        .fromMessage(responseMessage);
363:                if (content instanceof  RemoteInvocationResult) {
364:                    return (RemoteInvocationResult) content;
365:                }
366:                return onInvalidResponse(responseMessage);
367:            }
368:
369:            /**
370:             * Callback that is invoked by <code>extractInvocationResult</code>
371:             * when it encounters an invalid response message.
372:             * <p>The default implementation throws a MessageFormatException.
373:             * @param responseMessage the invalid response message
374:             * @return an alternative invocation result that should be
375:             * returned to the caller (if desired)
376:             * @throws JMSException if the invalid response should lead
377:             * to an infrastructure exception propagated to the caller
378:             * @see #extractInvocationResult
379:             */
380:            protected RemoteInvocationResult onInvalidResponse(
381:                    Message responseMessage) throws JMSException {
382:                throw new MessageFormatException("Invalid response message: "
383:                        + responseMessage);
384:            }
385:
386:            /**
387:             * Recreate the invocation result contained in the given RemoteInvocationResult
388:             * object. The default implementation calls the default recreate method.
389:             * <p>Can be overridden in subclass to provide custom recreation, potentially
390:             * processing the returned result object.
391:             * @param result the RemoteInvocationResult to recreate
392:             * @return a return value if the invocation result is a successful return
393:             * @throws Throwable if the invocation result is an exception
394:             * @see org.springframework.remoting.support.RemoteInvocationResult#recreate()
395:             */
396:            protected Object recreateRemoteInvocationResult(
397:                    RemoteInvocationResult result) throws Throwable {
398:                return result.recreate();
399:            }
400:
401:            /**
402:             * Convert the given JMS invoker access exception to an appropriate
403:             * Spring RemoteAccessException.
404:             * @param ex the exception to convert
405:             * @return the RemoteAccessException to throw
406:             */
407:            protected RemoteAccessException convertJmsInvokerAccessException(
408:                    JMSException ex) {
409:                throw new RemoteAccessException(
410:                        "Could not access JMS invoker queue [" + this .queue
411:                                + "]", ex);
412:            }
413:
414:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.