I have a repository class that is created in XML like so:
<bean id="stuffRepositoryTarget" class="my.stuff.RepositoryImpl">
<!-- some params -->
</bean>
<bean id="stuffRepository" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" primary="true">
<property name="target" ref="stuffRepositoryTarget" />
<property name="transactionAttributes">
<prop key="*">PROPAGATION_REQUIRED</prop>
</property>
</bean>
And then I have a class that uses the repository like this:
#Autowired Repository repository;
It appears that the #Autowired annotation is referring to my Impl object and not my transaction interceptor. What am I doing wrong?
The most likely explanation is that the bean created by the TransactionProxyFactoryBean does not implement Repository.
Just checking, but Repository is an interface, right?
Another thing to try is to mark stuffRepositoryTarget with autowire-candidate="false", which will prevent it from being accidentally auto-wired.
There may be confusion over which bean to inject... Add a qualifier to your bean reference with which you can specify the exact bean id that you wish to have injected.
Something like:
#Qualifier("stuffRepository")
#Autowired Repository repository;
Related
I'm currently getting started on a project that uses spring-data in combination with JPA/Hibernate.
Right now, I'm injecting JpaRepositories using #Autowired annotations on the properties in question, e.g.:
#Component
public class EmployeeGenerator implements IDataGenerator {
...
#Autowired
private IEmployeeDao dao;
...
}
.. where IEmployeeDao is an interface extending JpaRepository that is annotated as #Repository:
#Repository
public interface IEmployeeDao extends JpaRepository<Employee, Integer> {
/**
* Finds employees by username.
*
* #param username the username
* #return the list of employees
*/
List<Employee> findByUsername(String username);
Everything works fine using this approach - However, I'm rather used to doing most of my spring configuration work in XML because I personally like the idea of all relevant confguration being in the same place and visible at the first glance.
Now, as far as I understand JPA and spring-data, the repository instances are somehow created by the JPA entity manager, so I should be able to specify them as beans in the spring config xml using.. some kind of factory method?
I guess I'm looking for something along the lines of:
<import resource="classpath:spring/db-context.xml"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="..."/>
<property name="dataSource" ref="..."/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.connection.charSet">UTF-8</prop>
</props>
</property>
</bean>
...
<bean id="employeeDaoImpl" class="IEmployeeDao">
<factory-method="?????"> <!-- Is something like this possible??? -->
</bean>
After some reading I guess that autowiring the repositories is the "recommended" approach, and I do see some benefits doing it like that,
but still, out of interest, I'd like to get it working with pure-xml configuration (or at least without #Autowired, that is)
You can declare the repositories using <jpa:repositories />. Then you can use the repository references in your XML configuration.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<repositories base-package="com.acme.repositories" />
</beans:beans>
In this case we instruct Spring to scan com.acme.repositories and all its sub packages for interfaces extending Repository or one of its sub-interfaces. For each interface found it will register the persistence technology specific FactoryBean to create the according proxies that handle invocations of the query methods. Each of these beans will be registered under a bean name that is derived from the interface name, so an interface of UserRepository would be registered under userRepository. The base-package attribute allows the use of wildcards, so that you can have a pattern of scanned packages.
You can read more about it in the docs: http://docs.spring.io/spring-data/jpa/docs/1.3.0.RELEASE/reference/html/repositories.html#repositories.create-instances
I can't get #Transactional annotation to work with xml-defined bean. I don't know if xml definition has anything to do with it. Maybe it's the issue with OSGi.
<bean id="myDao"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="txManager"/>
<property name="target" ref="myDao_t"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_MANDATORY,
timeout_60,
-Exception
</prop>
</props>
</property>
</bean>
When I specify a proxy with xml like above it works.
I have <tx:annotation-driven transaction-manager="txManager" /> specified in the same bundle-context.xml where the bean definition is.
MyDao is just a simple class implementing interface with one method.
There is no exception, it just doesn't create proxy for myDao.
What might be missing?
<bean id="myPlanner" class="com.something.planner.MyPlanner">
<property name="myDao" ref="myDao" />
</bean>
Try this:
The class of the bean myDao should be MyDao (the type of the DAO instead of TransactionProxyFactoryBean).
Put the annotation #Transactional on each public method in MyDao.java.
Spring should then automatically create a proxy for you. The approach in your question looks like "I try to create and configure the proxy factory myself".
While there surely is away to do that, I don't know exactly how you would do that. Instead, I rely on <tx:annotation-driven> and the #Transactional annotation.
EDIT You're using Spring 2.5.6A.
I just checked and #Transactional was added with Spring 1.2. But I'm not sure when <tx:annotation-driven> was added. The related EnableTransactionManagement was added with 3.1.
But the XML element is in this schema: http://www.springframework.org/schema/tx/spring-tx-2.5.xsd so it should be available in 2.5.
Maybe you're missing the necessary AOP libraries (cglib) on the classpath?
I have two child classes(PermanentEmployee and ContractEmployee) of Employee class.
I want spring to inject the dependencies under TextEditor1 by type . Along with this i want to inject the PermanentEmployee depndency under TextEditor1.
similarily want to inject the contractEmployee dependency under TextEditor2. Rest should be injected
automatically by type?
<bean id="textEditor1" class="com.TextEditor" autowire="byType">
<property name="employee" ref="permanentEmployee" />
</bean>
<bean id="textEditor2" class="com.TextEditor" autowire="byType">
<property name="employee" ref="contractEmployee" />
</bean>
<bean id="permanentEmployee" class="com.PermanentEmployee" >
</bean>
<bean id="contractEmployee" class="com.ContractEmployee">
</bean>
But i get the error Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: saying two match are found ?
Update :- i also tried below but it didn't work either
<bean id="textEditor1" class="com.TextEditor" autowire="byType">
<qualifier type="permanentEmployee"/>
</bean>
I think that's because those two com.PermanentEmployee and com.ContractEmployee are implementing another interface like com.Employee?
That way, Spring will recognize those same type and can't choose which bean Spring have to auto-wire into the bean.
So you might need to add those byName, not byType in this case.
If you change those injection with #Autowired annotation or #Resource annotation, you can use #Qualifier( for Autowired ) or name property of Resource annotation to specify bean name.
I'm working with SpringFramework and Java. I use Spring xml files to define the flow of the architecture and also the beans that will be used in the Java part.
I have two beans of the same class in my xml file, but they have different arguments for the constructor:
<bean id="beanA" class="Class" >
<constructor-arg><value>valueA1</value></constructor-arg>
<constructor-arg><value>ValueA2</value></constructor-arg>
</bean>
<bean id="beanB" class="Class" >
<constructor-arg><value>valueB1</value></constructor-arg>
<constructor-arg><value>valueB2</value></constructor-arg>-->
</bean>
Is there a way to set one of the beans as default in order to #Autowired it from Java? And, when I want to use the non default bean, apply the #Qulifier("beanName") annotation.
try primary attribute, eg
<bean id="b1" class="test.B" />
<bean id="b2" class="test.B" />
<bean id="b3" class="test.B" primary="true" />
this guarantees that b3 bean will be injected here
public class Test {
#Autowired
B b;
...
Finally I used a the next thing: I have a setter (setClassValue(Class classValue)) in the java code for the class I want to use. Then, I set the property autowire-candidate to false in the bean that it's not going to be the default one:
<bean id="beanA" class="Class" autowire-candidate="false">
<constructor-arg><value>valueA1</value></constructor-arg>
<constructor-arg><value>valueA2</value></constructor-arg>
</bean>
<bean id="beanB" class="Class" >
<constructor-arg><value>valueB1</value></constructor-arg>
<constructor-arg><value>valueB2</value></constructor-arg>
</bean>
Then, in the xml file where I'm defining the bean of the class that is going to #Autowired the Class, I use the java setClassValue(Class classValue) method on this way:
<bean id="classThatAutowire" class="ClassThatAutowire" >
<property name="classValue" ref="beanA" />
</bean>
In the Java code yo will have #Autowired the beanB and then, set the beanA. It's not the best practice, but it works.
I have a JSF 2.0 application and I am integrating Spring so I can make use of the hibernateTemplate. I already consulted the Spring documentation on JSF integration and have taken steps to set it up. All of my bean classes extend an abstract super class called SuperBean. SuperBean is the desired point of injection, saving me from having to declare all of my beans in Spring. I was hoping to just declare it as abstract="true" and any subclass bean extending the SuperBean class would have the dao injected. At runtime it is null.
<bean id="serviceTemplate" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="*"/>
</props>
</property>
</bean>
<bean id="daoServiceTarget" class="com.example.service.DaoService">
<property name="mainDAO" ref="mainDAO"/>
</bean>
<bean id="daoService" parent="serviceTemplate">
<property name="target" ref="daoServiceTarget"/>
</bean>
<bean id="superBean" class="com.example.beans.SuperBean" abstract="true">
<property name="daoService" ref="daoService"/>
</bean>
Am I able to simply declare this superclass SuperBean and expect Spring to inject the dao? I don't want to have to declare every bean class in spring.
I suppose the alternative option (from a performance perspective) would be to not use Spring beans but declare the DAO's as #applicationScoped and inject them into the SuperBean class using JEE's CDI. Would this be better performance-wise?
In the example above it looks serviceTemplate is providing an example of what you want. Note the parent="serviceTemplate". You need to do something similar to those who inherit from superbean. There are other options but since you have working code in the serviceTemplate that might be the best place to start. Then read here for more details: