So I have the following structure
#Component
#RequiredArgsConstructor
ClassA{
ClassB b = new ClassB();
b.printTableName();
}
#Component
#RequiredArgsConstructor
ClassB{
#Value("${com.table}")
private String tableName;
public printTableName(){
System.out.println(tableName);
}
}
The printTableName function always prints null , the tableName in this function is always null . How do I go about fixing this ?
Thank you for the help !
You cannot instance the class manually if you need the spring manage your beans.
Try instance your beans with spring injects
#Component
public class ClassB {
#Value("${com.table1}")
private String valueRequiredOnProperties;
#Value("${com.table2:#{null}}")
private String valueNullByDefaultIfNotInformedOnProperties;
#Value("${com.table3:table_default}")
private String valueByDefaultTableIfNotInformedOnProperties;
public void printTableName(){
System.out.println(valueRequiredOnProperties);
System.out.println(valueNullByDefaultIfNotInformedOnProperties);
System.out.println(valueByDefaultTableIfNotInformedOnProperties);
}
}
#Component
public class ClassA { // you need call this class in controllers, configurations or others ways to spring manager the instances
// it's necessary indicate to spring manage the instance of beans
#Autowired
private ClassB classBManagedBySpring;
public void callPrintClassB(){
ClassB classB = new ClassB();
classBManagedBySpring.printTableName(); // this will work
classB.printTableName(); // this will not work
}
}
your application.properties
com.table1=TABELA_1
# com.table2=
# com.table3=
Related
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();
}
}
I am trying to do autowiring using dynamic parameter, I know we can declare a class with #component and make the class available for autowiring, but what if I have a class with parametrized construtor. I can we use autowiring and intialise the object with paramter?
Please see the below snippet.
#Component
public class A{
public A(Object B){
// do something
}
}
public class C{
#Autowire
private A a;
public foo(){
B b = getBfromSomewhere();
// create object of A using parameter B
// like a = new A(b);
}
}
I got the answer after going through the configuration annotation. One should first must tell spring, how it should create the bean for example.
#Configuration
public class Appconfig{
#Bean(name="a")
public A getA(B b){
return A(b);
}
}
Later when you are using it.
public class C{
#Autowire
private BeanFactory factory;
public foo(){
B b = getBfromSomewhere();
A a = factory.getBean(A.class,b)
}
}
I have a class that is annotated #Component that was then #Autowired into another class. However, I need to remove this #Component annotation and instead, create it with an #Bean annotated method in the class where its was previously autowired.
Where previously the classes looked like:
#Component
public class MyClass implements IMyClass
{
// Stuff
}
#Configuration
public class MyUsingClass
{
#Autowired
private IMyClass myClass;
private void methodUsingMyClass()
{
myClass.doStuff();
}
}
So now I have removed the #Component annotation and written a #Bean annotated method like this:
public class MyClass implements IMyClass
{
// Stuff
}
#Configuration
public class MyUsingClass
{
#Bean
public IMyClass getMyClass()
{
return new MyClass();
}
....
}
My question is around replacing the previous call of myClass.doStuff() to use the new bean. Do I now pass in a parameter of type MyClass to the private method:
private void methodUsingMyClass(final MyClass myClass)
{
myClass.doStuff();
}
... or do I call this method directly (doesn't seem the correct way to me):
private void methodUsingMyClass()
{
getMyClass().doStuff();
}
... or are neither of these correct?
I think you misunderstand the #Bean annotation. It can be used to create a Bean. So basically spring will scan all classes, will find your #Bean and create a Bean, not more. You can now use this bean, like if you would use one created with <bean></bean>. To actually use the bean you need to either get it from ApplicationContext or #Autowire it. Of course you can still use that function like any other function in your code, to create a new instance of that object, but that would contradict to what you want to achieve with beans
Using Annotations that solutions
public class MyClass implements IMyClass{
private OtherClassInjection otherClassInjection;
private OtherClassInjection2 otherClassInjection2;
MyClass(OtherClassInjection otherClassInjection, OtherClassInjection2 otherClassInjection2){
this.otherClassInjection=otherClassInjection;
this.otherClassInjection2=otherClassInjection2;
}
public void useObject(){
otherClassInjection.user();
}
}
#Bean(name = "myClass")
#Autowired
#Scope("prototype") //Define scope as needed
public MyClass getMyClass(#Qualifier("otherClassInjection") OtherClassInjection otherClassInjection,
OtherClassInjection2 otherClassInjection2) throws Exception
{
return new MyClass(otherClassInjection, otherClassInjection2);
}
that logical, it's work injection #Autowired when create a Bean if context are know that bean, that you will to want inject.
I'm use that way.
I seem to be having an issue with the way I have implemented autowiring in my Spring Batch application.For example if I use:
public class A{
#Autowired
BeanList beanList;
}
this works fine for Class A.In the sense that,beanList returns the values that it should.But if from a method from class A I am calling a method from a different class and then have the same
#Autowired
BeanList beanList
,beanList return a null.But autowiring seems to work fine across steps.I have
I'm not sure if I understood your question correctly. I assume, you have something like this:
public class A{
B aB;
#Autowired
BeanList beanList;
public void callToB() { aB.aMethod(); }
}
public class B {
#Autowired
BeanList beanList;
public void aMethod() {Assert.notNull(beanList);}
}
If this is correct, then the problem is likely that you didn't instantiate class B as a "spring bean".
The most simply way to do this would be to mark class B with #Component and to autowire it into class A.
public class A {
#Autowired
B aB;
or to instantiate it with an #Bean directly in class A
#Component
public class A {
#Autowired
BeanList beanList;
#Bean
B myBean() {return new B();}
public void callToB() { myBean().aMethod(); }
Does this describe and solve your problem?
I have an interface like this
public interface InterfaceA {
public String methodA();
}
and I have implemented it like this
public class ClassA implements InterfaceA {
#Override
public String methodA(){
return "HELLO";
}
}
I'm trying to reference a bean of this class in another class
public class ClassB {
#Autowired
private InterfaceA mybean;
String str = mybean.methodA();
}
I have the following bean configuration
<bean id="mybean" class="ClassA"></bean>
Most interesting point is if I remove all the declaration and implementation of the methodA in InterfaceA and ClassA and then try to just this
public class ClassB {
#Autowired
private InterfaceA mybean;
}
no error is shown.
In the other case the following error is shown when I try to run this application: "No qualifying bean of type [ClassA] found for dependency"
It is because of the livecyle of a bean and a java class!
in your ClassB you have two variables. mybean will been populated by Spring after the object instance ins created (by spring). But String str = mybean.methodA(); will be assinged as soon as the object instance is created. And at this point the variable mybean is still null, and therfor the instance creation will fail!
Solution: use #PostConstruct, spring init-method, or implement InitializingBean -- see this answer for an overview
public class ClassB {
#Autowired
private InterfaceA mybean;
private String str;
void afterPropertiesSet() {
String str = mybean.methodA();
}
}