Announcement Announcement Module
No announcement yet.
Load Beandefinitions in WebApplicationContext at runtime Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Load Beandefinitions in WebApplicationContext at runtime


    I try to create a modular structure with the spring framework (I am using Tomcat with JSF + Spring 2.0 RC3). My objectives are:

    - every Module has its own beandefinitions and hibernate mappings (+ XML MetaData + a SQL script)
    - during startup spring should first generate the WebApplicationListener (with standard ContextLoaderListener)
    - then for every module the content of its beandefinition.xml file should be added to the WebApplicationListener
    - same for the hibernate mappings

    I loaded with XmlBeanDefinitionReader the beandefinitions of all Modules in a GenericWebApplicationContext and added this as a child to the WebApplicationContext. But if requests are coming that require some bean(s) of the modules I get an error cause the beans are not located in the WebApplicationContext but in the GenericWebApplicationContext.

    How can I add the beandefinitions to the WebApplicationContext or make the WebApplicationContext find its child bean definitions?

    The Hibernate Mappings should be added to the mappingResources of the LocalSessionFactoryBean. How can I do this during runtime?

    As I'm quite new to Spring I have the strong feeling that I use a wrong approach Maybe someone knows a better one?

    Best regards,

  • #2
    Using the ContextLoaderListener out of the box limits the structure of ApplicationContext hierarchy to

      main web application context
        /  |  |   \
      <... child contexts, one per DispatcherServlet ...>
    The child contexts are "modular" in the sense that you seek - they do not know about each other's beans. The main web application context is global in scope.

    Maybe you can use the child contexts to create your "modules" by having a separate DispatcherServlet for each one? Are all the modules in the same VM even (you don't really say)?

    Or maybe you need to extend the ContextLoader to handle a more complex hierarchy.


    • #3
      First thanks for your quick answer. The modules are located in the same VM and dependencies between modules are unavoidable.

      What would solve these problems is if the beandefs of the modules could be integrated during startup in the WebApplicationContext. Doesn't exist a way to do this (without having to modify the ContextLoader Code)?


      • #4
        I don't really understand what you mean by "integrated". Is it sufficient just to load them all up into the same application context? I can see that it might not be completely trivial to convert a set of standalone contexts into a single context with all the beans from the original contexts. But that might not be what you are trying to do. It *would* be trivial if all the module contexts had unique bean ids - then you can just load all their context configurations into a single context by passing all the files into the ContextLoader.


        • #5
          Maybe I explain this better in scenarios that must be possible with the modular structure:

          - It must be possible to download a module during runtime (for example from an update server). This means a module must carry with it all necessary Information to run (classes, mappings, beandefinitions,...)

          - After downloading it must be installed. This means: register beandefinitions, add the mappings, put the class files in the right position. It is not absolutely necessary to install it during runtime (registering the beandefs should be possible during runtime but adding mappings to hibernate after a sessionfactory is already created I'm not sure if this works). But if its possible to to this all during runtime instead of restarting would be great.

          - It must be possible to delete it which means: deregister beandefs, remove mappings, (eventually) remove database tables, remove classes and other resources. The same here: would be great during runtime

          - It must be possible to update it which is more or less deleting and reinstalling (just the database tables are not allowed to delete but can be altered). The same here: would be great during runtime

          I think doing these processes during runtime is a lot more complicated than doing a restart after one of the described operations. At the moment I am checking what is possible and how much work would it be. Especially I am interested in what is possible during runtime.

          Every module will have an ID and it can be a convention that every bean gets the ID of its module as a prefix. So having a unique module ID shouldn't be a problem.

          This was a very general description of the problem. Hope it puts a bit light in the topic...

          Best regards,


          • #6
            You obviously have thought this one through in quite a lot of detail already, but it is a complicated scenario, and not a "standard" web application. There are many questions:

            Do you have a fixed number of modules? How often do they need to be updated? Do you want to keep them separate purely for design purposes, or is there a physical limitation which keeps them independent? Do they all depend on some common core components which might change at a different pace?

            Maybe if your modules are really self contained, or have at least no dependencies between each other, they can live in their own application context. You could use the standard layout with one per serlvlet (as described above), or you could maybe get a bit more flexibility by implementing your own context hierarchy and wiring it together in a bean factory, using SingletonBeanFactoryLocator to locate the contexts at run time.

            Regarding "deleting" contexts, and refreshing them in a running application, there is nothing that supports this kind of thing out of the box. It is actually quite difficult to re-configure a hibernate session in a running application (I have tried it in idle moments and never had much success). It may be possible, but it is certainly easier, and you will find more support for starting a new session when the the new application context is first created. Apart from anything else there are class loader limitations to think of - it is practically impossible to change a class definition in the middle of a running application, without some serious class loader shenanigans. You probably don't want to go there, but who knows, maybe your application warrants the effort involved.

            Why not go ahead and give it a try?


            • #7
              I don't have a fixed number of modules, the number varies on how much functionality will be used in one system. I want to keep them separate for design purposes, an easy updateable system is a great feature. Dependencies of one module with others will be unavoidable in practice. Almost all modules will depend on some common module(s) that provide helper or infrastructure functionality. Also the core will be just a (very important )module.

              As you already mentioned there are many difficulties if I am trying to do a module installation/update/deletion during runtime. Also the case if for example 50 users are around on the web application and the system is doing a live-update is unpredictable. What happens if one of the 50 needs a class that is at the moment updated? Or the module is at this moment half-updated? Or the class is deleted? The application can have many different, unpredictable states.

              Conclusion: doing all this at runtime is theoretically possible but for me in practice due to limited resources not. So what stays only is the much more easy restart way.

              For this I have an idea:

              I parse during startup all the beandef.xml files of the modules and create a .xml file that has for every module a <import resource="modulebeandef.xml">

              In the applicationcontext.xml I import this xml file. For the mappings I am planning to create a child bean of mySessionFactory that contains all the mappings. So the mapping list gets merged.

              Do you know an easier or more elegant solution?