提交 4955a730 编写于 作者: J Juergen Hoeller

added support for JAX-WS 2.1 WebServiceFeatures to...

added support for JAX-WS 2.1 WebServiceFeatures to JaxWsPortClientInterceptor/PortProxyFactoryBean (SPR-5712)
上级 11bb7264
...@@ -25,17 +25,22 @@ import javax.xml.ws.BindingProvider; ...@@ -25,17 +25,22 @@ import javax.xml.ws.BindingProvider;
import javax.xml.ws.ProtocolException; import javax.xml.ws.ProtocolException;
import javax.xml.ws.Service; import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException; import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.soap.SOAPFaultException; import javax.xml.ws.soap.SOAPFaultException;
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.AopUtils; 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.beans.factory.InitializingBean;
import org.springframework.remoting.RemoteAccessException; import org.springframework.remoting.RemoteAccessException;
import org.springframework.remoting.RemoteConnectFailureException; import org.springframework.remoting.RemoteConnectFailureException;
import org.springframework.remoting.RemoteLookupFailureException; import org.springframework.remoting.RemoteLookupFailureException;
import org.springframework.remoting.RemoteProxyFailureException; import org.springframework.remoting.RemoteProxyFailureException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/** /**
* {@link org.aopalliance.intercept.MethodInterceptor} for accessing a * {@link org.aopalliance.intercept.MethodInterceptor} for accessing a
...@@ -54,7 +59,7 @@ import org.springframework.remoting.RemoteProxyFailureException; ...@@ -54,7 +59,7 @@ import org.springframework.remoting.RemoteProxyFailureException;
* @see org.springframework.jndi.JndiObjectFactoryBean * @see org.springframework.jndi.JndiObjectFactoryBean
*/ */
public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
implements MethodInterceptor, InitializingBean { implements MethodInterceptor, BeanClassLoaderAware, InitializingBean {
private Service jaxWsService; private Service jaxWsService;
...@@ -74,10 +79,14 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory ...@@ -74,10 +79,14 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
private Map<String, Object> customProperties; private Map<String, Object> customProperties;
private Object[] webServiceFeatures;
private Class<?> serviceInterface; private Class<?> serviceInterface;
private boolean lookupServiceOnStartup = true; private boolean lookupServiceOnStartup = true;
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
private QName portQName; private QName portQName;
private Object portStub; private Object portStub;
...@@ -244,6 +253,15 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory ...@@ -244,6 +253,15 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
getCustomProperties().put(name, value); 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. * Set the interface of the service that this factory should create a proxy for.
*/ */
...@@ -271,6 +289,23 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory ...@@ -271,6 +289,23 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
this.lookupServiceOnStartup = lookupServiceOnStartup; 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() { public void afterPropertiesSet() {
if (this.lookupServiceOnStartup) { if (this.lookupServiceOnStartup) {
...@@ -278,6 +313,9 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory ...@@ -278,6 +313,9 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
} }
} }
/**
* Initialize the JAX-WS port for this interceptor.
*/
public void prepare() { public void prepare() {
if (getServiceInterface() == null) { if (getServiceInterface() == null) {
throw new IllegalArgumentException("Property 'serviceInterface' is required"); throw new IllegalArgumentException("Property 'serviceInterface' is required");
...@@ -287,8 +325,7 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory ...@@ -287,8 +325,7 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
serviceToUse = createJaxWsService(); serviceToUse = createJaxWsService();
} }
this.portQName = getQName(getPortName() != null ? getPortName() : getServiceInterface().getName()); this.portQName = getQName(getPortName() != null ? getPortName() : getServiceInterface().getName());
Object stub = (getPortName() != null ? Object stub = getPortStub(serviceToUse, (getPortName() != null ? this.portQName : null));
serviceToUse.getPort(this.portQName, getServiceInterface()) : serviceToUse.getPort(getServiceInterface()));
preparePortStub(stub); preparePortStub(stub);
this.portStub = stub; this.portStub = stub;
} }
...@@ -312,6 +349,23 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory ...@@ -312,6 +349,23 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
return this.portQName; 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. * Prepare the given JAX-WS port stub, applying properties to it.
* Called by {@link #prepare}. * Called by {@link #prepare}.
...@@ -424,4 +478,44 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory ...@@ -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());
}
}
}
} }
/* /*
* 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -19,9 +19,7 @@ package org.springframework.remoting.jaxws; ...@@ -19,9 +19,7 @@ package org.springframework.remoting.jaxws;
import javax.xml.ws.BindingProvider; import javax.xml.ws.BindingProvider;
import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
import org.springframework.util.ClassUtils;
/** /**
* {@link org.springframework.beans.factory.FactoryBean} for a specific port of a * {@link org.springframework.beans.factory.FactoryBean} for a specific port of a
...@@ -34,17 +32,11 @@ import org.springframework.util.ClassUtils; ...@@ -34,17 +32,11 @@ import org.springframework.util.ClassUtils;
* @see LocalJaxWsServiceFactoryBean * @see LocalJaxWsServiceFactoryBean
*/ */
public class JaxWsPortProxyFactoryBean extends JaxWsPortClientInterceptor public class JaxWsPortProxyFactoryBean extends JaxWsPortClientInterceptor
implements FactoryBean<Object>, BeanClassLoaderAware { implements FactoryBean<Object> {
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
private Object serviceProxy; private Object serviceProxy;
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
@Override @Override
public void afterPropertiesSet() { public void afterPropertiesSet() {
super.afterPropertiesSet(); super.afterPropertiesSet();
...@@ -54,7 +46,7 @@ public class JaxWsPortProxyFactoryBean extends JaxWsPortClientInterceptor ...@@ -54,7 +46,7 @@ public class JaxWsPortProxyFactoryBean extends JaxWsPortClientInterceptor
pf.addInterface(getServiceInterface()); pf.addInterface(getServiceInterface());
pf.addInterface(BindingProvider.class); pf.addInterface(BindingProvider.class);
pf.addAdvice(this); pf.addAdvice(this);
this.serviceProxy = pf.getProxy(this.beanClassLoader); this.serviceProxy = pf.getProxy(getBeanClassLoader());
} }
......
/* /*
* 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -18,14 +18,15 @@ package org.springframework.remoting.jaxws; ...@@ -18,14 +18,15 @@ package org.springframework.remoting.jaxws;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider; import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service; import javax.xml.ws.Service;
import javax.xml.ws.WebServiceClient; import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceRef; 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.BeanCreationException;
import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.GenericBeanDefinition;
...@@ -37,9 +38,29 @@ import org.springframework.context.support.GenericApplicationContext; ...@@ -37,9 +38,29 @@ import org.springframework.context.support.GenericApplicationContext;
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 2.5 * @since 2.5
*/ */
public class JaxWsSupportTests extends TestCase { public class JaxWsSupportTests {
@Test
public void testJaxWsPortAccess() throws Exception { 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(); GenericApplicationContext ac = new GenericApplicationContext();
GenericBeanDefinition serviceDef = new GenericBeanDefinition(); GenericBeanDefinition serviceDef = new GenericBeanDefinition();
...@@ -60,6 +81,9 @@ public class JaxWsSupportTests extends TestCase { ...@@ -60,6 +81,9 @@ public class JaxWsSupportTests extends TestCase {
clientDef.getPropertyValues().add("serviceName", "OrderService"); clientDef.getPropertyValues().add("serviceName", "OrderService");
clientDef.getPropertyValues().add("serviceInterface", OrderService.class); clientDef.getPropertyValues().add("serviceInterface", OrderService.class);
clientDef.getPropertyValues().add("lookupServiceOnStartup", Boolean.FALSE); clientDef.getPropertyValues().add("lookupServiceOnStartup", Boolean.FALSE);
if (features != null) {
clientDef.getPropertyValues().add("webServiceFeatures", features);
}
ac.registerBeanDefinition("client", clientDef); ac.registerBeanDefinition("client", clientDef);
GenericBeanDefinition serviceFactoryDef = new GenericBeanDefinition(); GenericBeanDefinition serviceFactoryDef = new GenericBeanDefinition();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册