Announcement Announcement Module
Collapse
No announcement yet.
How to auto-create non-existing beans during injection? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to auto-create non-existing beans during injection?

    Hi!

    I'm trying to do some "dynamic" injection using Spring. What the heck I mean by dynamic? I have a base abstract Dao class that has a generic type (which means the Model) nad has all basic (and even some advanced) persistence operations. Something like this:

    Code:
    public abstract class Dao<M extends PersistentModel> {
        // a bunch of methods: insert, update, findAll, findByExample, etc
    }
    The problem is, for simple CRUD operations I have to create "empty" Daos like this:

    Code:
    @Repository
    public class ProductDao extends Dao<Product> {
        // no methods needed
    }
    So, I want to achieve the following: if a Dao is not present for some model, create an anonymous implementation automatically and make it available for injection.
    Suppose this service class and that the ProductDao above does not exist:

    Code:
    @Service
    public class ProductService {
    
        @Autowired
        private Dao<Product> dao; // the bean is not found, create a new repository implementation and inject
    
    }
    Did you guys get it? Can someone point me in the right direction? I'm looking at BeanFactory, FactoryBean, PostProcessor but no success until now.

    Thanks in advance!

  • #2
    While there are things you could do with FactoryBeans and reflection, in the interest of keeping it simple, I'd suggest a slightly different approach.

    Add a constructor to your DAO class that takes the class of the type, i.e.

    Code:
    public class Dao<M extends PersistentModel> {
        Class<M> modelClass;
    
        public Dao(Class<M> modelClass) {
            this.modelClass = modelClass;
        }
    
        // a bunch of methods: insert, update, findAll, findByExample, etc
    }
    Now you can just define and inject your DAOs normally, without the need for subclasses. Only downside is you'll need to use XML or Java-based configuration to define the DAOs themselves.

    Hope this helps
    - Don

    Comment


    • #3
      Hey Don, thank you very much for your reply.
      However I'm looking for something automatic. It doesn't need to be simple because the functionality I've described will be encapsulated on a framework. The simplicity is in the fact that you don't need to create a Dao class (or a Dao definition on the XML) if you need no more than the persistence operations already defined on the abstract Dao.
      I'm trying to reach something simple and dynamic, like RoR, Grails and similar, but for Java. The statement is: you don't need to define beans/classes if the functionality you want is already present on a base class.

      Comment


      • #4
        I'm trying to do something similar (external, on-demand bean construction, based on type for autowiring).

        The closest I've come is InstantiationStrategy, which I've implemented but I haven't figured out how to wire it in. My current (broken) code:


        Code:
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
        context.refresh();
        AbstractAutowireCapableBeanFactory factory = (AbstractAutowireCapableBeanFactory)context.getBeanFactory();
        factory.setInstantiationStrategy(new CustomInstantiationStrategy());
        context.setConfigLocation(...);
        context.refresh();

        Comment


        • #5
          The closest I've come is InstantiationStrategy, which I've implemented but I haven't figured out how to wire it in. My current (broken) code:
          ClassPathXmlApplicationContext is a RefreshableApplicationContext implementation: it'll create a new BeanFactory each time you call refresh(). In order to register your InstantiationStrategy on the right BeanFactory, you need to add a BeanFactoryPostProcessor to the context.

          hth,
          Alessio

          Comment


          • #6
            I've came up with a working solution. But is not generic for any bean that does not exists yet, you gotta be careful about to generic solutions like that because they might cause some unexpected behavior.
            What I did was the following:
            - Since I want to create Dao classes for entities that are mapped but doesn't has a corresponding Dao, I've implemented a org.springframework.beans.factory.support.BeanDefi nitionRegistryPostProcessor that:
            1. Checks for all beans of type Dao are already registered and the corresponding entity type.
            2. For each registered SessionFactory I iterate thru all the mapped entities and those who haven't a corresponding Dao, I register a new bean definition.

            Now I can autowire them! (by name since Spring does not work well with generic types, for Spring they are beans of the same type, even if the generic defined types are different)

            The code bellow works even if I haven't created a Dao class for the specific entity:
            Code:
            @Autowired
            private Dao<Product> productDao; // note that the "entityname + Dao" is a convention defined on the PostProcessor for the @Autowired to work.
            If you're interested in the solution, check the source at
            https://github.com/brushingbits/jnap...Processor.java
            Last edited by daniel.rochetti; Feb 5th, 2011, 03:52 PM. Reason: typo

            Comment

            Working...
            X