Revised WebServiceFeature handling: requiring JAX-WS 2.1+, including support for JAX-WS 2.2 service-level features now

This commit is contained in:
Juergen Hoeller
2013-03-20 12:20:46 +01:00
parent bea990196d
commit bb14c16938
2 changed files with 86 additions and 52 deletions

View File

@@ -48,7 +48,7 @@ import org.springframework.util.StringUtils;
/**
* {@link org.aopalliance.intercept.MethodInterceptor} for accessing a specific
* port of a JAX-WS service. Compatible with JAX-WS 2.0, 2.1 and 2.2.
* port of a JAX-WS service. Compatible with JAX-WS 2.1 and 2.2.
*
* <p>Uses either {@link LocalJaxWsServiceFactory}'s facilities underneath,
* or takes an explicit reference to an existing JAX-WS Service instance
@@ -83,6 +83,8 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
private Map<String, Object> customProperties;
private WebServiceFeature[] portFeatures;
private Object[] webServiceFeatures;
private Class<?> serviceInterface;
@@ -258,10 +260,28 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
}
/**
* Allows for providing JAX-WS 2.1 WebServiceFeature specifications:
* Specify WebServiceFeature objects (e.g. as inner bean definitions)
* to apply to JAX-WS port stub creation.
* <p>Note: This mechanism requires a fully JAX-WS 2.1 compliant provider.
* @see Service#getPort(Class, javax.xml.ws.WebServiceFeature...)
* @see #setServiceFeatures
*/
public void setPortFeatures(WebServiceFeature... features) {
this.portFeatures = features;
}
/**
* Specify WebServiceFeature specifications for the JAX-WS port stub:
* in the form of actual {@link javax.xml.ws.WebServiceFeature} objects,
* WebServiceFeature Class references, or WebServiceFeature class names.
* <p>As of Spring 4.0, this is effectively just an alternative way of
* specifying {@link #setPortFeatures "portFeatures"}. Do not specify
* both properties at the same time; prefer "portFeatures" moving forward.
* @deprecated as of Spring 4.0, in favor of the differentiated
* {@link #setServiceFeatures "serviceFeatures"} and
* {@link #setPortFeatures "portFeatures"} properties
*/
@Deprecated
public void setWebServiceFeatures(Object[] webServiceFeatures) {
this.webServiceFeatures = webServiceFeatures;
}
@@ -406,14 +426,16 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
* {@code Service.getPort(...)}
*/
protected Object getPortStub(Service service, QName portQName) {
if (this.webServiceFeatures != null) {
try {
return new FeaturePortProvider().getPortStub(service, portQName, this.webServiceFeatures);
}
catch (LinkageError ex) {
throw new IllegalStateException(
"Specifying the 'webServiceFeatures' property requires JAX-WS 2.1 or higher at runtime", ex);
if (this.portFeatures != null || this.webServiceFeatures != null) {
WebServiceFeature[] portFeaturesToUse = this.portFeatures;
if (portFeaturesToUse == null) {
portFeaturesToUse = new WebServiceFeature[this.webServiceFeatures.length];
for (int i = 0; i < this.webServiceFeatures.length; i++) {
portFeaturesToUse[i] = convertWebServiceFeature(this.webServiceFeatures[i]);
}
}
return (portQName != null ? service.getPort(portQName, getServiceInterface(), portFeaturesToUse) :
service.getPort(getServiceInterface(), portFeaturesToUse));
}
else {
return (portQName != null ? service.getPort(portQName, getServiceInterface()) :
@@ -421,6 +443,34 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
}
}
/**
* Convert the given feature specification object to a WebServiceFeature instance
* @param feature the feature specification object, as passed into the
* {@link #setWebServiceFeatures "webServiceFeatures"} bean property
* @return the WebServiceFeature instance (never {@code null})
*/
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());
}
}
/**
* Prepare the given JAX-WS port stub, applying properties to it.
* Called by {@link #prepare}.
@@ -533,43 +583,4 @@ 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());
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* 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.
@@ -21,6 +21,7 @@ import java.net.URL;
import java.util.concurrent.Executor;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.handler.HandlerResolver;
import org.springframework.core.io.Resource;
@@ -48,6 +49,8 @@ public class LocalJaxWsServiceFactory {
private String serviceName;
private WebServiceFeature[] serviceFeatures;
private Executor executor;
private HandlerResolver handlerResolver;
@@ -108,6 +111,16 @@ public class LocalJaxWsServiceFactory {
return this.serviceName;
}
/**
* Specify WebServiceFeature objects (e.g. as inner bean definitions)
* to apply to JAX-WS service creation.
* <p>Note: This mechanism requires JAX-WS 2.2 or higher.
* @see Service#create(QName, WebServiceFeature...)
*/
public void setServiceFeatures(WebServiceFeature... serviceFeatures) {
this.serviceFeatures = serviceFeatures;
}
/**
* Set the JDK concurrent executor to use for asynchronous executions
* that require callbacks.
@@ -134,9 +147,18 @@ public class LocalJaxWsServiceFactory {
*/
public Service createJaxWsService() {
Assert.notNull(this.serviceName, "No service name specified");
Service service = (this.wsdlDocumentUrl != null ?
Service.create(this.wsdlDocumentUrl, getQName(this.serviceName)) :
Service.create(getQName(this.serviceName)));
Service service;
if (this.serviceFeatures != null) {
service = (this.wsdlDocumentUrl != null ?
Service.create(this.wsdlDocumentUrl, getQName(this.serviceName), this.serviceFeatures) :
Service.create(getQName(this.serviceName), this.serviceFeatures));
}
else {
service = (this.wsdlDocumentUrl != null ?
Service.create(this.wsdlDocumentUrl, getQName(this.serviceName)) :
Service.create(getQName(this.serviceName)));
}
if (this.executor != null) {
service.setExecutor(this.executor);
@@ -144,6 +166,7 @@ public class LocalJaxWsServiceFactory {
if (this.handlerResolver != null) {
service.setHandlerResolver(this.handlerResolver);
}
return service;
}