Announcement Announcement Module
Collapse

JavaConfig forum decommissioned in favor of Core Container

As described at

http://static.springsource.org/sprin...fig/README.TXT

key features of the Spring JavaConfig project have been migrated into the core Spring Framework as of version 3.0.

Please see the Spring 3.0 documentation on @Configuration and @Bean support:

http://static.springsource.org/sprin...tml#beans-java

For any questions related to @Configuration classes and @Bean methods in Spring 3.0, please post in the dedicated 'Core Container' forum at

http://forum.springsource.org/forumdisplay.php?f=26
See more
See less
Issue with Lazy init in configuration Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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
    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.

    Comment


    • #3
      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

      Comment


      • #4
        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.

        Comment


        • #5
          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

          Comment


          • #6
            OK - you can still feel free to post the code (attached to a JIRA issue), as long as it's complete with HSQL DDL.

            Comment


            • #7
              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

              Comment


              • #8
                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

                Comment


                • #9
                  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.

                  Comment


                  • #10
                    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

                    Comment


                    • #11
                      Chris,

                      I added the maven project to the JIRA. Hope this helps.

                      Thanks.
                      Arul

                      Comment

                      Working...
                      X