Spring Service name conflicting with Interface name - java

I have an Interface name
public interface ScoreDao {
public int storeScore(OverallScore overallScore);
public void storeIndividualScore(ScoreTO scoreTO);
}
The implementation class is like below
#Repository("scoreDao")
public class ScoreDaoImpl implements ScoreDao {
#Override
public int storeScore(OverallScore overallScore) {
//Implementation
}
#Override
public void storeIndividualScore(ScoreTO scoreTO){
//Implementation
}
}
The caller is using the service like below
#Service("scoreService")
public class scoreServiceImpl implements IScoreService {
#Autowired
private ScoreDao scoreDao;
#Override
public int storeScore(OverallScore overallScore) {
return scoreDao.storeOverallScore(overallScore);
}
#Override
public void storeIndividualScore(ScoreTO scoreTO) {
scoreDao.storeIndividualScore(scoreTO);
}
}
I'm using spring 4.x, while deploying I'm getting bean conflict error as below.
Caused by: java.lang.RuntimeException:
org.springframework.context.annotation.ConflictingBeanDefinitionException:
Annotation-specified bean name 'ScoreDao' for bean class [ScoreDao]
conflicts with existing, non-compatible bean definition of same name
and class [ScoreDaoImpl]
When I change the interface name to IScoreDao, it is working. Is it because of service name #Repository("scoreDao") same as Interface name?

The simple answer is Yes,it was due to that you have an interface called ScoreDao and you make the implementation of it as #Repository("scoreDao")
two ways to solve it:
Rename ScoreDao to other name
Change #Repository("scoreDao") to #Repository so that it will use the default name

there is one another solution mention #Repository on your interface so that you don't need to mention on your implementation class because you implements that interface. so it creates the bean automatically with the interface name.

Related

Is it possible to customize Jpa Repository with inheritance?

Let's say that i have two Classes: Subject and Client, Subject is base-class.
#Entity
public class Client extends Subject
Now i want to add customized Jpa base interface, so methods will be accessible in subinterfaces:
#NoRepositoryBean
public interface SubjectRepository <T extends Subject> extends
JpaRepository<T, Long>, CustomSubjectRepository<T> {}
CustomSubjectRepository looks like:
public interface CustomSubjectRepository<T extends Subject> {
void saveEncrypted(T subject);
}
I need implementation so i declare class:
#Repository
#Transactional
public class CustomSubjectRepositoryImpl<T extends Subject> implements
CustomSubjectRepository<T> {
#PersistenceContext
private EntityManager entityManager;
#Override
public void saveEncrypted(T subject) {
//implementation
}
}
Then wanted to create ClientRepository and inherit from SubjectRepository to have access to saveEncrypted method.
#Repository
public interface ClientRepository extends SubjectRepository<Client> {
}
But when it comes to compile i get:
Error creating bean with name 'clientRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract void com.path.repositories.CustomSubjectRepository.saveEncrypted(com.path.models.Subject)! No property saveEncrypted found for type Client!
You are extending the interface, this way Spring will try to create a query named saveEncrypted instead of using the customized method.
I believe the best solution is to extend the class CustomSubjectRepositoryImpl.
#Repository
public class ClientRepository extends CustomSubjectRepositoryImpl<Client> {
}

How to specify which version of a concrete implementation for an abstract class to autowire in Spring?

Having the following class structure:
public abstract class A {
String someProperty = "property"
public abstract void doSomething();
}
#Service
public class Aa extends A {
#Override
public abstract void doSomething() {
System.out.println("I did");
}
}
#Service
public class Ab extends A {
#Override
public abstract void doSomething() {
System.out.println("I did something else");
}
}
I need a way to tell Spring which A concrete class to Autowire in my Foo service, based on a property in a properties file.
#Service
public class Foo {
#Autowire
private A assignMeAConcreteClass;
}
And in my properties file I have this:
should-Aa-be-used: {true, false}
Remove the #Service annotation, instead write a #Bean-annotated method in a configuration class that reads the properties, and returns the appropriate A instance.
Not a new way but in your case I think that a possible suitable way would be to use
FactoryBean in the class that wants to inject the bean conditionally.
The idea is simple : you implement FactoryBean by parameterizing it with the interface of the bean that you want to inject and override getObject() to inject the wished implementation :
public class FactoryBeanA implements FactoryBean<A> {
#Autowired
private ApplicationContext applicationContext;
#Value("${should-Aa-be-used}")
private boolean shouldBeUsed;
#Override
public A getObject() {
if (shouldBeUsed) {
return applicationContext.getBean(Aa.class));
return applicationContext.getBean(Ab.class));
}
}
But FactoryBean instances are not classic beans. You have to configure it specifically.
You could configure it in a Spring Java configuration in this way :
#Configuration
public class FactoryBeanAConfiguration{
#Bean(name = "factoryBeanA")
public FactoryBeanA factoryBeanA() {
return new FactoryBeanA();
}
#Bean
public beanA() throws Exception {
return factoryBeanA().getObject();
}
}

Use entityManager in a single repository

I use spring-data-jpa to access my data. I need a way to detach an Object and store it as a new database row. My approach is currently to add a detach method to the repository, but for that, I need a EntityManager. And I haven't found a (nice) way of obtaining it... Any ideas?
#Repository
public interface InteractionRepository
extends JpaRepository<Interaction, Long>,
DetatchableItemRepository{}
public interface DetatchableItemRepository {
void detach(Interaction clone);
}
public class DetatchableItemRepositoryImpl implements DetatchableItemRepository {
#Autowired
EntityManager em;
public void detach(Interaction clone) {
em.detach(clone);
clone.id=null;
em.persist(clone);
}
}
However, spring dies with this error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'interactionRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property detach found for type Interaction!
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property detach found for type Interaction!
you use wrong name convention for custom repository , try this :
public interface DetatchableItemRepositoryCustom {
void detach(Interaction clone);
}
public interface DetatchableItemRepository extends JpaRepository<Interaction, Long>,
DetatchableItemRepositoryCustom {
}
public class DetatchableItemRepositoryImpl implements DetatchableItemRepositoryCustom {
}
spring data use name convention for custom repository and main repository.(see about name Adding custom behavior to single repositories)
If you have some SomeRepository , that extends some base spring data repository , and want to add custom behavior then it should be like :
interface SomeRepositoryCustom{
someMethod();
}
//XXXRepository - any base spring data repository
interface SomeRepository extends<T ,ID> extend XXXRepository , SomeRepositoryCustom {
.......
}
public class ARepositoryImpl implement SomeRepositoryCustom{
#Overide
someMethod(){
....
}

Injecting dependent bean

I have a class
EntiyFacadeImpl.java
#Stateless
public class EntityFacadeImpl implements EntityFacade {
#EJB
ICustomerBean customerBean;
public void printCustomer(Customer c) {
customerBean.printCustomer(c);
customerBean.additionalFieldsHandler(c.getAdditionalFields().toString());
}
}
Where ICustomerBean is #Local interface and have two implementation classes CustomerBean.java and CustomerBeanExt.java where later one extends CustomerBean.java
#Stateless(name = "CustomerBean")
public class CustomerBean implements ICustomerBean {
public void printCustomer(Customer customer) {
System.out.println(customer);
}
public void additionalFieldsHandler(String additionalFields) {
// an empty implemetation here
}
}
#Stateless(name = "CustomerExtBean")
public class CustomerExtBean extends CustomerBean implements ICustomerBean {
#Override
public void additionalFieldsHandler(String additionalFields) {
// some custom implemetation
System.out.println("Additional Fields: "+additionalFields);
}
}
ICustomer interface looks like this
#Local
public interface ICustomerBean {
public void printCustomer(Customer c);
public void additionalFieldsHandler(String additionalFields);
}
My aim is that whenever I inject my EntityFacade (interface for EntityFacadeImpl) in SimpleRESTPojo.java only, I want CustomerExtBean to be inject in it, while when any other class injects it I want CustomerBean to be injected
#Path("/pojo")
public class SimpleRESTPojo {
#EJB
private EntityFacade entityFacade;
}
My app's entry point is EntityFacade only. Is there a way to achieve this?
Actually, after reading your question, it looks like you're trying to introduce tight coupling. CDI doesn't make EntityFacade aware of where it was injected in to. I don't see a way to do this.
What you could do is create an extended version of EntityFacade that used this injection point:
#Inject
#Extended //or whatever qualifier you come up with
private ICustomerBean customerBean;
and then use that same qualifier on the extended EntityFacade.

Injection of autowired dependencies failed for abstract class

I am using Spring 3 and Hibernate 4
I have the following class structure
public interface GenericDAO<T> {
public void create(T entity);
public void update(T entity);
public void delete(T entity);
}
DAO class
public interface EmployeeDAO extends GenericDAO<Employee> {
public void findEmployee(EmployeeQueryData data);
}
DAO Implementation class
#Repository("employeeDAO")
public abstract class EmployeeDAOImpl implements EmployeeDAO {
protected EntityManager entityManager;
#Override
public void findEmployee(EmployeeQueryData data) {
...... code
}
The problem I am facing is when I try to deploy, I am getting the following exception.
If I remove abstract from EmployeeDAOImpl and remove extends GenericDAO<Employee> from EmployeeDAO then application gets deployed without errors. So it is not possible to have abstract class for EmployeeDAOImpl or I have need to implement all methods of GenericDAO in DAO implementation without abstract?
Error creating bean with
name 'employeeService': Injection of autowired dependencies failed; \
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: test.dao.EmployeeDAO
test.service.EmployeeServiceImpl.employeeDAO; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [test.dao.EmployeeDAO] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for
this dependency. Dependency annotations:
{#javax.inject.Inject()}.
Edit 1
GenericDAOImpl
public class GenericDAOImpl<T> implements GenericDAO<T> {
public void create(T entity) {
}
public void update(T entity) {
}
public void delete(T entity) {
}
EmployeeDAOImpl
public class EmployeeDAOImpl extends GenericDAOImpl<Employee> implements EmployeeDAO {
Java (and consequently Spring) cannot create instances of abstract classes: every method must have an implementation before Java will let you create an instance, otherwise you would get a runtime error when you tried to call the method. You need to remove "abstract" from EmployeeDAOImpl and implement the methods inherited from GenericDAO.
Why do you want to declare a class implementation as abstract? Conceptually it's a contradiction. Obviously Spring cannot instantiate it and fails.
Confirm if your EmployeeDAOImpl or other annotated class packages are mentioned in spring context xml in following tag. Unless this is done, annotations won't get read and will not be initialized.
<context:component-scan base-package="com.app.service" />

Categories