Conflict beeween JPA #Entity and Spring #Component/#Resource/#Configurable - spring

I want to Autowire a class which is annotated via JPA #Entity, so i added Spring's #Component/#Resource/#Configurable annotations but it will not allow me to autowire that class.
Is there any other annotation required ?.
Sample is:
#Component
#Entity
#Table
public class Employee{
#Autowired
TestService testService;
...
}
Where class TestService is annotated with #Service .

You can easily do that, make a constructor and pass the injected Service as perameter:
#Component
#Entity
#Table
public class Employee{
Employee(TestService testService){
//Do some work
}
...
}
now caller class..
#Service
public class CallerClass{
#Autowired
TestService testService;
Employee employee =new Employee(testService);
}

You need to use #Configurable
#Entity
#Table
#Configurable
public class Employee{
#Autowired
TestService testService;
...
}
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-atconfigurable

Related

I can't autowire Service class in Spring Boot Test

I created Dao Repository that uses jdbc for working with DB.
I autowired this repository in my Service class.
Then I try to autowire my service class in my test class.
#SpringBootTest
public class ServiceTest {
#MockBean
private Dao dao;
#Autowired
private Service service;
#Test
void whenSomething_thanSomething() {
when(Dao.getStatus(anyString())).thenReturn("green");
assertEquals(0, service.getStatus(""));
}
//other tests...
}
#Service
public class Service {
private DaoImpl daoImpl;
#Autowired
public Service(DaoImpl daoImpl) {
this.daoImpl = daoImpl;
}
//...
}
#Repository
public class DaoImpl omplements Dao {
private NamedParameterJdbcOperations jdbc;
#Autowired
public DaoImpl(NamedParametedJdbcOperations jdbc) {
this.jdbc = jdbc;
}
//...
}
When I start test I get the next error:
Parameter 0 of constructor in Service required a bean of type DaoImpl that could not be found.
How can I resolve my problem?
Since you inject DaoImpl in your service-class you were probably intending to mock DaoImpl instead of Dao:
#SpringBootTest
public class ServiceTest {
#MockBean
private DaoImpl daoImpl;
...
}

Why is the #Repository annotation necesssary on a JpaRepository?

I have the following repository:
import org.springframework.data.jpa.repository.JpaRepository;
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
Employee findByName(String name);
}
Assume Employee is your usual entity class with id, name and surname.
I wire this class to my EmployeeService and use it like this:
#Service
public class EmployeeService {
#Autowired
private EmployeeRepository repository;
public Employee saveEmployee(Employee employee) {
return repository.save(employee);
}
}
Would it make any difference to add the #Repository annotation to the repository?
Example:
import org.springframework.data.jpa.repository.JpaRepository;
#Repository
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
Employee findByName(String name);
}
The #Repository annotation is not required on Spring Data repositories. Spring Boot detects repository beans based on the fact that they extend the Repository interface.
In fact, you need to suppress this behavior using #NoRepositoryBean if you want the repository bean to not be created.
The #Repository annotation is a specialization of #Component. If you were implementing repositories without the help of Spring Data, you could annotate them with #Repository to declare them as beans as well as hint at their role in your app.

#Qualifier & #Autowired object coming as null

I am having following code below.
#Builder(toBuilder = true)
#AllArgsConstructor(access = AccessLevel.PRIVATE)
#NoArgsConstructor(access = AccessLevel.PRIVATE)
#ToString
#EqualsAndHashCode
#Configurable
public class Employee {
#Autowired
#Qualifier("findEmpByDepartment")
private Function<Long, Long> empByDepartment;
private void save() {
this.empByDepartment.getList();
}
}
and FindEmpByDepartment class below.
#Component("findEmpByDepartment")
public class FindEmpByDepartment implements Function<Long, Long> {
public void getList() {
}
....
}
My problem is I am always getting null when invoke
this.empByDepartment.getList();
line. Here this.empByDepartment is coming as null. Any idea why it is like this?
Thanks
May be you would have missed annotating any class in the flow hierarchy .
#Service, #Repository and #Controller are all specializations of #Component, so any class you want to auto-wire needs to be annotated with one of them.
IoC is like the cool kid on the block and if you are using Spring then you need to be using it all the time .
So make sure you do not have any object created with new operator in the entire flow .
#Controller
public class Controller {
#GetMapping("/example")
public String example() {
MyService my = new MyService();
my.doStuff();
}
}
#Service
public class MyService() {
#Autowired
MyRepository repo;
public void doStuff() {
repo.findByName( "steve" );
}
}
#Repository
public interface MyRepository extends CrudRepository<My, Long> {
List<My> findByName( String name );
}
This will throw a NullPointerException in the service class when it tries to access the MyRepository auto-wired Repository, not because there is anything wrong with the wiring of the Repository but because you instantiated MyService() manually with MyService my = new MyService().
For more details , you can check
https://www.moreofless.co.uk/spring-mvc-java-autowired-component-null-repository-service/

#Autowired is not working for CrudRepository

I have problems injecting a repository, there is no problem injecting a Service. Im injecting the repo in a service:
#Service
public class AuthorService {
#Autowired
private AuthorRepository repository;
public String getAll(){return "XXXXX";}
}
and the repository is:
public interface AuthorRepository extends CrudRepository<Author, Integer> {
}
And my code structure is the following:
with the main class:
#SpringBootApplication
public class AuthorBookGraphqlApplication {
public static void main(String[] args) {
SpringApplication.run(AuthorBookGraphqlApplication.class, args);
}
}
the error is thrown on start:
Field repository in com.author.book.graphql.demo.service.AuthorService required a bean of type 'com.author.book.graphql.demo.repository.AuthorRepository' that could not be found.
Update code as below
Spring will automatically import the beans into the container and inject to dependencies with these annotations.
#Component, #Controller, #Service and #Repository - Helps to define the beans so the container is aware of them and can inject them for you with #Autowired.
#Autowired - Handles only wiring part here.
#Service
public class AuthorService {
#Autowired
private AuthorRepository repository;
public String getAll(){return "XXXXX";}
}
#Repository
public interface AuthorRepository extends CrudRepository<Author, Integer> {}
Before class AuthorRepository, Let's put more annotation #Repository.

spring auto-wire failed when inject a dependent bean into a #component java class

I have a Service class with #Component annotation, and this bean dependent a DAO like this:
#Component
public class CustomerService
{
#Setter
private CustomerDAO customerDAO;
}
and XML file goes like this:
<context:component-scan base-package="com.mkyong.customer" />
<bean id="customerDAO" class="com.mkyong.customer.dao.CustomerDAO" autowire="byName"></bean>
But, after the app is running, the field customerDAO can't been injected. If I replace #Setter with #Resource, that's will be fine. I deeply wonders, why the #Componet bean can't be injected with setter methods.
I'm using Spring 2.5.6;
In order to inject on setter, you will have to create a setter and annotate it with #Autowired.
#Component
public class CustomerService {
private CustomerDAO customerDAO;
#Autowired
public void setCustomerDAO(CustomerDAO customerDAO) {
this.customerDAO = customerDAO;
}
}

Resources