Announcement Announcement Module
Collapse
No announcement yet.
Question about bean factory usage Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Question about bean factory usage

    Hi,

    I'm just delving into Spring. And I've got many questions.

    I'm confused about Spring and when to use the bean factory. I read in a
    post somewhere here in this forum (sorry I didn't copy down the link) that
    the Spring bean factory shouldn't be used for creating domain objects, but
    should rather be limited to creating DAOs, connections, etc.

    But, then on page 149 of J2EE Development with EJB, the author states
    "One of the main incentives for a lightweight container is to dispense with
    the multitude of custom factores and singletons often found in J2EE
    applications".

    So, should I use Spring for creating my business objects? It seems that if
    I'm using my own custom factories, I'm missing the boat if I don't, and
    rather missing out on the point of Spring (not to mention, I put more
    credence into what Rod Johnson says, than what the poster said).

    As a contrived example, here's yesterday's outmoded code.

    Say I have this factory:
    Code:
    package com.foo.bar;
    
    abstract class ReportWriterFactory {
        protected abstract ReportWriter create();
        private static Map factories = new HashMap();
        public static void addFactory(final String _id,
                                      final ReportWriterFactory _f) {
            factories.put(_id, _f);
        }
    
        public static final ReportWriter createReportWriter(final String _id)
            throws ReportWriterFactoryException {
            if (!factories.containsKey(_id)) {
                try {
                    // Next is loading the class dynamically from disk!
                    Class.forName(_id);
                } catch(ClassNotFoundException e) {
                    throw new ReportWriterFactoryException(_id);
                }
                if (!factories.containsKey(_id))
                    throw new ReportWriterFactoryException(_id);
            }
            return ((ReportWriterFactory)factories.get(_id)).create();
        }
    }
    And then I have classes that register themselves with the above factory, one example being:


    Code:
    package com.foo.bar;
    
    class PDFReportWriter implements ReportWriter {
        private PDFReportWriter() {}
    
        public void doThis() {
        }
    
        public void doThat() {
        }
    
    
        private static class Factory extends ReportWriterFactory {
            protected ReporterWriter create() {
                return new PDFReportWriter();
            }
        }
    
        static {
            ReportWriterFactory.addFactory("com.foo.bar.PDFReportWriter",
                                           new PDFReportWriter.Factory());
        }
    }
    Finally, I have some method that calls the factory method, getting whatever ReportWriter it needs, dynamically (ie at runtime):

    Code:
    pdfReportWriter = ReportWriterFactory.createReportWriter("PDFReportWriter");
                     -- or --
    htmlReportWriter = ReportWriterFactory.createReportWriter("HTMLReportWriter");
                     -- or --
    htmlReportWriter = ReportWriterFactory.createReportWriter("RDFReportWriter");
    etc.
    Well, it seems to me that using the Spring factory beans would be perfect here,
    as it does away with all of my factory code. Is that in fact true? Or should
    I still rely on my own factory code?

    Also, if in fact it's KOSHER AND GOOD to use Spring here, how to I gain access
    to the Application Context in my code (assuming this is a web application)?

    From the Petstore example, I can see that it's stored/gotten in the
    presentation layer. But then, say for the sake of argument, the objects
    I'm creating are in the business layer, does that mean I've got to pass the
    Application Context down to the business layer from the Persistence Layer
    so that I can call "getBean", or have the objects extend a base class that
    holds the Application Context? If so, this seems to go against "the
    Hollywood Principle" (although I realize you can't create these objects
    out of thin air).

    Please help me understand these basics.

    Thanks,
    Tony

  • #2
    Actually, what you said is no contradiction.
    You should (usually) not let Spring manage your domain objects directly. But you could use Spring very well for managing the factories that manage your domain objects.
    This way you have no trouble with factory singletons or replacing factory implementations since you can configure everything.

    As for accessing the application context from a web application: Have a look at org.springframework.web.context.support.WebApplica tionContextUtils.

    Regards,
    Andreas

    Comment


    • #3
      Thank you Andreas for the reply, I greatly appreciate it.

      Your answer leaves me just as baffled as before though. I apologize in advance for being dense...

      Originally posted by Andreas Senft
      You should (usually) not let Spring manage your domain objects directly. But you could use Spring very well for managing the factories that manage your domain objects.
      I'm building an all new app (no legacy code issues), so why shouldn't Spring manage the creation of my domain objects? In the J2EE Development without EJB book, there's at least one example that uses what I think is a "domain object"; the example on page 151 uses a "TextStyle" bean to illustrate the Spring bean factory. Maybe this is just a contrived example for simplicity's sake? Or, maybe my take on what a "domain object" is is all wrong?

      Judging by what I can figure out, I shouldn't have make my own custom factories. In the same book, on page 171, it says "While it's easy to implement a custom factory bean, applications will rarely have to implement the FactoryBean interface but will normally leverage prebuilt resource factories that ship with Spring...".

      Also, in the PDF documentation, Spring java/j2ee Application Framework, Reference Documentation Version 1.1.5, on page 9, there's a quote "...One use for such a bean definition is to call static factories in legacy code" (italics mine). This leads me to believe that I shouldn't have to have custom static factories in my new whizbang code. Now, it's possible, even likely that I'm totally confused and totally missing the point.

      Continuing my previous example, assuming you've got ReportWriter beans like "PDFReportWriter", "RDFReportWriter", "HTMLReportWriter", etc.

      Code:
      public void someClass(String reportType) {
         ReportWriter reportWriter = null;
      
         /* reportType has already been checked to make sure that it's
          * valid.
          */
      
         reportWriter = context.getBean(reportType);
         reportWriter.doThis();
         reportWriter.doThat();
         /* ... */
      }
      In the above snippet of code, the bean relationships would then be "wired up" in a Spring application context xml file (I'm not exactly sure how I do this-- maybe someone can point me in the right direction).

      Isn't the above a good thing to do? Or should I continue along with my custom factories?

      I certainly don't mean to be argumentative, I'm just trying to wrap my brain around what's the best way to leverage what Spring has to offer.

      Thanks again,
      Tony

      Comment


      • #4
        I don't believe there is always a hard and fast rule about what should and shouldn't use Spring wired up objects.

        Judging by what I can figure out, I shouldn't have make my own custom factories. In the same book, on page 171, it says "While it's easy to implement a custom factory bean, applications will rarely have to implement the FactoryBean interface but will normally leverage prebuilt resource factories that ship with Spring...".
        That is very true. In fact if you don't take advantage of any advanced features (transactions, AOP, etc) you don't need to ANY factories. You can specify stand-alone, non factory objects in your Spring XML file. And the ApplicationContext can act as factory itself.

        You would wire up your report writers like so:

        Code:
        <bean id="PDFReportWriter" class="PDFReportWriter">
          <!-- Any properties you want to set on this class -->
          <property name="foo"><value>10</value></property>
        </bean>
        
        <bean id="HTMLReportWriter" class="HTMLReportWriter">
          <!-- Any properties you want to set on this class -->
          <property name="myProperty"><value>myPropertyValue</value></property>
        </bean>
        
        <bean id="RDFReportWriter" class="RDFReportWriter">
          <!-- Any properties you want to set on this class -->
          <property name="bar"><value>10</value></property>
        </bean>

        Comment


        • #5
          Originally posted by wpoitras
          I don't believe there is always a hard and fast rule about what should and shouldn't use Spring wired up objects.
          I agree.

          As of domain objects (as mentioned by the original poster): For myself I discern between, say, "helper" types and real domain objects. Concerning the TextStyle and the ReportWriter (I read the book but haven't it at hand just now) I would classify them in the first category. These seem to be single instances (singletons managed by spring) which can be used where appropriate.

          As true domain objects I see mostly instances which will be frequently created (e.g. by user interaction) and mostly being persisted (or at least persistence capable). These will surely not be managed by Spring.

          Example: If you have an order management system then classes like Customer, Order, OrderItem etc. I would state to be domain objects. A ReportWriter which generates me reports of recent orders of a customer is (in my sense) more a supporting service object than a domain object.

          And if you like to model your domain objects with interfaces and implementing classes you need factories (not necessarily Spring's FactoryBeans). And instead of creating singleton factories yourself (which is discouraged), you can manage these with Spring. That's what I intended to say in my earlier (shorter) posting.

          Regards,
          Andreas

          Comment


          • #6
            Originally posted by wpoitras
            I don't believe there is always a hard and fast rule about what should and shouldn't use Spring wired up objects.
            Thanks for the reply; this helps me understand Spring a little better.

            As with life, using Spring factories in this context is about tradeoffs. The benefits seem to be:
            • 1. Not having to initialize the factory method
              2. Not having to to keep track of the factory reference.
              3. If I'm going to be using Spring anyway (in my case using Spring wrapper ibatis.SqlMapClientFactoryBean) for the DAO layer, then using a Spring factory for my objects keeps things consistent.
              4. A consistent exception handling mechanism.

            The downside might be:
            • 1. Having to deal with XML configuration files, which add complexity to the project.
              2. Having to deal with "black magic" when things go wrong (ie "how do things actually work under the covers?).
              3. Dependency upon yet another jar/library.

            Thanks again for the thoughtful replies.
            Tony

            Comment


            • #7
              Originally posted by Andreas Senft

              As of domain objects (as mentioned by the original poster): For myself I discern between, say, "helper" types and real domain objects. Concerning the TextStyle and the ReportWriter (I read the book but haven't it at hand just now) I would classify them in the first category. These seem to be single instances (singletons managed by spring) which can be used where appropriate.
              This makes perfect sense! My little brain is wrapped a little tighter around Spring now.

              Thanks a lot!
              Tony

              Comment

              Working...
              X