View Javadoc

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          // Take any bean name or alias that has a web service annotation
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 }