Property injection in the base class does not work - java

My problem is that a bean is not being injected in the base class. I read many questions and answers about this topic but none did really help me.
I have an abstract base class with a property that shall be injected:
public abstract class AbstractResearchService<R extends ResearchResult, S extends PredictionResult> {
#EJB(lookup = ResearchManager.JNDI_BINDING)
private ResearchManager researchManager;
protected R submit(final ResearchQuery query) {
// researchManager is null here
}
The inheriting child class is a stateless bean implementing a remote interface:
#Stateless
#Remote(VoyageResearchService.class)
#WebService(...)
public class VoyageResearchServiceBean extends AbstractResearchService<VoyageResearchResult, VoyagePredictionResult>
implements VoyageResearchService {
#Override
public VoyageResearchResult submitQuery(final VoyageResearchQuery query) {
return submit(query);
}
}
This is the bean with its interface that shall be injected:
#Local
public interface ResearchManager {
String JNDI_BINDING = "java:global/omd-research-manager/ResearchManagerBean";
ResearchResult submitQuery(ResearchQuery query);
}
#Singleton
#Startup
#ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class ResearchManagerBean implements ResearchManager {
...
}
I searched for the issue and found multiple statements:
Dependency injection in base classes does work.
The inheriting class must be container managed to make injection work.
Can you confirm these statements?
Since my VoyageResearchServiceBean is being instantiated by the container (due to the #Stateless annotation) I am wondering why the injection doesn't work. When the submit() method is being called, the property researchManager is null.
What I have tried:
When I inject the researchManager into the child class it works fine. But since I only need it in the base class, I would like to inject it there.
When I try to use setter injection:
#Inject
public void setResearchManager(final ResearchManager researchManager) {
this.researchManager = researchManager;
}
I get the following error:
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type ResearchManager with qualifiers #Default
at injection point [BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedMethod] #Inject public com.in.omd.researchmanager.AbstractResearchService.setResearchManager(ResearchManager)
Can you please give me an advice what is going wrong here or what I am overlooking? Thanks for your help in advance.

Related

Dependency injection from Quarkus (java)

Colleagues, hello! Is is possible to inject beans inside of class which is created via 'new' operator?
For example:
public class TestClass implements Callback {
#Inject
TestClassRepository repository;
//just only methods...
}
And 'TestClass' is created from another class:
Flyway.configure().collbacks(new TestClass()).load();
I have an issue with this,because 'repository.anyMethods()' inside of TestClass creates 'NullPointer' exception.
'TestClassRepository' is marked with the '#ApplicationScoped' and '#Startup' annotations.
#Singleton
public class TestConfig {
#javax.enterprise.inject.Produces
public TestClass testClass() {
return new TestClass();
}
}
another class annotated with the #ApplicationsScoped or #Singleton:
#Inject
public void method(TestClass testClass) {
Flyway.configure().collbacks(testClass).load();
// your code
}
If you create an object by yourself calling a constructor (new TestClass()) then quarkus doesn't manipulate that object, and doesn't inject a repository.
No you cannot inject beans inside a class that is instanciate with the new keyword.
But you can still find a way around like so :
#Dependent
public class BeanFactory {
#Inject
TestClassRepository repository
#Produces
public TestClass createTestClass() {
return new TestClass(this.repository);
}
You can find more details here : Quarkus Contexts and dependency Injection
Also you can define multiple beans for different profiles as mentionned few lines bellow Here
This means you can create a repository for your tests and one for prod or whatever is best for your case.
Also I do not think the annotation "#Startup" would add anything to your TestClassRepository bean.

Injecting spring bean among two beans- implementing same interface

I have two spring bean classes which are implemeting the same interface.
public interface Abc()
{
String getNumber();
}
The two classes are
#Service
public class SomeClass implements abc
{
#Override
public class getNumber()
{
}
}
#Service
public class SomeClass1 implements abc
{
#Override
public class getNumber()
{
}
}
In my Service class.
#Service
public class Demo
{
#Autowired
private Abc abc;
}
}
I got an error "required a single bean, but 2 were found"
For that error i can have the chance to put #Primary in the top of one of the bean.
But i have only way to say "one bean configuration" based on the value which i will get in runtime(From the database).
Can you please suggest me a way.
You can autowire a list of interfaces and then choose the right one. You can write:
#Autowired
List<Abc> abcs;
this will result in a list of implementations of the interface. In your method body you can then choose the right one.
Couple of ways you can autowire the correct implementation.
Change your autowired field name to the same name of the implementation class (in camelcase)
#Autowired
private Abc someClass;
This will attempt to find an implementation of interface 'Abc' with the classname 'SomeClass'.
Another way is to add a bean name to your service annotation
#Service("someClass")
public class SomeClass implements abc
This can then be autowired like the following
#Autowired
#Qualifier("someClass")
private Abc SomeClass;
I think the problem he is asking about how to configure two implentation and also using the right bean dynamically(based on data in DB) . It seems this is the an example for factory pattern
Psuedo Code
Class SomeFactory{
#Autowired
private Abc someClass;
#Autowired
private Abc someClass1;// keeping bean Name same as class name would solve bean finding issue
public Abc getBeanFor(String type) {
if("someClass".equals(type)
return someClass;
return someClass1;
}
}
Class TestClass{
#Autowired
private SomeFactory factory ;
private void someProcess() {
// Read type from DB for data
factory.getBeanFor(typeReadFromData)
.process();
}
}

#Autowire Spring Bean with Injected Constructor args?

I have a project structure similar to the one linked here: https://stackoverflow.com/a/29583882/1243462 . I have a util library containing a Service class in one JAR, meant to be consumed from another Java library/Maven project. However, my Service class itself uses Constructor Injection. So, where the original question had:
#Service
public class PermissionsService { ... }
I have
#Service
public class PermissionsService {
public PermissionsService(#Autowired PermissionsDao dao) {
//assign private dao field to autowired dao
}
}
And, like the original post, I want to create an instance of PermissionsService and inject it into my client/consumer application. I'm not sure of how to create a Configuration class.
#Configuration
public class PersistenceConfig {
public PermissionsService getPermissionsServiceBean() {
//What goes here?
}
}
For now, I have a workaround where I replaced the #Autowired PermissionsDao constructor argument with a field injection, and having a no-args constructor. This allows me to:
#Configuration
public class PersistenceConfig {
public PermissionsService getPermissionsServiceBean() {
return new PermissionsService();
}
}
But, since Field injection is discouraged, what is the right way to structure this code?
In your main module
#Configuration
#Import(PersistenceConfig.class)
public class ServiceConfig() {
}
In your utils module
#Configuration
#ComponentScan(basePackages = {"path-to-persistence-service-and-any-dependencies"})
public class PersistenceConfig {
}
The fact that you use constructor injection for PermissionsDao should not matter if you get the configuration right.

#Autowired attribute that needs a parameter to be instantiated

I'm new to spring boot, and I need to know how to use #autowired in an attribute that needs parameters to be instantiated.
Please bear in mind the following illustrative situation. It would be something like this:
public class MyClassA{
public SpecificClass myMethod(){
//some logic
}
}
public class MyClassB extends MyClassA{
#Autowired
MyComponent myComponent (myMethod()); //here is my doubt, because my component needs a parameter to be built
}
#Component
public class MyComponent{
public MyComponent(SpecificClass foo){
this.foo=foo;
}
That's not really proper design if your intention is to work with dependency injection. There shouldn't be a direct dependency to the superclass' method like that. Injecting the dependencies indirectly as you're supposed to do would result in something like the following
public class MyClassB extends MyClassA {
#Autowired
private MyComponent myComponent;
}
#Configuration
public class SomeConfig {
#Bean
#Autowired
public MyComponent createComponent(SpecificClass foo) {
// SpecificClass is also injected, providing another layer of indirection
return new MyComponent(foo);
}
}
#Autowired only tells Spring to inject a component into a constructor, field, or method parameter. The injected component is instantiated by the bean container before that. I assume what you are looking for is a way to create MyComponent in such a way that it also receives a Spring Bean.
In your example you could achieve this with the following
#Configuration
public class MyClassA{
#Bean //the bean would have the name 'myMethod', so maybe change that
public SpecificClass myMethod(){
//some logic
}
}
//this needs to be a component, service, ...
#Component
public class MyClassB {
#Autowired
MyComponent myComponent;
}
#Component
public class MyComponent{
#Autowired //Spring wires the Bean 'myMethod' in here, autowired is not needed in the latest Spring Versions
public MyComponent(SpecificClass foo){
this.foo=foo;
}
}
This is a basic Spring question, and not specific to Spring Boot. To better understand wiring you can take a look at the Spring 4 Framework Reference Documentation.

Autowire Generic Type Spring 4.1.7 [duplicate]

This question already has answers here:
Singleton Bean instance by generic parameter
(2 answers)
Closed 7 years ago.
I'm working in Spring version greater than 4.
I've got beans with the same super-class configured using #Configuration
#Configuration
public Class ConfigClass{
#Bean
public Apple apple(){stuff to return apple bean}
#Bean
public Orange orange(){stuff to return orange bean}
}
I've got an bean which maybe composed of either one of those two beans
#Component
public Class FruitEater<ReturnType extends Fruit>{
#Bean
ReturnType fruit;
}
And I get this beautiful ambiguity error message:
No qualifying bean of type [fruit] is defined: expected single matching bean but found 2: appleInjection,orangeInjection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: fruiteater.bean; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [fruit] is defined: expected single matching bean but found 2: apple,orange
My thinking is that since the ReturnType should be resolved at compile-time, spring should be able to Autowire based on the Generic Type. I've heard of the Spring's ResolvableType but I'm not sure how I can leverage that as I'm still pretty new to Spring.
Is there a way to resolve this and keep my FruitEater a generic FruitEater?
Thanks, in advance.
You've declared a singleton (default) FruitEater bean. Singleton beans are (YMMV) eagerly initialized.
In your case, Spring sees a bean definition for the type FruitEater, but that's it. There's no parameterization (argument for ReturnType), there's no hint for what should be injected into fruit. There's no way for it to pick between the two Apple and Orange beans.
Presumably, if, instead of a singleton, you had declared FruitEater with a prototype scope (or something similar) and had injection targets like
#Autowired
private FruitEater<Apple> fruitEater;
the bean to be injected would be created at injection time and there would be enough type information to create it and inject its field, ie. an Apple bean in this example.
This isn't currently supported.
One solution is to remove the FruitEater bean declaration (the #Component) and instead provide appropriate parameterized subtypes
#Component
class OrangeEater extends FruitEater<Orange> {
}
class FruitEater<ReturnType extends Fruit> {
#Autowired
protected ReturnType fruit;
}
Spring is now smart enough, with the type information provided in the extends clause, to create the OrangeEater bean and inject an Orange in its fruit field.
Complete example
public class Sample {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigClass.class);
System.out.println(ctx.getBean(Injected.class).orangerEater);
System.out.println(ctx.getBean(Injected.class).appleEater);
}
#Component
static class Injected {
#Autowired
FruitEater<Orange> orangerEater;
#Autowired
FruitEater<Apple> appleEater;
}
}
#Configuration
#ComponentScan
class ConfigClass {
#Bean
public Apple apple() {
return new Apple();
}
#Bean
public Orange orange() {
return new Orange();
}
}
class Fruit {
}
class Apple extends Fruit {
}
class Orange extends Fruit {
}
#Component
class AppleEater extends FruitEater<Apple> {
}
#Component
class OrangeEater extends FruitEater<Orange> {
}
class FruitEater<ReturnType extends Fruit> {
#Autowired
protected ReturnType fruit;
}
Alternatively, ditch the component scanning. Use constructor injection.
public FruitEater(ReturnType fruit) {
this.fruit = fruit;
}
then declare the beans explicitly
#Bean
public FruitEater<Apple> appleEater() {
return new FruitEater(apple());
}

Categories

Resources