<bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
          p:packagesToScan="jpatest.engine">
        <property name="dataSource">
            <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                <property name="driverClassName" value="org.firebirdsql.jdbc.FBDriver" />
                <property name="url"
                          value="jdbc:firebirdsql://localhost:3050/testdb" />
                <property name="username" value="xxxxxxxx" />
                <property name="password" value="yyyyyy" />
            </bean>
        </property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database" value="DEFAULT" />
                <property name="showSql" value="true" />
                <property name="databasePlatform" value="org.hibernate.dialect.FirebirdDialect" />
            </bean>
        </property>
        <property name="loadTimeWeaver">
            <bean
                    class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>

I have the following bean definition in my Spring application context, this gets loaded nicely and runs well.
Now, I may have the requirement to rewire this on the fly to point to a different database.
Is there any way to achieve this without stopping the application, modifying the application context xml, and starting it all up again?
I know you can inject properties from the runtime environment into the application context at startup, but this doesn't seem to work at changing the bean at runtime.

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setDatabase(Database.DEFAULT);
        vendorAdapter.setShowSql(false);
        vendorAdapter.setDatabasePlatform("org.hibernate.dialect.FirebirdDialect");
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("org.firebirdsql.jdbc.FBDriver");
        dataSource.setUsername("aaaaaaa");
        dataSource.setPassword("bbbbbbb");
        dataSource.setUrl("jdbc:firebirdsql://localhost:3050/testdb");
        Properties jpaProperties = new Properties();
        jpaProperties.put("hibernate.hbm2ddl.auto", "update");
        LocalContainerEntityManagerFactoryBean e = new LocalContainerEntityManagerFactoryBean();
        e.setPackagesToScan("jpatest.engine");
        e.setDataSource(dataSource);
        e.setJpaVendorAdapter(vendorAdapter);
        e.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
        e.setJpaProperties(jpaProperties);
        context.getAutowireCapableBeanFactory().configureBean(eb, "entityManagerFactory");
        context.getAutowireCapableBeanFactory().initializeBean(b, "entityManagerFactory");
        context.getAutowireCapableBeanFactory().applyBeanPropertyValues(eb, "entityManagerFactory");

does not have the desired effect. After this the application still writes to the initially configured database when requesting the EntityManagerFactory again from the application context (I would have expected Spring to replace the bean with the new one, but apparently it doesn't).

Partial solution, sadly more a workaround than a complete solution. We not create the EMF by feeding it a DataSource class that on construction gets its configuration from environment settings.

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        p:packagesToScan="foo.bar.model.entities">
        <property name="dataSource" ref="dataSource"/>   
        <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
        <property name="loadTimeWeaver">
            <bean
                class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">validate</prop>
            </props>
        </property>
    </bean>

    <bean id="dataSource" class="foo.bar.DataSource" init-method="init" />
    <bean id="jpaVendorAdapter" class="foo.bar.HibernateJpaVendorAdapter" init-method="init" />
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.