Browse Source

Removed JAX-RPC support

pull/263/head
Juergen Hoeller 12 years ago
parent
commit
f1258a6a02
  1. 749
      spring-web/src/main/java/org/springframework/remoting/jaxrpc/JaxRpcPortClientInterceptor.java
  2. 90
      spring-web/src/main/java/org/springframework/remoting/jaxrpc/JaxRpcPortProxyFactoryBean.java
  3. 47
      spring-web/src/main/java/org/springframework/remoting/jaxrpc/JaxRpcServicePostProcessor.java
  4. 72
      spring-web/src/main/java/org/springframework/remoting/jaxrpc/JaxRpcSoapFaultException.java
  5. 323
      spring-web/src/main/java/org/springframework/remoting/jaxrpc/LocalJaxRpcServiceFactory.java
  6. 64
      spring-web/src/main/java/org/springframework/remoting/jaxrpc/LocalJaxRpcServiceFactoryBean.java
  7. 151
      spring-web/src/main/java/org/springframework/remoting/jaxrpc/ServletEndpointSupport.java
  8. 11
      spring-web/src/main/java/org/springframework/remoting/jaxrpc/package-info.java
  9. 644
      spring-web/src/test/java/org/springframework/remoting/jaxrpc/JaxRpcSupportTests.java
  10. 292
      src/reference/docbook/remoting.xml

749
spring-web/src/main/java/org/springframework/remoting/jaxrpc/JaxRpcPortClientInterceptor.java

@ -1,749 +0,0 @@ @@ -1,749 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.remoting.jaxrpc;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.Stub;
import javax.xml.rpc.soap.SOAPFaultException;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.remoting.RemoteLookupFailureException;
import org.springframework.remoting.RemoteProxyFailureException;
import org.springframework.remoting.rmi.RmiClientInterceptorUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
/**
* {@link org.aopalliance.intercept.MethodInterceptor} for accessing a specific port
* of a JAX-RPC service. Uses either {@link LocalJaxRpcServiceFactory}'s facilities
* underneath or takes an explicit reference to an existing JAX-RPC Service instance
* (e.g. obtained via a {@link org.springframework.jndi.JndiObjectFactoryBean}).
*
* <p>Allows to set JAX-RPC's standard stub properties directly, via the
* "username", "password", "endpointAddress" and "maintainSession" properties.
* For typical usage, it is not necessary to specify those.
*
* <p>In standard JAX-RPC style, this invoker is used with an RMI service interface.
* Alternatively, this invoker can also proxy a JAX-RPC service with a matching
* non-RMI business interface, that is, an interface that declares the service methods
* without RemoteExceptions. In the latter case, RemoteExceptions thrown by JAX-RPC
* will automatically get converted to Spring's unchecked RemoteAccessException.
*
* <p>Setting "serviceInterface" is usually sufficient: The invoker will automatically
* use JAX-RPC "dynamic invocations" via the Call API in this case, no matter whether
* the specified interface is an RMI or non-RMI interface. Alternatively, a corresponding
* JAX-RPC port interface can be specified as "portInterface", which will turn this
* invoker into "static invocation" mode (operating on a standard JAX-RPC port stub).
*
* @author Juergen Hoeller
* @since 15.12.2003
* @see #setPortName
* @see #setServiceInterface
* @see #setPortInterface
* @see javax.xml.rpc.Service#createCall
* @see javax.xml.rpc.Service#getPort
* @see org.springframework.remoting.RemoteAccessException
* @see org.springframework.jndi.JndiObjectFactoryBean
* @deprecated in favor of JAX-WS support in {@code org.springframework.remoting.jaxws}
*/
@Deprecated
public class JaxRpcPortClientInterceptor extends LocalJaxRpcServiceFactory
implements MethodInterceptor, InitializingBean {
private Service jaxRpcService;
private Service serviceToUse;
private String portName;
private String username;
private String password;
private String endpointAddress;
private boolean maintainSession;
/** Map of custom properties, keyed by property name (String) */
private final Map<String, Object> customPropertyMap = new HashMap<String, Object>();
private Class serviceInterface;
private Class portInterface;
private boolean lookupServiceOnStartup = true;
private boolean refreshServiceAfterConnectFailure = false;
private QName portQName;
private Remote portStub;
private final Object preparationMonitor = new Object();
/**
* Set a reference to an existing JAX-RPC Service instance,
* for example obtained via {@link org.springframework.jndi.JndiObjectFactoryBean}.
* If not set, {@link LocalJaxRpcServiceFactory}'s properties have to be specified.
* @see #setServiceFactoryClass
* @see #setWsdlDocumentUrl
* @see #setNamespaceUri
* @see #setServiceName
* @see org.springframework.jndi.JndiObjectFactoryBean
*/
public void setJaxRpcService(Service jaxRpcService) {
this.jaxRpcService = jaxRpcService;
}
/**
* Return a reference to an existing JAX-RPC Service instance, if any.
*/
public Service getJaxRpcService() {
return this.jaxRpcService;
}
/**
* Set the name of the port.
* Corresponds to the "wsdl:port" name.
*/
public void setPortName(String portName) {
this.portName = portName;
}
/**
* Return the name of the port.
*/
public String getPortName() {
return this.portName;
}
/**
* Set the username to specify on the stub or call.
* @see javax.xml.rpc.Stub#USERNAME_PROPERTY
* @see javax.xml.rpc.Call#USERNAME_PROPERTY
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Return the username to specify on the stub or call.
*/
public String getUsername() {
return this.username;
}
/**
* Set the password to specify on the stub or call.
* @see javax.xml.rpc.Stub#PASSWORD_PROPERTY
* @see javax.xml.rpc.Call#PASSWORD_PROPERTY
*/
public void setPassword(String password) {
this.password = password;
}
/**
* Return the password to specify on the stub or call.
*/
public String getPassword() {
return this.password;
}
/**
* Set the endpoint address to specify on the stub or call.
* @see javax.xml.rpc.Stub#ENDPOINT_ADDRESS_PROPERTY
* @see javax.xml.rpc.Call#setTargetEndpointAddress
*/
public void setEndpointAddress(String endpointAddress) {
this.endpointAddress = endpointAddress;
}
/**
* Return the endpoint address to specify on the stub or call.
*/
public String getEndpointAddress() {
return this.endpointAddress;
}
/**
* Set the maintain session flag to specify on the stub or call.
* @see javax.xml.rpc.Stub#SESSION_MAINTAIN_PROPERTY
* @see javax.xml.rpc.Call#SESSION_MAINTAIN_PROPERTY
*/
public void setMaintainSession(boolean maintainSession) {
this.maintainSession = maintainSession;
}
/**
* Return the maintain session flag to specify on the stub or call.
*/
public boolean isMaintainSession() {
return this.maintainSession;
}
/**
* Set custom properties to be set on the stub or call.
* <p>Can be populated with a String "value" (parsed via PropertiesEditor)
* or a "props" element in XML bean definitions.
* @see javax.xml.rpc.Stub#_setProperty
* @see javax.xml.rpc.Call#setProperty
*/
public void setCustomProperties(Properties customProperties) {
CollectionUtils.mergePropertiesIntoMap(customProperties, this.customPropertyMap);
}
/**
* Set custom properties to be set on the stub or call.
* <p>Can be populated with a "map" or "props" element in XML bean definitions.
* @see javax.xml.rpc.Stub#_setProperty
* @see javax.xml.rpc.Call#setProperty
*/
public void setCustomPropertyMap(Map<String, Object> customProperties) {
if (customProperties != null) {
for (Map.Entry<String, Object> entry : customProperties.entrySet()) {
addCustomProperty(entry.getKey(), entry.getValue());
}
}
}
/**
* Allow Map access to the custom properties to be set on the stub
* or call, with the option to add or override specific entries.
* <p>Useful for specifying entries directly, for example via
* "customPropertyMap[myKey]". This is particularly useful for
* adding or overriding entries in child bean definitions.
*/
public Map<String, Object> getCustomPropertyMap() {
return this.customPropertyMap;
}
/**
* Add a custom property to this JAX-RPC Stub/Call.
* @param name the name of the attribute to expose
* @param value the attribute value to expose
* @see javax.xml.rpc.Stub#_setProperty
* @see javax.xml.rpc.Call#setProperty
*/
public void addCustomProperty(String name, Object value) {
this.customPropertyMap.put(name, value);
}
/**
* Set the interface of the service that this factory should create a proxy for.
* This will typically be a non-RMI business interface, although you can also
* use an RMI port interface as recommended by JAX-RPC here.
* <p>Calls on the specified service interface will either be translated to the
* underlying RMI port interface (in case of a "portInterface" being specified)
* or to dynamic calls (using the JAX-RPC Dynamic Invocation Interface).
* <p>The dynamic call mechanism has the advantage that you don't need to
* maintain an RMI port interface in addition to an existing non-RMI business
* interface. In terms of configuration, specifying the business interface
* as "serviceInterface" will be enough; this interceptor will automatically
* use dynamic calls in such a scenario.
* @see javax.xml.rpc.Service#createCall
* @see #setPortInterface
*/
public void setServiceInterface(Class serviceInterface) {
if (serviceInterface != null && !serviceInterface.isInterface()) {
throw new IllegalArgumentException("'serviceInterface' must be an interface");
}
this.serviceInterface = serviceInterface;
}
/**
* Return the interface of the service that this factory should create a proxy for.
*/
public Class getServiceInterface() {
return this.serviceInterface;
}
/**
* Set the JAX-RPC port interface to use. Only needs to be set if a JAX-RPC
* port stub should be used instead of the dynamic call mechanism.
* See the javadoc of the "serviceInterface" property for more details.
* <p>The interface must be suitable for a JAX-RPC port, that is, it must be
* an RMI service interface (that extends {@code java.rmi.Remote}).
* <p><b>NOTE:</b> Check whether your JAX-RPC provider returns thread-safe
* port stubs. If not, use the dynamic call mechanism instead, which will
* always be thread-safe. In particular, do not use JAX-RPC port stubs
* with Apache Axis, whose port stubs are known to be non-thread-safe.
* @see javax.xml.rpc.Service#getPort
* @see java.rmi.Remote
* @see #setServiceInterface
*/
public void setPortInterface(Class portInterface) {
if (portInterface != null &&
(!portInterface.isInterface() || !Remote.class.isAssignableFrom(portInterface))) {
throw new IllegalArgumentException(
"'portInterface' must be an interface derived from [java.rmi.Remote]");
}
this.portInterface = portInterface;
}
/**
* Return the JAX-RPC port interface to use.
*/
public Class getPortInterface() {
return this.portInterface;
}
/**
* Set whether to look up the JAX-RPC service on startup.
* <p>Default is "true". Turn this flag off to allow for late start
* of the target server. In this case, the JAX-RPC service will be
* lazily fetched on first access.
*/
public void setLookupServiceOnStartup(boolean lookupServiceOnStartup) {
this.lookupServiceOnStartup = lookupServiceOnStartup;
}
/**
* Set whether to refresh the JAX-RPC service on connect failure,
* that is, whenever a JAX-RPC invocation throws a RemoteException.
* <p>Default is "false", keeping a reference to the JAX-RPC service
* in any case, retrying the next invocation on the same service
* even in case of failure. Turn this flag on to reinitialize the
* entire service in case of connect failures.
*/
public void setRefreshServiceAfterConnectFailure(boolean refreshServiceAfterConnectFailure) {
this.refreshServiceAfterConnectFailure = refreshServiceAfterConnectFailure;
}
/**
* Prepares the JAX-RPC service and port if the "lookupServiceOnStartup"
* is turned on (which it is by default).
*/
public void afterPropertiesSet() {
if (this.lookupServiceOnStartup) {
prepare();
}
}
/**
* Create and initialize the JAX-RPC service for the specified port.
* <p>Prepares a JAX-RPC stub if possible (if an RMI interface is available);
* falls back to JAX-RPC dynamic calls else. Using dynamic calls can be enforced
* through overriding {@link #alwaysUseJaxRpcCall} to return {@code true}.
* <p>{@link #postProcessJaxRpcService} and {@link #postProcessPortStub}
* hooks are available for customization in subclasses. When using dynamic calls,
* each can be post-processed via {@link #postProcessJaxRpcCall}.
* @throws RemoteLookupFailureException if service initialization or port stub creation failed
*/
public void prepare() throws RemoteLookupFailureException {
if (getPortName() == null) {
throw new IllegalArgumentException("Property 'portName' is required");
}
synchronized (this.preparationMonitor) {
this.serviceToUse = null;
// Cache the QName for the port.
this.portQName = getQName(getPortName());
try {
Service service = getJaxRpcService();
if (service == null) {
service = createJaxRpcService();
}
else {
postProcessJaxRpcService(service);
}
Class portInterface = getPortInterface();
if (portInterface != null && !alwaysUseJaxRpcCall()) {
// JAX-RPC-compliant port interface -> using JAX-RPC stub for port.
if (logger.isDebugEnabled()) {
logger.debug("Creating JAX-RPC proxy for JAX-RPC port [" + this.portQName +
"], using port interface [" + portInterface.getName() + "]");
}
Remote remoteObj = service.getPort(this.portQName, portInterface);
if (logger.isDebugEnabled()) {
Class serviceInterface = getServiceInterface();
if (serviceInterface != null) {
boolean isImpl = serviceInterface.isInstance(remoteObj);
logger.debug("Using service interface [" + serviceInterface.getName() + "] for JAX-RPC port [" +
this.portQName + "] - " + (!isImpl ? "not" : "") + " directly implemented");
}
}
if (!(remoteObj instanceof Stub)) {
throw new RemoteLookupFailureException("Port stub of class [" + remoteObj.getClass().getName() +
"] is not a valid JAX-RPC stub: it does not implement interface [javax.xml.rpc.Stub]");
}
Stub stub = (Stub) remoteObj;
// Apply properties to JAX-RPC stub.
preparePortStub(stub);
// Allow for custom post-processing in subclasses.
postProcessPortStub(stub);
this.portStub = remoteObj;
}
else {
// No JAX-RPC-compliant port interface -> using JAX-RPC dynamic calls.
if (logger.isDebugEnabled()) {
logger.debug("Using JAX-RPC dynamic calls for JAX-RPC port [" + this.portQName + "]");
}
}
this.serviceToUse = service;
}
catch (ServiceException ex) {
throw new RemoteLookupFailureException(
"Failed to initialize service for JAX-RPC port [" + this.portQName + "]", ex);
}
}
}
/**
* Return whether to always use JAX-RPC dynamic calls.
* Called by {@code afterPropertiesSet}.
* <p>Default is "false"; if an RMI interface is specified as "portInterface"
* or "serviceInterface", it will be used to create a JAX-RPC port stub.
* <p>Can be overridden to enforce the use of the JAX-RPC Call API,
* for example if there is a need to customize at the Call level.
* This just necessary if you you want to use an RMI interface as
* "serviceInterface", though; in case of only a non-RMI interface being
* available, this interceptor will fall back to the Call API anyway.
* @see #postProcessJaxRpcCall
*/
protected boolean alwaysUseJaxRpcCall() {
return false;
}
/**
* Reset the prepared service of this interceptor,
* allowing for reinitialization on next access.
*/
protected void reset() {
synchronized (this.preparationMonitor) {
this.serviceToUse = null;
}
}
/**
* Return whether this client interceptor has already been prepared,
* i.e. has already looked up the JAX-RPC service and port.
*/
protected boolean isPrepared() {
synchronized (this.preparationMonitor) {
return (this.serviceToUse != null);
}
}
/**
* Return the prepared QName for the port.
* @see #setPortName
* @see #getQName
*/
protected final QName getPortQName() {
return this.portQName;
}
/**
* Prepare the given JAX-RPC port stub, applying properties to it.
* Called by {@link #prepare}.
* <p>Just applied when actually creating a JAX-RPC port stub, in case of a
* compliant port interface. Else, JAX-RPC dynamic calls will be used.
* @param stub the current JAX-RPC port stub
* @see #setUsername
* @see #setPassword
* @see #setEndpointAddress
* @see #setMaintainSession
* @see #setCustomProperties
* @see #setPortInterface
* @see #prepareJaxRpcCall
*/
protected void preparePortStub(Stub stub) {
String username = getUsername();
if (username != null) {
stub._setProperty(Stub.USERNAME_PROPERTY, username);
}
String password = getPassword();
if (password != null) {
stub._setProperty(Stub.PASSWORD_PROPERTY, password);
}
String endpointAddress = getEndpointAddress();
if (endpointAddress != null) {
stub._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, endpointAddress);
}
if (isMaintainSession()) {
stub._setProperty(Stub.SESSION_MAINTAIN_PROPERTY, Boolean.TRUE);
}
if (this.customPropertyMap != null) {
for (Map.Entry<String, Object> entry : this.customPropertyMap.entrySet()) {
stub._setProperty(entry.getKey(), entry.getValue());
}
}
}
/**
* Post-process the given JAX-RPC port stub. Called by {@link #prepare}.
* <p>The default implementation is empty.
* <p>Just applied when actually creating a JAX-RPC port stub, in case of a
* compliant port interface. Else, JAX-RPC dynamic calls will be used.
* @param stub the current JAX-RPC port stub
* (can be cast to an implementation-specific class if necessary)
* @see #setPortInterface
* @see #postProcessJaxRpcCall
*/
protected void postProcessPortStub(Stub stub) {
}
/**
* Return the underlying JAX-RPC port stub that this interceptor delegates to
* for each method invocation on the proxy.
*/
protected Remote getPortStub() {
return this.portStub;
}
/**
* Translates the method invocation into a JAX-RPC service invocation.
* <p>Prepares the service on the fly, if necessary, in case of lazy
* lookup or a connect failure having happened.
* @see #prepare()
* @see #doInvoke
*/
public Object invoke(MethodInvocation invocation) throws Throwable {
if (AopUtils.isToStringMethod(invocation.getMethod())) {
return "JAX-RPC proxy for port [" + getPortName() + "] of service [" + getServiceName() + "]";
}
// Lazily prepare service and stub if necessary.
synchronized (this.preparationMonitor) {
if (!isPrepared()) {
prepare();
}
}
return doInvoke(invocation);
}
/**
* Perform a JAX-RPC service invocation based on the given method invocation.
* <p>Uses traditional RMI stub invocation if a JAX-RPC port stub is available;
* falls back to JAX-RPC dynamic calls else.
* @param invocation the AOP method invocation
* @return the invocation result, if any
* @throws Throwable in case of invocation failure
* @see #getPortStub()
* @see #doInvoke(org.aopalliance.intercept.MethodInvocation, java.rmi.Remote)
* @see #performJaxRpcCall(org.aopalliance.intercept.MethodInvocation, javax.xml.rpc.Service)
*/
protected Object doInvoke(MethodInvocation invocation) throws Throwable {
Remote stub = getPortStub();
try {
if (stub != null) {
// JAX-RPC port stub available -> traditional RMI stub invocation.
if (logger.isTraceEnabled()) {
logger.trace("Invoking operation '" + invocation.getMethod().getName() + "' on JAX-RPC port stub");
}
return doInvoke(invocation, stub);
}
else {
// No JAX-RPC stub -> using JAX-RPC dynamic calls.
if (logger.isTraceEnabled()) {
logger.trace("Invoking operation '" + invocation.getMethod().getName() + "' as JAX-RPC dynamic call");
}
return performJaxRpcCall(invocation, this.serviceToUse);
}
}
catch (RemoteException ex) {
throw handleRemoteException(invocation.getMethod(), ex);
}
catch (SOAPFaultException ex) {
throw new JaxRpcSoapFaultException(ex);
}
catch (JAXRPCException ex) {
throw new RemoteProxyFailureException("Invalid JAX-RPC call configuration", ex);
}
}
/**
* Perform a JAX-RPC service invocation on the given port stub.
* @param invocation the AOP method invocation
* @param portStub the RMI port stub to invoke
* @return the invocation result, if any
* @throws Throwable in case of invocation failure
* @see #getPortStub()
* @see #doInvoke(org.aopalliance.intercept.MethodInvocation, java.rmi.Remote)
* @see #performJaxRpcCall
*/
protected Object doInvoke(MethodInvocation invocation, Remote portStub) throws Throwable {
try {
return RmiClientInterceptorUtils.invokeRemoteMethod(invocation, portStub);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
/**
* Perform a JAX-RPC dynamic call for the given AOP method invocation.
* Delegates to {@link #prepareJaxRpcCall} and
* {@link #postProcessJaxRpcCall} for setting up the call object.
* <p>The default implementation uses method name as JAX-RPC operation name
* and method arguments as arguments for the JAX-RPC call. Can be
* overridden in subclasses for custom operation names and/or arguments.
* @param invocation the current AOP MethodInvocation that should
* be converted to a JAX-RPC call
* @param service the JAX-RPC Service to use for the call
* @return the return value of the invocation, if any
* @throws Throwable the exception thrown by the invocation, if any
* @see #prepareJaxRpcCall
* @see #postProcessJaxRpcCall
*/
protected Object performJaxRpcCall(MethodInvocation invocation, Service service) throws Throwable {
Method method = invocation.getMethod();
QName portQName = this.portQName;
// Create JAX-RPC call object, using the method name as operation name.
// Synchronized because of non-thread-safe Axis implementation!
Call call = null;
synchronized (service) {
call = service.createCall(portQName, method.getName());
}
// Apply properties to JAX-RPC stub.
prepareJaxRpcCall(call);
// Allow for custom post-processing in subclasses.
postProcessJaxRpcCall(call, invocation);
// Perform actual invocation.
return call.invoke(invocation.getArguments());
}
/**
* Prepare the given JAX-RPC call, applying properties to it. Called by {@link #invoke}.
* <p>Just applied when actually using JAX-RPC dynamic calls, i.e. if no compliant
* port interface was specified. Else, a JAX-RPC port stub will be used.
* @param call the current JAX-RPC call object
* @see #setUsername
* @see #setPassword
* @see #setEndpointAddress
* @see #setMaintainSession
* @see #setCustomProperties
* @see #setPortInterface
* @see #preparePortStub
*/
protected void prepareJaxRpcCall(Call call) {
String username = getUsername();
if (username != null) {
call.setProperty(Call.USERNAME_PROPERTY, username);
}
String password = getPassword();
if (password != null) {
call.setProperty(Call.PASSWORD_PROPERTY, password);
}
String endpointAddress = getEndpointAddress();
if (endpointAddress != null) {
call.setTargetEndpointAddress(endpointAddress);
}
if (isMaintainSession()) {
call.setProperty(Call.SESSION_MAINTAIN_PROPERTY, Boolean.TRUE);
}
if (this.customPropertyMap != null) {
for (Map.Entry<String, Object> entry : this.customPropertyMap.entrySet()) {
call.setProperty(entry.getKey(), entry.getValue());
}
}
}
/**
* Post-process the given JAX-RPC call. Called by {@link #invoke}.
* <p>The default implementation is empty.
* <p>Just applied when actually using JAX-RPC dynamic calls, i.e. if no compliant
* port interface was specified. Else, a JAX-RPC port stub will be used.
* @param call the current JAX-RPC call object
* (can be cast to an implementation-specific class if necessary)
* @param invocation the current AOP MethodInvocation that the call was
* created for (can be used to check method name, method parameters
* and/or passed-in arguments)
* @see #setPortInterface
* @see #postProcessPortStub
*/
protected void postProcessJaxRpcCall(Call call, MethodInvocation invocation) {
}
/**
* Handle the given RemoteException that was thrown from a JAX-RPC port stub
* or JAX-RPC call invocation.
* @param method the service interface method that we invoked
* @param ex the original RemoteException
* @return the exception to rethrow (may be the original RemoteException
* or an extracted/wrapped exception, but never {@code null})
*/
protected Throwable handleRemoteException(Method method, RemoteException ex) {
boolean isConnectFailure = isConnectFailure(ex);
if (isConnectFailure && this.refreshServiceAfterConnectFailure) {
reset();
}
Throwable cause = ex.getCause();
if (cause != null && ReflectionUtils.declaresException(method, cause.getClass())) {
if (logger.isDebugEnabled()) {
logger.debug("Rethrowing wrapped exception of type [" + cause.getClass().getName() + "] as-is");
}
// Declared on the service interface: probably a wrapped business exception.
return ex.getCause();
}
else {
// Throw either a RemoteAccessException or the original RemoteException,
// depending on what the service interface declares.
return RmiClientInterceptorUtils.convertRmiAccessException(
method, ex, isConnectFailure, this.portQName.toString());
}
}
/**
* Determine whether the given RMI exception indicates a connect failure.
* <p>The default implementation returns {@code true} unless the
* exception class name (or exception superclass name) contains the term
* "Fault" (e.g. "AxisFault"), assuming that the JAX-RPC provider only
* throws RemoteException in case of WSDL faults and connect failures.
* @param ex the RMI exception to check
* @return whether the exception should be treated as connect failure
* @see org.springframework.remoting.rmi.RmiClientInterceptorUtils#isConnectFailure
*/
protected boolean isConnectFailure(RemoteException ex) {
return (!ex.getClass().getName().contains("Fault") &&
!ex.getClass().getSuperclass().getName().contains("Fault"));
}
}

90
spring-web/src/main/java/org/springframework/remoting/jaxrpc/JaxRpcPortProxyFactoryBean.java

@ -1,90 +0,0 @@ @@ -1,90 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.remoting.jaxrpc;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.util.ClassUtils;
/**
* {@link FactoryBean} for a specific port of a JAX-RPC service.
* Exposes a proxy for the port, to be used for bean references.
* Inherits configuration properties from {@link JaxRpcPortClientInterceptor}.
*
* <p>This factory is typically used with an RMI service interface. Alternatively,
* this factory can also proxy a JAX-RPC service with a matching non-RMI business
* interface, i.e. an interface that mirrors the RMI service methods but does not
* declare RemoteExceptions. In the latter case, RemoteExceptions thrown by the
* JAX-RPC stub will automatically get converted to Spring's unchecked
* RemoteAccessException.
*
* <p>If exposing the JAX-RPC port interface (i.e. an RMI interface) directly,
* setting "serviceInterface" is sufficient. If exposing a non-RMI business
* interface, the business interface needs to be set as "serviceInterface",
* and the JAX-RPC port interface as "portInterface".
*
* @author Juergen Hoeller
* @since 15.12.2003
* @see #setServiceInterface
* @see #setPortInterface
* @see LocalJaxRpcServiceFactoryBean
* @deprecated in favor of JAX-WS support in {@code org.springframework.remoting.jaxws}
*/
@Deprecated
public class JaxRpcPortProxyFactoryBean extends JaxRpcPortClientInterceptor
implements FactoryBean<Object>, BeanClassLoaderAware {
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
private Object serviceProxy;
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
@Override
public void afterPropertiesSet() {
if (getServiceInterface() == null) {
// Use JAX-RPC port interface (a traditional RMI interface)
// as service interface if none explicitly specified.
if (getPortInterface() != null) {
setServiceInterface(getPortInterface());
}
else {
throw new IllegalArgumentException("Property 'serviceInterface' is required");
}
}
super.afterPropertiesSet();
this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(this.beanClassLoader);
}
public Object getObject() {
return this.serviceProxy;
}
public Class<?> getObjectType() {
return getServiceInterface();
}
public boolean isSingleton() {
return true;
}
}

47
spring-web/src/main/java/org/springframework/remoting/jaxrpc/JaxRpcServicePostProcessor.java

@ -1,47 +0,0 @@ @@ -1,47 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.remoting.jaxrpc;
import javax.xml.rpc.Service;
/**
* Callback interface for post-processing a JAX-RPC Service.
*
* <p>Implementations can be registered with {@link LocalJaxRpcServiceFactory}
* or one of its subclasses: {@link LocalJaxRpcServiceFactoryBean},
* {@link JaxRpcPortClientInterceptor}, or {@link JaxRpcPortProxyFactoryBean}.
*
* @author Juergen Hoeller
* @since 1.1.4
* @see LocalJaxRpcServiceFactory#setServicePostProcessors
* @see LocalJaxRpcServiceFactoryBean#setServicePostProcessors
* @see JaxRpcPortClientInterceptor#setServicePostProcessors
* @see JaxRpcPortProxyFactoryBean#setServicePostProcessors
* @see javax.xml.rpc.Service#getTypeMappingRegistry
* @deprecated in favor of JAX-WS support in {@code org.springframework.remoting.jaxws}
*/
@Deprecated
public interface JaxRpcServicePostProcessor {
/**
* Post-process the given JAX-RPC {@link Service}.
* @param service the current JAX-RPC {@code Service}
* (can be cast to an implementation-specific class if necessary)
*/
void postProcessJaxRpcService(Service service);
}

72
spring-web/src/main/java/org/springframework/remoting/jaxrpc/JaxRpcSoapFaultException.java

@ -1,72 +0,0 @@ @@ -1,72 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.remoting.jaxrpc;
import javax.xml.namespace.QName;
import javax.xml.rpc.soap.SOAPFaultException;
import org.springframework.remoting.soap.SoapFaultException;
/**
* Spring SoapFaultException adapter for the JAX-RPC
* {@link javax.xml.rpc.soap.SOAPFaultException} class.
*
* @author Juergen Hoeller
* @since 2.5
* @deprecated in favor of JAX-WS support in {@code org.springframework.remoting.jaxws}
*/
@Deprecated
@SuppressWarnings("serial")
public class JaxRpcSoapFaultException extends SoapFaultException {
/**
* Constructor for JaxRpcSoapFaultException.
* @param original the original JAX-RPC SOAPFaultException to wrap
*/
public JaxRpcSoapFaultException(SOAPFaultException original) {
super(original.getMessage(), original);
}
/**
* Return the wrapped JAX-RPC SOAPFaultException.
*/
public final SOAPFaultException getOriginalException() {
return (SOAPFaultException) getCause();
}
@Override
public String getFaultCode() {
return getOriginalException().getFaultCode().toString();
}
@Override
public QName getFaultCodeAsQName() {
return getOriginalException().getFaultCode();
}
@Override
public String getFaultString() {
return getOriginalException().getFaultString();
}
@Override
public String getFaultActor() {
return getOriginalException().getFaultActor();
}
}

323
spring-web/src/main/java/org/springframework/remoting/jaxrpc/LocalJaxRpcServiceFactory.java

@ -1,323 +0,0 @@ @@ -1,323 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.remoting.jaxrpc;
import java.net.URL;
import java.util.Properties;
import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.ServiceFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
/**
* Factory for locally defined JAX-RPC {@link javax.xml.rpc.Service} references.
* Uses a JAX-RPC {@link javax.xml.rpc.ServiceFactory} underneath.
*
* <p>Serves as base class for {@link LocalJaxRpcServiceFactoryBean} as well as
* {@link JaxRpcPortClientInterceptor} and {@link JaxRpcPortProxyFactoryBean}.
*
* @author Juergen Hoeller
* @since 15.12.2003
* @see javax.xml.rpc.ServiceFactory
* @see javax.xml.rpc.Service
* @see LocalJaxRpcServiceFactoryBean
* @see JaxRpcPortClientInterceptor
* @see JaxRpcPortProxyFactoryBean
* @deprecated in favor of JAX-WS support in {@code org.springframework.remoting.jaxws}
*/
@Deprecated
public class LocalJaxRpcServiceFactory {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
private ServiceFactory serviceFactory;
private Class serviceFactoryClass;
private URL wsdlDocumentUrl;
private String namespaceUri;
private String serviceName;
private Class jaxRpcServiceInterface;
private Properties jaxRpcServiceProperties;
private JaxRpcServicePostProcessor[] servicePostProcessors;
/**
* Set the ServiceFactory instance to use.
* <p>This is an alternative to the common "serviceFactoryClass" property,
* allowing for a pre-initialized ServiceFactory instance to be specified.
* @see #setServiceFactoryClass
*/
public void setServiceFactory(ServiceFactory serviceFactory) {
this.serviceFactory = serviceFactory;
}
/**
* Return the specified ServiceFactory instance, if any.
*/
public ServiceFactory getServiceFactory() {
return this.serviceFactory;
}
/**
* Set the ServiceFactory class to use, for example
* "org.apache.axis.client.ServiceFactory".
* <p>Does not need to be set if the JAX-RPC implementation has registered
* itself with the JAX-RPC system property "SERVICEFACTORY_PROPERTY".
* @see javax.xml.rpc.ServiceFactory
*/
public void setServiceFactoryClass(Class serviceFactoryClass) {
if (serviceFactoryClass != null && !ServiceFactory.class.isAssignableFrom(serviceFactoryClass)) {
throw new IllegalArgumentException("'serviceFactoryClass' must implement [javax.xml.rpc.ServiceFactory]");
}
this.serviceFactoryClass = serviceFactoryClass;
}
/**
* Return the ServiceFactory class to use, or {@code null} if default.
*/
public Class getServiceFactoryClass() {
return this.serviceFactoryClass;
}
/**
* Set the URL of the WSDL document that describes the service.
*/
public void setWsdlDocumentUrl(URL wsdlDocumentUrl) {
this.wsdlDocumentUrl = wsdlDocumentUrl;
}
/**
* Return the URL of the WSDL document that describes the service.
*/
public URL getWsdlDocumentUrl() {
return this.wsdlDocumentUrl;
}
/**
* Set the namespace URI of the service.
* Corresponds to the WSDL "targetNamespace".
*/
public void setNamespaceUri(String namespaceUri) {
this.namespaceUri = (namespaceUri != null ? namespaceUri.trim() : null);
}
/**
* Return the namespace URI of the service.
*/
public String getNamespaceUri() {
return this.namespaceUri;
}
/**
* Set the name of the service to look up.
* Corresponds to the "wsdl:service" name.
* @see javax.xml.rpc.ServiceFactory#createService(javax.xml.namespace.QName)
* @see javax.xml.rpc.ServiceFactory#createService(java.net.URL, javax.xml.namespace.QName)
* @see javax.xml.rpc.ServiceFactory#loadService(java.net.URL, javax.xml.namespace.QName, java.util.Properties)
*/
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
/**
* Return the name of the service.
*/
public String getServiceName() {
return this.serviceName;
}
/**
* Set the JAX-RPC service interface to use for looking up the service.
* If specified, this will override a "serviceName" setting.
* <p>The specified interface will usually be a generated JAX-RPC service
* interface that directly corresponds to the WSDL service declaration.
* Note that this is not a port interface or the application-level service
* interface to be exposed by a port proxy!
* <p>Only supported by JAX-RPC 1.1 providers.
* @see #setServiceName
* @see javax.xml.rpc.ServiceFactory#loadService(Class)
* @see javax.xml.rpc.ServiceFactory#loadService(java.net.URL, Class, java.util.Properties)
*/
public void setJaxRpcServiceInterface(Class jaxRpcServiceInterface) {
this.jaxRpcServiceInterface = jaxRpcServiceInterface;
}
/**
* Return the JAX-RPC service interface to use for looking up the service.
*/
public Class getJaxRpcServiceInterface() {
return this.jaxRpcServiceInterface;
}
/**
* Set JAX-RPC service properties to be passed to the ServiceFactory, if any.
* <p>Only supported by JAX-RPC 1.1 providers.
* @see javax.xml.rpc.ServiceFactory#loadService(java.net.URL, javax.xml.namespace.QName, java.util.Properties)
* @see javax.xml.rpc.ServiceFactory#loadService(java.net.URL, Class, java.util.Properties)
*/
public void setJaxRpcServiceProperties(Properties jaxRpcServiceProperties) {
this.jaxRpcServiceProperties = jaxRpcServiceProperties;
}
/**
* Return JAX-RPC service properties to be passed to the ServiceFactory, if any.
*/
public Properties getJaxRpcServiceProperties() {
return this.jaxRpcServiceProperties;
}
/**
* Set the JaxRpcServicePostProcessors to be applied to JAX-RPC Service
* instances created by this factory.
* <p>Such post-processors can, for example, register custom type mappings.
* They are reusable across all pre-built subclasses of this factory:
* LocalJaxRpcServiceFactoryBean, JaxRpcPortClientInterceptor,
* JaxRpcPortProxyFactoryBean.
* @see LocalJaxRpcServiceFactoryBean
* @see JaxRpcPortClientInterceptor
* @see JaxRpcPortProxyFactoryBean
*/
public void setServicePostProcessors(JaxRpcServicePostProcessor[] servicePostProcessors) {
this.servicePostProcessors = servicePostProcessors;
}
/**
* Return the JaxRpcServicePostProcessors to be applied to JAX-RPC Service
* instances created by this factory.
*/
public JaxRpcServicePostProcessor[] getServicePostProcessors() {
return this.servicePostProcessors;
}
/**
* Create a JAX-RPC Service according to the parameters of this factory.
* @see #setServiceName
* @see #setWsdlDocumentUrl
* @see #postProcessJaxRpcService
*/
public Service createJaxRpcService() throws ServiceException {
ServiceFactory serviceFactory = getServiceFactory();
if (serviceFactory == null) {
serviceFactory = createServiceFactory();
}
// Create service based on this factory's settings.
Service service = createService(serviceFactory);
// Allow for custom post-processing in subclasses.
postProcessJaxRpcService(service);
return service;
}
/**
* Return a QName for the given name, relative to the namespace URI
* of this factory, if given.
* @see #setNamespaceUri
*/
protected QName getQName(String name) {
return (getNamespaceUri() != null ? new QName(getNamespaceUri(), name) : new QName(name));
}
/**
* Create a JAX-RPC ServiceFactory, either of the specified class
* or the default.
* @throws ServiceException if thrown by JAX-RPC methods
* @see #setServiceFactoryClass
* @see javax.xml.rpc.ServiceFactory#newInstance()
*/
protected ServiceFactory createServiceFactory() throws ServiceException {
if (getServiceFactoryClass() != null) {
return (ServiceFactory) BeanUtils.instantiateClass(getServiceFactoryClass());
}
else {
return ServiceFactory.newInstance();
}
}
/**
* Actually create the JAX-RPC Service instance,
* based on this factory's settings.
* @param serviceFactory the JAX-RPC ServiceFactory to use
* @return the newly created JAX-RPC Service
* @throws ServiceException if thrown by JAX-RPC methods
* @see javax.xml.rpc.ServiceFactory#createService
* @see javax.xml.rpc.ServiceFactory#loadService
*/
protected Service createService(ServiceFactory serviceFactory) throws ServiceException {
if (getServiceName() == null && getJaxRpcServiceInterface() == null) {
throw new IllegalArgumentException("Either 'serviceName' or 'jaxRpcServiceInterface' is required");
}
if (getJaxRpcServiceInterface() != null) {
// Create service via generated JAX-RPC service interface.
// Only supported on JAX-RPC 1.1
if (getWsdlDocumentUrl() != null || getJaxRpcServiceProperties() != null) {
return serviceFactory.loadService(
getWsdlDocumentUrl(), getJaxRpcServiceInterface(), getJaxRpcServiceProperties());
}
return serviceFactory.loadService(getJaxRpcServiceInterface());
}
// Create service via specified JAX-RPC service name.
QName serviceQName = getQName(getServiceName());
if (getJaxRpcServiceProperties() != null) {
// Only supported on JAX-RPC 1.1
return serviceFactory.loadService(getWsdlDocumentUrl(), serviceQName, getJaxRpcServiceProperties());
}
if (getWsdlDocumentUrl() != null) {
return serviceFactory.createService(getWsdlDocumentUrl(), serviceQName);
}
return serviceFactory.createService(serviceQName);
}
/**
* Post-process the given JAX-RPC Service. Called by {@link #createJaxRpcService}.
* Useful, for example, to register custom type mappings.
* <p>The default implementation delegates to all registered
* {@link JaxRpcServicePostProcessor JaxRpcServicePostProcessors}.
* It is usually preferable to implement custom type mappings etc there rather
* than in a subclass of this factory, to allow for reuse of the post-processors.
* @param service the current JAX-RPC Service
* (can be cast to an implementation-specific class if necessary)
* @see #setServicePostProcessors
* @see javax.xml.rpc.Service#getTypeMappingRegistry()
*/
protected void postProcessJaxRpcService(Service service) {
JaxRpcServicePostProcessor[] postProcessors = getServicePostProcessors();
if (postProcessors != null) {
for (int i = 0; i < postProcessors.length; i++) {
postProcessors[i].postProcessJaxRpcService(service);
}
}
}
}

64
spring-web/src/main/java/org/springframework/remoting/jaxrpc/LocalJaxRpcServiceFactoryBean.java

@ -1,64 +0,0 @@ @@ -1,64 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.remoting.jaxrpc;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
/**
* {@link org.springframework.beans.factory.FactoryBean} for locally
* defined JAX-RPC Service references.
* Uses {@link LocalJaxRpcServiceFactory}'s facilities underneath.
*
* <p>Alternatively, JAX-RPC Service references can be looked up
* in the JNDI environment of the J2EE container.
*
* @author Juergen Hoeller
* @since 15.12.2003
* @see javax.xml.rpc.Service
* @see org.springframework.jndi.JndiObjectFactoryBean
* @see JaxRpcPortProxyFactoryBean
* @deprecated in favor of JAX-WS support in {@code org.springframework.remoting.jaxws}
*/
@Deprecated
public class LocalJaxRpcServiceFactoryBean extends LocalJaxRpcServiceFactory
implements FactoryBean<Service>, InitializingBean {
private Service service;
public void afterPropertiesSet() throws ServiceException {
this.service = createJaxRpcService();
}
public Service getObject() throws Exception {
return this.service;
}
public Class<? extends Service> getObjectType() {
return (this.service != null ? this.service.getClass() : Service.class);
}
public boolean isSingleton() {
return true;
}
}

151
spring-web/src/main/java/org/springframework/remoting/jaxrpc/ServletEndpointSupport.java

@ -1,151 +0,0 @@ @@ -1,151 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.remoting.jaxrpc;
import java.io.File;
import javax.servlet.ServletContext;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.server.ServiceLifecycle;
import javax.xml.rpc.server.ServletEndpointContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.util.WebUtils;
/**
* Convenience base class for JAX-RPC servlet endpoint implementations.
* Provides a reference to the current Spring application context,
* e.g. for bean lookup or resource loading.
*
* <p>The Web Service servlet needs to run in the same web application
* as the Spring context to allow for access to Spring's facilities.
* In case of Axis, copy the AxisServlet definition into your web.xml,
* and set up the endpoint in "server-config.wsdd" (or use the deploy tool).
*
* <p>This class does not extend
* {@link org.springframework.web.context.support.WebApplicationObjectSupport}
* to not expose any public setters. For some reason, Axis tries to
* resolve public setters in a special way...
*
* <p>JAX-RPC service endpoints are usually required to implement an
* RMI port interface. However, many JAX-RPC implementations accept plain
* service endpoint classes too, avoiding the need to maintain an RMI port
* interface in addition to an existing non-RMI business interface.
* Therefore, implementing the business interface will usually be sufficient.
*
* @author Juergen Hoeller
* @since 16.12.2003
* @see #init
* @see #getWebApplicationContext
* @deprecated in favor of JAX-WS support in {@code org.springframework.remoting.jaxws}
*/
@Deprecated
public abstract class ServletEndpointSupport implements ServiceLifecycle {
protected final Log logger = LogFactory.getLog(getClass());
private ServletEndpointContext servletEndpointContext;
private WebApplicationContext webApplicationContext;
private MessageSourceAccessor messageSourceAccessor;
/**
* Initialize this JAX-RPC servlet endpoint.
* Calls onInit after successful context initialization.
* @param context ServletEndpointContext
* @throws ServiceException if the context is not a ServletEndpointContext
* @see #onInit
*/
public final void init(Object context) throws ServiceException {
if (!(context instanceof ServletEndpointContext)) {
throw new ServiceException("ServletEndpointSupport needs ServletEndpointContext, not [" + context + "]");
}
this.servletEndpointContext = (ServletEndpointContext) context;
ServletContext servletContext = this.servletEndpointContext.getServletContext();
this.webApplicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
this.messageSourceAccessor = new MessageSourceAccessor(this.webApplicationContext);
onInit();
}
/**
* Return the current JAX-RPC ServletEndpointContext.
*/
protected final ServletEndpointContext getServletEndpointContext() {
return this.servletEndpointContext;
}
/**
* Return the current Spring ApplicationContext.
*/
protected final ApplicationContext getApplicationContext() {
return this.webApplicationContext;
}
/**
* Return the current Spring WebApplicationContext.
*/
protected final WebApplicationContext getWebApplicationContext() {
return this.webApplicationContext;
}
/**
* Return a MessageSourceAccessor for the application context
* used by this object, for easy message access.
*/
protected final MessageSourceAccessor getMessageSourceAccessor() {
return this.messageSourceAccessor;
}
/**
* Return the current ServletContext.
*/
protected final ServletContext getServletContext() {
return this.webApplicationContext.getServletContext();
}
/**
* Return the temporary directory for the current web application,
* as provided by the servlet container.
* @return the File representing the temporary directory
*/
protected final File getTempDir() {
return WebUtils.getTempDir(getServletContext());
}
/**
* Callback for custom initialization after the context has been set up.
* @throws ServiceException if initialization failed
*/
protected void onInit() throws ServiceException {
}
/**
* This implementation of destroy is empty.
* Can be overridden in subclasses.
*/
public void destroy() {
}
}

11
spring-web/src/main/java/org/springframework/remoting/jaxrpc/package-info.java

@ -1,11 +0,0 @@ @@ -1,11 +0,0 @@
/**
*
* Remoting classes for Web Services via JAX-RPC.
* This package provides proxy factories for accessing JAX-RPC
* services and ports, and a support class for implementing
* JAX-RPC Servlet endpoints.
*
*/
package org.springframework.remoting.jaxrpc;

644
spring-web/src/test/java/org/springframework/remoting/jaxrpc/JaxRpcSupportTests.java

@ -1,644 +0,0 @@ @@ -1,644 +0,0 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.remoting.jaxrpc;
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.ServiceFactory;
import javax.xml.rpc.Stub;
import junit.framework.TestCase;
import org.springframework.remoting.RemoteAccessException;
import org.springframework.remoting.RemoteLookupFailureException;
import static org.mockito.BDDMockito.*;
/**
* @author Juergen Hoeller
* @since 18.12.2003
*/
@Deprecated
public class JaxRpcSupportTests extends TestCase {
public void testLocalJaxRpcServiceFactoryBeanWithServiceNameAndNamespace() throws Exception {
LocalJaxRpcServiceFactoryBean factory = new LocalJaxRpcServiceFactoryBean();
factory.setServiceFactoryClass(MockServiceFactory.class);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myService1");
factory.afterPropertiesSet();
assertEquals(MockServiceFactory.service1, factory.getObject());
}
public void testLocalJaxRpcServiceFactoryBeanWithServiceNameAndWsdl() throws Exception {
LocalJaxRpcServiceFactoryBean factory = new LocalJaxRpcServiceFactoryBean();
factory.setServiceFactoryClass(MockServiceFactory.class);
factory.setServiceName("myService2");
factory.setWsdlDocumentUrl(new URL("http://myUrl1"));
factory.afterPropertiesSet();
assertTrue("Correct singleton value", factory.isSingleton());
assertEquals(MockServiceFactory.service2, factory.getObject());
}
public void testLocalJaxRpcServiceFactoryBeanWithServiceNameAndWsdlAndProperties() throws Exception {
LocalJaxRpcServiceFactoryBean factory = new LocalJaxRpcServiceFactoryBean();
factory.setServiceFactoryClass(MockServiceFactory.class);
factory.setServiceName("myService2");
factory.setWsdlDocumentUrl(new URL("http://myUrl1"));
Properties props = new Properties();
props.setProperty("myKey", "myValue");
factory.setJaxRpcServiceProperties(props);
factory.afterPropertiesSet();
assertTrue("Correct singleton value", factory.isSingleton());
assertEquals(MockServiceFactory.service1, factory.getObject());
}
public void testLocalJaxRpcServiceFactoryBeanWithJaxRpcServiceInterface() throws Exception {
LocalJaxRpcServiceFactoryBean factory = new LocalJaxRpcServiceFactoryBean();
factory.setServiceFactoryClass(MockServiceFactory.class);
factory.setJaxRpcServiceInterface(IRemoteBean.class);
factory.afterPropertiesSet();
assertTrue("Correct singleton value", factory.isSingleton());
assertEquals(MockServiceFactory.service2, factory.getObject());
}
public void testLocalJaxRpcServiceFactoryBeanWithJaxRpcServiceInterfaceAndWsdl() throws Exception {
LocalJaxRpcServiceFactoryBean factory = new LocalJaxRpcServiceFactoryBean();
factory.setServiceFactoryClass(MockServiceFactory.class);
factory.setWsdlDocumentUrl(new URL("http://myUrl1"));
factory.setJaxRpcServiceInterface(IRemoteBean.class);
Properties props = new Properties();
props.setProperty("myKey", "myValue");
factory.setJaxRpcServiceProperties(props);
factory.afterPropertiesSet();
assertTrue("Correct singleton value", factory.isSingleton());
assertEquals(MockServiceFactory.service1, factory.getObject());
}
public void testJaxRpcPortProxyFactoryBean() throws Exception {
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactoryClass(MockServiceFactory.class);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myService1");
factory.setPortName("myPort");
factory.setPortInterface(IRemoteBean.class);
factory.afterPropertiesSet();
assertTrue("Correct singleton value", factory.isSingleton());
assertTrue(factory.getPortStub() instanceof Stub);
assertTrue(factory.getObject() instanceof IRemoteBean);
IRemoteBean proxy = (IRemoteBean) factory.getObject();
proxy.setName("myName");
assertEquals("myName", RemoteBean.name);
}
public void testJaxRpcPortProxyFactoryBeanWithProperties() throws Exception {
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactoryClass(MockServiceFactory.class);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myService1");
factory.setPortName("myPort");
factory.setUsername("user");
factory.setPassword("pw");
factory.setEndpointAddress("ea");
factory.setMaintainSession(true);
factory.setPortInterface(IRemoteBean.class);
factory.afterPropertiesSet();
assertTrue("Correct singleton value", factory.isSingleton());
assertTrue(factory.getPortStub() instanceof Stub);
Stub stub = (Stub) factory.getPortStub();
assertEquals("user", stub._getProperty(Stub.USERNAME_PROPERTY));
assertEquals("pw", stub._getProperty(Stub.PASSWORD_PROPERTY));
assertEquals("ea", stub._getProperty(Stub.ENDPOINT_ADDRESS_PROPERTY));
assertTrue(((Boolean) stub._getProperty(Stub.SESSION_MAINTAIN_PROPERTY)).booleanValue());
assertTrue(factory.getObject() instanceof IRemoteBean);
IRemoteBean proxy = (IRemoteBean) factory.getObject();
proxy.setName("myName");
assertEquals("myName", RemoteBean.name);
}
public void testJaxRpcPortProxyFactoryBeanWithCustomProperties() throws Exception {
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactoryClass(MockServiceFactory.class);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myService1");
factory.setPortName("myPort");
factory.setUsername("user");
factory.setPassword("pw");
Properties customProps = new Properties();
customProps.setProperty("myProp", "myValue");
factory.setCustomProperties(customProps);
factory.setPortInterface(IRemoteBean.class);
factory.afterPropertiesSet();
assertTrue("Correct singleton value", factory.isSingleton());
assertTrue(factory.getPortStub() instanceof Stub);
Stub stub = (Stub) factory.getPortStub();
assertEquals("user", stub._getProperty(Stub.USERNAME_PROPERTY));
assertEquals("pw", stub._getProperty(Stub.PASSWORD_PROPERTY));
assertEquals("myValue", stub._getProperty("myProp"));
assertTrue(factory.getObject() instanceof IRemoteBean);
IRemoteBean proxy = (IRemoteBean) factory.getObject();
proxy.setName("myName");
assertEquals("myName", RemoteBean.name);
}
public void testJaxRpcPortProxyFactoryBeanWithCustomPropertyMap() throws Exception {
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactoryClass(MockServiceFactory.class);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myService1");
factory.setPortName("myPort");
factory.setEndpointAddress("ea");
factory.setMaintainSession(true);
Map customProps = new HashMap();
customProps.put("myProp", new Integer(1));
factory.setCustomPropertyMap(customProps);
factory.addCustomProperty("myOtherProp", "myOtherValue");
factory.setPortInterface(IRemoteBean.class);
factory.afterPropertiesSet();
assertTrue("Correct singleton value", factory.isSingleton());
assertTrue(factory.getPortStub() instanceof Stub);
Stub stub = (Stub) factory.getPortStub();
assertEquals("ea", stub._getProperty(Stub.ENDPOINT_ADDRESS_PROPERTY));
assertTrue(((Boolean) stub._getProperty(Stub.SESSION_MAINTAIN_PROPERTY)).booleanValue());
assertEquals(new Integer(1), stub._getProperty("myProp"));
assertEquals("myOtherValue", stub._getProperty("myOtherProp"));
assertTrue(factory.getObject() instanceof IRemoteBean);
IRemoteBean proxy = (IRemoteBean) factory.getObject();
proxy.setName("myName");
assertEquals("myName", RemoteBean.name);
}
public void testJaxRpcPortProxyFactoryBeanWithDynamicCalls() throws Exception {
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactoryClass(CallMockServiceFactory.class);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myService1");
factory.setPortName("myPort");
factory.setServiceInterface(IBusinessBean.class);
factory.afterPropertiesSet();
assertNull(factory.getPortStub());
assertTrue(factory.getObject() instanceof IBusinessBean);
IBusinessBean proxy = (IBusinessBean) factory.getObject();
proxy.setName("myName");
}
public void testJaxRpcPortProxyFactoryBeanWithDynamicCallsAndProperties() throws Exception {
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactoryClass(CallMockServiceFactory.class);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myService1");
factory.setPortName("myPort");
factory.setUsername("user");
factory.setPassword("pw");
factory.setEndpointAddress("ea");
factory.setMaintainSession(true);
factory.setServiceInterface(IBusinessBean.class);
factory.afterPropertiesSet();
assertNull(factory.getPortStub());
assertTrue(factory.getObject() instanceof IBusinessBean);
IBusinessBean proxy = (IBusinessBean) factory.getObject();
proxy.setName("myName");
verify(CallMockServiceFactory.call1).setProperty(Call.USERNAME_PROPERTY, "user");
verify(CallMockServiceFactory.call1).setProperty(Call.PASSWORD_PROPERTY, "pw");
verify(CallMockServiceFactory.call1).setTargetEndpointAddress("ea");
verify(CallMockServiceFactory.call1).setProperty(Call.SESSION_MAINTAIN_PROPERTY, Boolean.TRUE);
}
public void testJaxRpcPortProxyFactoryBeanWithDynamicCallsAndServiceException() throws Exception {
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactoryClass(CallMockServiceFactory.class);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myServiceX");
factory.setPortName("myPort");
factory.setServiceInterface(IRemoteBean.class);
try {
factory.afterPropertiesSet();
fail("Should have thrown RemoteLookupFailureException");
}
catch (RemoteLookupFailureException ex) {
// expected
}
}
public void testJaxRpcPortProxyFactoryBeanWithDynamicCallsAndLazyLookupAndServiceException() throws Exception {
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactoryClass(CallMockServiceFactory.class);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myServiceX");
factory.setPortName("myPort");
factory.setServiceInterface(IRemoteBean.class);
factory.setLookupServiceOnStartup(false);
factory.afterPropertiesSet();
assertTrue(factory.getObject() instanceof IRemoteBean);
IRemoteBean proxy = (IRemoteBean) factory.getObject();
try {
proxy.setName("exception");
fail("Should have thrown RemoteException");
}
catch (RemoteLookupFailureException ex) {
// expected
assertTrue(ex.getCause() instanceof ServiceException);
}
}
public void testJaxRpcPortProxyFactoryBeanWithDynamicCallsAndRemoteException_() throws Exception {
ExceptionCallMockServiceFactory serviceFactory = new ExceptionCallMockServiceFactory();
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactory(serviceFactory);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myService1");
factory.setPortName("myPort");
factory.setServiceInterface(IRemoteBean.class);
factory.afterPropertiesSet();
assertTrue(factory.getObject() instanceof IRemoteBean);
IRemoteBean proxy = (IRemoteBean) factory.getObject();
try {
proxy.setName("exception");
fail("Should have thrown RemoteException");
}
catch (RemoteException ex) {
// expected
}
proxy.setName("myName");
assertEquals("myName", RemoteBean.name);
proxy.setName("myName");
assertEquals("myName", RemoteBean.name);
assertEquals(1, serviceFactory.serviceCount);
}
public void testJaxRpcPortProxyFactoryBeanWithDynamicCallsAndRemoteExceptionAndRefresh() throws Exception {
ExceptionCallMockServiceFactory serviceFactory = new ExceptionCallMockServiceFactory();
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactory(serviceFactory);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myService1");
factory.setPortName("myPort");
factory.setServiceInterface(IRemoteBean.class);
factory.setRefreshServiceAfterConnectFailure(true);
factory.afterPropertiesSet();
assertTrue(factory.getObject() instanceof IRemoteBean);
IRemoteBean proxy = (IRemoteBean) factory.getObject();
try {
proxy.setName("exception");
fail("Should have thrown RemoteException");
}
catch (RemoteException ex) {
// expected
}
proxy.setName("myName");
assertEquals("myName", RemoteBean.name);
proxy.setName("myName");
assertEquals("myName", RemoteBean.name);
assertEquals(2, serviceFactory.serviceCount);
}
public void testJaxRpcPortProxyFactoryBeanWithPortInterface() throws Exception {
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactoryClass(MockServiceFactory.class);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myService1");
factory.setPortName("myPort");
factory.setPortInterface(IRemoteBean.class);
factory.setServiceInterface(IBusinessBean.class);
factory.afterPropertiesSet();
assertTrue(factory.getObject() instanceof IBusinessBean);
assertFalse(factory.getObject() instanceof IRemoteBean);
IBusinessBean proxy = (IBusinessBean) factory.getObject();
proxy.setName("myName");
assertEquals("myName", RemoteBean.name);
}
public void testJaxRpcPortProxyFactoryBeanWithPortInterfaceAndServiceException() throws Exception {
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactoryClass(MockServiceFactory.class);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myServiceX");
factory.setPortInterface(IRemoteBean.class);
factory.setPortName("myPort");
factory.setServiceInterface(IRemoteBean.class);
try {
factory.afterPropertiesSet();
fail("Should have thrown RemoteLookupFailureException");
}
catch (RemoteLookupFailureException ex) {
// expected
}
}
public void testJaxRpcPortProxyFactoryBeanWithPortInterfaceAndLazyLookupAndServiceException() throws Exception {
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactoryClass(MockServiceFactory.class);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myServiceX");
factory.setPortName("myPort");
factory.setPortInterface(IRemoteBean.class);
factory.setServiceInterface(IRemoteBean.class);
factory.setLookupServiceOnStartup(false);
factory.afterPropertiesSet();
assertTrue(factory.getObject() instanceof IRemoteBean);
IRemoteBean proxy = (IRemoteBean) factory.getObject();
try {
proxy.setName("exception");
fail("Should have thrown Service");
}
catch (RemoteLookupFailureException ex) {
// expected
assertTrue(ex.getCause() instanceof ServiceException);
}
}
public void testJaxRpcPortProxyFactoryBeanWithPortInterfaceAndRemoteException() throws Exception {
MockServiceFactory serviceFactory = new MockServiceFactory();
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactory(serviceFactory);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myService1");
factory.setPortName("myPort");
factory.setPortInterface(IRemoteBean.class);
factory.setServiceInterface(IBusinessBean.class);
factory.afterPropertiesSet();
assertTrue(factory.getObject() instanceof IBusinessBean);
assertFalse(factory.getObject() instanceof IRemoteBean);
IBusinessBean proxy = (IBusinessBean) factory.getObject();
try {
proxy.setName("exception");
fail("Should have thrown RemoteAccessException");
}
catch (RemoteAccessException ex) {
// expected
}
proxy.setName("myName");
assertEquals("myName", RemoteBean.name);
proxy.setName("myName");
assertEquals("myName", RemoteBean.name);
assertEquals(1, serviceFactory.serviceCount);
}
public void testJaxRpcPortProxyFactoryBeanWithPortInterfaceAndRemoteExceptionAndRefresh() throws Exception {
ExceptionMockServiceFactory serviceFactory = new ExceptionMockServiceFactory();
JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
factory.setServiceFactory(serviceFactory);
factory.setNamespaceUri("myNamespace");
factory.setServiceName("myService1");
factory.setPortName("myPort");
factory.setPortInterface(IRemoteBean.class);
factory.setServiceInterface(IBusinessBean.class);
factory.setRefreshServiceAfterConnectFailure(true);
factory.afterPropertiesSet();
assertTrue(factory.getObject() instanceof IBusinessBean);
assertFalse(factory.getObject() instanceof IRemoteBean);
IBusinessBean proxy = (IBusinessBean) factory.getObject();
try {
proxy.setName("exception");
fail("Should have thrown RemoteAccessException");
}
catch (RemoteAccessException ex) {
// expected
}
proxy.setName("myName");
assertEquals("myName", RemoteBean.name);
proxy.setName("myName");
assertEquals("myName", RemoteBean.name);
assertEquals(2, serviceFactory.serviceCount);
}
public static class MockServiceFactory extends ServiceFactory {
protected static Service service1;
protected static Service service2;
protected int serviceCount = 0;
public MockServiceFactory() throws Exception {
service1 = mock(Service.class);
service2 = mock(Service.class);
initMocks();
}
protected void initMocks() throws Exception {
RemoteBean remoteBean = new RemoteBean();
given(service1.getPort(new QName("myNamespace", "myPort"),
IRemoteBean.class)).willReturn(remoteBean);
}
@Override
public Service createService(QName qName) throws ServiceException {
if (!"myNamespace".equals(qName.getNamespaceURI()) || !"myService1".equals(qName.getLocalPart())) {
throw new ServiceException("not supported");
}
serviceCount++;
return service1;
}
@Override
public Service createService(URL url, QName qName) throws ServiceException {
try {
if (!(new URL("http://myUrl1")).equals(url) || !"".equals(qName.getNamespaceURI()) ||
!"myService2".equals(qName.getLocalPart())) {
throw new ServiceException("not supported");
}
}
catch (MalformedURLException ex) {
}
serviceCount++;
return service2;
}
@Override
public Service loadService(URL url, QName qName, Properties props) throws ServiceException {
try {
if (!(new URL("http://myUrl1")).equals(url) || !"".equals(qName.getNamespaceURI()) ||
!"myService2".equals(qName.getLocalPart())) {
throw new ServiceException("not supported");
}
}
catch (MalformedURLException ex) {
}
if (props == null || !"myValue".equals(props.getProperty("myKey"))) {
throw new ServiceException("invalid properties");
}
serviceCount++;
return service1;
}
@Override
public Service loadService(Class ifc) throws ServiceException {
if (!IRemoteBean.class.equals(ifc)) {
throw new ServiceException("not supported");
}
serviceCount++;
return service2;
}
@Override
public Service loadService(URL url, Class ifc, Properties props) throws ServiceException {
try {
if (!(new URL("http://myUrl1")).equals(url) || !IRemoteBean.class.equals(ifc)) {
throw new ServiceException("not supported");
}
}
catch (MalformedURLException ex) {
}
if (props == null || !"myValue".equals(props.getProperty("myKey"))) {
throw new ServiceException("invalid properties");
}
serviceCount++;
return service1;
}
}
public static class ExceptionMockServiceFactory extends MockServiceFactory {
public ExceptionMockServiceFactory() throws Exception {
super();
}
@Override
protected void initMocks() throws Exception {
super.initMocks();
given(service1.getPort(new QName("myNamespace", "myPort"),
IRemoteBean.class)).willReturn(new RemoteBean());
}
}
public static class CallMockServiceFactory extends MockServiceFactory {
protected static Call call1;
public CallMockServiceFactory() throws Exception {
super();
}
@Override
protected void initMocks() throws Exception {
call1 = mock(Call.class);
given(service1.createCall(new QName("myNamespace", "myPort"), "setName")).willReturn(call1);
}
}
public static class ExceptionCallMockServiceFactory extends MockServiceFactory {
protected static Call call1;
protected static Call call2;
public ExceptionCallMockServiceFactory() throws Exception {
}
@Override
protected void initMocks() throws Exception {
call1 = mock(Call.class);
call2 = mock(Call.class);
given(service1.createCall(new QName("myNamespace", "myPort"), "setName")).willReturn(call2, call1);
given(call2.invoke(new Object[] { "exception" })).willThrow(new RemoteException());
}
}
public static interface IBusinessBean {
public void setName(String name);
}
public static interface IRemoteBean extends Remote {
public void setName(String name) throws RemoteException;
}
public static class RemoteBean implements IRemoteBean, Stub {
private static String name;
private static Map properties;
public RemoteBean() {
properties = new HashMap();
}
@Override
public void setName(String nam) throws RemoteException {
if ("exception".equals(nam)) {
throw new RemoteException();
}
name = nam;
}
@Override
public void _setProperty(String key, Object o) {
properties.put(key, o);
}
@Override
public Object _getProperty(String key) {
return properties.get(key);
}
@Override
public Iterator _getPropertyNames() {
return properties.keySet().iterator();
}
}
}

292
src/reference/docbook/remoting.xml

@ -51,11 +51,6 @@ @@ -51,11 +51,6 @@
<classname>BurlapServiceExporter</classname>.</para>
</listitem>
<listitem>
<para><emphasis>JAX-RPC</emphasis>. Spring provides remoting support
for web services via JAX-RPC (J2EE 1.4's web service API).</para>
</listitem>
<listitem>
<para><emphasis>JAX-WS</emphasis>. Spring provides remoting support
for web services via JAX-WS (the successor of JAX-RPC, as introduced
@ -501,14 +496,6 @@ public class AccountServiceImpl implements AccountService { @@ -501,14 +496,6 @@ public class AccountServiceImpl implements AccountService {
APIs:</para>
<itemizedlist>
<listitem>
<para>Exposing web services using JAX-RPC</para>
</listitem>
<listitem>
<para>Accessing web services using JAX-RPC</para>
</listitem>
<listitem>
<para>Exposing web services using JAX-WS</para>
</listitem>
@ -518,285 +505,13 @@ public class AccountServiceImpl implements AccountService { @@ -518,285 +505,13 @@ public class AccountServiceImpl implements AccountService {
</listitem>
</itemizedlist>
<note>
<para>Why two standard Java web services APIs?</para>
<para>JAX-RPC 1.1 is the standard web service API in J2EE 1.4. As its
name indicates, it focuses on on RPC bindings, which became less and
less popular in the past couple of years. As a consequence, it has been
superseded by JAX-WS 2.0 in Java EE 5, being more flexible in terms of
bindings but also being heavily annotation-based. JAX-WS 2.1 is also
included in Java 6 (or more specifically, in Sun's JDK 1.6.0_04 and
above; previous Sun JDK 1.6.0 releases included JAX-WS 2.0), integrated
with the JDK's built-in HTTP server.</para>
<para>Spring can work with both standard Java web services APIs. On Java
EE 5 / Java 6, the obvious choice is JAX-WS. On J2EE 1.4 environments
that run on Java 5, you might have the option to plug in a JAX-WS
provider; check your Java EE server's documentation.</para>
</note>
<para>In addition to stock support for JAX-RPC and JAX-WS in Spring Core,
<para>In addition to stock support for JAX-WS in Spring Core,
the Spring portfolio also features <link
xl:href="http://www.springframework.org/spring-ws">Spring Web
Services</link>, a solution for contract-first, document-driven web
services - highly recommended for building modern, future-proof web
services.</para>
<section xml:id="remoting-web-services-jaxrpc-export">
<title>Exposing servlet-based web services using JAX-RPC</title>
<para>Spring provides a convenience base class for JAX-RPC servlet
endpoint implementations -
<classname>ServletEndpointSupport</classname>. To expose our
<interfacename>AccountService</interfacename> we extend Spring's
<classname>ServletEndpointSupport</classname> class and implement our
business logic here, usually delegating the call to the business
layer.</para>
<programlisting language="java"><lineannotation>/**
* JAX-RPC compliant RemoteAccountService implementation that simply delegates
* to the AccountService implementation in the root web application context.
*
* This wrapper class is necessary because JAX-RPC requires working with dedicated
* endpoint classes. If an existing service needs to be exported, a wrapper that
* extends ServletEndpointSupport for simple application context access is
* the simplest JAX-RPC compliant way.
*
* This is the class registered with the server-side JAX-RPC implementation.
* In the case of Axis, this happens in "server-config.wsdd" respectively via
* deployment calls. The web service engine manages the lifecycle of instances
* of this class: A Spring application context can just be accessed here.
*/</lineannotation>import org.springframework.remoting.jaxrpc.ServletEndpointSupport;
public class AccountServiceEndpoint extends ServletEndpointSupport implements RemoteAccountService {
private AccountService biz;
protected void onInit() {
this.biz = (AccountService) getWebApplicationContext().getBean("accountService");
}
public void insertAccount(Account acc) throws RemoteException {
biz.insertAccount(acc);
}
public Account[] getAccounts(String name) throws RemoteException {
return biz.getAccounts(name);
}
}</programlisting>
<para>Our <classname>AccountServletEndpoint</classname> needs to run in
the same web application as the Spring context to allow for access to
Spring's facilities. In case of Axis, copy the
<classname>AxisServlet</classname> definition into your
<filename>'web.xml'</filename>, and set up the endpoint in
<filename>'server-config.wsdd'</filename> (or use the deploy tool). See
the sample application JPetStore where the
<interfacename>OrderService</interfacename> is exposed as a web service
using Axis.</para>
</section>
<section xml:id="remoting-web-services-jaxrpc-access">
<title>Accessing web services using JAX-RPC</title>
<para>Spring provides two factory beans to create JAX-RPC web service
proxies, namely <classname>LocalJaxRpcServiceFactoryBean</classname> and
<classname>JaxRpcPortProxyFactoryBean</classname>. The former can only
return a JAX-RPC service class for us to work with. The latter is the
full-fledged version that can return a proxy that implements our
business service interface. In this example we use the latter to create
a proxy for the <interfacename>AccountService</interfacename> endpoint
we exposed in the previous section. You will see that Spring has great
support for web services requiring little coding efforts - most of the
setup is done in the Spring configuration file as usual:</para>
<programlisting language="xml">&lt;bean id="accountWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean"&gt;
&lt;property name="serviceInterface" value="example.RemoteAccountService"/&gt;
&lt;property name="wsdlDocumentUrl" value="http://localhost:8080/account/services/accountService?WSDL"/&gt;
&lt;property name="namespaceUri" value="http://localhost:8080/account/services/accountService"/&gt;
&lt;property name="serviceName" value="AccountService"/&gt;
&lt;property name="portName" value="AccountPort"/&gt;
&lt;/bean&gt;</programlisting>
<para>Where <literal>serviceInterface</literal> is our remote business
interface the clients will use. <literal>wsdlDocumentUrl</literal> is
the URL for the WSDL file. Spring needs this at startup time to create
the JAX-RPC Service. <literal>namespaceUri</literal> corresponds to the
targetNamespace in the .wsdl file. <literal>serviceName</literal>
corresponds to the service name in the .wsdl file.
<literal>portName</literal> corresponds to the port name in the .wsdl
file.</para>
<para>Accessing the web service is now very easy as we have a bean
factory for it that will expose it as
<literal>RemoteAccountService</literal> interface. We can wire this up
in Spring:</para>
<programlisting language="xml">&lt;bean id="client" class="example.AccountClientImpl"&gt;
...
&lt;property name="service" ref="accountWebService"/&gt;
&lt;/bean&gt;</programlisting>
<para>From the client code we can access the web service just as if it
was a normal class, except that it throws
<exceptionname>RemoteException</exceptionname>.</para>
<programlisting language="java">public class AccountClientImpl {
private RemoteAccountService service;
public void setService(RemoteAccountService service) {
this.service = service;
}
public void foo() {
try {
service.insertAccount(...);
}
catch (RemoteException ex) {
<lineannotation>// ouch</lineannotation>
}
}
}
</programlisting>
<para>We can get rid of the checked
<exceptionname>RemoteException</exceptionname> since Spring supports
automatic conversion to its corresponding unchecked
<exceptionname>RemoteException</exceptionname>. This requires that we
provide a non-RMI interface also. Our configuration is now:</para>
<programlisting language="xml">&lt;bean id="accountWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean"&gt;
&lt;property name="serviceInterface" value="example.AccountService"/&gt;
&lt;property name="portInterface" value="example.RemoteAccountService"/&gt;
...
&lt;/bean&gt;</programlisting>
<para>Where <literal>serviceInterface</literal> is changed to our non
RMI interface. Our RMI interface is now defined using the property
<literal>portInterface</literal>. Our client code can now avoid handling
<exceptionname>java.rmi.RemoteException</exceptionname>:</para>
<programlisting language="java">public class AccountClientImpl {
private AccountService service;
public void setService(AccountService service) {
this.service = service;
}
public void foo() {
service.insertAccount(...);
}
}</programlisting>
<para>Note that you can also drop the "portInterface" part and specify a
plain business interface as "serviceInterface". In this case,
<classname>JaxRpcPortProxyFactoryBean</classname> will automatically
switch to the JAX-RPC "Dynamic Invocation Interface", performing dynamic
invocations without a fixed port stub. The advantage is that you don't
even need to have an RMI-compliant Java port interface around (e.g. in
case of a non-Java target web service); all you need is a matching
business interface. Check out
<classname>JaxRpcPortProxyFactoryBean</classname>'s javadoc for details
on the runtime implications.</para>
</section>
<section xml:id="remoting-web-services-jaxrpc-mapping-registration">
<title>Registering JAX-RPC Bean Mappings</title>
<para>To transfer complex objects over the wire such as
<classname>Account</classname> we must register bean mappings on the
client side.</para>
<note>
<para>On the server side using Axis registering bean mappings is
usually done in the <filename>'server-config.wsdd'</filename>
file.</para>
</note>
<para>We will use Axis to register bean mappings on the client side. To
do this we need to register the bean mappings programmatically:</para>
<programlisting language="java">public class AxisPortProxyFactoryBean extends JaxRpcPortProxyFactoryBean {
protected void postProcessJaxRpcService(Service service) {
TypeMappingRegistry registry = service.getTypeMappingRegistry();
TypeMapping mapping = registry.createTypeMapping();
registerBeanMapping(mapping, Account.class, "Account");
registry.register("http://schemas.xmlsoap.org/soap/encoding/", mapping);
}
protected void registerBeanMapping(TypeMapping mapping, Class type, String name) {
QName qName = new QName("http://localhost:8080/account/services/accountService", name);
mapping.register(type, qName,
new BeanSerializerFactory(type, qName),
new BeanDeserializerFactory(type, qName));
}
}</programlisting>
</section>
<section xml:id="remoting-web-services-jaxrpc-handler-registration">
<title>Registering your own JAX-RPC Handler</title>
<para>In this section we will register our own
<interfacename>javax.rpc.xml.handler.Handler</interfacename> to the web
service proxy where we can do custom code before the SOAP message is
sent over the wire. The <interfacename>Handler</interfacename> is a
callback interface. There is a convenience base class provided in
<filename class="libraryfile">jaxrpc.jar</filename>, namely
<classname>javax.rpc.xml.handler.GenericHandler</classname> that we will
extend:</para>
<programlisting language="java">public class AccountHandler extends GenericHandler {
public QName[] getHeaders() {
return null;
}
public boolean handleRequest(MessageContext context) {
SOAPMessageContext smc = (SOAPMessageContext) context;
SOAPMessage msg = smc.getMessage();
try {
SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
SOAPHeader header = envelope.getHeader();
...
}
catch (SOAPException ex) {
throw new JAXRPCException(ex);
}
return true;
}
}</programlisting>
<para>What we need to do now is to register our AccountHandler to
JAX-RPC Service so it would invoke
<methodname>handleRequest(..)</methodname> before the message is sent
over the wire. Spring has at this time of writing no declarative support
for registering handlers, so we must use the programmatic approach.
However Spring has made it very easy for us to do this as we can
override the <methodname>postProcessJaxRpcService(..)</methodname>
method that is designed for this:</para>
<programlisting language="java">public class AccountHandlerJaxRpcPortProxyFactoryBean extends JaxRpcPortProxyFactoryBean {
protected void postProcessJaxRpcService(Service service) {
QName port = new QName(this.getNamespaceUri(), this.getPortName());
List list = service.getHandlerRegistry().getHandlerChain(port);
list.add(new HandlerInfo(AccountHandler.class, null, null));
logger.info("Registered JAX-RPC AccountHandler on port " + port);
}
}</programlisting>
<para>The last thing we must remember to do is to change the Spring
configuration to use our factory bean:</para>
<programlisting language="xml">&lt;bean id="accountWebService" class="example.AccountHandlerJaxRpcPortProxyFactoryBean"&gt;
...
&lt;/bean&gt;</programlisting>
</section>
<section xml:id="remoting-web-services-jaxws-export-servlet">
<title>Exposing servlet-based web services using JAX-WS</title>
@ -937,9 +652,8 @@ public class AccountServiceEndpoint { @@ -937,9 +652,8 @@ public class AccountServiceEndpoint {
<section xml:id="remoting-web-services-jaxws-access">
<title>Accessing web services using JAX-WS</title>
<para>Analogous to the JAX-RPC support, Spring provides two factory
beans to create JAX-WS web service proxies, namely
<classname>LocalJaxWsServiceFactoryBean</classname> and
<para>Spring provides two factory beans to create JAX-WS web service
proxies, namely <classname>LocalJaxWsServiceFactoryBean</classname> and
<classname>JaxWsPortProxyFactoryBean</classname>. The former can only
return a JAX-WS service class for us to work with. The latter is the
full-fledged version that can return a proxy that implements our

Loading…
Cancel
Save