added support for JAX-WS 2.1 WebServiceFeatures to JaxWsPortClientInterceptor/PortProxyFactoryBean (SPR-5712)
This commit is contained in:
parent
11bb7264a2
commit
4955a73047
|
|
@ -25,17 +25,22 @@ import javax.xml.ws.BindingProvider;
|
|||
import javax.xml.ws.ProtocolException;
|
||||
import javax.xml.ws.Service;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
import javax.xml.ws.WebServiceFeature;
|
||||
import javax.xml.ws.soap.SOAPFaultException;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.remoting.RemoteAccessException;
|
||||
import org.springframework.remoting.RemoteConnectFailureException;
|
||||
import org.springframework.remoting.RemoteLookupFailureException;
|
||||
import org.springframework.remoting.RemoteProxyFailureException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link org.aopalliance.intercept.MethodInterceptor} for accessing a
|
||||
|
|
@ -54,7 +59,7 @@ import org.springframework.remoting.RemoteProxyFailureException;
|
|||
* @see org.springframework.jndi.JndiObjectFactoryBean
|
||||
*/
|
||||
public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
|
||||
implements MethodInterceptor, InitializingBean {
|
||||
implements MethodInterceptor, BeanClassLoaderAware, InitializingBean {
|
||||
|
||||
private Service jaxWsService;
|
||||
|
||||
|
|
@ -74,10 +79,14 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
|
|||
|
||||
private Map<String, Object> customProperties;
|
||||
|
||||
private Object[] webServiceFeatures;
|
||||
|
||||
private Class<?> serviceInterface;
|
||||
|
||||
private boolean lookupServiceOnStartup = true;
|
||||
|
||||
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
||||
|
||||
private QName portQName;
|
||||
|
||||
private Object portStub;
|
||||
|
|
@ -244,6 +253,15 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
|
|||
getCustomProperties().put(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows for providing JAX-WS 2.1 WebServiceFeature specifications:
|
||||
* in the form of actual {@link javax.xml.ws.WebServiceFeature} objects,
|
||||
* WebServiceFeature Class references, or WebServiceFeature class names.
|
||||
*/
|
||||
public void setWebServiceFeatures(Object[] webServiceFeatures) {
|
||||
this.webServiceFeatures = webServiceFeatures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the interface of the service that this factory should create a proxy for.
|
||||
*/
|
||||
|
|
@ -271,6 +289,23 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
|
|||
this.lookupServiceOnStartup = lookupServiceOnStartup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean ClassLoader to use for this interceptor:
|
||||
* for resolving WebServiceFeature class names as specified through
|
||||
* {@link #setWebServiceFeatures}, and also for building a client
|
||||
* proxy in the {@link JaxWsPortProxyFactoryBean} subclass.
|
||||
*/
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean ClassLoader to use for this interceptor.
|
||||
*/
|
||||
protected ClassLoader getBeanClassLoader() {
|
||||
return this.beanClassLoader;
|
||||
}
|
||||
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
if (this.lookupServiceOnStartup) {
|
||||
|
|
@ -278,6 +313,9 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the JAX-WS port for this interceptor.
|
||||
*/
|
||||
public void prepare() {
|
||||
if (getServiceInterface() == null) {
|
||||
throw new IllegalArgumentException("Property 'serviceInterface' is required");
|
||||
|
|
@ -287,8 +325,7 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
|
|||
serviceToUse = createJaxWsService();
|
||||
}
|
||||
this.portQName = getQName(getPortName() != null ? getPortName() : getServiceInterface().getName());
|
||||
Object stub = (getPortName() != null ?
|
||||
serviceToUse.getPort(this.portQName, getServiceInterface()) : serviceToUse.getPort(getServiceInterface()));
|
||||
Object stub = getPortStub(serviceToUse, (getPortName() != null ? this.portQName : null));
|
||||
preparePortStub(stub);
|
||||
this.portStub = stub;
|
||||
}
|
||||
|
|
@ -312,6 +349,23 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
|
|||
return this.portQName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the port stub from the given JAX-WS Service.
|
||||
* @param service the Service object to obtain the port from
|
||||
* @param portQName the name of the desired port, if specified
|
||||
* @return the corresponding port object as returned from
|
||||
* <code>Service.getPort(...)</code>
|
||||
*/
|
||||
protected Object getPortStub(Service service, QName portQName) {
|
||||
if (this.webServiceFeatures != null) {
|
||||
return new FeaturePortProvider().getPortStub(service, portQName, this.webServiceFeatures);
|
||||
}
|
||||
else {
|
||||
return (portQName != null ? service.getPort(portQName, getServiceInterface()) :
|
||||
service.getPort(getServiceInterface()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the given JAX-WS port stub, applying properties to it.
|
||||
* Called by {@link #prepare}.
|
||||
|
|
@ -424,4 +478,44 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class in order to avoid a hard-coded JAX-WS 2.1 dependency.
|
||||
* JAX-WS 2.0, as used in Java EE 5, didn't have WebServiceFeatures yet...
|
||||
*/
|
||||
private class FeaturePortProvider {
|
||||
|
||||
public Object getPortStub(Service service, QName portQName, Object[] features) {
|
||||
WebServiceFeature[] wsFeatures = new WebServiceFeature[features.length];
|
||||
for (int i = 0; i < features.length; i++) {
|
||||
wsFeatures[i] = convertWebServiceFeature(features[i]);
|
||||
}
|
||||
return (portQName != null ? service.getPort(portQName, getServiceInterface(), wsFeatures) :
|
||||
service.getPort(getServiceInterface(), wsFeatures));
|
||||
}
|
||||
|
||||
private WebServiceFeature convertWebServiceFeature(Object feature) {
|
||||
Assert.notNull(feature, "WebServiceFeature specification object must not be null");
|
||||
if (feature instanceof WebServiceFeature) {
|
||||
return (WebServiceFeature) feature;
|
||||
}
|
||||
else if (feature instanceof Class) {
|
||||
return (WebServiceFeature) BeanUtils.instantiate((Class<?>) feature);
|
||||
}
|
||||
else if (feature instanceof String) {
|
||||
try {
|
||||
Class<?> featureClass = getBeanClassLoader().loadClass((String) feature);
|
||||
return (WebServiceFeature) BeanUtils.instantiate(featureClass);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new IllegalArgumentException("Could not load WebServiceFeature class [" + feature + "]");
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown WebServiceFeature specification type: " + feature.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 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.
|
||||
|
|
@ -19,9 +19,7 @@ package org.springframework.remoting.jaxws;
|
|||
import javax.xml.ws.BindingProvider;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.FactoryBean} for a specific port of a
|
||||
|
|
@ -34,17 +32,11 @@ import org.springframework.util.ClassUtils;
|
|||
* @see LocalJaxWsServiceFactoryBean
|
||||
*/
|
||||
public class JaxWsPortProxyFactoryBean extends JaxWsPortClientInterceptor
|
||||
implements FactoryBean<Object>, BeanClassLoaderAware {
|
||||
|
||||
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
||||
implements FactoryBean<Object> {
|
||||
|
||||
private Object serviceProxy;
|
||||
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
super.afterPropertiesSet();
|
||||
|
|
@ -54,7 +46,7 @@ public class JaxWsPortProxyFactoryBean extends JaxWsPortClientInterceptor
|
|||
pf.addInterface(getServiceInterface());
|
||||
pf.addInterface(BindingProvider.class);
|
||||
pf.addAdvice(this);
|
||||
this.serviceProxy = pf.getProxy(this.beanClassLoader);
|
||||
this.serviceProxy = pf.getProxy(getBeanClassLoader());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 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.
|
||||
|
|
@ -18,14 +18,15 @@ package org.springframework.remoting.jaxws;
|
|||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.ws.BindingProvider;
|
||||
import javax.xml.ws.Service;
|
||||
import javax.xml.ws.WebServiceClient;
|
||||
import javax.xml.ws.WebServiceRef;
|
||||
import javax.xml.ws.soap.AddressingFeature;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
|
|
@ -37,9 +38,29 @@ import org.springframework.context.support.GenericApplicationContext;
|
|||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
*/
|
||||
public class JaxWsSupportTests extends TestCase {
|
||||
public class JaxWsSupportTests {
|
||||
|
||||
@Test
|
||||
public void testJaxWsPortAccess() throws Exception {
|
||||
doTestJaxWsPortAccess((Object[]) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJaxWsPortAccessWithFeatureObject() throws Exception {
|
||||
doTestJaxWsPortAccess(new AddressingFeature());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJaxWsPortAccessWithFeatureClass() throws Exception {
|
||||
doTestJaxWsPortAccess(AddressingFeature.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJaxWsPortAccessWithFeatureString() throws Exception {
|
||||
doTestJaxWsPortAccess("javax.xml.ws.soap.AddressingFeature");
|
||||
}
|
||||
|
||||
private void doTestJaxWsPortAccess(Object... features) throws Exception {
|
||||
GenericApplicationContext ac = new GenericApplicationContext();
|
||||
|
||||
GenericBeanDefinition serviceDef = new GenericBeanDefinition();
|
||||
|
|
@ -60,6 +81,9 @@ public class JaxWsSupportTests extends TestCase {
|
|||
clientDef.getPropertyValues().add("serviceName", "OrderService");
|
||||
clientDef.getPropertyValues().add("serviceInterface", OrderService.class);
|
||||
clientDef.getPropertyValues().add("lookupServiceOnStartup", Boolean.FALSE);
|
||||
if (features != null) {
|
||||
clientDef.getPropertyValues().add("webServiceFeatures", features);
|
||||
}
|
||||
ac.registerBeanDefinition("client", clientDef);
|
||||
|
||||
GenericBeanDefinition serviceFactoryDef = new GenericBeanDefinition();
|
||||
|
|
|
|||
Loading…
Reference in New Issue