From bb14c16938d3b885a032243ced30d461c62affa8 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 20 Mar 2013 12:20:46 +0100 Subject: [PATCH] Revised WebServiceFeature handling: requiring JAX-WS 2.1+, including support for JAX-WS 2.2 service-level features now --- .../jaxws/JaxWsPortClientInterceptor.java | 107 ++++++++++-------- .../jaxws/LocalJaxWsServiceFactory.java | 31 ++++- 2 files changed, 86 insertions(+), 52 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/remoting/jaxws/JaxWsPortClientInterceptor.java b/spring-web/src/main/java/org/springframework/remoting/jaxws/JaxWsPortClientInterceptor.java index 9efd206e5f..815f15e932 100644 --- a/spring-web/src/main/java/org/springframework/remoting/jaxws/JaxWsPortClientInterceptor.java +++ b/spring-web/src/main/java/org/springframework/remoting/jaxws/JaxWsPortClientInterceptor.java @@ -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. * *

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 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. + *

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. + *

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()); - } - } - } - } diff --git a/spring-web/src/main/java/org/springframework/remoting/jaxws/LocalJaxWsServiceFactory.java b/spring-web/src/main/java/org/springframework/remoting/jaxws/LocalJaxWsServiceFactory.java index 7f95b3acd6..c3f5c35ed0 100644 --- a/spring-web/src/main/java/org/springframework/remoting/jaxws/LocalJaxWsServiceFactory.java +++ b/spring-web/src/main/java/org/springframework/remoting/jaxws/LocalJaxWsServiceFactory.java @@ -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. + *

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; }