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