Advantages of injecting by ObjectProvider in Spring - spring

Could you clarify what is the reason for the autowiring by ObjectProvider, if I can autowire the bean by class or interface?
public class MyBean {...}
public class MyService {
#Autowire
private ObjectProvider<MyBean> myBean;
}
vs
public class MyService {
#Autowire
private MyBean myBean;
}
Are the pros only in having the optionality check (getIfAvailable) and not-unique check (getIfUnique) methods?

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;
...
}

Mock bean is autowired into #Spy bean mockito

My unit test try #Spy beanA. But BeanA #autowire bean B as bellow:
#RunWith(SpringRunner.class)
public class MyServiceImplTest {
#Spy
private BeanA beanA;
#InjectMocks
private MyService myService = new MyServiceImpl();
#Test
public void testDoSomeThing(){
myService.doSomeThing();
}
}
MyServiceImpl as bellow :
#Service
public class MyServiceImpl {
#Autowired
private BeanA beanA;
public doSomeThing(){
....
beanA.beanADoSomeThing()
....
}
}
beanA as bellow
#Service
public class BeanA {
#Autowired
private BeanB beanB;
public beanADoSomeThing(){
...
//Null pointer exception in here because beanB=null
beanB.beanBDoSomeThing()
}
}
when run unit test i get null pointer exception at line beanB.beanBDoSomeThing(), I can understand the reason but how to resolve this issue?
I have tried
#Mock
private BeanB beanB;
But this not work, how to resolve this issue ?
If you want to spy your bean in context, you need #SpyBean annotation instead of #Spy and also you should autowire your service to be tested, smth like this:
#SpringBootTest
#RunWith(SpringRunner.class)
public class ExTest {
#SpyBean
private BeanA beanA;
#Autowired
private MyService myService;
#Test
public void testDoSomeThing() {
myService.doSomeThing();
}
}
If you don't want to load application context and test only MyServiceImpl behavior in isolation, you can use pure Mockito and mock or spy dependencies of MyServiceImpl:
#RunWith(MockitoJUnitRunner.class)
public class MockitTest {
#InjectMocks
private MyServiceImpl myService;
#Mock
private BeanA beanA;
#Test(expected = RuntimeException.class)
public void test() {
doThrow(new RuntimeException()).when(beanA).beanADoSomeThing();
myService.doSomeThing();
}
}

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;
}
}

Spring Inject Collection From Superclass

I have the following scenario:
class Super{
private List<String> someStringsThatWillBeDifferentForEveryInstancePerDerivedType;
}
#Component
class Derived1 extends Super{
#Autowired
private String name;
}
#Component
class Derived2 extends Super{
#Autowired
private Long configId;
}
I have a different List defined as Spring bean in xml for each derived class…call them listForDerived1 and listForDerived2. How can I wire these lists into my derived classes? I attempted constructor injection but I can't seem to find any luck injecting both the collection and the other deps.
You can use constructor injection with #Qualifier.
class Super {
private List<String> someStrings;
public Super(private List<String> someStrings) {
this.someStrings = someStrings;
}
}
#Component
class Derived1 extends Super {
#Autowired
public Derived1(#Qualifier("listForDerived1") List<String> listForDerived1, OtherBean bean) {
super(listForDerived1);
}
}
#Component
class Derived2 extends Super {
#Autowired
public Derived1(#Qualifier("listForDerived2") List<String> listForDerived1, OtherBean bean) {
super(listForDerived2);
}
}
Also see official Spring doc: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-autowired-annotation-qualifiers

Where is the #Autowired annotation supposed to go - on the property or the method?

Which is more correct?
This (with the #Autowired annotation on the method)?
#Controller
public class MyController
{
private MyDao myDao;
#Autowired
public MyController(MyDao myDao)
{
this.myDao = myDao;
}
This (with the #Autowired annotation on the property)?
#Controller
public class MyController
{
#Autowired
private MyDao myDao;
public MyController(MyDao myDao)
{
this.myDao = myDao;
}
Where is the #Autowired annotation supposed to go?
According to the Javadoc for Autowired, the annotation can be used on "a constructor, field, setter method or config method". See the full documentation for more details.
I personally prefer your first option (constructor injection), because the myDao field can be marked as final:
#Controller
public class MyControllear {
private final MyDao myDao;
#Autowired
public MyController(MyDao myDao) {
this.myDao = myDao;
}
Constructor injection also allows you to test the class in a unit test without code that depends on Spring.
The second option would be better written as:
#Controller
public class MyControllear {
#Autowired
private MyDao myDao;
MyController() {
}
With field injection, Spring will create the object, then update the fields marked for injection.
One option you didn't mention was putting #Autowired on a setter method (setter injection):
#Controller
public class MyControllear {
private MyDao myDao;
MyController() {
}
#Autowired
public void setMyDao(MyDao myDao) {
this.myDao = myDao;
}
You do not have to choose one or another. You can use field injection for some dependencies and constructor injection for others for the same object.
The annotation goes with the property, because that's what's being autowired; the property to be automatically set. This tutorial has a nice example. This more advanced example shows how to use qualifiers to disambiguate the wiring.

Resources