Announcement Announcement Module
No announcement yet.
Writing to a file from service bean as HTTP invoker Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Writing to a file from service bean as HTTP invoker


    If HttpInvokerServiceExporter is used to export service bean A as HTTP invoker how can A write to a local file in web application's root directory?

    From servlet one would simply do the following:

    ServletContext sc = this.getServletContext();
    path = sc.getRealPath("/path/to/file");
    FileOutputStream fos = new FileOutputStream(path);

    But in the case of service bean A, I am not sure how to achieve this. Ideas?


  • #2
    I suppose the most straightforward way is to have Bean A implementing ServletContextAware. But it couples Bean A with the servlet API, and it could be a problem if Bean A (being a service bean) needs to be called from different servlet contexts in the same web application.


    • #3
      So all I have to do is to have bean A implement ServletContextAware? I've tried that. My bean does not get callback with ServletContext when deployed in DispatcherServlet. Anything else needs to be done (some manual configration)?



      • #4
        Originally posted by vladimir
        Anything else needs to be done (some manual configration)?
        Nothing else as far as I can see... How are you loading your context(s)?


        • #5
          Originally posted by manifoldronin
          Nothing else as far as I can see... How are you loading your context(s)?
          I am not sure what do you mean. I have A,B,C,D beans that are exposed as HttpInvoker(s). The most simple setup through one servlet. I was expecting that spring web will detect that my bean A implements ServletContextAware and give bean A context through setServletContext(ServletContext servletContext) callback when bean A gets deployed/bound as HttpInvoker?

          But setServletContext callback never gets executed.



          • #6
            I looked through the source code (2.0 rc1). It seems that as long as a ServletContextAware bean is declared in an AbstractRefreshableWebApplicationContext, it will get the setter call. And when a context is loaded through either DispatchServlet itself or ContextLoaderListener, the default context class is XmlWebApplicationContext, which extends AbstractRefreshableWebApplicationContext.

            Maybe someone from the Spring Team can shed a light?


            • #7
              Ok, I've looked through the source myself and I found a somewhat crude way to do it. If anyone knows a better solution let me know.

              When HttpInvokerServiceExporter is declared in configuration xml file with a name attribute Spring recognizes this bean and uses BeanNameUrlHandlerMapping to map path and HttpInvokerServiceExporter instance. Another way to map path to HttpInvokerServiceExporter is to use SimpleUrlHandlerMapping and declare mappings from path to beans that are HttpInvokerServiceExporter. For example,

              <bean id="httpinvokers"
              class="org.springframework.web.servlet.handler.Sim pleUrlHandlerMapping">
              <property name="mappings">
              <prop key="/a">httpInvokerA</prop>
              <prop key="/b">httpInvokerB</prop>
              <prop key="/c">httpInvokerC</prop>
              <prop key="/d">httpInvokerD</prop>

              This mapping is executed in SimpleUrlHandlerMapping#initApplicationContext. At that moment bean instance of SimpleUrlHandlerMapping has a valid ServletContext instance since SimpleUrlHandlerMapping implements ServletContextAware.

              Now all that needs to be done is to make a subclass of SimpleUrlHandlerMapping and override initApplicationContext. In that overriden method for each HttpInvokerServiceExporter handler invoke getService() and pass instance of ServletContext to it.

              Thanks for your help manifoldronin.



              • #8
                Actually you were right. All you have to do is have a bean declare ServletContextAware. Oh well, at least I learned some insides of spring.