Announcement Announcement Module
Collapse
No announcement yet.
Dynamically adding transaction managers/session factories/data sources Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dynamically adding transaction managers/session factories/data sources

    Hi,

    my application must support the following use case:
    - dynamically add datasources to the context (by specifying connection parameters in a web admin console)
    - dynamically add transaction managers/sessionfactory beans to the context
    - dynamically create some DAO objects and DI existing service beans with those objects (by adding them to an autowired map)
    - persist all these configuration changes

    I see the following options:

    - refresh the application context with each configuration change (either by adding xml config location or creating a client context and replace the current context): this might work but i have my doubts on performance/stability
    - create my own factories/registrars for each of those beans inside the context and do the bean management programmatically by calling those directly: would be nice to know if someone has done this already ? As for the persistence part, is there a library for persisting a spring context (in a structured way) ?

    Thanks for helping me out !

  • #2
    You can't "DI existing service beans with those objects" with Spring (not out of the box, that is). If you refresh the context, you will create new instances of all the beans. You may be able to organize the context into sub-contexts and only refresh those that may be interested by the change, to limit unnecessary reloading. However, if service beans are stateful, or are registered somewhere (JMS listeners, web service endpoints, ...), this can be a problem.

    I think you can use factory beans and/or static factory methods in a way that allows you to reconfigure your existing (singleton) service beans. Roughly sketched:

    Code:
    public class Foo {
    ...
    ApplicationContext baseContext = ...
    GenericApplicationContext newContext = new GenericApplicationContext();
    ...load xml files with DAOs and whatever...
    newContext.registerSingleton("myServiceBean-original", baseContext.getBean("myServiceBean"));
    GenericBeanDefinition myServiceBeanFactory = new GenericBeanDefinition();
    myServiceBeanFactory.setBeanClass(Foo.class);
    myServiceBeanFactory.setFactoryMethodName("identity");
    myServiceBeanFactory.setConstructorArgumentValues(...ref="myServiceBean-original"...);
    myServiceBeanFactory.setPropertyValues(...user-defined properties...);
    ...
    public static Object identity(Object o) { return o; } //Dummy factory-method
    ...
    }
    I'm not sure if autowiring will work in such a scenario: I'll do some tests.

    Comment


    • #3
      Thanks for the response. I was not aware of the possibility of rewiring a bean in this way, but if i'm not mistaking it forces a context refresh for the context in which the service beans reside ?
      Your suggestion of splitting up the context is something i did read about. I suppose this type of solution involves the creation of a new application context by inheriting from a parent context and reinjecting that context in the appropriate places. Are people actually using this in a web admin scenario ? I do have some service end points, what about those ? Is is possible to inject the new application context in, let's say, the dispatcher servlet ?
      Another question: would the configurable annotation allow me to create beans outside the context and yet have DI from an existing context ?

      Comment


      • #4
        Hi.

        Thanks for the response. I was not aware of the possibility of rewiring a bean in this way, but if i'm not mistaking it forces a context refresh for the context in which the service beans reside ?
        Your suggestion of splitting up the context is something i did read about. I suppose this type of solution involves the creation of a new application context by inheriting from a parent context and reinjecting that context in the appropriate places. Are people actually using this in a web admin scenario ? I do have some service end points, what about those ?
        The pseudo-code I posted is precisely intended to avoid the refresh on the context that defines the service beans. If you look closely, you'll see that such context (which I called baseContext) is not used as a parent (which would force refresh) but individual beans are manually put in a fresh context as singletons. The hack of passing through a dummy factory method allows you to at least inject new values for the bean's properties, and, as I found out, also to autowire them with @Resource (provided that you instruct newContext to do so, e.g. by loading a .xml file with <context:annotation-config /> via an XmlBeanDefinitionReader). This way you won't create any new service beans: instead you'll be able to change their properties at runtime and still leverage Spring's infrastructure.

        Of course, not using baseContext as a parent implies that you must manually pull all desired beans in the new context, which can be cumbersome. But at least some of this work can be automatized, and as an added benefit you can restrict which beans are visible to your users, if you need to.

        Note also that you should probably make all beans in each new context be prototype-scoped or I suspect you won't be able to get rid of the context when you don't need it anymore (because calling destroy on it will call the destroy-methods on all your beans, which is bad; and I don't know the consequences of simply letting it be gc'ed).

        Is is possible to inject the new application context in, let's say, the dispatcher servlet ?
        I believe you can make your dispatcher servlet implement ApplicationContextAware to have its application context injected into it. But I've not much experience with that.

        Another question: would the configurable annotation allow me to create beans outside the context and yet have DI from an existing context ?
        Yes, with the dummy factory method hack above. To have DI, the beans must be known to the context as bean definitions some way.

        hth,
        Alessio

        Comment


        • #5
          Originally posted by astalla View Post
          Hi.



          The pseudo-code I posted is precisely intended to avoid the refresh on the context that defines the service beans. If you look closely, you'll see that such context (which I called baseContext) is not used as a parent (which would force refresh) but individual beans are manually put in a fresh context as singletons. The hack of passing through a dummy factory method allows you to at least inject new values for the bean's properties, and, as I found out, also to autowire them with @Resource (provided that you instruct newContext to do so, e.g. by loading a .xml file with <context:annotation-config /> via an XmlBeanDefinitionReader). This way you won't create any new service beans: instead you'll be able to change their properties at runtime and still leverage Spring's infrastructure.
          Ok, i understand what you mean, very clever indeed !

          Of course, not using baseContext as a parent implies that you must manually pull all desired beans in the new context, which can be cumbersome. But at least some of this work can be automatized, and as an added benefit you can restrict which beans are visible to your users, if you need to.

          Note also that you should probably make all beans in each new context be prototype-scoped or I suspect you won't be able to get rid of the context when you don't need it anymore (because calling destroy on it will call the destroy-methods on all your beans, which is bad; and I don't know the consequences of simply letting it be gc'ed).
          Thanks for mentioning. That actually pops up the question whether it's possible at all to remove beans from the context ?


          I believe you can make your dispatcher servlet implement ApplicationContextAware to have its application context injected into it. But I've not much experience with that.
          If i can keep the current context that should be no longer a problem i guess.

          Yes, with the dummy factory method hack above. To have DI, the beans must be known to the context as bean definitions some way.

          hth,
          Alessio
          You were very helpful, thanks a lot !

          Comment

          Working...
          X