EJB override injection of abstract bean - java

I have an abstract bean with injected ISomeOtherBean interface:
public abstract class AbstractBean {
#EJB ISomeOtherBean myService;
}
The ISomeOtherBean is interface. He have many implementations, for example: SomeBeanA, SomeBeanB...
#Stateless
public class SomeBeanA implements ISomeOtherBean {
}
#Stateless
public class SomeBeanB implements ISomeOtherBean {
}
How can I inject concrete implementation of ISomeOtherBean inside some implementation of the AbstractBean?
#Stateless
public class BeanImpl extends AbstractBean {
// how write that I want inject SomeBeanB which implements ISomeOtherBean
}
First i tried to inject concrete implementation inside BeanImpl, then I passed it to additional method of superclass (Abstractbean) which writed it to field myService.
But this solution is bad for me. I remember Spring has ability to pass some beans to constructor of given bean. But it was inside XML configuration. I want something like this, but with EJB and annotation configurations.
Anyone knows how do it?

Related

Injection issue for exception mapper with abstract parent (Quarkus REST client)

I'm trying to create an ExceptionMapper with an abstract parent class and some injected fields. Here is the part of code, simplified:
#Provider
#Produces(MediaType.APPLICATION_JSON)
public class MyExceptionMapper extends GenericExceptionMapper<MyException> {
#Override
public Response toResponse(MyException exception) {
...
}
}
public abstract class GenericExceptionMapper<T extends WebApplicationException> implements ExceptionMapper<T> {
#Inject
private ClassA fieldInParentA; // will be null.
#Inject
private ClassB fieldInParentB; // will be null.
// all kind of other stuff, including getters
...
}
ClassA and ClassB are simple classes with #Dependent, #ApplicationScoped or #Singleton scopes (tried all these).
The problem is, that the fields of the parent don't get injected (nor do I see any error report in logs) and the result of getFieldInParentA() or of getFieldInParentB() return null in toResponse(), although the problem is not with the injected objects (they gets injected properly in other places).
Further, to my biggest surprise, all of fieldInParentA, fieldInParentB and fieldInChild will be injected when also the child class contains injected field. This is so with any dependent, singleton or application scoped fields:
#Provider
#Produces(MediaType.APPLICATION_JSON)
public class MyExceptionMapper extends GenericExceptionMapper<MyException> {
#Inject
private ClassC fieldInChild; // **will be initialized!**
#Override
public Response toResponse(MyException exception) {
...
}
}
public abstract class GenericExceptionMapper<T extends WebApplicationException> implements ExceptionMapper<T> {
#Inject
private ClassA fieldInParentA; // **will be initialized!**
#Inject
private ClassB fieldInParentB; // **will be initialized!**
...
}
I might not understand properly the scopes (might it be the #Provider for blame?) or the inheritance of injected fields in Jakarta Dependency Injection, but besides not being able to initialize my classes (you might have guessed, that I don't want fields in the child class :) ) it is also bothering, that I do not understand this (apparently strange) behavior: how can the injection of a field in a parent depend on whether we there are fields in the child or not?!
1.
I did a lot of search, but I unfortunately couldn't find anything useful.

Dependency inversion in EJB based application

I want to make some of parts my JEE application independent from others ones using dependency inversion and dependency injection. Below is some code of main core part, that uses MyService, but is independent from other module that should provide implementation of MyService.
public interface MyService {
public void send(MyObject myObject);
}
.
#Stateless
#LocalBean
public class MyServiceWrapper implements MyService {
#Inject
private MyService myService;
#Override
public void send(MyObject myObject) {
myService.send(myObject);
}
}
To clarify:
Module A contains classes:
MyObject,
MyService,
MyServiceWrapper,
Module B contains implementation of MyService.
I want MyServiceWrapper to have injected implementation of MyService provided by module B, so module A can call implementation of MyService by using MyServiceWrapper, but in te same time module A is independent from module B.
The problem with above code, is that container do not know which implementation of MyService should be injected.
How it should be written so MyServiceWrapper, so it won't be injected to itself, but proper implementation (provided in other module) will be injected instead?
The correct way would be to use what is known as a Qualifier , one example from CDI would be the annotation #Named, this would get rid of ambiguity for the container.
public interface MyService {
void send(MyObject myObject);
}
and the implementation of MyService :
#Named("fromModuleA")
#ApplicationScoped
public class MyServiceWrapper implements MyService {
#Inject
#Named("fromModuleB")
private MyService someOtherBean;
#Override
public void send(MyObject myObject) {
this.someOtherBean.send(myObject);
}
}
#Named("fromModuleB")
#ApplicationScoped
public class SomeOtherBeanFromModuleB implements MyService{
#Override
public void send(MyObject myObject) {
// implementation
}
}
The #Inject comes from a Java specification called CDI (Context and Dependency Injection), with this annotation it doesn't matter whether you use it on EJBs or CDI beans, but #EJB will only work with the EJB Container. Also note you don't really need the Interface MyService at least not anymore but it's a good practice to code to the interface.

Spring's #Autowired constructor gets overriden/ignored

I have SomeStartegy interface with two implementations:
#Primary
#Component
public class OneStrategy implements SomeStrategy {...}
#Component
public class SecondStrategy implements SomeStrategy {...}
I need one of them to be used as a default (primary) implementation and the other to override the default in some cases.
So I wrote something like this:
public class SuperClass {
#Autowired
SomeStrategy strategy;
}
public class SubClass extends SuperClass {
#Autowired
public SubClass(SecondStrategy secondStrategy) {
this.strategy = secondStrategy;
}
}
Injecting SubClass, I can see in debug that it's ctor is called and the assignment is done like I would expect.
However, somehow it ends up with an instance of OneStrategy instead.
What am I missing here? or am I doing this all wrong?
Field injection is made after constructor injection.
Use constructor injection for the superclass too, and call super(secondStrategy) from the subclass constructor.

Singleton Bean instance by generic parameter

I would like to have a singleton bean instance by generic parameter based on a single #Component generic class.
(I am using Spring 4.)
My code :
I have an interface like this :
public interface Mapper<I, O> {
...
}
And multiple implementation of it which are Spring #Components (singletons). Something like this :
#Component
public class MapperA implements Mapper<ClazzAI, ClazzAO> {
...
}
and
#Component
public class MapperB implements Mapper<ClazzBI, ClazzBO> {
...
}
where ClazzAI, ClazzAO, ClazzBI and ClazzBO are basic Java classes.
I have another Spring #Component (singleton) which have a Mapper class as a generic parameter :
#Component
public class TransformerImpl<I, O, M extends Mapper<I, O>> {
/** The Mapper */
protected final M mapper;
#Inject
private TransformerImpl(final M mapper) {
this.mapper= mapper;
}
...
}
and I would like to use it like this :
#Inject
private TransformerImpl<ClazzAI, ClazzAO, MapperA> transformerA;
#Inject
private TransformerImpl<ClazzBI, ClazzBO, MapperB> transformerB;
The problem :
But Spring is not able to instantiate those 2 objects because it founds 2 implementations of Mapper : MapperA and MapperB even if I specify which implementation I want as a generic parameter.
Any idea how to make it without the need of instantiate all of those beans in a #Configuration class ?
You're asking for a singleton but requiring two injection points
#Inject
private TransformerImpl<ClazzAI, ClazzAO, MapperA> transformerA;
#Inject
private TransformerImpl<ClazzBI, ClazzBO, MapperB> transformerB;
for differently constructed objects. That doesn't make much sense.
You now realize you need two beans. If you can't (don't want to) do it in a #Configuration class with #Bean factory methods, you'll need to declare (and scan) two separate #Component classes. (I made your parent constructor public here.)
#Component
class MapperATransformerImpl extends TransformerImpl<ClazzAI, ClazzAO, MapperA> {
#Inject
public MapperATransformerImpl(MapperA mapper) {
super(mapper);
}
}
#Component
class MapperBTransformerImpl extends TransformerImpl<ClazzBI, ClazzBO, MapperB> {
#Inject
public MapperBTransformerImpl(MapperB mapper) {
super(mapper);
}
}
When processing the injection target
#Inject
private TransformerImpl<ClazzAI, ClazzAO, MapperA> transformerA;
Spring will find the MapperATransformerImpl, which is of type TransformerImpl<ClazzAI, ClazzAO, MapperA> and inject that.
Try with Spring 4. See Using generics as autowiring qualifiers
Edit
Like #SotiriosDelimanolis explained in his answer, Spring 4 can use type parameter information as qualifiers to select which bean definition matches a particular injection point, but in the end, it will only match against bean definition with concrete type definitions. In your case, the problem is that you need a TransformerImpl bean definition for each concrete type you want to inject.
As an alternative to defining all bean definition explicitly, check my answer to Spring autowiring issues on paramaterized class

How to specify which subclass Spring should use

In my spring-based project I have a core module ('core') with a class
#Component
public class Superclass {
// stuff
}
instances of which are injected by type throughout the code like this:
public class AService {
#Autowired
private Superclass superclass;
// service stuff
}
I also have two other modules that depend on the core module and one of which (let's call it 'module1') extends Superclass:
#component
public class Subclass extends Superclass {
// overridden stuff
}
The other module ('module2') uses Superclass as is.
Now I want that when I compile and run 'child1' an instance of Subclass is used everywhere an instance of Superclass is expected. So I write a configuration class:
#Configuration
public class Module2Configuration {
#Bean
public Superclass superclass(){
return new Subclass();
}
}
When I run this I see both Superclass and Subclass instantiated which is definitely not what I want. How do specify in 'module1' which type Spring should instantiate?
You can use #Qualifier("some name") annotation.
There is more information about that: http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/
Spring eagerly instantiates singleton beans as stated in the documentation:
By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process.
which might explain why both #Components are created.
To specifiy which implementation is provided as a dependency you might want to check on Qualifiers that enable to choose between different implementations. In combination with lazy loading this should do the trick.
Depending on your personal taste you could also use delegation instead of inheritance using a separated interface:
public interface MyService {
public String foobar(int baz);
}
public static class CommonBehavior {
// whatever is used by Superclass and Subclass
}
#Component #Lazy
public class FormerSuperClass implements MyService {
private final CommonBehavior ...;
...
}
#Component #Lazy
public class FormerSubClass implements MyService {
private final CommonBehavior ...;
...
}
Good luck!
There are 2 methods: Use #Qualifier("SubclassName") Or Mark your subclass as #Component and declare the subclass when #Autowired
In your case:
Use #Qualifier("SubclassName")
#Component
public class Superclass {
// stuff
}
#component
public class Subclass extends Superclass {
// overridden stuff
}
public class AService {
#Autowired
#Qualifier("Subclass")
private Superclass superclass;
// service stuff
}
2.Mark your subclass as #Component and declare the subclass when #Autowired
public class Superclass {
// stuff
}
#component
public class Subclass extends Superclass {
// overridden stuff
}
public class AService {
#Autowired
private Subclass subclass;
// service stuff
}

Categories