#Autowired a class member in Java #Configuration file - java

in these days i'm studying how to define beans with Spring Core, in the XML file and/or the Java notation. These methods seem equivalent, but are they still so if we add the following condition?
It is not possible to change the class file.
In this case, everything written in the XML file should be written in the AppConfig file (the one in which the class has the #Configuration annotation).
Sadly i found a counterexample: setting a class member (an attribute) with the autowire. While it is possible to precede the class member definition with the #Autowired annotation, that's not the case when using only the Java configuration file.
#Component
public class Foo{
#Autowired
private Bar bar;
}
The following code in fact is wrong:
public class AppConfig{
#Bean
Foo foo(){
Foo foo = new Foo();
#Autowired
Bar foo.bar ?? ;
return foo;
}
}
I've already searched every documentation and every question, but I'm still in confusion about this topic.

Let the method Foo foo() accept the Bar bar as the parameter. Spring framework recognizes the bean instance available by its type to be injected. Beware of more bean instances of Bar, then the #Qualifier must be used to differentiate them and inject the correct one. There is no need to use #Autowired again.
#Bean
Foo foo(Bar bar){
Foo foo = new Foo();
foo.method(bar); // Or whatsoever...
return foo;
}
Read more at D-Zone article about injecting beans in Spring, it might help.

Related

Why does the nested class in a ConfigurationProperties class need to be static?

I am using an application.yml file as the external configuration in my spring boot application which is bound to AppConfig.java using the #ConfigurationProperties annotation. Inside AppConfig.java I have nested classes based on the hierarchy in application.yml. When I use static to declare the nested classes, everything works fine. But recently in a project I missed static for one of the nested classes and it led to a NullPointerException. Through online resources, I have read when to and when not make nested classes static. However, I need to understand how the binding of application.yml and AppConfig.java occurs in spring boot and why the nested classes need to be static.
application.yml
spring:
foo:
host: localhost
bar:
endpoint: localhost
AppConfig.java
#Component
#ConfigurationProperties("spring")
public class AppConfig {
private Foo foo;
private Bar bar;
public static class Foo {
private String host;
// getter, setter
}
public class Bar {
private String host;
// getter, setter
}
//getters, setters
}
When I Autowire AppConfig.java in other classes, appConfig.getFoo() works fine but appConfig.getBar() leads to a NullPointerException.
I have not found why it must be static particularly.
However, I have found other comment in the documentation. It is related to the validation of #ConfigurationProperties bean.
Here it is:
The configuration properties validator is created very early in the application’s lifecycle, and declaring the #Bean method as static lets the bean be created without having to instantiate the #Configuration class.
It was about inner class.
More details : https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config-validation
Spring is using a Binder to apply the properties to ConfigurationProperty beans.
The Binder, that Spring uses, can create instances, if a getX() doesn't return a class. This however is limited to simple constructors. A class, which is not static, can only be instantiated with a reference to the instance, in which it is contained.
If this is REALLY, what you need, you could create an instance of the class during bean creation.
#Component
#ConfigurationProperties("spring")
public class AppConfig {
private Foo foo = new Foo();
private Bar bar = new Bar();
public static class Foo {
private String host;
// getter, setter
}
public class Bar {
private String host;
// getter, setter
}
//getters, setters
}
The inner class has to be static as spring while instantiating the main class, won't be able to set the properties for the inner class because there is no instance yet. So the inner static class is frist of all instantiated by the classloader then, spring will be able to set its properties.

Android Architecture Blueprints "todo‑mvp‑dagger", where is #Provides for TasksRepository?

Looking at the Android Architecture Blueprints "todo‑mvp‑dagger" from here: https://github.com/googlesamples/android-architecture.
I'm trying to understand the Dagger2 implementation and I can't seem to figure out how they are getting Dagger2 to provide the TasksRepository.
They have #Provides for "provideTasksLocalDataSource" and "provideTasksRemoteDataSource" but where is the one for the actual TaskRepository?
In the TodoApplication class they have this:
#Inject
TasksRepository tasksRepository;
How can it inject this without an #Provides for it anywhere?
If I try to use this same approach in my own app I get this error:
cannot be provided without an #Provides- or #Produces-annotated method
So I went looking everywhere in the Blueprints code but I can't see how they did it themselves. Is there some trick to it that allows them to not have an #Provides? It definitely builds so they've gotten around it somehow.
Someone has asked this same question on the actual github page but there are no answers at the time of writing. https://github.com/googlesamples/android-architecture/issues/561.
I'm on the latest commit which at the time of writing is "082bd72d62472f9caadd2979046067fb928bbfef".
In the repository you mentioned, Dagger 2 knows how to inject TasksRepository through the constructor being marked with #Inject. From the source:
#Inject
TasksRepository(#Remote TasksDataSource tasksRemoteDataSource,
#Local TasksDataSource tasksLocalDataSource) {
mTasksRemoteDataSource = tasksRemoteDataSource;
mTasksLocalDataSource = tasksLocalDataSource;
}
Since the constructor is annotated with #Inject, Dagger 2 will attempt to use the constructor to inject TasksRepository into consumers like TodoApplication.
Since TasksDataSource are already bound in TasksRepositoryModule there is enough information for Dagger 2 to perform injection without the burden of extra #Provides or #Binds methods.
Similarly, you can do the following:
class Foo {
private final Bar bar;
#Inject
Foo(Bar bar) {
this.bar = bar;
}
}
class Bar {
#Inject
Bar() {}
}
class Activity extends AppCompatActivity {
#Inject Foo foo;
}
And Dagger 2 will be able to inject Foo inside AppCompatActivity. Why?
Dagger 2 knows how to construct a Bar object (through calling the empty constructor)
Dagger 2 knows that when creating instances of Foo it must use the constructor annotated with #Inject with the single parameter Bar.
There are no other dependencies for Foo, in other words the complete object graph is available.

How to make Spring to pick a subclass in a property reference?

I am trying to use a specialized subclass in a Spring web application for testing.
The application context xml files reference a class in a few bean's properties by the fully qualified class name, like this:
<bean id="blahblah" class="x.y.z.Blah">
<property name="myFooAttribute" ref="x.y.z.Foo"/>
</bean>
and I would like to instantiate and use x.y.z.Bar instead of x.y.z.Foo, everywhere it is used.
In my test I am using a Java based config and importing the XML configuration (legacy stuff that I don't really want to mess too much around) since it feels more natural when I'm going to be patching things and using mocks declared inline.
#Configuration
#ImportResource({
"classpath:applicationContext-common.xml",
"classpath:app-servlet.xml"
})
static class TestConfig {
static class Bar extends Foo {
//some stuff overridden here
}
}
How can I make all the places that reference to x.y.z.Foo use my Bar class instead? Preferably without changing the xml files...
Creating a bean named as the class that you are trying to override works. It can be achieved in the Java style configuration using the Bean annotation.
#Configuration
#ImportResource({
"classpath:applicationContext-common.xml",
"classpath:app-servlet.xml"
})
static class TestConfig {
static class Bar extends Foo {
//some stuff overridden here
}
private Bar myTestBar = new Bar();
#Bean(name="x.y.z.Foo")
public Foo getFoo() {
return myTestBar;
}
}

inject object without access to injector in Guice

I am working on an existing Java code base that uses Guice for Dependency Injection. I have a new class Foo that has one member field (bar) I wanted to inject in. Like this:
public class Foo {
#Inject
private Bar bar;
}
However, there are two things:
There is no direct access to the injector where the Foo is used.
The client wants to use "new" to create Foo.
Is it still possible to inject Bar into Foo object when the clients do:
myFoo = new Foo();
I am very new to DI and Guice, don't really understand how you can inject objects without calling injector.createInstance() on its class or its container class. It seems not working in my testing.
No DI tool works if you create your instances via "new" yourself. That's not guice specific. So unless you drop your constraint "2", you will have a hard time.
With Guice you can force the injection of fields if you have a reference to the injector. Like this:
injector.injectMembers(fooObject);
Your first point says you don't have access to the injector where Foo is used. Well, you can try to solve that giving Foo a static reference to the injector.
public class Foo {
#Inject private static Injector injector;
#Inject
private Bar bar;
public Foo() {
injector.injectMembers(this);
}
}
But wait, that won't work out of the box because the injector field would just be null. You need to inject it also but, as it is a static field, you just do it once. It is called static injection. Probably at application start where you have access to the Guice injector, in any of the guice modules.
There, you just execute this:
requestStaticInjection(Foo.class)

What is the purpose of the Spring Bean annotation name attribute?

I'm just learning spring, and something struck me as very odd about the annotation configurations using the name attribute as a string.
#Bean(name = "com.my.injected.Service")
public InjectedService injectedService() {
return injectedService;
}
Is this name similar to the Spring Bean XML configuration id and class attributes?
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
Why isn't this simply
#Bean(clazz = com.my.injected.Service.class)
public InjectedService injectedService() {
return injectedService;
}
instead?
You're fully qualifying the path in both cases and actually using the class makes it way easier for your IDE to tell you when you've screwed it up. I understand that the XML configuration came first, and naturally it was always looking up things by string, so is this just a holdover? Is there some advantage to using strings or major disadvantage to using .class?
Question was originally based on a false premise. I edited it to spell out what this premise was and make it less confusing for new people who come along. Hopefully I did this such that the given answers are still exactly applicable; apologies if not.
#Bean annotation is meant to provide a spring bean. The type of the bean to provide will be the same type of the class/interface you define in the return method. So, instead of declaring to return a concrete class in the method, return the top (abstract) class/interface instead.
Imagine this case:
public interface MyEntityDao {
MyEntity get(String id);
}
#Repository
public class MyEntityDaoDatabaseImpl implements MyEntityDao {
#Override
public MyEntity get(String id) {
/* implementation that goes to database every time */
}
}
#Repository
public class MyEntityDaoCacheImpl implements MyEntityDao {
#Override
public MyEntity get(String id) {
/* implementation that looks the data
up in cache, never in database */
}
}
#Configuration
public class MyAppConfiguration {
#Bean
public MyEntityDaoDatabaseImpl method1() {
return new MyEntityDaoDatabaseImpl();
}
#Bean
public MyEntityDaoCacheImpl method2() {
return new MyEntityDaoCacheImpl();
}
}
#Service
public class MyEntityService {
#Autowired //what to inject here?
MyEntityDao dao;
}
In case above, there are two implementations of the proposed interface. How the framework may be able to understand which implementation to use except for the name?
#Service
public class MyEntityService {
#Autowired
#Qualifier("properBeanNameToInject")
MyEntityDao dao;
}
Bean name is not necessarily related to its class or even any of interfaces it implements. It is a name and nothing more. When you use the annotation configuration, Spring figures out what the exact class or interface the #Bean provides like the rest of java code would: either through the fully qualified name in the code or through the imports specified in the file. In your case, you presumably have an import com.my.injected.Service; statement at the top of the java file.
Your example is using the fully qualified class name as the bean name. It is your choice. You could use any other identifier. Using the fully qualified name could be useful if your code is providing an object that is named exactly like another 3rd party #Bean object that your code must include or consume. However, you could just as easily use name = "myService".
The bean name helps Spring (and application programmer) to distinguish between multiple instances of of the same bean class because you can deploy the same class as bean several times. If only one instance of bean type appear you event do not have to give it name manually: spring does this by default.
If you have several beans that have the same type or implement the same interface and you want to refer specific bean use #Qualifier annotation.

Categories

Resources