icedek
icedek

Reputation: 584

Two session Factories found when one was expected

I have referred to the question asked at Hibernate using multiple databases. My problem is similar but I am facing a different problem.I created two xml file each has a separate datasource and session factory. In my web.xml I have

 <context-param>
 <param-name>contextConfigLocation</param-name>
     <param-value>*The xml files* </param-value>

Once I run the project,the various loadings and the bindings are done from both the xml files.The various annotations and databases/tables are properly identified.But just after this is done before the control even goes outside.I get the following error.

    main ERROR [org.springframework.web.context.ContextLoader] - Context initialization failed  
    org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'daoEager' defined in URL [jar:file:/C:/Users/.../.metadata/.plugins/org.eclipse.wst.server.core/tmp1/wtpwebapps/infobutton-service/WEB-INF/lib/core-data-1.0.0-SNAPSHOT.jar!/.../DaoHibernateEagerImpl.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.hibernate.SessionFactory]: : No unique bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: [sessionFactory, profilesessionFactory]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: [sessionFactory, profilesessionFactory]

The class DaoHibernateEagerImpl is

@Implementation
@Repository("daoEager")
public class DaoHibernateEagerImpl extends DaoHibernateImpl
{
// ========================= CONSTANTS =================================

/**
 * A logger that helps identify this class' printouts.
 */
private static final Logger log = getLogger(DaoHibernateEagerImpl.class);

// ========================= CONSTRUCTORS ==============================

/**
 * Required for a Spring DAO bean.
 *
 * @param sessionFactory
 *            Hibernate session factory
 */
@Autowired
public DaoHibernateEagerImpl(final SessionFactory sessionFactory)
{
    super(sessionFactory);
}

// ========================= DEPENDENCIES ==============================

// ========================= IMPLEMENTATION: Dao =======================



// ========================= IMPLEMENTATION: SearchEngine ==============


}

One of the xml files is

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"                  
    xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"     
    xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <context:annotation-config />

<!--
    Data source: reads a properties file and injects them into a DBCP DS
    Second datasource for Resource Profiles
-->
<bean id="profiledataSource"
    class=".....ConfigurableBasicDataSource">
    <constructor-arg index="0">
        <bean class="org.apache.commons.dbcp.BasicDataSource" />
    </constructor-arg>
    <property name="properties">
        <bean

    class="org.springframework.beans.factory.config.PropertiesFactoryBean">
            <property name="locations">
                <list>
                    <value>WEB-INF/datasource-local.properties
                    </value>
                </list>
            </property>
        </bean>
    </property>

    <!-- FUR-946: idle connections break. Adding connection testing. -->
    <property name="testOnBorrow" value="true" />
    <property name="testWhileIdle" value="true" />
</bean>




    <!-- Session factory -->
<!-- Session Factory for the second datasource-->
<bean id="profilesessionFactory"


   class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="profiledataSource" />

    <!--
        Hibernate configuration properties (read from a properties file)
    -->
    <property name="hibernateProperties">
        <bean

    class="org.springframework.beans.factory.config.PropertiesFactoryBean">
            <property name="locations">
                <list>
                    <value>WEB-INF/hibernate.properties
                    </value>
                    <value>WEB-INF/datasource-local.properties
                    </value>

                </list>
            </property>
        </bean>
    </property>

    <!-- Using improved naming strategy -->
    <property name="namingStrategy">
        <bean class="org.hibernate.cfg.DefaultNamingStrategy" />
    </property>




    <!-- Mapping annotated classes using search patterns -->
    <property name="annotatedClasses">
        <list>
            <value><![CDATA[....profiledb.domain.Profiles]]></value>
        </list>
    </property>
</bean>

 <!--   Hibernate data access template -->
 <bean id="profilehibernateTemplate"      
  class="org.springframework.orm.hibernate3.HibernateTemplate">

  <property name="sessionFactory" ref="profilesessionFactory" />
</bean>


<tx:annotation-driven />

<!-- a PlatformTransactionManager is still required -->
<bean id="profiletransactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="profilesessionFactory" />
</bean>


<bean id="profilesdbDao" class="....profiledb.service.ProfilesDaoImpl" >
    <property name="sessionFactory" ref="profilesessionFactory"></property>

<context:component-scan base-package="....core.data" />

The other xml file is similar but has a different datasource and the session factory is

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
 .....

Upvotes: 1

Views: 4403

Answers (2)

R Pidugu
R Pidugu

Reputation: 538

Its because of...if you dont mention @Primary(annotation) / primary="true"(in xml config), Hiibernate does not know which sessionfactory to pick up.In that case it will give you the error mentioned. Just try with @Primary annotation it will work...

Upvotes: 0

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340708

The error message is pretty clear:

expected single matching bean but found 2: [sessionFactory, profilesessionFactory]

Which is understandable:

<bean id="profilesessionFactory"
<!-- ... -->
<bean id="sessionFactory"

The fix should be simple:

@Autowired
public DaoHibernateEagerImpl(
  @Qualifier("profilesessionFactory") final SessionFactory sessionFactory)

If you cannot modify DaoHibernateEagerImpl class, you can always fall-back to XML-based configuration. First disable CLASSPATH scanning of DaoHibernateEagerImpl so that @Autowired is not picked up. Then simply write:

<bean class="DaoHibernateEagerImpl">
   <constructor-arg ref="profilesessionFactory"/>
   <!-- ... -->
</bean>

Finally you can take advantage of @Primary annotation / primary="true" directive:

<bean id="sessionFactory" primary="true">
   <!-- ... -->

This will prefer sessionFactory when autowiring and there are two possibilities instead of throwing an exception.

Upvotes: 4

Related Questions