Announcement Announcement Module
Collapse
No announcement yet.
Servlet DI Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    A year ago (?) someone created something that would do DI into a servlet, if I remember correctly. Or perhaps it was just related to unit testing.

    Its probably in the older forum messages.

    Comment


    • #17
      Any further developments here?

      I a trying to move some legacy servlets into an environment that is otherwise utilzing springs AOP and IoC capabilities. Thus, DI for these servlets would be a big help to me. It seems that the Struts-centered solution employing the ServletWrappingController comes very close to a solution applicable to servlet DI in general and would only need to allow a <ref bean="foo"/> capability to accomplish it.

      ... my legacy app uses applets to post to these servlets.... try using jsf for that ( and fully justify it) ....and webservices must wait.

      As soon as I can synch up the applets post sessions with the UI's I will know if I an employ Rod's suggestion... but a non-static bootstrap would take away the Spring code dependencies.

      Best Regards
      Jp

      Comment


      • #18
        Originally posted by Rod Johnson View Post
        You can call WebApplicationContextUtils.getWebApplicationContex t(ServletContext), get the bean factory, cast it to AutowireCapableBeanFactory (which is safe) and call autowireBeanProperties on the servlet. This will give you setter injection.
        Can you be more specific?
        I tried, but it doesn't work. This is my code:
        Code:
        @Override
        	public void init(ServletConfig config) throws ServletException {	
        		super.init(config);
        		
        		WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(config.getServletContext());
        		
        		AutowireCapableBeanFactory factory = context.getAutowireCapableBeanFactory();
        		
        		factory.autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
        	}

        Comment


        • #19
          If I use factory.applyBeanPropertyValues(this, beanName), it works.

          Is it a correct way to do?

          [Edit]
          All right, it works now. But if I want to inject primitive values such as String, can I use autowireBeanProperties()?
          Last edited by Mr.A; Nov 25th, 2008, 04:34 AM. Reason: Add more comment

          Comment


          • #20
            i dont see a reason why Spring should inject directly something into a servlet.

            As servlets are running in the web container, the lifecycle and management of the servlet is done there... Spring has it's own IoC container which manages the POJO-friendly beans.

            I dont see any reason why someone should inject a bean into a servlet.

            Comment


            • #21
              The reason is if I don't use a web MVC framework, and I don't implement page controllers, just use servlets that delegate to POJOs.

              It's good if I can inject POJOs to servlets.

              All right, it works now. But if I want to inject primitive values such as String, can I use autowireBeanProperties()?
              For this question, Spring doesn't support autowire primitive values.

              Please also note that it is not currently possible to autowire so-called simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). (This is by-design and should be considered a feature.)

              Comment


              • #22
                It is possible; use ServletContextAttributeExporter

                This thread is almost 3 years old... It is possible to inject your POJOs (Spring-defined) into the servlet context from where your servlet code will be able to extract them. It's very easy.

                1) Define your POJO bean that will be used by a servlet - in your Spring context configuration file.

                2) To ensure that the instance of that object is injected into the web application's servlet context and is accessible in that context as an attribute, an entry for this bean must be added to the application's ServletContextAttributeExporter definition - also in one of your application's Spring context files. Here's how:

                Code:
                    <bean id="myBean1" class="com.yourcompany.something.MyService" />
                    ....
                    
                    <!-- definition for the Exporter object that puts Spring-defined beans into a Servlet Context as attributes -->
                    <!-- The exported beans will be accessible in the Servlet Context via the attributes' keys -->
                    
                    <bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
                        <property name="attributes">
                            <map>
                                <entry key="lookupAttr1" value-ref="myBean1"/>
                                <entry key="lookupAttr2" value-ref="myBean2"/>
                            </map>
                        </property>
                    </bean>
                3) The servlet code will be able to retrieve an instance of each bean exported into the servlet context in the following manner:

                Code:
                MyService mySvc = (MyService) getServletContext().getAttribute("lookupAttr1");
                where "lookupAttr1" is the look-up key specified in the ServletContextAttributeExporter's attribute entry for the bean of type "MyService " in the servlet context.

                If you want to inject "primitives" into your servlet context, why not package them inside a custom bean first? It's easier to group things in some config object anyway.

                This will make your servlet totally Spring-agnostic. The only caveat is that it needs to know which attribute to look up in its context. Of course, the servlet must be defined in your web.xml (d'oh!) and live in the same war with your spring-configured stuff.

                I don't know why this is not very well documented. As the result I see many people trying to re-invent the wheel and come up with crafty ways of injecting Spring-configured beans into servlets.
                Last edited by constv; Nov 26th, 2008, 10:08 AM.

                Comment


                • #23
                  what is the goal/reason of injecting something into a bean that is not managed by spring? There are very simple ways to retrieve the beans from the beanfactory, which seems the logical way to me

                  Comment


                  • #24
                    Originally posted by uenluena View Post
                    what is the goal/reason of injecting something into a bean that is not managed by spring? There are very simple ways to retrieve the beans from the beanfactory, which seems the logical way to me
                    I am sure you know that you can have multiple servlets deployed inside a single war, and often you have reasons to do just that.

                    You may have an independent little servlet deployed with your Spring application that your views access directly via a link/tag. For example, it may be some Spring-agnostic servlet that pours generated content into a section of the view that calls it. That servlet could be reused in various applications to generate various types of content. If implemented properly, such servlet should delegate all its logic to some POJO(s) that actually generate the content and produce a stream. The servlet can just expect to retrieve the correct content generator from its context, query it for the content type, call some "generate" method on it, and write the resulting stream to the Response using the appropriate type... Something like that... You write the actual POJO that does the work, configure and load it into the current application context through Spring. (You don't want to burn your reusable content generation code into the servlet itself, but would rather have it as a reusable java class, right?) That same POJO may also be used by other modules in your application. So, you want such servlet to be deployed with your app and reuse that POJO. You export that POJO to the servlet context using ServletContextAttributeExporter. This way, the functionality is not only available to the other services in your Spring app, but also to any Spring-agnostic stand-alone servlets that are defined in your application's web.xml.

                    Cheers,
                    Constantine

                    Comment


                    • #25
                      its not about using the spring managed beans...which is fine and i see no problem with it...

                      If i have a IoC container that is responsible for the lifcycle of my beans and on the other hand my portlet/servlet container that is responsible for the lifecycle of those modules, i see no reason why someone should try to inject a bean into a servlet...

                      By using the WebApplicationContextUtils class you can get a bean that is managed bye spring and load them in your servlet

                      Non of the stuff you describe, justifies or explains why its necessary to inject a bean into a servlet and not use the Application Context utility classes in the Spring Framework to load a bean from the BeanFactory.

                      If i want to delegate the logic/job to a POJO, which you should always do in my opinion and not put any business logic to a servlet, then you can do that without problems...

                      This is what i do on a daily basis....im using Servlets and Portlets and access my Service functionality through Business Delegators...

                      Those business delegators are encapsulated with a bean utility that is context aware and can load the Service Beans from a FacesContext (we're using faces portlets) or from the Servlet Context. The developer uses just

                      BeanUtils.getABCBusinessDelegateFactory().createMy OrderService().getAllOrders();

                      And this lookup is used in every environment the same way...Servlet or Portlet world...The framework in the background resolves the rest...

                      Comment


                      • #26
                        Originally posted by uenluena View Post

                        By using the WebApplicationContextUtils class you can get a bean that is managed bye spring and load them in your servlet
                        Well, d'oh... Of course you can make your servlet or portlet Spring-aware, and easily get any bean out of the web application context! This discussion was not about that.The question was about "injecting" Spring-managed beans into a servlet that is not aware of Spring. This is the general philosophy of Spring - to allow people to program POJOs, and other types of Java classes without forcing them to be aware of Spring itself, and then use Spring to wire them together in an application. Personally, I see no issue having a servlet that has a Spring dependency. But exactly for the purpose of allowing people to code "pure" servlets that would work with or without Spring, the ServletContextAttributeExporter class was introduced - by Juergen Hoeller, I believe. It injects Spring managed beans into a servlet context, not the instance of the servlet. After that, the servlet can extract it in a good old-fashioned way - as a context attribute.

                        Comment


                        • #27
                          Yeah Juergen Hoeller also wrote the SqlMapClientDaoSupport, which is at the end also forcing you to be "aware" of Spring ;-)

                          In an ideal world the developer would just write the code as Spring would not be there and someone, lets call him the Wire-man, would wire all the beans through the configuration.

                          As you can see in my cases...one cant totally avoid of being "aware" of spring ;-D

                          Comment


                          • #28
                            As you can see in the javadoc of the api, he also mentiones the usage of the WebApplicationContextUtils class, but points out that this would make the used context Spring aware, which is the case in many classes that are provided with the Spring API

                            Comment


                            • #29
                              Originally posted by constv View Post
                              Well, d'oh... Of course you can make your servlet or portlet Spring-aware, and easily get any bean out of the web application context! This discussion was not about that.The question was about "injecting" Spring-managed beans into a servlet that is not aware of Spring.
                              Correct. This topic is about "dependency injection", not about "service locator".

                              Originally posted by constv View Post
                              But exactly for the purpose of allowing people to code "pure" servlets that would work with or without Spring, the ServletContextAttributeExporter class was introduced - by Juergen Hoeller, I believe. It injects Spring managed beans into a servlet context, not the instance of the servlet. After that, the servlet can extract it in a good old-fashioned way - as a context attribute.
                              I think using ServletContextAttributeExporter is the best option, there will not be dependency to Spring API in servlet code, a servlet just needs to know that the things it want to use are in ServletContext.

                              Comment


                              • #30
                                Originally posted by uenluena View Post
                                Yeah Juergen Hoeller also wrote the SqlMapClientDaoSupport, which is at the end also forcing you to be "aware" of Spring ;-)

                                In an ideal world the developer would just write the code as Spring would not be there and someone, lets call him the Wire-man, would wire all the beans through the configuration.

                                As you can see in my cases...one cant totally avoid of being "aware" of spring ;-D
                                SqlMapClientDaoSupport is just a utility class to use SqlMapClient easier, it's a different case. It's totally up to us to use it or not, Spring framework doesn't force us to use it, it's for convenient. If we don't want to use SqlMapClientDaoSupport we can work with iBATIS API directly (we inject SqlMapClient implementation by using DI of course ).

                                But about dependency injection, client code doesn't need to know that what happens behind the scene.

                                [Edit]
                                To be more specific, using DI decouple client code from IoC container, so we don't need to use Spring, we can change to other IoC container that support setter injection for example.
                                Last edited by Mr.A; Nov 26th, 2008, 10:03 PM. Reason: Add more info.

                                Comment

                                Working...
                                X