Source Code Cross Referenced for JaxRpcPortClientInterceptor.java in  » J2EE » spring-framework-2.5 » org » springframework » remoting » jaxrpc » 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.remoting.jaxrpc 
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.remoting.jaxrpc;
018:
019:        import java.lang.reflect.InvocationTargetException;
020:        import java.lang.reflect.Method;
021:        import java.rmi.Remote;
022:        import java.rmi.RemoteException;
023:        import java.util.HashMap;
024:        import java.util.Iterator;
025:        import java.util.Map;
026:        import java.util.Properties;
027:
028:        import javax.xml.namespace.QName;
029:        import javax.xml.rpc.Call;
030:        import javax.xml.rpc.JAXRPCException;
031:        import javax.xml.rpc.Service;
032:        import javax.xml.rpc.ServiceException;
033:        import javax.xml.rpc.Stub;
034:        import javax.xml.rpc.soap.SOAPFaultException;
035:
036:        import org.aopalliance.intercept.MethodInterceptor;
037:        import org.aopalliance.intercept.MethodInvocation;
038:
039:        import org.springframework.aop.support.AopUtils;
040:        import org.springframework.beans.factory.InitializingBean;
041:        import org.springframework.remoting.RemoteLookupFailureException;
042:        import org.springframework.remoting.RemoteProxyFailureException;
043:        import org.springframework.remoting.rmi.RmiClientInterceptorUtils;
044:        import org.springframework.util.CollectionUtils;
045:        import org.springframework.util.ReflectionUtils;
046:
047:        /**
048:         * {@link org.aopalliance.intercept.MethodInterceptor} for accessing a specific port
049:         * of a JAX-RPC service. Uses either {@link LocalJaxRpcServiceFactory}'s facilities
050:         * underneath or takes an explicit reference to an existing JAX-RPC Service instance
051:         * (e.g. obtained via {@link org.springframework.jndi.JndiObjectFactoryBean}).
052:         *
053:         * <p>Allows to set JAX-RPC's standard stub properties directly, via the
054:         * "username", "password", "endpointAddress" and "maintainSession" properties.
055:         * For typical usage, it is not necessary to specify those.
056:         *
057:         * <p>In standard JAX-RPC style, this invoker is used with an RMI service interface.
058:         * Alternatively, this invoker can also proxy a JAX-RPC service with a matching
059:         * non-RMI business interface, that is, an interface that declares the service methods
060:         * without RemoteExceptions. In the latter case, RemoteExceptions thrown by JAX-RPC
061:         * will automatically get converted to Spring's unchecked RemoteAccessException.
062:         *
063:         * <p>Setting "serviceInterface" is usually sufficient: The invoker will automatically
064:         * use JAX-RPC "dynamic invocations" via the Call API in this case, no matter whether
065:         * the specified interface is an RMI or non-RMI interface. Alternatively, a corresponding
066:         * JAX-RPC port interface can be specified as "portInterface", which will turn this
067:         * invoker into "static invocation" mode (operating on a standard JAX-RPC port stub).
068:         *
069:         * @author Juergen Hoeller
070:         * @since 15.12.2003
071:         * @see #setPortName
072:         * @see #setServiceInterface
073:         * @see #setPortInterface
074:         * @see javax.xml.rpc.Service#createCall
075:         * @see javax.xml.rpc.Service#getPort
076:         * @see org.springframework.remoting.RemoteAccessException
077:         * @see org.springframework.jndi.JndiObjectFactoryBean
078:         */
079:        public class JaxRpcPortClientInterceptor extends
080:                LocalJaxRpcServiceFactory implements  MethodInterceptor,
081:                InitializingBean {
082:
083:            private Service jaxRpcService;
084:
085:            private Service serviceToUse;
086:
087:            private String portName;
088:
089:            private String username;
090:
091:            private String password;
092:
093:            private String endpointAddress;
094:
095:            private boolean maintainSession;
096:
097:            /** Map of custom properties, keyed by property name (String) */
098:            private final Map customPropertyMap = new HashMap();
099:
100:            private Class serviceInterface;
101:
102:            private Class portInterface;
103:
104:            private boolean lookupServiceOnStartup = true;
105:
106:            private boolean refreshServiceAfterConnectFailure = false;
107:
108:            private QName portQName;
109:
110:            private Remote portStub;
111:
112:            private final Object preparationMonitor = new Object();
113:
114:            /**
115:             * Set a reference to an existing JAX-RPC Service instance,
116:             * for example obtained via {@link org.springframework.jndi.JndiObjectFactoryBean}.
117:             * If not set, {@link LocalJaxRpcServiceFactory}'s properties have to be specified.
118:             * @see #setServiceFactoryClass
119:             * @see #setWsdlDocumentUrl
120:             * @see #setNamespaceUri
121:             * @see #setServiceName
122:             * @see org.springframework.jndi.JndiObjectFactoryBean
123:             */
124:            public void setJaxRpcService(Service jaxRpcService) {
125:                this .jaxRpcService = jaxRpcService;
126:            }
127:
128:            /**
129:             * Return a reference to an existing JAX-RPC Service instance, if any.
130:             */
131:            public Service getJaxRpcService() {
132:                return this .jaxRpcService;
133:            }
134:
135:            /**
136:             * Set the name of the port.
137:             * Corresponds to the "wsdl:port" name.
138:             */
139:            public void setPortName(String portName) {
140:                this .portName = portName;
141:            }
142:
143:            /**
144:             * Return the name of the port.
145:             */
146:            public String getPortName() {
147:                return this .portName;
148:            }
149:
150:            /**
151:             * Set the username to specify on the stub or call.
152:             * @see javax.xml.rpc.Stub#USERNAME_PROPERTY
153:             * @see javax.xml.rpc.Call#USERNAME_PROPERTY
154:             */
155:            public void setUsername(String username) {
156:                this .username = username;
157:            }
158:
159:            /**
160:             * Return the username to specify on the stub or call.
161:             */
162:            public String getUsername() {
163:                return this .username;
164:            }
165:
166:            /**
167:             * Set the password to specify on the stub or call.
168:             * @see javax.xml.rpc.Stub#PASSWORD_PROPERTY
169:             * @see javax.xml.rpc.Call#PASSWORD_PROPERTY
170:             */
171:            public void setPassword(String password) {
172:                this .password = password;
173:            }
174:
175:            /**
176:             * Return the password to specify on the stub or call.
177:             */
178:            public String getPassword() {
179:                return this .password;
180:            }
181:
182:            /**
183:             * Set the endpoint address to specify on the stub or call.
184:             * @see javax.xml.rpc.Stub#ENDPOINT_ADDRESS_PROPERTY
185:             * @see javax.xml.rpc.Call#setTargetEndpointAddress
186:             */
187:            public void setEndpointAddress(String endpointAddress) {
188:                this .endpointAddress = endpointAddress;
189:            }
190:
191:            /**
192:             * Return the endpoint address to specify on the stub or call.
193:             */
194:            public String getEndpointAddress() {
195:                return this .endpointAddress;
196:            }
197:
198:            /**
199:             * Set the maintain session flag to specify on the stub or call.
200:             * @see javax.xml.rpc.Stub#SESSION_MAINTAIN_PROPERTY
201:             * @see javax.xml.rpc.Call#SESSION_MAINTAIN_PROPERTY
202:             */
203:            public void setMaintainSession(boolean maintainSession) {
204:                this .maintainSession = maintainSession;
205:            }
206:
207:            /**
208:             * Return the maintain session flag to specify on the stub or call.
209:             */
210:            public boolean isMaintainSession() {
211:                return this .maintainSession;
212:            }
213:
214:            /**
215:             * Set custom properties to be set on the stub or call.
216:             * <p>Can be populated with a String "value" (parsed via PropertiesEditor)
217:             * or a "props" element in XML bean definitions.
218:             * @see javax.xml.rpc.Stub#_setProperty
219:             * @see javax.xml.rpc.Call#setProperty
220:             */
221:            public void setCustomProperties(Properties customProperties) {
222:                CollectionUtils.mergePropertiesIntoMap(customProperties,
223:                        this .customPropertyMap);
224:            }
225:
226:            /**
227:             * Set custom properties to be set on the stub or call.
228:             * <p>Can be populated with a "map" or "props" element in XML bean definitions.
229:             * @see javax.xml.rpc.Stub#_setProperty
230:             * @see javax.xml.rpc.Call#setProperty
231:             */
232:            public void setCustomPropertyMap(Map customProperties) {
233:                if (customProperties != null) {
234:                    Iterator it = customProperties.entrySet().iterator();
235:                    while (it.hasNext()) {
236:                        Map.Entry entry = (Map.Entry) it.next();
237:                        if (!(entry.getKey() instanceof  String)) {
238:                            throw new IllegalArgumentException(
239:                                    "Illegal property key [" + entry.getKey()
240:                                            + "]: only Strings allowed");
241:                        }
242:                        addCustomProperty((String) entry.getKey(), entry
243:                                .getValue());
244:                    }
245:                }
246:            }
247:
248:            /**
249:             * Allow Map access to the custom properties to be set on the stub
250:             * or call, with the option to add or override specific entries.
251:             * <p>Useful for specifying entries directly, for example via
252:             * "customPropertyMap[myKey]". This is particularly useful for
253:             * adding or overriding entries in child bean definitions.
254:             */
255:            public Map getCustomPropertyMap() {
256:                return this .customPropertyMap;
257:            }
258:
259:            /**
260:             * Add a custom property to this JAX-RPC Stub/Call.
261:             * @param name the name of the attribute to expose
262:             * @param value the attribute value to expose
263:             * @see javax.xml.rpc.Stub#_setProperty
264:             * @see javax.xml.rpc.Call#setProperty
265:             */
266:            public void addCustomProperty(String name, Object value) {
267:                this .customPropertyMap.put(name, value);
268:            }
269:
270:            /**
271:             * Set the interface of the service that this factory should create a proxy for.
272:             * This will typically be a non-RMI business interface, although you can also
273:             * use an RMI port interface as recommended by JAX-RPC here.
274:             * <p>Calls on the specified service interface will either be translated to the
275:             * underlying RMI port interface (in case of a "portInterface" being specified)
276:             * or to dynamic calls (using the JAX-RPC Dynamic Invocation Interface).
277:             * <p>The dynamic call mechanism has the advantage that you don't need to
278:             * maintain an RMI port interface in addition to an existing non-RMI business
279:             * interface. In terms of configuration, specifying the business interface
280:             * as "serviceInterface" will be enough; this interceptor will automatically
281:             * use dynamic calls in such a scenario.
282:             * @see javax.xml.rpc.Service#createCall
283:             * @see #setPortInterface
284:             */
285:            public void setServiceInterface(Class serviceInterface) {
286:                if (serviceInterface != null && !serviceInterface.isInterface()) {
287:                    throw new IllegalArgumentException(
288:                            "'serviceInterface' must be an interface");
289:                }
290:                this .serviceInterface = serviceInterface;
291:            }
292:
293:            /**
294:             * Return the interface of the service that this factory should create a proxy for.
295:             */
296:            public Class getServiceInterface() {
297:                return this .serviceInterface;
298:            }
299:
300:            /**
301:             * Set the JAX-RPC port interface to use. Only needs to be set if a JAX-RPC
302:             * port stub should be used instead of the dynamic call mechanism.
303:             * See the javadoc of the "serviceInterface" property for more details.
304:             * <p>The interface must be suitable for a JAX-RPC port, that is, it must be
305:             * an RMI service interface (that extends <code>java.rmi.Remote</code>).
306:             * <p><b>NOTE:</b> Check whether your JAX-RPC provider returns thread-safe
307:             * port stubs. If not, use the dynamic call mechanism instead, which will
308:             * always be thread-safe. In particular, do not use JAX-RPC port stubs
309:             * with Apache Axis, whose port stubs are known to be non-thread-safe.
310:             * @see javax.xml.rpc.Service#getPort
311:             * @see java.rmi.Remote
312:             * @see #setServiceInterface
313:             */
314:            public void setPortInterface(Class portInterface) {
315:                if (portInterface != null
316:                        && (!portInterface.isInterface() || !Remote.class
317:                                .isAssignableFrom(portInterface))) {
318:                    throw new IllegalArgumentException(
319:                            "'portInterface' must be an interface derived from [java.rmi.Remote]");
320:                }
321:                this .portInterface = portInterface;
322:            }
323:
324:            /**
325:             * Return the JAX-RPC port interface to use.
326:             */
327:            public Class getPortInterface() {
328:                return this .portInterface;
329:            }
330:
331:            /**
332:             * Set whether to look up the JAX-RPC service on startup.
333:             * <p>Default is "true". Turn this flag off to allow for late start
334:             * of the target server. In this case, the JAX-RPC service will be
335:             * lazily fetched on first access.
336:             */
337:            public void setLookupServiceOnStartup(boolean lookupServiceOnStartup) {
338:                this .lookupServiceOnStartup = lookupServiceOnStartup;
339:            }
340:
341:            /**
342:             * Set whether to refresh the JAX-RPC service on connect failure,
343:             * that is, whenever a JAX-RPC invocation throws a RemoteException.
344:             * <p>Default is "false", keeping a reference to the JAX-RPC service
345:             * in any case, retrying the next invocation on the same service
346:             * even in case of failure. Turn this flag on to reinitialize the
347:             * entire service in case of connect failures.
348:             */
349:            public void setRefreshServiceAfterConnectFailure(
350:                    boolean refreshServiceAfterConnectFailure) {
351:                this .refreshServiceAfterConnectFailure = refreshServiceAfterConnectFailure;
352:            }
353:
354:            /**
355:             * Prepares the JAX-RPC service and port if the "lookupServiceOnStartup"
356:             * is turned on (which it is by default).
357:             */
358:            public void afterPropertiesSet() {
359:                if (this .lookupServiceOnStartup) {
360:                    prepare();
361:                }
362:            }
363:
364:            /**
365:             * Create and initialize the JAX-RPC service for the specified port.
366:             * <p>Prepares a JAX-RPC stub if possible (if an RMI interface is available);
367:             * falls back to JAX-RPC dynamic calls else. Using dynamic calls can be enforced
368:             * through overriding {@link #alwaysUseJaxRpcCall} to return <code>true</code>.
369:             * <p>{@link #postProcessJaxRpcService} and {@link #postProcessPortStub}
370:             * hooks are available for customization in subclasses. When using dynamic calls,
371:             * each can be post-processed via {@link #postProcessJaxRpcCall}.
372:             * @throws RemoteLookupFailureException if service initialization or port stub creation failed
373:             */
374:            public void prepare() throws RemoteLookupFailureException {
375:                if (getPortName() == null) {
376:                    throw new IllegalArgumentException(
377:                            "Property 'portName' is required");
378:                }
379:
380:                synchronized (this .preparationMonitor) {
381:                    this .serviceToUse = null;
382:
383:                    // Cache the QName for the port.
384:                    this .portQName = getQName(getPortName());
385:
386:                    try {
387:                        Service service = getJaxRpcService();
388:                        if (service == null) {
389:                            service = createJaxRpcService();
390:                        } else {
391:                            postProcessJaxRpcService(service);
392:                        }
393:
394:                        Class portInterface = getPortInterface();
395:                        if (portInterface != null && !alwaysUseJaxRpcCall()) {
396:                            // JAX-RPC-compliant port interface -> using JAX-RPC stub for port.
397:
398:                            if (logger.isDebugEnabled()) {
399:                                logger
400:                                        .debug("Creating JAX-RPC proxy for JAX-RPC port ["
401:                                                + this .portQName
402:                                                + "], using port interface ["
403:                                                + portInterface.getName() + "]");
404:                            }
405:                            Remote remoteObj = service.getPort(this .portQName,
406:                                    portInterface);
407:
408:                            if (logger.isDebugEnabled()) {
409:                                Class serviceInterface = getServiceInterface();
410:                                if (serviceInterface != null) {
411:                                    boolean isImpl = serviceInterface
412:                                            .isInstance(remoteObj);
413:                                    logger.debug("Using service interface ["
414:                                            + serviceInterface.getName()
415:                                            + "] for JAX-RPC port ["
416:                                            + this .portQName + "] - "
417:                                            + (!isImpl ? "not" : "")
418:                                            + " directly implemented");
419:                                }
420:                            }
421:
422:                            if (!(remoteObj instanceof  Stub)) {
423:                                throw new RemoteLookupFailureException(
424:                                        "Port stub of class ["
425:                                                + remoteObj.getClass()
426:                                                        .getName()
427:                                                + "] is not a valid JAX-RPC stub: it does not implement interface [javax.xml.rpc.Stub]");
428:                            }
429:                            Stub stub = (Stub) remoteObj;
430:
431:                            // Apply properties to JAX-RPC stub.
432:                            preparePortStub(stub);
433:
434:                            // Allow for custom post-processing in subclasses.
435:                            postProcessPortStub(stub);
436:
437:                            this .portStub = remoteObj;
438:                        }
439:
440:                        else {
441:                            // No JAX-RPC-compliant port interface -> using JAX-RPC dynamic calls.
442:                            if (logger.isDebugEnabled()) {
443:                                logger
444:                                        .debug("Using JAX-RPC dynamic calls for JAX-RPC port ["
445:                                                + this .portQName + "]");
446:                            }
447:                        }
448:
449:                        this .serviceToUse = service;
450:                    } catch (ServiceException ex) {
451:                        throw new RemoteLookupFailureException(
452:                                "Failed to initialize service for JAX-RPC port ["
453:                                        + this .portQName + "]", ex);
454:                    }
455:                }
456:            }
457:
458:            /**
459:             * Return whether to always use JAX-RPC dynamic calls.
460:             * Called by <code>afterPropertiesSet</code>.
461:             * <p>Default is "false"; if an RMI interface is specified as "portInterface"
462:             * or "serviceInterface", it will be used to create a JAX-RPC port stub.
463:             * <p>Can be overridden to enforce the use of the JAX-RPC Call API,
464:             * for example if there is a need to customize at the Call level.
465:             * This just necessary if you you want to use an RMI interface as
466:             * "serviceInterface", though; in case of only a non-RMI interface being
467:             * available, this interceptor will fall back to the Call API anyway.
468:             * @see #postProcessJaxRpcCall
469:             */
470:            protected boolean alwaysUseJaxRpcCall() {
471:                return false;
472:            }
473:
474:            /**
475:             * Reset the prepared service of this interceptor,
476:             * allowing for reinitialization on next access.
477:             */
478:            protected void reset() {
479:                synchronized (this .preparationMonitor) {
480:                    this .serviceToUse = null;
481:                }
482:            }
483:
484:            /**
485:             * Return whether this client interceptor has already been prepared,
486:             * i.e. has already looked up the JAX-RPC service and port.
487:             */
488:            protected boolean isPrepared() {
489:                synchronized (this .preparationMonitor) {
490:                    return (this .serviceToUse != null);
491:                }
492:            }
493:
494:            /**
495:             * Return the prepared QName for the port.
496:             * @see #setPortName
497:             * @see #getQName
498:             */
499:            protected final QName getPortQName() {
500:                return this .portQName;
501:            }
502:
503:            /**
504:             * Prepare the given JAX-RPC port stub, applying properties to it.
505:             * Called by {@link #afterPropertiesSet}.
506:             * <p>Just applied when actually creating a JAX-RPC port stub, in case of a
507:             * compliant port interface. Else, JAX-RPC dynamic calls will be used.
508:             * @param stub the current JAX-RPC port stub
509:             * @see #setUsername
510:             * @see #setPassword
511:             * @see #setEndpointAddress
512:             * @see #setMaintainSession
513:             * @see #setCustomProperties
514:             * @see #setPortInterface
515:             * @see #prepareJaxRpcCall
516:             */
517:            protected void preparePortStub(Stub stub) {
518:                String username = getUsername();
519:                if (username != null) {
520:                    stub._setProperty(Stub.USERNAME_PROPERTY, username);
521:                }
522:                String password = getPassword();
523:                if (password != null) {
524:                    stub._setProperty(Stub.PASSWORD_PROPERTY, password);
525:                }
526:                String endpointAddress = getEndpointAddress();
527:                if (endpointAddress != null) {
528:                    stub._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY,
529:                            endpointAddress);
530:                }
531:                if (isMaintainSession()) {
532:                    stub._setProperty(Stub.SESSION_MAINTAIN_PROPERTY,
533:                            Boolean.TRUE);
534:                }
535:                if (this .customPropertyMap != null) {
536:                    for (Iterator it = this .customPropertyMap.keySet()
537:                            .iterator(); it.hasNext();) {
538:                        String key = (String) it.next();
539:                        stub._setProperty(key, this .customPropertyMap.get(key));
540:                    }
541:                }
542:            }
543:
544:            /**
545:             * Post-process the given JAX-RPC port stub. Called by {@link #prepare}.
546:             * <p>The default implementation is empty.
547:             * <p>Just applied when actually creating a JAX-RPC port stub, in case of a
548:             * compliant port interface. Else, JAX-RPC dynamic calls will be used.
549:             * @param stub the current JAX-RPC port stub
550:             * (can be cast to an implementation-specific class if necessary)
551:             * @see #setPortInterface
552:             * @see #postProcessJaxRpcCall
553:             */
554:            protected void postProcessPortStub(Stub stub) {
555:            }
556:
557:            /**
558:             * Return the underlying JAX-RPC port stub that this interceptor delegates to
559:             * for each method invocation on the proxy.
560:             */
561:            protected Remote getPortStub() {
562:                return this .portStub;
563:            }
564:
565:            /**
566:             * Translates the method invocation into a JAX-RPC service invocation.
567:             * <p>Prepares the service on the fly, if necessary, in case of lazy
568:             * lookup or a connect failure having happened.
569:             * @see #prepare()
570:             * @see #doInvoke
571:             */
572:            public Object invoke(MethodInvocation invocation) throws Throwable {
573:                if (AopUtils.isToStringMethod(invocation.getMethod())) {
574:                    return "JAX-RPC proxy for port [" + getPortName()
575:                            + "] of service [" + getServiceName() + "]";
576:                }
577:                // Lazily prepare service and stub if necessary.
578:                synchronized (this .preparationMonitor) {
579:                    if (!isPrepared()) {
580:                        prepare();
581:                    }
582:                }
583:                return doInvoke(invocation);
584:            }
585:
586:            /**
587:             * Perform a JAX-RPC service invocation based on the given method invocation.
588:             * <p>Uses traditional RMI stub invocation if a JAX-RPC port stub is available;
589:             * falls back to JAX-RPC dynamic calls else.
590:             * @param invocation the AOP method invocation
591:             * @return the invocation result, if any
592:             * @throws Throwable in case of invocation failure
593:             * @see #getPortStub()
594:             * @see #doInvoke(org.aopalliance.intercept.MethodInvocation, java.rmi.Remote)
595:             * @see #performJaxRpcCall(org.aopalliance.intercept.MethodInvocation, javax.xml.rpc.Service)
596:             */
597:            protected Object doInvoke(MethodInvocation invocation)
598:                    throws Throwable {
599:                Remote stub = getPortStub();
600:                try {
601:                    if (stub != null) {
602:                        // JAX-RPC port stub available -> traditional RMI stub invocation.
603:                        if (logger.isTraceEnabled()) {
604:                            logger.trace("Invoking operation '"
605:                                    + invocation.getMethod().getName()
606:                                    + "' on JAX-RPC port stub");
607:                        }
608:                        return doInvoke(invocation, stub);
609:                    } else {
610:                        // No JAX-RPC stub -> using JAX-RPC dynamic calls.
611:                        if (logger.isTraceEnabled()) {
612:                            logger.trace("Invoking operation '"
613:                                    + invocation.getMethod().getName()
614:                                    + "' as JAX-RPC dynamic call");
615:                        }
616:                        return performJaxRpcCall(invocation, this .serviceToUse);
617:                    }
618:                } catch (RemoteException ex) {
619:                    throw handleRemoteException(invocation.getMethod(), ex);
620:                } catch (SOAPFaultException ex) {
621:                    throw new JaxRpcSoapFaultException(ex);
622:                } catch (JAXRPCException ex) {
623:                    throw new RemoteProxyFailureException(
624:                            "Invalid JAX-RPC call configuration", ex);
625:                }
626:            }
627:
628:            /**
629:             * Perform a JAX-RPC service invocation on the given port stub.
630:             * @param invocation the AOP method invocation
631:             * @param portStub the RMI port stub to invoke
632:             * @return the invocation result, if any
633:             * @throws Throwable in case of invocation failure
634:             * @see #getPortStub()
635:             * @see #doInvoke(org.aopalliance.intercept.MethodInvocation, java.rmi.Remote)
636:             * @see #performJaxRpcCall
637:             */
638:            protected Object doInvoke(MethodInvocation invocation,
639:                    Remote portStub) throws Throwable {
640:                try {
641:                    return RmiClientInterceptorUtils.doInvoke(invocation,
642:                            portStub);
643:                } catch (InvocationTargetException ex) {
644:                    throw ex.getTargetException();
645:                }
646:            }
647:
648:            /**
649:             * Perform a JAX-RPC dynamic call for the given AOP method invocation.
650:             * Delegates to {@link #prepareJaxRpcCall} and
651:             * {@link #postProcessJaxRpcCall} for setting up the call object.
652:             * <p>The default implementation uses method name as JAX-RPC operation name
653:             * and method arguments as arguments for the JAX-RPC call. Can be
654:             * overridden in subclasses for custom operation names and/or arguments.
655:             * @param invocation the current AOP MethodInvocation that should
656:             * be converted to a JAX-RPC call
657:             * @param service the JAX-RPC Service to use for the call
658:             * @return the return value of the invocation, if any
659:             * @throws Throwable the exception thrown by the invocation, if any
660:             * @see #prepareJaxRpcCall
661:             * @see #postProcessJaxRpcCall
662:             */
663:            protected Object performJaxRpcCall(MethodInvocation invocation,
664:                    Service service) throws Throwable {
665:                Method method = invocation.getMethod();
666:                QName portQName = this .portQName;
667:
668:                // Create JAX-RPC call object, using the method name as operation name.
669:                // Synchronized because of non-thread-safe Axis implementation!
670:                Call call = null;
671:                synchronized (service) {
672:                    call = service.createCall(portQName, method.getName());
673:                }
674:
675:                // Apply properties to JAX-RPC stub.
676:                prepareJaxRpcCall(call);
677:
678:                // Allow for custom post-processing in subclasses.
679:                postProcessJaxRpcCall(call, invocation);
680:
681:                // Perform actual invocation.
682:                return call.invoke(invocation.getArguments());
683:            }
684:
685:            /**
686:             * Prepare the given JAX-RPC call, applying properties to it. Called by {@link #invoke}.
687:             * <p>Just applied when actually using JAX-RPC dynamic calls, i.e. if no compliant
688:             * port interface was specified. Else, a JAX-RPC port stub will be used.
689:             * @param call the current JAX-RPC call object
690:             * @see #setUsername
691:             * @see #setPassword
692:             * @see #setEndpointAddress
693:             * @see #setMaintainSession
694:             * @see #setCustomProperties
695:             * @see #setPortInterface
696:             * @see #preparePortStub
697:             */
698:            protected void prepareJaxRpcCall(Call call) {
699:                String username = getUsername();
700:                if (username != null) {
701:                    call.setProperty(Call.USERNAME_PROPERTY, username);
702:                }
703:                String password = getPassword();
704:                if (password != null) {
705:                    call.setProperty(Call.PASSWORD_PROPERTY, password);
706:                }
707:                String endpointAddress = getEndpointAddress();
708:                if (endpointAddress != null) {
709:                    call.setTargetEndpointAddress(endpointAddress);
710:                }
711:                if (isMaintainSession()) {
712:                    call.setProperty(Call.SESSION_MAINTAIN_PROPERTY,
713:                            Boolean.TRUE);
714:                }
715:                if (this .customPropertyMap != null) {
716:                    for (Iterator it = this .customPropertyMap.keySet()
717:                            .iterator(); it.hasNext();) {
718:                        String key = (String) it.next();
719:                        call.setProperty(key, this .customPropertyMap.get(key));
720:                    }
721:                }
722:            }
723:
724:            /**
725:             * Post-process the given JAX-RPC call. Called by {@link #invoke}.
726:             * <p>The default implementation is empty.
727:             * <p>Just applied when actually using JAX-RPC dynamic calls, i.e. if no compliant
728:             * port interface was specified. Else, a JAX-RPC port stub will be used.
729:             * @param call the current JAX-RPC call object
730:             * (can be cast to an implementation-specific class if necessary)
731:             * @param invocation the current AOP MethodInvocation that the call was
732:             * created for (can be used to check method name, method parameters
733:             * and/or passed-in arguments)
734:             * @see #setPortInterface
735:             * @see #postProcessPortStub
736:             */
737:            protected void postProcessJaxRpcCall(Call call,
738:                    MethodInvocation invocation) {
739:            }
740:
741:            /**
742:             * Handle the given RemoteException that was thrown from a JAX-RPC port stub
743:             * or JAX-RPC call invocation.
744:             * @param method the service interface method that we invoked
745:             * @param ex the original RemoteException
746:             * @return the exception to rethrow (may be the original RemoteException
747:             * or an extracted/wrapped exception, but never <code>null</code>)
748:             */
749:            protected Throwable handleRemoteException(Method method,
750:                    RemoteException ex) {
751:                boolean isConnectFailure = isConnectFailure(ex);
752:                if (isConnectFailure && this .refreshServiceAfterConnectFailure) {
753:                    reset();
754:                }
755:                Throwable cause = ex.getCause();
756:                if (cause != null
757:                        && ReflectionUtils.declaresException(method, cause
758:                                .getClass())) {
759:                    if (logger.isDebugEnabled()) {
760:                        logger.debug("Rethrowing wrapped exception of type ["
761:                                + cause.getClass().getName() + "] as-is");
762:                    }
763:                    // Declared on the service interface: probably a wrapped business exception.
764:                    return ex.getCause();
765:                } else {
766:                    // Throw either a RemoteAccessException or the original RemoteException,
767:                    // depending on what the service interface declares.
768:                    return RmiClientInterceptorUtils.convertRmiAccessException(
769:                            method, ex, isConnectFailure, portQName.toString());
770:                }
771:            }
772:
773:            /**
774:             * Determine whether the given RMI exception indicates a connect failure.
775:             * <p>The default implementation returns <code>true</code> unless the
776:             * exception class name (or exception superclass name) contains the term
777:             * "Fault" (e.g. "AxisFault"), assuming that the JAX-RPC provider only
778:             * throws RemoteException in case of WSDL faults and connect failures.
779:             * @param ex the RMI exception to check
780:             * @return whether the exception should be treated as connect failure
781:             * @see org.springframework.remoting.rmi.RmiClientInterceptorUtils#isConnectFailure
782:             */
783:            protected boolean isConnectFailure(RemoteException ex) {
784:                return (ex.getClass().getName().indexOf("Fault") == -1 && ex
785:                        .getClass().getSuperclass().getName().indexOf("Fault") == -1);
786:            }
787:
788:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.