I'm trying to make dependencies injection for DAO and services. But I get stuck with an error "cannot find bean for metier". Here is my controller code:
#Autowired
#Qualifier("metier")
private MetierInterface metierInterface;
And my applicationContext.xml
<bean id="dao" class="com.act.cours.dao.DaoImplement"></bean>
<bean id="metier" class="com.act.cours.metier.MetierImplement">
<property name="dao" ref="dao"></property>
</bean>
I have interfaces DaoInterface.java, MetierInterface.java and implementing classes DaoImplement.java, MetierImplement.java.
Related
Premise
I have a Spring 5.1.5 project with Hibernate 5.4.1
The compilation goes through fine but while running test cases for a particular package I see multiple tests failing. All with the same error:
javax.persistence.TransactionRequiredException: no transaction is in progress at com.project.server.package.dao.impl.SomeDAOImplTest.someTest(SomeDAOImplTest.java:54)
The Problem
Now I know that Hibernate 5 enforces the check for a transaction and it doesn't find one here and throws an exception. My question is why does it do that given I have transactions initialized via spring context.
My test case:
#ContextConfiguration({ "classpath:/spring/applicationContext-package-dao--test.xml" })
public class SomeDAOImplTest extends AbstractDAOTest {
#Autowired
private SomeDAO someDAO;
private className obj;
#Before
public void setUp() {
obj = new ClassName();
obj.setId(3);
someDAO.saveOrUpdate(obj);
}
My applicationContext-package-dao--test.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:/spring/applicationContext-persistence-datasource-test.xml" />
<import resource="classpath:/spring/applicationContext-package-dao.xml" />
</beans>
The imported context applicationContext-persistence-datasource-test.xml has a bean txProxyTemplate as below:
<beans>
.
.//other beans
.
<bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager" />
</bean>
<bean id="transactionManager" class="com.desktone.transaction.DtResourcelessTransactionManager" />
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
.
.//other beans
.
</beans>
The other applicationContext-package-dao.xml has the bean definition for SomeDAO which has txProxyTemplate as it's parent.
<bean id="SomeDAO" parent="txProxyTemplate">
<property name="target">
<bean class="com.project.server.package.dao.impl.SomeDAOImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</property>
<property name="transactionAttributes">
<props>
<prop key="saveOrUpdate">PROPAGATION_REQUIRED</prop>
<prop key="delete">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
</props>
</property>
</bean>
The saveorupdate call from SomeDAOImplTest calls SomeDAOImpl whose spring context config is applicationContext-package-dao.xml and has the Hibernate saveorupdate() call.
Things I have Tried:
Manually adding #Transactional tag to SomeDAOImplTest. (still throws no tx error)
Experimenting with PROPAGATION.REQUIRES_NEW (still throws no tx error) & PROPAGATION.MANDATORY(says marked mandatory but no tx).
Made sure the autowire is initialzing the bean.
Primary Suspicion
I suspect somehow the someDAO bean is initialized but txProxyTemplate bean isn't, so no transactionManager is in place. However, I have found no clues to coroborate this.
For me, this was happening because of a very fundamental issue. I'll explain the issue and the fix will be intuitive to everyone afterward.
When a Spring application runs all the beans are loaded in a single/global context. So even if some spring bean configuration depends on a transaction bean(for me it was txProxyTemplate) which isn't present in the same package at runtime it will be able to access it.
However, that's not true for a test case. My tests were reporting no transaction in progress since they couldn't load the txProxyTemplate and actually start a transaction. So my tests never ran in a transaction and I didn't know any better until I upgraded to Hibernate 5 and they put a hard constraint on this.
As you might have guessed defining the txProxyTemplate in the same spring config helped me work past this issue.
Good learning.
I'm using spring-data-couchbase 2.1.2, I want add methods to a single repository.
In implementation class:
public class MyRepositoryImpl implements MyRepositoryCustom {
#Autowired
RepositoryOperationsMapping templateProvider;
....
}
I added the RepositoryOperationsMapping but the object is not injected, I have the error below:
[org.springframework.data.couchbase.repository.config.RepositoryOperationsMapping]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException
For spring configuration I used the spring.xml file, how add in xml file the RepositoryOperationsMapping reference?
Thanks. Bye.
I solved the issue, below a snippet my spring.xml file
<couchbase:clusterInfo login="${cluster.username}" password="${cluster.password}" id="clusterInfo" />
<couchbase:bucket bucketName="${bucket.name}" bucketPassword="${bucket.password}" id="bucket"/>
<!-- template is just using default parameters and references as well -->
<couchbase:template translation-service-ref="myCustomTranslationService" />
<bean id="myCustomTranslationService"
class="org.springframework.data.couchbase.core.convert.translation.JacksonTranslationService"/>
<bean id="couchbaseTemplate" class="org.springframework.data.couchbase.core.CouchbaseTemplate">
<constructor-arg ref="clusterInfo"/>
<constructor-arg ref="bucket" />
<constructor-arg ref="myCustomTranslationService" />
</bean>
<bean id="repositoryOperationsMapping" class="org.springframework.data.couchbase.repository.config.RepositoryOperationsMapping">
<constructor-arg ref="couchbaseTemplate"/>
</bean>
I am able to inject EntityManager in my Service class without defining any persistence-unit.
This is my configuration:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
<jpa:repositories base-package="com.example"></jpa:repositories>
In my Service class:
#PersistenceContext
private EntityManager entityManager;
// THIS WORKS!
final Session session = entityManager.unwrap(Session.class);
Is it because of the jpa:repositories ?
Spring ORM package's LocalContainerEntityManagerFactoryBean class makes this possible. It uses DefaultPersistenceUnitManager class to build an instance of PersistenceUnitInfo which can then be provided to PersistenceProvider class's createContainerEntityManagerFactory. Hibernate implements this interface so that Spring can create an instance of EntityMangerFactory class.
DefaultPersistenceUnitManager class is the one that creates a persistenceUnit called default and finds all the entity classes going through the classes on the classpath. Same information acquired from the persistence.xml has been taken in with a alternative approach like this without having a physical persistence.xml file.
Finally Spring uses JpaVendorAdapter configured to get the JPA provider- specific EntityManagerFactory instance.
Spring data JPA specific <jpa:repositories base-package="...." /> or #EnableJpaRepositories uses to scan all the beans annotated with #Repository to provide dynamic queries and other features. This is not an exhaustive explanation but you see how this "magic" happens.
You can find more on grepcode or download the sources to explore more.
I am new to Spring, and have a simple problem.
I have written a simple controller with a simple constructor, annotated as shown below.
#Controller
public class LoginController
{
private LoginService loginService;
#Inject
public LoginController(LoginService loginService)
{
System.out.println("LoginController constructor - initializing login service");
this.loginService = loginService;
}
When I try to access my web app in a browser, I get the following error:
No default constructor found;
When I replace the #Inject annotation with the #Autowired annotation, it works. Can anyone explain why? Everything I've read says that have identical behavior. I'm using Tomcat 6.0.43.
Also, below is my spring dispatcher servlet xml:
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:annotation-driven/>
<context:component-scan base-package="com.rockwell_collins.webquery"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
You must be missing the JavaEE Inject API from your runtime classpath. Spring will only look for #Inject if the class is found in the classpath.
You can get it from Maven here and add it to your runtime classpath (manually or through dependencies).
In my dispatcher-servlet.xml I defined a bean as follows:
<bean id="worplacementDAO" class="com.mycompany.maventestwebapp.db.dao">
<property name="dataSource" value="dataSource" />
</bean>
Is it possible to inject the bean into a controller via applicationContext configuration file, without using #Autowired?
Simple answer - No.
You can implement BeanPostProcessor to do something with your beans (e.g. inject dependency). Or you can manually register the bean as <bean> instead of letting component-scan do that for you. But that is all you can do.