Bean annotated abstract method - Factory method implementation with spring - spring

Let's get quickly to the real thing. We have 6 classes as described below. Classes A,B,C implement the Factory Method design pattern while the caller and consumer is expected to be the spring (instantiating the E,F instances with the factory methods in B,C).
I would expect that #Bean is derived to the implementation of the abstract method in B,C subclasses. Such that once spring instantiates B,C, it will instantiate also the implementation of the abstract method in both of the classes. Which causes me to expect to have beans for E and F.
However, spring instantiates only E and skips instantiation of F. (which is very strange. I would expect it to either work as I thought, or to throw an Exception for trying to instantiate a bean with the same name which is derived from the method name)
Would appreciate a lot your input guys,
Thanks,
public abstract class D
{
}
public class E extends D
{
}
public class F extends D
{
}
public abstract class A
{
#Bean
protected abstract D createService();
}
#Configuration
public class B extends A
{
#Override
protected D createService()
{
return new E();
}
}
#Configuration
public class C extends A
{
#Override
protected D createService()
{
return new F();
}
}

Related

Generic type reverse lookup with Spring Boot #Service autowirings

Spring Boot & Java 11 here. I have an abstract base class:
public abstract class AbstractBurninator {
// ...
}
And some subclasses, such as:
public class FizzBurninator extends AbstractBurninator {}
public class BuzzBurninator extends AbstractBurninator {}
public class FoobazBurninator extends AbstractBurninator {}
But there are many more subclasses of it besides those three. I also have an interface:
public interface DoesThings<B extends AbstractBurninator> {
void doAllTheThings(B burninator, String payload);
}
So each implementation of the interface must specify the AbstractBurninator subclass it operates on. Hence I have:
public class DoesFizzThings implements DoesThings<FizzBurninator> {}
public class DoesBuzzThings implements DoesThings<BuzzBurninator> {}
public class DoesFoobazThings imlpements DoesThings<FoobazBurninator> {}
etc.
I now have a Spring Boot service (annotated with #Service) that gets autowired with a list of all List<DoesThings>. Inside that service I have a method that will infer (from certain logic) and instantiate an AbstractBurninator subclass, and it then needs to look up the DoesThings implementation associated with it. Hence if it infers an instance of FizzBurninator, I want it to select the DoesFizzThings instance from the autowired list:
#Service
public class BurninationService {
#Autowired
private List<DoesThings> thingDoers;
public void hahaha(Whistlefeather wf) {
// use 'wf' and other stateful data to infer a subclassed instance of 'AbstractBurninator':
AbstractBurninator burninator = inferSomehow();
// TODO: how to figure out which item of 'thingDoers' matches 'burninator'?
}
What's an easy and elegant way of doing this TBD lookup? I could inject a map instead:
private Map<AbstractBurninator,DoesThings> thingDoers;
But that seems unnecessary since each DoesThing has 1-and-only-1 corresponding AbstractBurninator. Any ideas? It's possible this can be done with straight Java generics, but I'm guessing Spring has some nifty utility that can help here.
If you are comfortable with wiring your Spring context into your service, you could do something like this (inspired by this SO accepted answer)
private <T extends AbstractBurninator> DoesThings<T> getSomeBurn(Class<T> clazz) {
String[] arr = ctx.getBeanNamesForType(ResolvableType.forClassWithGenerics(DoesThings.class, clazz));
if (arr.length == 1) {
return (DoesThings<T>) ctx.getBean(arr[0]);
} else {
throw new IllegalArgumentException("No burninator found");
}
}
This comes with a beautiful "unchecked cast" warning. Also, in my experience, wiring the application context indicates a design problem and definitely complicates testing.

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.

spring dependency interface injection with two implemented classes

consider a scenario of interface injection in spring, I have an interface which was implemented by two class. If we inject the Interface in another class using #Autowired. Now if we call a method in that interface then which class implemented method will be called? consider that we are not using #Qualifier annotation.
enter code here
public interface EmployeeDAOI{
void save();
}
public class Emp1 implements EmployeeDAOI{
public void save(){
//some logic
}
}
public class Emp2 implements EmployeeDAOI{
public void save(){
//some logic
}
}
now we inject EmployeeDAOI to some class
public class IterfaceEx{
#Autowired
private EmployeeDAOI edaoi;
public void setEmployeeDAOI(EmployeeDAOI edaoi){
this.edaoi=edaoi;
}
edaoi.save(); // My question is here which class method will be called ?
}
None.
You get an exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [EmployeeDAOI] is defined: expected single matching bean but found 2: [emp1 , emp2]
Spring expects exactly one instance, unless the injection is done for a Collection of those instances or you use a way of differentiating (#Qualifier).

Spring can you autowire inside an abstract class?

Spring is failing to autowire my object? Is it possible to autowire an object within an abstract class. Assume all schemas are supplied in application-context.xml
Question: What annotation should be on the base and extending classes (if any) #Service #Component?
Example
abstract class SuperMan {
#Autowire
private DatabaseService databaseService;
abstract void Fly();
protected void doSuperPowerAction(Thing thing) {
//busy code
databaseService.save(thing);
}
}
Extending class
public class SuperGirl extends SuperMan {
#Override
public void Fly() {
//busy code
}
public doSomethingSuperGirlDoes() {
//busy code
doSuperPowerAction(thing)
}
application-context.xml
<context:component-scan base-package="com.baseLocation" />
<context:annotation-config/>
I have that kind of spring setup working
an abstract class with an autowired field
public abstract class AbstractJobRoute extends RouteBuilder {
#Autowired
private GlobalSettingsService settingsService;
and several children defined with #Component annotation.
Normally, Spring should do the autowiring, as long as your abstract class is in the base-package provided for component scan.
See this and this for further reference.
#Service and #Component are both stereotypes that creates beans of the annotated type inside the Spring container. As Spring Docs state,
This annotation serves as a specialization of #Component, allowing for
implementation classes to be autodetected through classpath scanning.
What if you need any database operation in SuperGirl you would inject it again into SuperGirl.
I think the main idea is using the same object reference in different classes.
So what about this:
//There is no annotation about Spring in the abstract part.
abstract class SuperMan {
private final DatabaseService databaseService;
public SuperMan(DatabaseService databaseService) {
this.databaseService = databaseService;
}
abstract void Fly();
protected void doSuperPowerAction(Thing thing) {
//busy code
databaseService.save(thing);
}
}
#Component
public class SuperGirl extends SuperMan {
private final DatabaseService databaseService;
#Autowired
public SuperGirl (DatabaseService databaseService) {
super(databaseService);
this.databaseService = databaseService;
}
#Override
public void Fly() {
//busy code
}
public doSomethingSuperGirlDoes() {
//busy code
doSuperPowerAction(thing)
}
In my opinion, inject once run everywhere :)
In my case, inside a Spring4 Application, i had to use a classic Abstract Factory Pattern(for which i took the idea from - http://java-design-patterns.com/patterns/abstract-factory/) to create instances each and every time there was a operation to be done.So my code was to be designed like:
public abstract class EO {
#Autowired
protected SmsNotificationService smsNotificationService;
#Autowired
protected SendEmailService sendEmailService;
...
protected abstract void executeOperation(GenericMessage gMessage);
}
public final class OperationsExecutor {
public enum OperationsType {
ENROLL, CAMPAIGN
}
private OperationsExecutor() {
}
public static Object delegateOperation(OperationsType type, Object obj)
{
switch(type) {
case ENROLL:
if (obj == null) {
return new EnrollOperation();
}
return EnrollOperation.validateRequestParams(obj);
case CAMPAIGN:
if (obj == null) {
return new CampaignOperation();
}
return CampaignOperation.validateRequestParams(obj);
default:
throw new IllegalArgumentException("OperationsType not supported.");
}
}
}
#Configurable(dependencyCheck = true)
public class CampaignOperation extends EO {
#Override
public void executeOperation(GenericMessage genericMessage) {
LOGGER.info("This is CAMPAIGN Operation: " + genericMessage);
}
}
Initially to inject the dependencies in the abstract class I tried all stereotype annotations like #Component, #Service etc but even though Spring context file had ComponentScanning for the entire package, but somehow while creating instances of Subclasses like CampaignOperation, the Super Abstract class EO was having null for its properties as spring was unable to recognize and inject its dependencies.After much trial and error I used this **#Configurable(dependencyCheck = true)** annotation and finally Spring was able to inject the dependencies and I was able to use the properties in the subclass without cluttering them with too many properties.
<context:annotation-config />
<context:component-scan base-package="com.xyz" />
I also tried these other references to find a solution:
http://www.captaindebug.com/2011/06/implementing-springs-factorybean.html#.WqF5pJPwaAN
http://forum.spring.io/forum/spring-projects/container/46815-problem-with-autowired-in-abstract-class
https://github.com/cavallefano/Abstract-Factory-Pattern-Spring-Annotation
http://www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring
https://www.madbit.org/blog/programming/1074/1074/#sthash.XEJXdIR5.dpbs
Using abstract factory with Spring framework
Spring Autowiring not working for Abstract classes
Inject spring dependency in abstract super class
Spring and Abstract class - injecting properties in abstract classes
Spring autowire dependency defined in an abstract class
Please try using **#Configurable(dependencyCheck = true)** and update this post, I might try helping you if you face any problems.

Resources