Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Issue with Lazy init in configuration

  1. #1
    Join Date
    Aug 2008
    Location
    Billings, Montana
    Posts
    47

    Default Issue with Lazy init in configuration

    Hi,

    I am trying to do lazy init my database configuration so that I can override default configuration at runtime. I have tried different combinations using Lazy and Prototype scopes, but with out any success.

    Here is my JPA configuration:

    Code:
    @Configuration
    @AnnotationDrivenConfig
    @AnnotationDrivenTx
    @ComponentScan(value = "test.dynaconfig")
    public abstract class JpaConfig extends ConfigurationSupport {
    
        public
        @Bean(scope=DefaultScopes.PROTOTYPE)                
        DataSource dataSource() {
            ComboPooledDataSource dataSource = null;
            try {
                dataSource = new ComboPooledDataSource();
                DefaultConfig config = defaultConfig();
                dataSource.setDriverClass(config.getDriverClass());
                dataSource.setJdbcUrl(config.getUrl());
                dataSource.setUser(config.getUsername());
                dataSource.setPassword(config.getPassword());
            } catch (Exception e) {
    
            }
            return dataSource;
        }
    
        public
        @Bean
        DefaultConfig defaultConfig() {
            DefaultConfig config = new DefaultConfig();
            config.setDriverClass("org.hsqldb.jdbcDriver");
            config.setUrl("jdbc:hsqldb:hsql://localhost:9001");
            config.setUsername("sa");
            config.setPassword("");
            return config;
        }
    
        public
        @Bean
        DialectConfig dialectConfig() {
            DialectConfig dialectConfig = new DialectConfig();
            dialectConfig.setDialect("org.hibernate.dialect.HSQLDialect");
            return dialectConfig;
        }
    
        public
        @Bean
        Properties jpaProperties() {
            Properties jpaProperties = new Properties();        
            jpaProperties.put("hibernate.dialect", dialectConfig().getDialect());
            jpaProperties.put("hibernate.hbm2ddl.auto", "update");
            return jpaProperties;
        }    
    
        public
        @Bean
        EntityManagerFactory entityManagerFactory() {
            LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
            em.setJpaProperties(jpaProperties());
            em.setDataSource(dataSource());
            em.setJpaVendorAdapter(jpaVendorAdapter());
            em.setLoadTimeWeaver(loadTimeWeaver());
            return this.getObject(em, EntityManagerFactory.class);
        }
    
        abstract
        @AutoBean
        HibernateJpaVendorAdapter jpaVendorAdapter();
    
        abstract
        @AutoBean
        InstrumentationLoadTimeWeaver loadTimeWeaver();
    
        public
        @Bean
        PlatformTransactionManager transactionManager() {
            JpaTransactionManager txManager = new JpaTransactionManager();
            txManager.setEntityManagerFactory(entityManagerFactory());
            return txManager;
        }
    }
    Here is my test:
    Code:
    public class TestDynaConfig {
        @Test
        public void testDefaultConfig() throws Exception {
            JavaConfigApplicationContext context = new JavaConfigApplicationContext(JpaConfig.class);
            DataSource dataSource = context.getBean(DataSource.class);
            assertEquals("HSQL Database Engine", dataSource.getConnection().getMetaData().getDatabaseProductName());
            DefaultConfig config = context.getBean(DefaultConfig.class);
            config.setDriverClass("com.mysql.jdbc.Driver");
            config.setUrl("jdbc:mysql://localhost:3306/foo");
            config.setUsername("root");
            config.setPassword("mysql");
            DialectConfig dialect = context.getBean(DialectConfig.class);
            dialect.setDialect("org.hibernate.dialect.MySQLInnoDBDialect");
            dataSource = context.getBean(DataSource.class);
            assertEquals("MySQL", dataSource.getConnection().getMetaData().getDatabaseProductName());//SUCCESS        
            Dao dao = context.getBean(Dao.class);
            Foo foo = new Foo();
            foo.setName("foo bar");
            long id = dao.insertFoo(foo);
            assertEquals("foo bar", dao.getFoo(id).getName());
        }
    }
    DefaultConfig and DialectConfig classes are just java beans.

    This test runs fine, but it always uses HSQL database for persistence. Interestingly, the test succeeds when it tries to assert the database vendor and indeed the datasource is MySQL at that point. But, it always inserts into HSQL table.

    Appreciate any inputs. I may be doing something stupid here.

    Thanks!
    Arul

  2. #2
    Join Date
    Apr 2007
    Posts
    307

    Default

    What is the scope of the Dao bean? I assume it is getting picked up when the test.dynaconfig package is scanned?

    In order for the dynamic switching of the dialect to propagate all the way to the Dao, it too will need to be prototype-scoped (which may or may not be acceptable for your application's needs).

    Remember that you can do this as follows:

    Code:
    @Repository // (or, @Component)
    @Scope("prototype")
    public FooDao implements Dao {
       // ...
    }
    While this will work in terms of picking up the dynamic changes to the Hibernate dialect, it will also break your transaction management, because the transactionManager bean must have a reference to the same DataSource as the Dao.
    Chris Beams
    Spring Framework committer, VMware
    http://github.com/cbeams

  3. #3
    Join Date
    Aug 2008
    Location
    Billings, Montana
    Posts
    47

    Default

    Thanks Chris for your suggestion.

    I did not specify the scope earlier. I just added prototype scope to my DaoImpl class and tested. But, it seems to have no effect.

    Here is my DaoImpl code:

    Code:
    @Repository
    @Transactional
    @Scope("prototype")
    public class DaoImpl implements Dao {
        @PersistenceContext
        private EntityManager em;
    
        @Transactional(readOnly = true)
        public Foo getFoo(long id) {
            return this.em.find(Foo.class, id);
        }
    
        public long insertFoo(Foo foo) {
            this.em.persist(foo);
            return foo.getId();
        }
    
        public void updateFoo(Foo foo) {
            this.em.merge(foo);
        }
    
        public void deleteFoo(int id) {
            this.em.remove(id);
        }
    }

    -Arul

  4. #4
    Join Date
    Apr 2007
    Posts
    307

    Default

    See if you can put together the simplest possible reproduction of this, complete with a failing test case, and I'll look into it.

    Ideally, no database setup should be required. See if you can just reproduce the scoping problem that you're seeing with dummy objects.
    Chris Beams
    Spring Framework committer, VMware
    http://github.com/cbeams

  5. #5
    Join Date
    Aug 2008
    Location
    Billings, Montana
    Posts
    47

    Default

    Hi Chris,

    I tried creating a simple test case without using database, but I was not able to derive a similar use case for scoping. I suspect this problem could not be reproduced without the database involved.

    -Arul

  6. #6
    Join Date
    Apr 2007
    Posts
    307

    Default

    OK - you can still feel free to post the code (attached to a JIRA issue), as long as it's complete with HSQL DDL.
    Chris Beams
    Spring Framework committer, VMware
    http://github.com/cbeams

  7. #7
    Join Date
    Aug 2008
    Location
    Billings, Montana
    Posts
    47

    Default

    Chris,

    I created a JIRA issue (http://jira.springframework.org/browse/SJC-247) and attached the original test case to the issue.

    Thanks for your support again.

    -Arul

  8. #8
    Join Date
    Aug 2008
    Location
    Billings, Montana
    Posts
    47

    Default

    Hi Chris,

    Did you had any chance to look into this issue? Do you think of any work around for this problem? We have been stuck with this for a while.

    On a different note, I was reading the blog post related to SpringOne Americas discussion where it says some parts of SJC will be moved to Spring 3.0 Core. Interesting to hear that development.

    -Arul

  9. #9
    Join Date
    Apr 2007
    Posts
    307

    Default

    Hi Arul, sorry for the delayed response. Just catching up on this now. Are you familiar with Maven? Would you repackage this as a maven project with a POM? It makes the process of just getting going and diagnosing much, much more efficient for me. Thanks.
    Chris Beams
    Spring Framework committer, VMware
    http://github.com/cbeams

  10. #10
    Join Date
    Aug 2008
    Location
    Billings, Montana
    Posts
    47

    Default

    Hi Chris,

    No problem.
    Sure I can package it as a maven project and resubmit to the JIRA later today.

    Thanks once again for taking time to look into this issue.

    Best regards,
    Arul

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •