1 package org.codehaus.xfire.spring.remoting;
2
3 import org.codehaus.xfire.XFire;
4 import org.codehaus.xfire.aegis.AegisBindingProvider;
5 import org.codehaus.xfire.aegis.type.TypeMappingRegistry;
6 import org.codehaus.xfire.annotations.AnnotationServiceFactory;
7 import org.codehaus.xfire.annotations.WebAnnotations;
8 import org.codehaus.xfire.service.Service;
9 import org.codehaus.xfire.service.ServiceInfo;
10 import org.codehaus.xfire.service.binding.BeanInvoker;
11 import org.codehaus.xfire.service.binding.ObjectBinding;
12 import org.codehaus.xfire.wsdl11.WSDL11ParameterBinding;
13 import org.springframework.beans.BeansException;
14 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
15 import org.springframework.context.ApplicationContextException;
16 import org.springframework.context.ConfigurableApplicationContext;
17 import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping;
18 import org.springframework.web.servlet.mvc.Controller;
19
20 /***
21 * Implementation of the {@link org.springframework.web.servlet.HandlerMapping} interface that recognizes {@link
22 * org.codehaus.xfire.annotations.WebServiceAnnotation web service annotations} on Spring-managed beans and
23 * automatically wires them into the current servlet's WebApplicationContext.
24 * <p/>
25 * All beans Services are exposed by their {@link org.codehaus.xfire.annotations.WebServiceAnnotation#getServiceName()
26 * service name}, with a defined {@link #setUrlPrefix(String) prefix}. For instance, a bean annotated with the service
27 * name <code>EchoService</code> will be exposed as <code>/services/EchoService</code>.
28 *
29 * @author <a href="mailto:poutsma@mac.com">Arjen Poutsma</a>
30 * @see WebAnnotations
31 * @see org.codehaus.xfire.annotations.WebServiceAnnotation
32 */
33 public class Jsr181HandlerMapping
34 extends AbstractUrlHandlerMapping
35 {
36 private WebAnnotations webAnnotations;
37 private XFire xFire;
38 private TypeMappingRegistry typeMappingRegistry;
39 private String urlPrefix = "/services/";
40
41
42 protected void initApplicationContext()
43 throws BeansException
44 {
45 if (!(getApplicationContext() instanceof ConfigurableApplicationContext))
46 {
47 throw new ApplicationContextException(
48 "[" + getClass().getName() + "] needs to run in a ConfigurableApplicationContext");
49 }
50 ConfigurableListableBeanFactory beanFactory =
51 ((ConfigurableApplicationContext) getApplicationContext()).getBeanFactory();
52
53 String[] beanNames = getApplicationContext().getBeanDefinitionNames();
54
55 AnnotationServiceFactory serviceFactory =
56 new AnnotationServiceFactory(webAnnotations,
57 xFire.getTransportManager(),
58 new AegisBindingProvider(typeMappingRegistry));
59
60
61 for (int i = 0; i < beanNames.length; i++)
62 {
63 Class clazz = getApplicationContext().getType(beanNames[i]);
64 if (webAnnotations.hasWebServiceAnnotation(clazz))
65 {
66 Service endpoint = serviceFactory.create(clazz);
67 ServiceInfo service = endpoint.getServiceInfo();
68 if (logger.isInfoEnabled())
69 {
70 WSDL11ParameterBinding binding = (WSDL11ParameterBinding) endpoint.getBinding();
71 logger.info("Exposing SOAP v." + endpoint.getSoapVersion().getVersion() + " service " +
72 service.getName() + " to " + urlPrefix + endpoint.getName() +
73 " as " + binding.getStyle() + "/" + binding.getUse());
74 }
75
76 xFire.getServiceRegistry().register(endpoint);
77 ((ObjectBinding) endpoint.getBinding()).setInvoker(new BeanInvoker(beanFactory.getBean(beanNames[i])));
78 Controller controller = new XFireServletControllerAdapter(xFire, endpoint.getServiceInfo().getName());
79 registerHandler(urlPrefix + endpoint.getName(), controller);
80 }
81 else
82 {
83 if (logger.isDebugEnabled())
84 {
85 logger.debug("Rejected bean '" + beanNames[i] + "' since it has no WebService annotation");
86 }
87 }
88 }
89 }
90
91 /***
92 * Sets the web annotations implementation to use.
93 */
94 public void setWebAnnotations(WebAnnotations webAnnotations)
95 {
96 this.webAnnotations = webAnnotations;
97 }
98
99 /***
100 * Sets the XFire instance.
101 */
102 public void setXfire(XFire xFire)
103 {
104 this.xFire = xFire;
105 }
106
107 /***
108 * Sets the type mapping registry.
109 */
110 public void setTypeMappingRegistry(TypeMappingRegistry typeMappingRegistry)
111 {
112 this.typeMappingRegistry = typeMappingRegistry;
113 }
114
115 /***
116 * Sets the url prefix used when exposing services. Defaults to <code>/services/</code>.
117 */
118 public void setUrlPrefix(String urlPrefix)
119 {
120 this.urlPrefix = urlPrefix;
121 }
122 }