Announcement Announcement Module
No announcement yet.
How to use default-lazy-init to speed app development debug cycles Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to use default-lazy-init to speed app development debug cycles

    Hi, everyone.

    We have a very large spring app, with multiple imported application context files imported by the root (top-level) app context file. I noticed (kinda hard to ignore :-)) that it was taking about 7-10 minutes to start up a POJO test of the functionality. I added TRACE level logging to the spring packages and can see that all of the time is being taken up in spring loading of the app config this statement in my POJO's main method:

    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-DataFix.xml"); I googled around and found out about default-lazy-init="true", which I assumed would speed up the above statement. It didn't, so I googled some more and found this: I coded that as described and added it to my POJO test class's main method, so it now looks like this:

    ApplicationContext context = new LazyClassPathXmlApplicationContext("applicationCon text-DataFix.xml");

    Sometimes, the above statement runs in about a minute. Other times, it runs in the (unacceptable) 7-10 minutes. I cannot yet get a pattern on why it loads fast sometimes and not others. I've tried all kinds of stuff, including coming out of Eclipse, checking for left-over java processes and so on, trying to imagine what's going on back there.

    On the surface, it appears that default-lazy-init (in the <beans> element or programmatically as above) just doesn't work (or works randomly)....but I'm betting I'm just missing something simple about it, since it looks like it's been around for a while.

    Also, I'm seeing lots of log statements like this: istableBeanFactory - Creating shared instance of singleton bean 'productTransChannelVOValidator'

    ...and this: istableBeanFactory - Returning cached instance of singleton bean 'updateProductTransRelatedVOValidator'

    and I'm wondering why Spring would be creating these bean instances and returning the cached ones, when I just told Spring to not do that?

    The bottom line is that I want to configure Spring so that it eagerly inits (and caches) in the deployed environments and lazily inits (and doesn't cache diddly-squat) when I'm step-debugging in Eclipse, since there's no point in eagerly init'ing 500 spring beans when I'm only going to use 5 of them on this particular debug cycle ("debug cycle" meaning I run the driving POJO, step through the code, see a bug, stop the debug run, fix the bug, save the class and run the POJO again).

    High-level, I have 2 questions:

    1. Does the reason I want to do this make sense? (I'm betting it will coz I'm seeing many other who want to do the same and can't make it happen). Assuming it makes sense....

    2. How do I make this happen? i.e. how do I use default-lazy-init (or possibly some other Spring flag/flags) to tell Spring not to instantiate or cache or even reflect on a bean class until I attempt to instantiate the bean at statement execution time?

    Ben Ethridge

  • #2
    Lazy-init is just an indication to spring to defer the creation of the bean until it is needed i.e. it is referenced.

    <bean id="b1" class="SomeBean">
      <property name="b2" ref="b2" />
    <bean id="b2" class="SomeOtherBean" lazy-init="true" />
    The above code basically renders the lazy-init useless as 'b1' is still constructed and needs 'b2' and as such 'b2' is still needed.

    So if you mark evereything lazy but you still have controllers (which are always instantiated because spring needs to detect the requestmappings) basically evereything will be instantiated because a controller probably needs a service, which needs a dao which... Well you probably get the point.


    • #3
      So all Spring lazy-init's (default- or bean-level) are effectively useless?

      If so, then why did they write the things? What problem were they intended to solve?



      • #4
        It depends on your application. If you make all beans lazy and load all beans in a testcase (without your controllers) you effectivly load nothing and only instantiate the beans you need (the beans which are @Autowired in the testcase all other non related beans aren't constructed).

        The same goes for an application in which one only needs to get a bean in a certain situation (factory bean which does some selection of which bean to use for instance).

        So there are some usecases but one can wonder how useful it actually is. You can always wrap all the beans in a LazyInitTargetSource which will only instantiate the beans when there are actuall calls to the underlying object.


        • #5
          "Always"? I don't think I can wrap all the beans in LazyInitTargetSource. There are hundreds of them and this is a production app, not a new app, so I'm not free to change much just to speed up unit testing...unless you are saying there is a single hook-in point where I can wrap them all once, and only have this take effect during unit-testing (somehow?), similar to what this developer did:

          ...and which I also implemented in a slightly different fashion, as I explained above.

          ...and which common sense (and googling the term) would say is the whole point of the default-lazy-init="true" flag. (By "common sense", I mean someone who is not intimately familiar with Spring and its syntax.)

          Based on your answer, I'm not sure you yet understand what I'm trying to do high-level. See the above developer's first and last paragraphs. See his "use case"? That is an extremely useful use case, and is essentially why I need to lazy-init all the fact the entire Spring container, if I can do such. To help explain the why, I have take this to an even higher level:

          Caching, as used in the software world today, is great for QA and production server performance, but is probably the biggest hindrance to rapid in-IDE debugging, both from a performance and a reliability standpoint, coz you don't know what you can count on to still be there when you bounce your app server, re-run your POJO, re-boot your OS, and so on. You don't know what's cached vs what is persisted to disk. I made this point to the lead developer of WebSphere, back in the year 1999. He agreed and said he would add a no-caching flag to WebSphere to aid debugging...though I never saw this flag in the later documentation. Probably too difficult to implement...and he was trying to sell us on WebSphere, so he'd probably tell me whatever I wanted to hear. :-)