Announcement Announcement Module
Collapse
No announcement yet.
Trying to understand dependency injection with spring - newbie. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Trying to understand dependency injection with spring - newbie.

    Hi there,

    I'm trying to create a simple Spring example using beans and annotations, but my @Autowired does not seem to work, nor does the container seem to instantiate my bean automatically. This is what I did:

    1. In web.xml, set up a org.springframework.web.context.ContextLoaderListe ner and pointed the contextConfigLocation listener to by XML doc, /WEB-INF/spring-context.xml

    2. Created spring-context.xml in such a way that the entire system uses annotation-based configuration and set up the "base-package" as the lowest common denominator as follows:

    Code:
    <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:context="http://www.springframework.org/schema/context"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
             http://www.springframework.org/schem...-beans-3.0.xsd
             http://www.springframework.org/schema/context
             http://www.springframework.org/schema/context/spring-context-3.0.xsd">
                 
    
        <context:annotation-config base-package="com.foxbomb.springtest"/>
    
    </beans>
    3. Set up a @Service Service Bean - which doesn't get instantiated... as such:

    Code:
    package com.foxbomb.springtest.domain.time;
    
    import java.util.Date;
    import org.springframework.stereotype.Service;
    
    @Service
    public class TimeService {
    
        public TimeService() {
            System.out.println("Instantiating Time Service");
        }    
        
        public Date getTime() {
            return new Date();
        }
    }
    4. Then I set up a class, that every time I instantiate it, realizes that it's a Spring configured class (annotated with @configurable), and injects the dependencies automatically. This is TimeManager.class. Here the @Autowired dependency seems to fail:

    Code:
    package com.foxbomb.springtest;
    
    import com.foxbomb.springtest.domain.time.TimeService;
    import java.util.Date;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Configurable
    public class TimeManager {
        
        public TimeManager() {
            System.out.println("Instantiating Time Manager");
        }
        
        @Autowired
        protected TimeService timeService;
        
        public Date getTime() {
            return timeService.getTime();
        }
        
    }
    5. Then I created a JSP, for the simple purpose of interrogating the TimeManager class. Instantiating the TimeManager class in the JSP I hoped, would wake up Spring (cause it's @configurable) and quickly inject the protected TimeService timeService dependency in for me. Alas, the JSP reports a NullPointerException at return timeService.getTime();

    Code:
    <%@page import="com.foxbomb.springtest.ApplicationContextImpl"%>
    <%@page import="com.foxbomb.springtest.TimeManager"%>
    <%! TimeManager manager = new TimeManager(); %>
    <html>
        <body>
            <h1>Autowired Dependencies....</h1>
            <p>
                Time is now <%=manager.getTime()%>!
            </p>
            
        </body>
    </html>
    What am I doing wrong? Your help is greatly appreciated...
    Last edited by SparkySpider; Oct 3rd, 2011, 04:19 AM.

  • #2
    Last time I checked, <context:annotation-config/> only registers common bean post-processors that handle @Autowired an other annotations, and it does not have a base-package attribute. I assume you want to automatically register all @Component beans (and the like) in some base backage - that's what <context:component-scan base-package="..."/> is for.

    For @Configurable to work, you need to setup some AspectJ magic. This ain't exactly "simple Spring example" - it's an advanced technique that is also of limited use (I for one never actually needed it in any of my real life projects). If you insist on doing @Configurable stuff, read through AspectJ section in Spring docs - you will need <context:spring-configured/> and some container-specific configuration to enable load-time weaving.

    Comment


    • #3
      For starters please use [ code][/code ] tags that way your code actually remains readable ..

      As the previous poster already mentioned context:annotation-config doesn't do anything but register some post-processors (it doesn't even have a base-package attribute so I would expect your application to blow up). What you want is context:component-scan which does register the post processors AND scans packages for @Component annotated classed (@Service is a @Component).

      I suggest a read of the reference guide and take a look at the sample application.

      Comment


      • #4
        Originally posted by Marten Deinum View Post
        For starters please use [ code][/code ] tags that way your code actually remains readable ..

        As the previous poster already mentioned context:annotation-config doesn't do anything but register some post-processors (it doesn't even have a base-package attribute so I would expect your application to blow up). What you want is context:component-scan which does register the post processors AND scans packages for @Component annotated classed (@Service is a @Component).

        I suggest a read of the reference guide and take a look at the sample application.
        Hi Marten,

        Thanks for your warm welcome.

        Apologies for not using the tags. I didn't see recognize them in the toolbar - sorry I'm new to both Spring and this forum. I see that I made a TYPO.

        Fortunately, Osvaldas, in his USEFUL post kindly pointed that out, and that fixed my first problem. Since then I've been reading about Ajpect/J and Weaving.

        I have read almost the entire Spring 3.0.0 reference guide, and checked out various tutorials and still find it confusing - hence posting to the forum.

        Thanks,

        Mark

        Comment


        • #5
          Thanks for that. I made a silly mistake in my XML. The system is now loading my beans. Tell me, I couldn't find a simple way to access a bean in the documentation. As you know, I assumed that @Confurable and @Autowired would simply magically return a reference to my bean (not knowing that the example I was shown was an Aspect/J Weaving Magic Example).

          There is this common problem I find in web application development where you can't easily get hold of the ServletContext or ApplicationContext from your business logic - which is interrogated from the web tier. I thought the whole point of Spring is that it solves problems like these. In my above example, I created a TimeManager that could easily be instantiated from anywhere, hoping that it could find a reference to my bean and return that to my JSP.

          I know that a MVC approach using controllers and saving model parameters would be the "smart" way to do this, but I'm more interested in getting access to my beans from strange places. I'm planning on using .zul pages (ZK Framworks) and having their "code-behind" pages (GenericForwardComposer) be able to easily access business login from Spring beans.

          Pointing me in the right direction would be appreciated.

          Thanks,

          Mark

          Comment


          • #6
            Create a class which is ApplicationContextAware and configure it in your spring context. Make a static getBean method on it and you have an easy way to access the ApplicationContext/Beans anywhere. Not that I would recommend it because in general that is an anti-pattern (at least in my book). In general an Object that needs access to other objects should simply be given those dependencies (dependency injection), next to that you want to keep your view layer clean and not directly access the service (or even worst data) layer of your application (that is the whole point of MVC).

            Comment


            • #7
              There is this common problem I find in web application development where you can't easily get hold of the ServletContext or ApplicationContext from your business logic - which is interrogated from the web tier. I thought the whole point of Spring is that it solves problems like these.
              Business logic components by definition should not be concerned about the infrastructure they're running in, that is, they should not care about ServletContext (infrastructure of web container) nor ApplicationContext (infrastructure of DI container). Spring does solve this problem by helping you write context-independent POJO @Components which simply declare their inter-dependencies through fields, constructor args or arbitrary method args. You will typically want to access ApplicationContext only if you're extending Spring or integrating it to some other framework or library.

              I know that a MVC approach using controllers and saving model parameters would be the "smart" way to do this, but I'm more interested in getting access to my beans from strange places. I'm planning on using .zul pages (ZK Framworks) and having their "code-behind" pages (GenericForwardComposer) be able to easily access business login from Spring beans.
              A Spring-based web application will typically have some "root" class which is aware of ServletContext and which instantiates top-level Spring beans by doing explicit lookup against ApplicationContext - the method that Marten mentioned. This is usually hidden behind Spring infrastructure, e.g. in Spring MVC the DispatcherServlet is responsible for loading and invoking various @Controllers based on HTTP request. If you do not use Spring MVC and you want to get a handle of some Spring beans, you should either look for Spring integration in your presentation framework of choice (the preferred way) or do an explicit dependency lookup against ApplicationContext (not very elegant). I have never used ZK, but I can see that Spring integration is mentioned in their feature list, so be sure to check that out.

              Comment

              Working...
              X