How to use Autowired annotations - spring

I have a doubt to use autowire annotation in different scenarios...
public Class A {
#Autowired
public B b;
public void print() {
System.out.println("the value is " + b.getValue());
}
}
Example 2:
public Class A {
public B b;
#Autowired
Public A(B b){}
public void print() {
System.out.println("the value is " + b.getValue());
}
}

The first method to autowire objects is called field-injection and the second one is called constructor-injection. There are many posts on SO about these two topics! E.g. What exactly is Field Injection and how to avoid it?
This should answer all of your questions.

Related

Inversion of control based on properties file

Below is my interface :-
interface Student {
findById();
}
Below are my 2 implementations of interface :-
class Matriculation implements Student {
findById(){
//implementation
}
}
class Graduation implements Student {
findById(){
//implementation
}
}
application.properties
graduation=true
Calling class :-
class Test {
#Autowired
Student student ;
method(){
student.findById();
}
}
If graduation is true i want to call Graduation class findById else i want to call Matriculation findById method .How can i achieve this in SpringBoot?
you can use the #ConditionalOnProperty annotation. Like this:
#ConditionalOnProperty(name = "graduation", havingValue = "true")
#Service
public class Graduation implements Student
{
#Override
public String findById()
{
return "Graduation";
}
}
correctly indicated in comments, here is a possible implementation.
class Test {
#Autowired
Matriculation matriculationStudent ;
#Autowired
Graduation graduationStudent;
#Value("${graduation}")
private boolean graduation;
void method(){
if (graduation) {
graduationStudent.findById();
} else {
matriculationStudent.findById();
}
}
}
You're gonna create a Spring Component like this:
#Component
public class StudentFactory {
#Autowired
private Matriculation matriculation;
#Autowired
private Graduation graduation;
#Value("${graduation}")
private boolean graduationValue;
public Student getImplementation() {
if (graduationValue) {
return graduation;
} else {
return matriculation;
}
}
}
and then you just inject the factory in the Test class and call getImplementation method

MyHow to inject bean using constructor and call method in springboot

#Service
abstract class A {
protected MyObj obj;
protected A(MyObj obj) {
this.obj = obj;
}
public abstract XYZ getTrade();
}
#Service
public class B extends A {
B(MyObj obj) {
super(obj);
}
public XYZ getTrade() {}
}
#Service
public class C extends A {
C(MyObj obj) {
super(obj);
}
public XYZ getTrade() {}
}
#Controller
public class MyController {
#GemMapping("/test")
public void test() {
MyObj obj = new MyObj();
if(condition 1) {
//call getTrade() method of class B
}
if(condition 2) {
//call getTrade() method of class C
}
}
}
MyObj is a user-defined POJO that is not managed bean.
I have the above classes. now I have to call getTrade() method based on some condition in Controller. Could you please help/advise?
this answer is based on the information provided by the question.
to inject beans you could do:
#Controller
public class MyController {
private final B b;
private final C c;
public MyController (B b, C c) {
this.b = b;
this.c = c;
}
.........
}
in this case, beans must have to have one no-args constructor. so, In your case what you can do is have a no-args constructor in each service. then set your myObj by setter. that will do the trick.
If you want to achieve polyformism on your sevices you need to add a Qualifier in your classes B and C. So the question now became how to inject a service dynamically on runtime, and this is answered here:
How to dynamically inject a service using a runtime "qualifier" variable?

How #Autowired Work using Reflection and how invoke appropriate Setter Method

My Main Problem is that i can use Reflection API and i can invoke the setter method in my User bean class.But I have Only have UserBean objects. I does not know which setter method to invoke.i want extract all information in my User bean Object and the invoke appropriate Method using Reflection.
//-->This My User Bean Class
public class User {
private String name;
private int age;
private String getName() {
return name;
}
private void setName(String name) {
this.name = name;
}
private int getAge() {
return age;
}
private void setAge(int age) {
this.age = age;
}
void callMethod() { System.out.println("Name :- "+name+" Age :-"+age); }
#Override
public String toString() { return "User [name=" + name + ", age=" + age + "]";}
}
//--->This My Main Method
public class TestCase {
public static Object getBean(String beanClassName) throws Exception
{
Class klass = Class.forName(beanClassName);
Object obj = klass.newInstance();
Method[] b = klass.getDeclaredMethods();
String MethodName1 = "setName";
String MethodName2 = "setAge";
String name ="sanket";
int age = 21;
for(int i=0;i<b.length;i++)
{
if(b[i].getParameterTypes().toString().equals(MethodName1))
{
b[i].setAccessible(true);
b[i].invoke(obj,name);
}
if(b[i].getName().equals(MethodName2))
{
b[i].setAccessible(true);
b[i].invoke(obj,age);
}
}
return obj;
}
public static void main(String ars[]) throws Exception
{
Object obj1 = getBean("www.Fouth.User");
System.out.println(obj1.toString());
}
}
I my case I can invoke the setter method manually because i can invoke the setter method bases of method name.
I want Extract information in User Bean Class, and identify on the bases of value which setter to invoked.
In spring #AutoWired is does that.How they will identify which setter to invoke and inject dependency.
The Spring identifies which setters to inject dependencies by figuring out which setters are annotated with #Autowired , #Inject , #Resources etc.
Then it figures out which value to inject into the setter by checking the type of the setter arguments and injects the bean that has the same type.
If multiple beans have the same type, it then check the bean name. It will inject the bean that has the same name as configured in the injection point using #Qaulifer or #Resources.
If there are still multiple beans that satisfy to inject , NoUniqueBeanDefinitionException happens.
If there are no beans that satisfy to inject, NoSuchBeanDefinitionException happens.

How to use a property in spring data #Query

I can't manage to inject a property from application.yml to a spring data #Query.
The following results in an EL1008E error:
public interface MyRepository extends JpaRepository<MyEntity, Long> {
#Query("select e from MyEntity e where e.foo = :foo and e.env= ?#{env}")
MyEntity findByFoo(#Param("foo") String foo);
}
According to this blog it is possible to inject a property of spring's principal, which is not very different from what I would like to do.
Any hints on this?
I should really stop asking questions and answer them by myself shortly after ... That is not on purpose.
The mentioned blog has the solution included. Add this:
public class PropertyEvaluationContextExtension extends EvaluationContextExtensionSupport {
private final MyProps p;
public PropertyEvaluationContextExtension(final MyProps p) {
this.p= p;
}
#Override
public String getExtensionId() {
return "foo";
}
#Override
public MyProps getRootObject() {
return this.p;
}
}
#Configuration
public class PropertyConfig {
private final MyProps p;
public PropertyConfig(final MyProps p) {
this.p= p;
}
#Bean
EvaluationContextExtensionSupport propertyExtension() {
return new PropertyEvaluationContextExtension(p);
}
}
Now every property of MyProps is accessible via SpEL.

Why it seems impossible to use BeanUtils.copyProperties from a JPA entity to a JAX-B Bean?

We are using JPA Entities to get the database rows and then when we transfer that to the external, we want to use disconnected object (DTO) which are simple beans annotated with JAX-B.
We use a mapper and its code looks like this:
public BillDTO map(BillEntity source, BillDTO target) {
BeanUtils.copyProperties(source, target);
return target;
}
But when the code is running we get an error like this:
java.lang.IllegalArgumentException: argument type mismatch
Note this is the Spring implementation of the BeanUtils:
import org.springframework.beans.BeanUtils
And the naming of the properties are identical (with their getter/setter).
Anybody knows why the error happens?
And how to use a fast way instead just copying properties one by one?
This example working well. Here String property is copied to enum property:
Entity:
public class A {
private String valueFrom;
public String getValue() {
return valueFrom;
}
public void setValue(String value) {
this.valueFrom = value;
}
}
DTO (En is enumeration):
public class B {
private En valueTo;
public void setValue(String def) {
this.valueTo = En.valueOf(def);
}
public void setEnumValue(En enumVal) {
this.valueTo = enumVal;
}
}
As for your GitHub example, problem in class B in getter should be:
public String getValue()
Example:
public String getValue() {
return value.toString();
}

Resources