001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.remoting.jaxws; 018 019import java.util.Collections; 020import java.util.LinkedHashSet; 021import java.util.Map; 022import java.util.Set; 023import java.util.concurrent.Executor; 024 025import javax.jws.WebService; 026import javax.xml.ws.Endpoint; 027import javax.xml.ws.WebServiceFeature; 028import javax.xml.ws.WebServiceProvider; 029 030import org.springframework.beans.factory.BeanFactory; 031import org.springframework.beans.factory.BeanFactoryAware; 032import org.springframework.beans.factory.CannotLoadBeanClassException; 033import org.springframework.beans.factory.DisposableBean; 034import org.springframework.beans.factory.InitializingBean; 035import org.springframework.beans.factory.ListableBeanFactory; 036import org.springframework.beans.factory.config.ConfigurableBeanFactory; 037import org.springframework.lang.Nullable; 038import org.springframework.util.Assert; 039 040/** 041 * Abstract exporter for JAX-WS services, autodetecting annotated service beans 042 * (through the JAX-WS {@link javax.jws.WebService} annotation). 043 * 044 * <p>Subclasses need to implement the {@link #publishEndpoint} template methods 045 * for actual endpoint exposure. 046 * 047 * @author Juergen Hoeller 048 * @since 2.5.5 049 * @see javax.jws.WebService 050 * @see javax.xml.ws.Endpoint 051 * @see SimpleJaxWsServiceExporter 052 */ 053public abstract class AbstractJaxWsServiceExporter implements BeanFactoryAware, InitializingBean, DisposableBean { 054 055 @Nullable 056 private Map<String, Object> endpointProperties; 057 058 @Nullable 059 private Executor executor; 060 061 @Nullable 062 private String bindingType; 063 064 @Nullable 065 private WebServiceFeature[] endpointFeatures; 066 067 @Nullable 068 private ListableBeanFactory beanFactory; 069 070 private final Set<Endpoint> publishedEndpoints = new LinkedHashSet<>(); 071 072 073 /** 074 * Set the property bag for the endpoint, including properties such as 075 * "javax.xml.ws.wsdl.service" or "javax.xml.ws.wsdl.port". 076 * @see javax.xml.ws.Endpoint#setProperties 077 * @see javax.xml.ws.Endpoint#WSDL_SERVICE 078 * @see javax.xml.ws.Endpoint#WSDL_PORT 079 */ 080 public void setEndpointProperties(Map<String, Object> endpointProperties) { 081 this.endpointProperties = endpointProperties; 082 } 083 084 /** 085 * Set the JDK concurrent executor to use for dispatching incoming requests 086 * to exported service instances. 087 * @see javax.xml.ws.Endpoint#setExecutor 088 */ 089 public void setExecutor(Executor executor) { 090 this.executor = executor; 091 } 092 093 /** 094 * Specify the binding type to use, overriding the value of 095 * the JAX-WS {@link javax.xml.ws.BindingType} annotation. 096 */ 097 public void setBindingType(String bindingType) { 098 this.bindingType = bindingType; 099 } 100 101 /** 102 * Specify WebServiceFeature objects (e.g. as inner bean definitions) 103 * to apply to JAX-WS endpoint creation. 104 * @since 4.0 105 */ 106 public void setEndpointFeatures(WebServiceFeature... endpointFeatures) { 107 this.endpointFeatures = endpointFeatures; 108 } 109 110 /** 111 * Obtains all web service beans and publishes them as JAX-WS endpoints. 112 */ 113 @Override 114 public void setBeanFactory(BeanFactory beanFactory) { 115 if (!(beanFactory instanceof ListableBeanFactory)) { 116 throw new IllegalStateException(getClass().getSimpleName() + " requires a ListableBeanFactory"); 117 } 118 this.beanFactory = (ListableBeanFactory) beanFactory; 119 } 120 121 122 /** 123 * Immediately publish all endpoints when fully configured. 124 * @see #publishEndpoints() 125 */ 126 @Override 127 public void afterPropertiesSet() throws Exception { 128 publishEndpoints(); 129 } 130 131 /** 132 * Publish all {@link javax.jws.WebService} annotated beans in the 133 * containing BeanFactory. 134 * @see #publishEndpoint 135 */ 136 public void publishEndpoints() { 137 Assert.state(this.beanFactory != null, "No BeanFactory set"); 138 139 Set<String> beanNames = new LinkedHashSet<>(this.beanFactory.getBeanDefinitionCount()); 140 Collections.addAll(beanNames, this.beanFactory.getBeanDefinitionNames()); 141 if (this.beanFactory instanceof ConfigurableBeanFactory) { 142 Collections.addAll(beanNames, ((ConfigurableBeanFactory) this.beanFactory).getSingletonNames()); 143 } 144 145 for (String beanName : beanNames) { 146 try { 147 Class<?> type = this.beanFactory.getType(beanName); 148 if (type != null && !type.isInterface()) { 149 WebService wsAnnotation = type.getAnnotation(WebService.class); 150 WebServiceProvider wsProviderAnnotation = type.getAnnotation(WebServiceProvider.class); 151 if (wsAnnotation != null || wsProviderAnnotation != null) { 152 Endpoint endpoint = createEndpoint(this.beanFactory.getBean(beanName)); 153 if (this.endpointProperties != null) { 154 endpoint.setProperties(this.endpointProperties); 155 } 156 if (this.executor != null) { 157 endpoint.setExecutor(this.executor); 158 } 159 if (wsAnnotation != null) { 160 publishEndpoint(endpoint, wsAnnotation); 161 } 162 else { 163 publishEndpoint(endpoint, wsProviderAnnotation); 164 } 165 this.publishedEndpoints.add(endpoint); 166 } 167 } 168 } 169 catch (CannotLoadBeanClassException ex) { 170 // ignore beans where the class is not resolvable 171 } 172 } 173 } 174 175 /** 176 * Create the actual Endpoint instance. 177 * @param bean the service object to wrap 178 * @return the Endpoint instance 179 * @see Endpoint#create(Object) 180 * @see Endpoint#create(String, Object) 181 */ 182 protected Endpoint createEndpoint(Object bean) { 183 return (this.endpointFeatures != null ? 184 Endpoint.create(this.bindingType, bean, this.endpointFeatures) : 185 Endpoint.create(this.bindingType, bean)); 186 } 187 188 189 /** 190 * Actually publish the given endpoint. To be implemented by subclasses. 191 * @param endpoint the JAX-WS Endpoint object 192 * @param annotation the service bean's WebService annotation 193 */ 194 protected abstract void publishEndpoint(Endpoint endpoint, WebService annotation); 195 196 /** 197 * Actually publish the given provider endpoint. To be implemented by subclasses. 198 * @param endpoint the JAX-WS Provider Endpoint object 199 * @param annotation the service bean's WebServiceProvider annotation 200 */ 201 protected abstract void publishEndpoint(Endpoint endpoint, WebServiceProvider annotation); 202 203 204 /** 205 * Stops all published endpoints, taking the web services offline. 206 */ 207 @Override 208 public void destroy() { 209 for (Endpoint endpoint : this.publishedEndpoints) { 210 endpoint.stop(); 211 } 212 } 213 214}