Spring bean with #Autowire in superclass - java

I have a subclass like below:-
#Component
public class Subclass extends Superclass {
//few inherited methods implementation
}
Superclass is like below:-
#Component
public class Superclass implements InterfaceA {
#Autowired
#Qualifier("envBean")
private EnvironmentBean envBean;
private DateTime effective_date = envBean.getProperty("effective.date");
}
Now while deploying the application, I am getting below errors
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name "Subclass"
Constructor threw exception; nested exception is java.lang.NullPointerException
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [Subclass]:Constructor threw exception; nested exception is java.lang.NullPointerException.
and finally I saw -
Caused by: java.lang.NullPointerException: null
at Superclass <init> (SuperClass.java:{lineNumber}
which is at the below line :-
**envBean.getProperty("effective.date");**
I have tried using constructor injection of EnvironmentBean property from the subclass itself
Tried configuring it in xml and to instantiate Superclass bean with constructor injection.
Does someone have any idea how to resolve it?

Maybe you can try interface -> InitializingBean, and override method 'afterPropertiesSet', then you can assign effective_date value. just like:
#Override
public void afterPropertiesSet() {
effective_date = envBean.getProperty("effective.date");
}

It seems that this is because Spring has to first create an instance of the class Superclass and only then inject EnvironmentBean. That is, when the class Superclass is instantiated, Java will try to instantiate the field DateTime effective_date even before Spring tries to inject the dependency #Autowired #Qualifier("envBean") private EnvironmentBean envBean;. At this time, envBean refers to null. Hence, this will surely throw an NPE. (My view.)
So, not sure if this is really related to the class hierarchy itself.

There must be a class called EnvironmentBean It must be annotated with any one of Spring stereotype shown in doc https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/stereotype/package-summary.html
Component - Indicates that an annotated class is a "component".
Controller - Indicates that an annotated class is a "Controller"
Indexed - Indicate that the annotated element represents a stereotype for the index.
Repository - Indicates that an annotated class is a "Repository", originally defined by Domain-Driven Design (Evans, 2003) as "a mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects".
Service - Indicates that an annotated class is a "Service", originally defined by Domain-Driven Design (Evans, 2003) as "an operation offered as an interface that stands alone in the model, with no encapsulated state."

Related

Access to the classType of generics in an autowired component

I have a component that is autowired in my controller,
Here is the code of my component :
#Component
public class Utils<T> {
#Autowired
ObjectMapper objectMapper;
private Class<T> mappedClass;
public Utils(Class<T> mappedClass) { this.mappedClass = mappedClass; }
public T builder(String stringJson, T object) {
/* doing staff ...*/
return objectMapper.readValue(new TreeTraversingParser(jsonNode), mappedClass);
}
}
my autowired component is using generics and when I m trying to access to the class type by passing it in the constructor. however i m getting this error :
Could not autowire. No beans of 'Class' type found. Checks
autowiring problems in a bean class.
and when I launch my spring boot it says :
Parameter 0 of constructor in ca.util.Utils required a bean of type
'java.lang.Class' that could not be found.
Action:
Consider defining a bean of type 'java.lang.Class' in your
configuration.
How may I avoid that ?
You don't show how you try to instatiate Utils so we don't have all the information necessary.
Your first problem is that your #Component needs a constructor argument.
You can solve this if you instantiate your component using the ApplicationContext.getBean version that passes parameters.
Alternatively, You can supply the constructor argument using a #Qualifer annotation ( give the constructor argument a name, then supply it elsewhere )
Another Issue is that you have a raw generic type as your #Component. I've not seen that, so I'm not sure its possible. For #Component spring needs to create an instance of the concrete class.

How can I get Generic injection entities use Class and generic class name in Spring?

I only have two determine the type,one of is my Basic Class, another is generic class name.
BasicOrmDao.class;
Class cls = Class.forName("com.base.Role");
My injection class is
class RoleDao extends BasicOrmDao<Role> {
}
I don't know bean name roleDao, because of it maybe BasicOrmDao.
So how can I get my bean "roleDao" use BasicOrmDao.class and String name = "com.base.Role";.
I want use java code to do this, like #Autowired, but I only known basic type BasicOrmDao, and generic class name "com.base.Role"

WELD-001409: Ambiguous dependencies for type T with qualifiers #Default

I got 2 beans.
The first one is the model I use in production, Model.
#Named("model")
#RequestScoped
public class Model{
}
The second one is the extension of Model that I use for testing.
#Named("modelTest")
#RequestScoped
public class ModelTest extends Model{
}
How can I force CDI to select Model by default?
Since you want to change the 'default' bean for given type and you don't want to use qualifiers, I assume the original bean is not to be injected anywhere. Therefore, what you are probably after is either an alternative or a specialization.
If we talk about alternatives, you need to mark the new bean with #Alternative annotation and also 'select' it - that can be done on a per bean archive basis in beans.xml or simply globally with #Priority(int). Here is a code snippet:
#Named("modelTest")
#RequestScoped
#Alternative
#Priority(1) // "activates"/selects the alternative
public class ModelTest extends Model{
}
With a selected alternative, whenever you inject the previous type (Model), CDI will instead inject this alternative (ModelTest), as it fits the injection point as well.
Secondary option is specialization. It is very similar to alternatives but stricter in a way that the original bean is 'discarded', you can read more about that in CDI spec. Specialization also comes with qualifier and bean name inheritance (not the scope though!). There is also no need to select the bean (as opposed to alternatives). Here is the code:
#RequestScoped
#Specializes
public class ModelTest extends Model{
// bean name with be inherited automatically as "model"
}
Note that a bean can only have one bean name at a time, as per specification. Therefore if you inherit one name and declare another, you will be getting errors - alter your code accordingly.

How to access main repository from cusom repository in Spring Data JPA?

I am writing repository for variables table and wish to access specific rows with it. For this I am trying to autowire main repository into custom implementation, like this:
public interface VariableRepo extends CrudRepository<Variable, Long>, VariableRepoCustom {
Variable getByName(String name);
}
public interface VariableRepoCustom {
...
Variable getPopulationSingle();
...
}
public class VariableRepoCustomImpl implements VariableRepoCustom {
private final VariableRepo variableRepo;
#Autowired
public VariableRepoCustomImpl(VariableRepo variableRepo) {
this.variableRepo = variableRepo;
}
#Override
public Variable getPopulationSingle() {
return getByName("Population single");
}
...
}
Unfortunately, Spring like to go crazy with this, throwing an exception:
Error creating bean with name 'variableRepo': Invocation of init
method failed; nested exception is
org.springframework.data.mapping.PropertyReferenceException: No
property getPopulationSingle found for type Variable!
I.e. it tries to find repository method inside entity class (Variable) which of course should not contained inside.
How to solve this?
What you named VariableRepoCustom/VariableRepoCustomImpl should be in fact a service (not a repository in terms of spring-data-jpa).
The interface VariableRepoCustom should not be present in JPA searchpath, to prevent JPA to generate an implementation
I think might be your repository impl does not have #Repository annotation. Please make both repository and impl as #Repository. it should fix your problem.
For best practice, No need to autowire VariableRepo interface into impl class.
Edit:
Also remove custom from impl. The name will be RepoName by append impl. it is definition like VariableRepoImpl

java spring javax.inject.provider throwing class cast exception

Im currently creating a spring bean with the following javax inject provider annotation:
#Autowired
Provider<Table> provider;
in one of the init methods i call :
Table table = provider.get();
this throws : java.lang.ClassCastException: $Proxy127
The table is configured as a
#Component
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class Table extends Furniture<
Square,
Round> {
...............
...............
}
With the parent class being abstract:
public abstract class Furniture<
E extends Legs,
M extends Corners> {
.............
.............
}
Anyone got any ideas why i cannot get an instance to be created on init?
I know spring has method injection using the lookup method, but i dont really want to use the XML.
It seems that the bean returned by the provider gets proxied. Try to extract an interface that the Table class can implement, and use a Provider<TableInterface> instead. Then you can get an instance like:
TableInterface table = provider.get();
Which would still return a Proxy, but you wouldn't get the ClassCastException on this assignment, because the proxy implements the TableInterface interface.
Another possibility is to enable class proxying with CGLIB, in which case you don't need to extract an interface.

Categories