I have a spring mvc application. There is a class A as shown below:
public class A extends X {
private final RetryRegistry retryReg;
#value("${retry.attempts:5}")
private int retryAttempts;
#value("${retry.delay:5000}")
private int retryDelay;
public A( B b, C c, D d){
super(b,c,d);
this.retryReg = RetryRegistry.of(RetryConfig.custom()
.maxAttempts(this.retryAttempts)
.waitDuration(Duration.ofMillis(this.retryDelay))
.build());
}
.......
}
The test class for class A is as shown below:
#PrepareForTest(A.class)
#runWith(PowerMockRunner.class)
#SupressWarnings("unchecked")
public class ATest {
#InjectMocks
private A a;
........
}
Now when test class injects mock and calls A's constructor, the value for retryAttempts is 0 inside the constructor, hence an exception is thrown.
It seems that the configurable properties (from the properties file whose path has been mentioned in servlet-context are no being read) when inject mock tries to construct A.
I tried many things like adding #TestPropertySource to my test file, but it doesn't work.
#TestPropertySource(locations="classpath:SettingsTest.properties")
#PrepareForTest(A.class)
#runWith(PowerMockRunner.class)
#SupressWarnings("unchecked")
public class ATest {
#InjectMocks
private A a;
........
}
Am I doing something wrong, or is #TestPropertySource is only supported for Springboot apps.
Any suggestions on how I can set the configurable properties before #InjectMocks tries to access class A'constructor.
How about you create the registry as a bean in a #Configuration?
// this will automatically be initialized with yours properties
#ConfigurationProperties(prefix="retry)
class RetryProperties {
private int attempts;
private int delay;
}
#Configuration
class RetryConfiguration {
#Bean RetryRegistry registry(RetryProperties props) {
return RetryRegistry.of(RetryConfig.custom()
.maxAttempts(retryProperties)
.waitDuration(Duration.ofMillis(this.retryDelay))
.build());
}
}
#Component // I assume, otherwise the #Value properties wouldn't work
public class A extends X {
private final RetryRegistry retryReg;
public A( B b, C c, D d, RetryRegistry reg){
super(b,c,d);
this.retryReg = reg;
}
.......
}
Now you can mock and inject the registry.
Overall, your structure looks a bit all over the place, with some constructor autowiring, some initialization in the constructor, some fields read from properties. You should probably stick to one of them. Also super(b,c,d) looks pretty suspicious, I've rarely seen a class hierarchy be a good idea for components (with three parameters no less).
I have a class file as below
import com.google.inject.Inject;
import lombok.Builder;
#Builder
public class A {
private final B objB;
private final C objC;
#Inject
public A(B b, C c) {
this.objB = b;
this.objC = c;
}
}
Now if I have to use this object in another class, will the .builder() method takes care of the dependencies being injected.
public class Main {
public void doSomething() {
A a = A.builder().build();
a.getObjB(); // Will it be null ?
a.getObjC(); // Will it be null ?
Injection always only works when you let guice deal with instance creation.
So when you use
#Inject
private A a;
guice will find that it needs a B and a C to create A and inject it.
But when you instantiate A yourself, it does not matter if via new or via builder() guice does not know about the instance creation, thus in your example, B and C will be null.
I've a Component as follows:
#Component
class A(){
private s;
public A(){}
public A(String s){this.s=s;}
}
Here is the other class Where I'm auto wiring the above class:
#Component
class B(){
#Autowire
private A a;
}
In the above autowiring, I need to use the parameterized constructor. How can I pass the constructor args?
You can't, at least not via #Autowired in B but there are other ways to do it:
Wire the parameter into A's constructor:
One constructor is annotated with #Autowired because:
As of Spring Framework 4.3, the #Autowired constructor is no longer
necessary if the target bean only defines one constructor. If several
constructors are available, at least one must be annotated to teach
the container which one it has to use.
#Component
class A(){
private s;
public A(){}
#Autowired
public A(#Value("${myval}") String s){this.s=s;}
}
Expose A as a #Bean
Straight from the docs:
#Configuration
public class AppConfig {
#Bean
public A a(#Value("${myval}") String s) {
return new A(s);
}
}
Construct A in B using an initialization callback
Docs
#Component
class B(){
private A a;
#Value("${myval}")
private String myval;
#PostConstruct
private void init()
{
a = new A(myval);
}
}
There is a concept of prototype bean which I think you require in your case. #Component will create a singleton bean and changing it in one place will change in all parent classes where this was injected.
You need to understand how to inject a prototype bean in singleton bean.
Follow this example
https://stackoverflow.com/a/25165971/949912
Just use setters instead of constructor.
If you want to create object by yourself with new keyword then this object will not be managed by container.
How can I inject a mocked bean that has certain behaviour defined into a a class that is under test but when it's initiated the constructor calls that mock and execute certain action against it.
So for example I have this class that I would like to test:
public class A {
#Autowired
private B b;
private String result = null;
public A(int c) {
result = b.calculateStuff(c) + "AA";
}
public String getResult() {
return result + "A";
}
}
Now the test class:
public class ATest{
#Mock
private B b;
#InjectMocks
private A a;
#Before
public void setUp() {
doReturn("String result!").when(B).get(anyInt());
MockitoAnnotations.initMocks(this);
}
public void testGetResult() {
assertEquals(a.getResult(),"String result!AAA");
}
}
How can I actually inject a mock into A ? Is there a better way of approaching this?
As per the documentation the constructor of your object under test has to match the mocks in the test for injection to happen. So you need to redesign your constructor for this to work. An int can't be mocked.
As a general note, you should try to keep your Spring beans stateless, meaning that the only allowed class variables are other stateless beans (so no String, int, other literals). For instance:
public class A {
#Autowired
private B b;
public String getResult(int c) {
return b.calculateStuff(c) + "AAA";
}
}
MockitoAnnotations.initMocks(this); should be the first invocation in the #Before-annotated method.
Also, you have your expected and actual arguments the wrong way.
I assume that if you are injecting a bean in your class A then it needs to be singleton. What are you trying to achieve by creating a constructor and passing an argument to it? If you want to execute something as soon as the bean is created then I would suggest you to replace the constructor with a normal method and use #PostConstruct on it. Example:
#PostConstruct
public void init () {
/* Do Something */
}
You need to tweak some things in case you want to utilize the Testing Frameworks like Mockito up to its full potential.
Tell me if I misunderstood your requirements.
How does Spring resolve this: bean A is dependent on bean B, and bean B on bean A.
The Spring reference manual explains how circular dependencies are resolved. The beans are instantiated first, then injected into each other.
Consider this class:
package mypackage;
public class A {
public A() {
System.out.println("Creating instance of A");
}
private B b;
public void setB(B b) {
System.out.println("Setting property b of A instance");
this.b = b;
}
}
And a similar class B:
package mypackage;
public class B {
public B() {
System.out.println("Creating instance of B");
}
private A a;
public void setA(A a) {
System.out.println("Setting property a of B instance");
this.a = a;
}
}
If you then had this configuration file:
<bean id="a" class="mypackage.A">
<property name="b" ref="b" />
</bean>
<bean id="b" class="mypackage.B">
<property name="a" ref="a" />
</bean>
You would see the following output when creating a context using this configuration:
Creating instance of A
Creating instance of B
Setting property a of B instance
Setting property b of A instance
Note that when a is injected into b, a is not yet fully initialised.
As the other answers have said, Spring just takes care of it, creating the beans and injecting them as required.
One of the consequences is that bean injection / property setting might occur in a different order to what your XML wiring files would seem to imply. So you need to be careful that your property setters don't do initialization that relies on other setters already having been called. The way to deal with this is to declare beans as implementing the InitializingBean interface. This requires you to implement the afterPropertiesSet() method, and this is where you do the critical initialization. (I would also include code to check that important properties have actually been set.)
In the codebase I'm working with (1 million + lines of code) we had a problem with long startup times, around 60 seconds. We were getting 12000+ FactoryBeanNotInitializedException.
What I did was set a conditional breakpoint in AbstractBeanFactory#doGetBean
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
where it does destroySingleton(beanName) I printed the exception with conditional breakpoint code:
System.out.println(ex);
return false;
Apparently this happens when FactoryBeans are involved in a cyclic dependency graph. We solved it by implementing ApplicationContextAware and InitializingBean and manually injecting the beans.
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class A implements ApplicationContextAware, InitializingBean{
private B cyclicDepenency;
private ApplicationContext ctx;
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
ctx = applicationContext;
}
#Override
public void afterPropertiesSet() throws Exception {
cyclicDepenency = ctx.getBean(B.class);
}
public void useCyclicDependency()
{
cyclicDepenency.doSomething();
}
}
This cut down the startup time to around 15 secs.
So don't always assume that spring can be good at solving these references for you.
For this reason I'd recommend disabling cyclic dependency resolution with AbstractRefreshableApplicationContext#setAllowCircularReferences(false) to prevent many future problems.
Problem ->
Class A {
private final B b; // must initialize in ctor/instance block
public A(B b) { this.b = b };
}
Class B {
private final A a; // must initialize in ctor/instance block
public B(A a) { this.a = a };
}
// Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'A': Requested bean is currently in creation: Is there an unresolvable circular reference?
Solution 1 ->
Class A {
private B b;
public A( ) { };
//getter-setter for B b
}
Class B {
private A a;
public B( ) { };
//getter-setter for A a
}
Solution 2 ->
Class A {
private final B b; // must initialize in ctor/instance block
public A(#Lazy B b) { this.b = b };
}
Class B {
private final A a; // must initialize in ctor/instance block
public B(A a) { this.a = a };
}
It just does it. It instantiates a and b, and injects each one into the other (using their setter methods).
What's the problem?
Say A depends on B, then Spring will first instantiate A, then B, then set properties for B, then set B into A.
But what if B also depends on A?
My understanding is: Spring just found that A has been constructed (constructor executed), but not fully initialized (not all injections done), well, it thought, it's OK, it's tolerable that A is not fully initialized, just set this not-fully-initialized A instances into B for now. After B is fully initialized, it was set into A, and finally, A was fully initiated now.
In other words, it just expose A to B in advance.
For dependencies via constructor, Sprint just throw BeanCurrentlyInCreationException, to resolve this exception, set lazy-init to true for the bean which depends on others via constructor-arg way.
Circular dependency in Spring : Dependency of one Bean to other. Bean A → Bean B → Bean A
Solutions:
Use #Lazy Annotation
Redesign you class dependency
Use Setter/Field Injection
Use #PostConstruct Annotation
From the Spring Reference:
You can generally trust Spring to do
the right thing. It detects
configuration problems, such as
references to non-existent beans and
circular dependencies, at container
load-time. Spring sets properties and
resolves dependencies as late as
possible, when the bean is actually
created.
The Spring container is able to resolve Setter-based circular dependencies but gives a runtime exception BeanCurrentlyInCreationException in case of Constructor-based circular dependencies.
In case of Setter-based circular dependency, the IOC container handles it differently from a typical scenario wherein it would fully configure the collaborating bean before injecting it.
For eg., if Bean A has a dependency on Bean B and Bean B on Bean C, the container fully initializes C before injecting it to B and once B is fully initialized it is injected to A. But in case of circular dependency, one of the beans is injected to the other before it is fully initialized.
Its clearly explained here. Thanks to Eugen Paraschiv.
Circular dependency is a design smell, either fix it or use #Lazy for the dependency which causes problem to workaround it.
If you generally use constructor-injection and don't want to switch to property-injection then Spring's lookup-method-injection will let one bean lazily lookup the other and hence workaround the cyclic dependency. See here: http://docs.spring.io/spring/docs/1.2.9/reference/beans.html#d0e1161
Constructor Injection fails when there is Circular Dependency between spring beans. So in this case we Setter injection helps to resolve the issue.
Basically, Constructor Injection is useful for Mandatory dependencies, for optional dependencies better to use Setter injection because we can do re-injection.
If two beans are dependent on each other then we should not use Constructor injection in both the bean definitions. Instead we have to use setter injection in any one of the beans. (of course we can use setter injection n both the bean definitions, but constructor injections in both throw 'BeanCurrentlyInCreationException'
Refer Spring doc at "https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#resources-resource"
Also we use #Lazy Annotation
#Component
public class ClassA {
private ClassB classB;
public ClassB getClassB() {
return classB;
}
#Lazy
#Autowired
public void setClassB(ClassB classB) {
this.classB = classB;
}
}
#Component
public class ClassB {
private ClassA classA;
#Autowired
public ClassB(ClassA classA) {
super();
this.classA = classA;
}
public ClassA getClassA() {
return classA;
}
public void setClassA(ClassA classA) {
this.classA = classA;
}
}