my question is how can I access bean in class X, that is autowired in class Y?
I'm using spring boot, I have 2 controllers:
#Controller
public class OwnerController {
#Autowired
StandardDaoAction<Owner> ownerDao;
and another one
#Controller
public class VisitController {
#Autowired
StandardDaoAction<Pet> petDao;
now I need to add StandardDaoAction ownerDao bean in VisitController class, but when I use simply autowired, I get exception, because multiple beans of the same class defined and spring does not know what to do. I tried somehow to distinguish them with #Qualifier, but it did not worked or I messed up with something.
It's pretty basic question but Im stuck with it and cant find the solution
ok So I ran into conclusion that the core problem is with my implementation of dao's and interface aka something is wrong with my usage of generics:
my interface :
public interface StandardDaoAction<T> {
public T get(int id);
public void remove(int id);
public void add(T Type);
public void update(T type);
public List<T> getAll();
}
implementation of the interface by both classes:
#Repository
public class PetDaoImpl implements StandardDaoAction<Pet> {
#PersistenceContext
EntityManager em;
#Transactional
public Pet get(int id) {
return em.find(Pet.class, id);
}
#Transactional
public void remove(int id) {
em.remove(id);
}
#Transactional
public void add(Pet pet) {
em.persist(pet);
}
#Transactional
public void update(Pet pet) {
em.merge(pet);
}
#SuppressWarnings("unchecked")
#Transactional
public List<Pet> getAll() {
return em.createQuery("from Pet").getResultList();
}
}
#Repository
public class OwnerDaoImpl implements StandardDaoAction<Owner> {
#PersistenceContext
EntityManager em;
#Transactional
public Owner get(int id) {
return em.find(Owner.class, id);
}
#Transactional
public void remove(int id) {
em.remove(get(id));
}
#Transactional
public void add(Owner owner) {
em.persist(owner);
}
#Transactional
public void update(Owner owner) {
em.merge(owner);
}
#SuppressWarnings("unchecked")
#Transactional
public List<Owner> getAll() {
return em.createQuery("From Owner").getResultList();
}
}
when I add:
#Controller
public class VisitController {
#Autowired
StandardDaoAction<Pet> petDao;
#Autowired
StandardDaoAction<Owner> ownerDao;
this is the error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'visitController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: pl.kaczynski.dao.StandardDaoAction pl.kaczynski.controller.VisitController.ownerDao; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [pl.kaczynski.dao.StandardDaoAction] is defined: expected single matching bean but found 3: ownerDaoImpl,petDaoImpl,vetDaoImpl
there is also vetDaoImpl because there is another controller:
#Controller
public class VetListController {
#Autowired
StandardDaoAction<Vet> vetDao;
which also implements the interface, as you can see above.
so As long as I have one bean that implements StandardDaoActions interface , it's working because it goes autowired by type, but when I add another autowired bean in different controller , the error occurs.
Because of type erasure you will have two beans of type StandardDaoAction.
inject either by the concrete type as #Autowired private PetDaoImpl petDao
or use #Autowired #Qualifier("petDaoImpl") private StandardDaoAction<Pet> petDao
Related
I have the following class for a resource in my Spring Application
#RestController
#RequestMapping("/whatever")
public class SomeResource {
#Autowired
private CoolService coolService;
#RequestMapping(
path = "",
method = RequestMethod.GET)
#PreAuthorize("hasPerm(#coolService.resolve(#attribute))")
public void resource(#PathVariable("attribute") int attribute) {
...
}
And I want to call the bean implementing CoolService that has been autowired by the Spring context, because for CoolService I have two beans that get activated depending on the profile at startup.
public interface CoolService {
resolve(int attribute);
}
#Service
#Profile("super")
public interface SuperCoolService implements CoolService {
public Object resolve(int attribute){...}
}
#Service
#Profile("ultra")
public interface UltraCoolService implements CoolService {
public Object resolve(int attribute){...}
}
However it seems that Spring does not know which bean to use because there is no single bean just named CoolService, and inside the Preauthorize I can't write #superCoolService or #ultraCoolService because it is profile-dependant.
How can I achieve this?
If you want to define 2 bean implement same interface, then you can user annotation #Qualifier.
For example:
#Service
#Qualifier("service1")
public interface SuperCoolService implements CoolService {
public Object resolve(int attribute){...}
}
#Service
#Qualifier("service1")
public interface UltraCoolService implements CoolService {
public Object resolve(int attribute){...}
}
In the first case the autowired cartService works fine, but I don't know why in the second case when I want to use the autowired cartService(in an another class) I get null as its value.
Here is a part of the source:
Repository:
#Repository
public interface CartRepository extends JpaRepository<Cart, Integer> {
Cart findById(int id);
}
Service:
public interface CartService{
Iterable<Cart> getAllCart();
Cart getCart(int id);
void save(Cart cart);
}
Service Implementation:
#Service
public class CartServiceImpl implements CartService{
#Autowired
CartRepository cartRepository;
#Override
public Iterable<Cart> getAllCart() {
return cartRepository.findAll();
}
#Override
public Cart getCart(int id) {
return cartRepository.findById(id);
}
#Override
public void save(Cart cart) {
cartRepository.saveAndFlush(cart);
}
}
#Component
public class ColumnLay extends VerticalLayout {
#Autowired
CartService cartService;
//...some code...cartService works fine
}
UI class
#Route("purchase")
#Component
#UIScope
public class Purchase extends VerticalLayout {
#Autowired
CartService cartService;
//here when I use cartService I get null
//some code goes here
}
You did not show where in the Purchase class you happen to get a NullPointerException, but I suspect that it happens in the constructor, because that would make perfect sense.
Autowiring happens after the construction of an object. Therefore, your autowired cartService is null in your constructor. If there is a method annotated with #PostConstruct, then this is called after the autowiring - your service will be there then.
Or you could switch from field injection to constructor injection. By using constructor injection, the cartService will be available in the constructor already.
#Route("purchase")
#Component
#UIScope
public class Purchase extends VerticalLayout {
// no annotation here!
CartService cartService;
//this way cartService is not null in constructor
#Autowired
public Purchase(CartService cartService){
this.cartService = cartService;
}
}
I have a confusion in Dependency Injection in Spring MVC.
First Code:-
#Service
#Transactional
public class UserServiceImpl implements UserService {
#Autowired
private Userdao udo;
#Override
#Transactional
public List<Positions> plist() {
return udo.plist();
}
}
It is working Fine.
I would like to implement Dependency Injection in this class.Am doing right or wrong?
second code:-
`#Service
#Transactional
public class UserServiceImpl implements UserService {
#Autowired
private Userdao udo;
public UserServiceImpl(Userdao udo) {
this.udo = udo;
}
#Override
#Transactional
public List<Positions> plist() {
return udo.plist();
}
}
Its not working.ERROR: org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.xxx.Services.UserService com.xxx.java.HomeController.uservice; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceImpl' defined in file [D:\xxxWorkspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\abcd\WEB-INF\classes\com\xxx\ServiceImp\UserServiceImpl.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.xxx.ServiceImp.UserServiceImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.xxx.ServiceImp.UserServiceImpl.<init>()
I am a beginner .please help me to solve this.How to implement DI in Spring MVC.
You can do this two ways.
You can use field based autowiring. But in this case you will need a default constructor.
#Service
#Transactional
public class UserServiceImpl implements UserService {
#Autowired // field based DI
private Userdao udo;
// default constructor
public UserServiceImpl() {}
#Override
#Transactional
public List<Positions> plist() {
return udo.plist();
}
}
You can use constructor based dependency injection. To do this simply move your #Autowire annotation to your constructor. And remove it from the field.
#Service
#Transactional
public class UserServiceImpl implements UserService {
private Userdao udo;
#Autowired // constructor based DI
public UserServiceImpl(Userdao udo) {
this.udo = udo;
}
#Override
#Transactional
public List<Positions> plist() {
return udo.plist();
}
}
First setup is alright, and should work.
In the second setup you're getting following exception
class [com.xxx.ServiceImp.UserServiceImpl]: No default constructor found;
Which means what it says, since you've defined a constructor public UserServiceImpl(Userdao udo) Spring can't find an no-argument constructor.
You can either remove this constructor and use the first one or you can define the no argument constructor yourself.
You shouldn't actually need to define a constructor in a bean as you're not going to create bean object yourself. You would only need it if you're autorwiring constructor arguments.
If you're trying to autowire constructor then you can do it like below.
#Service
#Transactional
public class UserServiceImpl implements UserService {
private Userdao udo;
#Autowired //autowired constructor, instead of the field
public UserServiceImpl(Userdao udo) {
this.udo = udo;
}
#Override
#Transactional
public List<Positions> plist() {
return udo.plist();
}
}
In simple words: If you define a constructor (overloaded) then you must use the #Autowired annotation on the constructor, if you do not define a constructor, then you must use the #Autowired annotation for each Object you need to add as dependency injection. For example:
With constructor overloaded:
#Service
#Transactional
public class UserServiceImpl implements UserService {
private final Userdao userDao;
private final RoleDao roleDao;
#Autowired
public UserServiceImpl(Userdao userDao, RoleDao roleDao) {
this.userDao = userDao;
this.roleDao = roleDao;
}
}
Without constructor overloaded
#Service
#Transactional
public class UserServiceImpl implements UserService {
#Autowired
private UserDao userDao;
#Autowired
private RoleDao roleDao;
// default constructor
public UserServiceImpl() {}
}
Defining a constructor with a single #Autowired is better than having many objects #Autowired
I have a class like this -
#Service
public class SomeClass {
#Autowired
Environment env;
private String property;
#Value("${pty}")
public void setPty(String pty) {
pty = environment.getProperty("pty");
}
}
I'm trying to inject the 'pty' variable from another class 'Environment' which is autowired and I get this exception when my server startups
Error creating bean with name 'someClass': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire method: public void
service.facade.ActionFacade.setPty(java.lang.String);
nested exception is java.lang.IllegalArgumentException: Could not
resolve placeholder 'pty' in string value "${pty}"
The exception is because there is no property pty in your Spring context. #Value lookup the placeholder 'pty' in the resource files loaded.
In your case it is not required as you need to get it from Environment class which you have Autowired already, below code will give you the idea.
#Service
public class SomeClass {
#Autowired
Environment env;
private String property;
#PostConstruct
public void init(){
property=env.getProperty("pty");
}
}
Try #PostConstruct
The PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization.
#PostConstruct
public void init() {
property = env.getProperty("pty");
}
You can do this with the help of Spring bean life cycles:
1. InitializingBean -> afterPropertiesSet
2. #PostConstruct
public class EmployeeService implements InitializingBean{
private Employee employee;
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
#PostConstruct
public void init() {
property = env.getProperty("pty");
}
#Override
public void afterPropertiesSet() throws Exception {
}
}
I got another problem when working on my current Spring and Hibernate application. I have built my DAO interfaces/classes, as well as my Service interfaces/classes and of course the Entities.
Everything is being deployed well but as soon as I add the #Transactional annotation to my XXXServiceImpl classes, I get the following exception during deployment (tested on Glassfish AND Tomcat):
Caused by: java.lang.IllegalStateException: Cannot convert value of type [com.sun.proxy.$Proxy25 implementing net.dreamcode.bleevle.persistence.service.IntranetService,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [net.dreamcode.bleevle.persistence.service.impl.IntranetServiceImpl] for property 'intranetService': no matching editors or conversion strategy found
Of course, I tried to find something about that and I guess it's basically because interface and class are not matching when adding the annotation. But I also tried adding the annotation on my interfaces, which didn't help along to solve the problem, producing the same error as stated above.
Here's some example code from my project (BasicService, UserService and UserServiceImpl):
BasicService (Interface):
public interface BasicService<T> {
T findById(String id);
void create(T entity);
void delete(T entity);
void update(T entity);
}
UserService (Interface):
import net.dreamcode.bleevle.data.User;
public interface UserService extends BasicService<User> {
User findByName(String name);
}
UserServiceImpl (Class):
public class UserServiceImpl implements UserService {
#Autowired
UserDao userDao;
#Override
public User findByName(String name) {
return userDao.findByName(name);
}
#Override
public User findById(String id) {
return userDao.findById(id);
}
#Override
public void create(User entity) {
userDao.create(entity);
}
#Override
public void delete(User entity) {
userDao.delete(entity);
}
#Override
public void update(User entity) {
userDao.update(entity);
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
Is there a specific thing to do when working with this kind of pattern (I guess it's some kind of design pattern with Service and Dao stuff)?
Any kind of help is greatly appreciated. Thanks in advance!
You have a property
#Autowired private IntranetServiceImpl intranetService;
(or an equivalent thereof, such as an annotated constructor parameter or a setter) whose type is the implementation type of your service. This is wrong: you should always use the interface type for your properties.
The reason why it fails as soon, but no earlier than, you annotate with #Transactional is that this annotation causes Spring to create a dynamic proxy of your interface where otherwise there would be the naked implementation class instance. This dynamic proxy fails to be downcast into your implemantation type, but would be successfully cast into the interface type.