Spring Boot with Scala - spring

Consider there is a trait defined (Parent)
and two classes are defined class child1 and class child2 extending Parent (annotated with #Component)
And a third class Factory(Parent: Array[Parent]) (annotated with #Service)
trait Parent {}
#Component
class Child1 extends Parent {}
#Component
class Child2 extends Parent {}
#Service
class Factory(children: Array[Parent]) {
#PostConstruct
val test: Unit = children.map(x => println(x.getClass)
// printing Child1 and Child2
}
I am autowiring the Factory class in the Class Field like this
class Main #Autowired()(factory: Factory) {
//
}
I am very new to Scala.
How the children is getting initilaized with both the child classes even if it has not been instantiated explicitly in the Factory class.

Related

unable to child autowire bean in abstract parent class

abstract class Parent {
private Parent self;
private ParentMember parentMember;
#MyAspect
private void functionality() {
//some functionality
}
}
#Component
class Child1 extends Parent {
#Autowire
private ChildMember childMember;
}
Restrictions -
There are more than 50 classes implementing Parent. And I dont want to make changes to them.
I have to add some functionality in parent now in legacy code. And for that I need to self inject the child bean into parent to access the inner method call functionality via spring AOP.
Another issue is the parent class is in a library where spring is not a dependency so spring annotations like #Autowire, etc are not available.
I can create abstract class parent bean in xml probably in the service where child class is defined.
Child class beans are created using component scan in a package. So, these child classes dont have any beans defined in XML.
With so much restrictions, do we have a way to inject the created child bean into parent post construction of bean? I don't think this is possible now.

Kotlin: problem using autowired class in inheritors

I have a class:
open class AbstractMapper<E : AbstractEntity, D : AbstractDto> #Autowired constructor(
protected val mapper: ModelMapper
) : EntityDtoMapper<E, D>
It have autowired bean ModelMapper in main constructor. I try to inherit other class from it:
class UserParamsMapper : AbstractMapper<UserParams, UserParamsDto>()
IDE ask to declare field, autowired in class-paernt:
No value passed for parameter ModelMapper
Please advice, how to do it? Or I can autowire bean in AbstractMapper other way?
You need to pass all superclass constructor arguments in the subclass constructor. The #Autowired annotation is pointless on an abstract class constructor, as it only applies to the constructor of a class that is instantiated itself. You can make this work by changing your subclass:
class UserParamsMapper #Autowired constructor(
mapper: ModelMapper
) : AbstractMapper<UserParams, UserParamsDto>(mapper)
Alternatively you can change to field injection instead of constructor injection in your superclass.
open class AbstractMapper<E : AbstractEntity, D : AbstractDto> : EntityDtoMapper<E, D> {
#field:Autowired
protected lateinit var mapper: ModelMapper
}

Spring-Boot #Async causes NoSuchBeanDefinitionException when invoker bean is instatiated from a #Configuration created bean

I am getting NoSuchBeanDefinitionException if I add #Async on a method in a class annotated with #Service, if that class is used in another bean instantiated with #Bean in a #Configuration class.
Below I sketched a simple example:
#Configuration
#EnableAsync
public class Configuration() {
#Bean
public A a(C c) {
return new A(c);
}
}
public interface B {
public void asyncMethod();
}
public class A {
private B b;
public A (B b) {
this.b = b;
}
public void someMethod() {
b.asyncMethod();
}
}
#Service
public class C implements B{
#Async
#Overrides
public void asyncMethod() {
// to stuff
}
}
If I remove the #Async from asyncMethod, the application starts.
If I instantiate A by annotating it with #Service and #Autowired on the constructor, the application starts.
The constraint is that I must instantiate class A from a separate #Configuration class.
I am using a clean code architecture on the application, where classes in the core domain don't use any spring annotations on them. A class is part of the core domain.
I am instantiating some of these classes as Spring Beans from an outer layer so I don't "pollute" them with spring-specific annotations. B is part of the outer layer and can have Spring annotations.
If I put a break-point in class B's constructor, I can see it is instantiated by spring just before I get: NoSuchBeanDefinitionException for it.
I assume that the #Async is causing some weird behavior on the proxies. How can I approach this?

Spring Abstract class #Autowire null while using that field in subclass constructor

Following is the code:
public abstract class A {
#Autowired
public Provider provider;
}
#Component
public class B extends A {
B() {
provider.get();
}
}
Spring is throwing NullPointerException, while instantiating Bean of Class B.
I know #Autowired defined in Abstract class are injected, but don't know in which order they are injected.
Earlier my understanding was, While instance creation of B, Spring will autowire fields of all subclasses and then will create instance of B.
But here it seems, it overlooks the subclass concept while instance creation, and just scans B to identify #Autowire field.
Use #PostConstruct. Java Object Instantiation and Spring Dependency Injection are two different flows.
#Component
public class B extends A {
#PostConstruct
void init() {
provider.get();
}
}
If autowiring your constructors is an option the following can be helpful.
public abstract class A {
protected final Provider provider;
#Autowired
public A(Provider provider) {
this.provider = provider;
}
}
#Component
public class B extends A {
#Autowired
B(Provider provider) {
super(provider);
provider.get();
}
}
Note since the latest Spring Versions you do not need to annotate the constructor with #Autowire. If you do things right the spring framework auto-detects the constructor.

Are Spring's #Autowired object reused?

And if they are, How to stop that?
It depends on the scope of the bean being annotated. If it is of scope singleton, then it the same instance will be used everywhere in the Spring ApplicationContext. If it is of scope prototype, then a new instance will be used in each location.
<bean id="id" class="some.NewObject" scope="prototype"/>
<bean id="id2" class="some.AnotherNewObject" scope="singleton"/>
These bean definitions coupled with the following code will help to illustrate.
class Class1 {
#Autowired
some.AnotherNewObject obj;
}
class Class2 {
#Autowired
some.AnotherNewObject obj;
}
class Class3 {
#Autowired
some.NewObject obj;
}
class Class4 {
#Autowired
some.NewObject obj;
}
Class1 and Class2 will receive a reference to the same instance of some.AnotherNewObject. Class3 and Class4 will receive references to different instances of some.NewObject.
If you are using annotations and package scanning for configuration, then you can can use the #Scope annotation to specify your scope:
#Component
#Scope("prototype")
class NewObject {
...
}
#Component
#Scope("singleton")
class AnotherNewObject {
...
}
#Service
#Scope("prototype")
public class CustomerService
{}

Resources