Announcement Announcement Module
Collapse
No announcement yet.
IoC object creation without importing Spring API Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • IoC object creation without importing Spring API

    I apologize if this has been asked and answered, but I've been unable to find the solution. In short, I thought I could use Spring in my application without ever having Java code which imports classes from the Spring API.

    In my test class, I use the following code to access a bean, defined in
    applicationContext.xml.

    XmlBeanFactory mBeanFactory = new XmlBeanFactory(new
    ClassPathResource("applicationContext.xml", getClass()));
    TestObject test = (TestObject)mBeanFactory.getBean("testObject");
    String strSomething = test.getSomething();
    System.out.println("strSomething = " + strSomething);

    This works fine, in that strSomething has alreaady been injected, since it
    was specified in applicationContext.xml.

    However, I'm unsuccessful in setting this up in a servlet container. I used
    the same applicationContext.xml, and made reference to it from web.xml using
    the following:

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

    <listener>
    <listener-class>org.springframework.web.context.ContextLoade rListener</lis
    tener-class>
    </listener>

    The part that I haven't figured out yet is how to access, get a new
    TestObject *without explicitly using the Spring API in code*. I presume its
    unlikely/unreasonable to expect that Spring, once loaded into the context
    (which does happen as confirmed in log files) will watch for any usage/request for a TestObject and
    instantiate as needed.

    But alas, I've searched far and wide, and only find reference to using through
    Struts/MVC style code which again, is coded to use the Spring API (e.g. WebApplicationContextUtils).

    Please help, is there a way to do this without having the dependency on Spring in Java (declaratively in XML is great, just not java).

  • #2
    In some cases your code will be dependant on Spring. If every object was created by Spring this problem would occur less, but not all objects are create by Spring, so some Spring specific code is required (access to the appcontext is required in those cases).

    And in most cases you will make use of functionality Spring provides, DAO support for example. So 100% Spring independant code is very unlikely.
    Last edited by Alarmnummer; Oct 25th, 2005, 04:50 PM.

    Comment


    • #3
      At a minimum, you'll need to use org.springframework.web.context.support.WebApplica tionContextUtils to get the context and then retrieve the instance of your POJO.

      Comment


      • #4
        You might be able to do this with AspectJ. You could try to create an aspect which would be called anytime a method which returns a TestObject was made from inside a method which was passed a ServletContext. It could use WebApplicationContextUtils to get the object from the ServletContext.

        Unfortunately I haven't studied AspectJ enough to sketch out what you would need to do that. Anybody else want to comment if this is possible?

        Comment


        • #5
          Method Injection

          Maybe I don't fully understand your problem, but if your object is created by Spring, you may use method injection (take a look at the docs).

          This way, Spring replaces an arbitrary method (say getMyBean()) by a method that retrieves objects from Spring, without you or your code knowing it.
          No import is necessary in this case, AFAIK.

          Regards,
          Esteve

          Comment


          • #6
            Originally posted by rstearns01
            At a minimum, you'll need to use org.springframework.web.context.support.WebApplica tionContextUtils to get the context and then retrieve the instance of your POJO.
            In essence, this is the part that I wanted to avoid. I recently attended a Java User's Group meeting where Justin Gehtland (co-author of Spring: A Developer's Notebook) gave a presentation on Spring. At any rate, I seem to recall he said you could have Spring inject dependencies without ever having to refer (import) directly to the Spring API in your Java code.

            Comment


            • #7
              Unfortunately, there has to be some "glue" code. An object instantiated via new, or through reflection, just won't have a handle to the factory/context, and since it wasn't created by the factory, it won't be injected. At some point, you must create, or at least get a handle to, a minimum of one bean that was created by the container. After that, you're in. I'm not aware of any way for an application to be entirely devoid of any Spring reference.

              Comment


              • #8
                Originally posted by athieme
                In essence, this is the part that I wanted to avoid. I recently attended a Java User's Group meeting where Justin Gehtland (co-author of Spring: A Developer's Notebook) gave a presentation on Spring. At any rate, I seem to recall he said you could have Spring inject dependencies without ever having to refer (import) directly to the Spring API in your Java code.
                When you create a class A that depends on class B, you can use Spring IoC to instanciate both A and B, set properties, and inject B instance into A instance. Neither B nor A need to know anything about Spring. But to use these two instances, you have to reference Spring API to access the ApplicationContext. The point is to minimize dependency on Spring API, but I beleive it is "not possible" to avoid it.

                Comment


                • #9
                  athieme,

                  I notice that you're in a web application so, from my experience, the key points to note are the entry points into your application - i.e. servlets, Struts actions, etc. and as long as they're managed by Spring then you shouldn't ever need to know about Spring's classes.

                  Let's take a servlet filter as an example:

                  Suppose you have the class TestFilter. Write this class as normal, wire it up in the bean config file and then use a DelegatingFilterProxy to handle the original request.

                  As TestFilter is now a bean, inject its dependencies using setter methods, e.g. a TestObject, and viola, you have something similar to your original code without needing to go via a BeanFactory.

                  There's similar support for Struts Action classes and probably other web frameworks but, strangely, there doesn't seem to be something like a DelegatingServletProxy but it's relatively easy to implement the principle (for example, I implemented delegating proxies for Struts's tile controllers).

                  HTH,

                  Cuong.

                  Comment


                  • #10
                    Originally posted by cuong

                    I notice that you're in a web application so, from my experience, the key points to note are the entry points into your application - i.e. servlets, Struts actions, etc. and as long as they're managed by Spring then you shouldn't ever need to know about Spring's classes.

                    ...
                    Thanks for the useful suggestion. I too have seen similar code for web applications. However, if I understand what you mean, this may only solve when the entry point is web app based. In fact, the code I am most concerned about, while technically running in JBoss, is decoupled from the app server. Ideally, I could find a solution which would be type safe (e.g. not requiring access to beans through a name/lookup/type cast convention) but also be extensible enough that I wouldn't need to define special methods for each class type.

                    Comment


                    • #11
                      Correct me if I'm wrong but are you looking for a way to do something like

                      Code:
                      public class MyClass
                      {
                         public void someMethod ()
                         {
                             TestObject myTestObject = new TestObject ();
                         }
                      }
                      where new TestObject may be replaced by Spring, automagically returning a bean from the application context?

                      As irbouho said, that's not really possible without maybe using AOP to intercept the construction of TestObject. Your best bet is to have a some kind of factory which is injected into MyClass.

                      Code:
                      public class MyClass {
                         TestObjectFactory toFactory;
                      
                         public void setFactory ( TestObjectFactory tof ) {
                            toFactory = tof;
                         }
                      
                         public void someMethod () {
                             TestObject myTestObject = toFactory.newTestObject ();
                         }
                      }
                      The factory can then decide how it wants to create/acquire a new TestObject instance. OK, it's one more class but it's still ignorant of Spring.

                      My experience is that maybe 85% of my classes have no knowledge of Spring but to harness the full power of Spring you need to use it's API, ideally only in your-own-framework classes.

                      Maybe you can give us an example of your ideal code and we'll try to help

                      Cuong.

                      Comment

                      Working...
                      X