This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 5 years ago.
Lets say that I have a model for an object X, this object implements all the CRUD operations with the help of Spring Boot.
Now, I need to be able to edit this object using an standard POJO. The POJO looks like this:
public class Foo {
#Autowired
private XRepository xDAO;
/*
Do whatever I want with X and then save it again in the DB using xDAO
*/
}
So far I've tried using #Configurable, #Component and even #Service, but neither of those can #Autowire my XRepository.
What can I do?
What you describe is not possible. Components can be wired only if the object is managed by Spring. In your case it's not and as such it's not possible to autowire in any dependency. You have various options. Here are some:
Use repository outside of Foo class. Orchestrate the operations in another
class that is managed by Spring
Pass repository as dependency to
Foo in the constructor by class that is managed by Spring
This is somewhat hacky and probably not recommended but you can make repository a static variable in Foo and set it up by Spring managed component in something like #PostConstruct
In my opinion the best is to use option 1.
I think that I didn't express myself sufficiently, either way I found a solution to my problem.
The solution is here.
I only declared Foo as a #Service, then I just #Autowired Foo:
#Autowired
public class Foo {
#Autowired
private XRepository xDAO;
//some code
}
Then I call this class using the #Autowired annotation
#Autowired Foo foo
foo.doThings();
Related
This question already has answers here:
What exactly is Field Injection and how to avoid it?
(4 answers)
Closed 2 years ago.
can anyone tell me why #autowired is saying field injection is not recommended and the TextWriter object 'text' also says it could not autowire because there is more than one bean of textwriter type.
#RestController
public class HelloWorld{
#Autowired
TextWriter text
public HelloWorld(TextWriter text){
this.text = text;
}
#RequestMapping("/")
public String index(){
return "Hello World";
}
}
can anyone tell me why #autowired is saying field injection is not
recommended ?
For a design reason. Injecting beans directly into fields makes your dependencies "hidden" and encourage bad design :
the class API (public/protected member) doesn't specify them while they exist.
no way to unit test without reflection or a Spring container (the most important part for me)
you may finish by declaring potentially many injected fields. Which may make your class with a strong coupling to other classes without that you are "really" aware of that.
Generally constructor injection should be favored (no need to annotate the constructor with #Autowired since Spring 4) if few fields, otherwise setters should be the way.
Both ways don't have all drawbacks mentioned above.
I assume Spring does not see your TextWriter class as a bean. Probably TextWriter is in another package. For example, in the “models” package. If you use Spring Boot, then this will help you:
#SpringBootApplication(scanBasePackages={"com.programwithwaqas.restservice.models"})
I recommend you read the #SpringBootApplication annotation. Pay attention to the annotation #ComponentScan.
This is in case you are not using Spring Boot
#ComponentScan(basePackages={"com.programwithwaqas.restservice.models"})
I know that there are questions similar to this one, but none of them have helped me. I'm following along this tutorial, and the part I can't wrap my mind around is:
#SpringBootApplication
public class Application {
private static final Logger log =
LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
#Bean
public CommandLineRunner demo(CustomerRepository repository) {
return (args) -> {
// save a couple of customers
...
// more lines, etc...
What I don't understand is where the repository passed into demo comes from. I know that the Autowired annotation can do something like that, but it isn't used at all here.
The more specific reason I ask is because I'm trying to adapt what they do here to an application I'm working on. I have a class, separate from all of the persistence/repository stuff, and I want to call repository methods like save and findAll. The issue is that the repository is an interface, so I can't instantiate an object of it to call the methods. So do I have to make a new class that implements the interface and create an object of that? Or is there an easier way using annotations?
When creating a #Bean, adding the repository in the parameters of the bean is enough to wire the repos in your bean. This works pretty much like adding #Autowired annotation inside a class that is annotated as #Component or something similar.
Spring works mostly with interface, since that is simplier to wire vs wiring concrete classes.
Can you try #Repository before the declaration of class? Worked for me in a Spring MVC structure.
#Repository
public class EntityDAOImpl implements EntityDAO{
...
}
The thing to wrap your head around is a Spring Boot application at startup time aims to resolve its dependancy tree. This means discovering and instantiating Beans that the application defines, and those are classes annotated with #Service, #Repository, etc.
This means the default constructor (or the one marked with #Autowire) of all beans is invoked, and after all beans have been constructed the application starts to run.
Where the #Bean annotation comes into play is if you have a bean which does not know the values of it's constructor parameters at compile time (e.g. if you want to wire in a "started at" timestamp): then you would define a class with an #Configuration annotation on it, and expose an #Bean method in it, which would return your bean and have parameters that are the beans dependencies. In it you would invoke the beans constructor and return the bean.
Now, if you want a certain method of some class to be invoked after the application is resolved, you can implement the CommandLineRunner interface, or you can annotate a method with #PostConstruct.
Some useful links / references:
https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html
https://www.baeldung.com/spring-inject-prototype-bean-into-singleton
Running code after Spring Boot starts
Execute method on startup in Spring
This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 4 years ago.
In my Spring boot application, I have a dependency Spring project. From my SpringBoot class, I am trying to call a dependency class but the class has no value set.
#CrossOrigin(origins = "*")
#RestController
#Configuration
#ComponentScan(basePackages = "com.dependency.package")
public class BootClass {
private DependencyClass dependencyClass;
public BootClass() {
this.dependencyClass = new DependencyClass();
}
}
My DependencyClass object just gives me an empty object {}. Any ideas?
My Dependency class looks like this:
#Component
public class DependencyClass {
#Value("${jdbc.driver.class.name}")
private String driver;
#Value("${jdbc.url}")
private String url;
}
Thank you,
Julian
This is the classic Spring beginner mistake: calling new to instantiate an object.
You cannot call new if you want Spring to manage beans and provide dependencies. You have to give it to the Spring bean factory to manage. It's all or none.
Yours looks like a perfect case for constructor injection.
#Configuration
#ComponentScan(basePackages = "com.dependency.package")
public class BootClass {
private final DependencyClass dependencyClass;
#Autowired
public BootClass(#Qualifier(name = "dependencyClass") DependencyClass dependencyClass) {
this.dependencyClass = dependencyClass;
}
}
Surely you can think of a better name for DependencyClass. I'd suggest something like DatabaseConfiguration.
That is not to say that every object should be under the control of the bean factory, or that new should never be called. Objects with short scope that aren't shared can certainly be instantiated.
It's objects that require dependency injection that need to be under the control of the bean factory.
Just Mark that with #Autowired Annotation as shown below. That would do.
#Autowired
private DependencyClass dependencyClass;
Extending the answer of #duffymo:
Once you are done what he suggested, also make sure that "jdbc.driver.class.name" and "jdbc.url" are present in your main project properties file. If you are expecting that these values will be populated just because you have it in
properties file of "Dependent" project, you might get disappointed. Check this for more details:
https://stackoverflow.com/a/49564724/3458292
I'm migrating code from JEE to SpringBoot. I was using cool dynamic injection in JEE with javax.enterprise.inject.Instance class:
Just annotating:
#Inject
private Instance<CCIntentHandler> allMycandidates;
Will make allMycandidates be filled with all classes inheriting CCIntentHandler interface in my classpath which then I can iterate simply with:
Iterator<CCIntentHandler> iterator = allMycandidates.iterator()
Nothing more needed. How can I achieve this in Spring Boot?
Thanks
Spring will inject all instances of Foo if you #Autowire a List<Foo>.
So, the Spring equivalent of ...
#Inject
private Instance<CCIntentHandler> allMycandidates;
... is:
#Autowire
private List<CCIntentHandler> allMycandidates;
Update 1 in response to this comment:
Do CCIntentHandler interface or classes implementing this interface need any Spring annotations?
Spring must be aware of any instances of CCIntentHandler, this could achieved as follows:
Annotate each class implementing CCIntentHandler with #Component and ensure that these classes are scanned by Spring Boot
Or
Provide a public method to return each class implementing CCIntentHandler and annotate each of these public methods with #Bean and ensure that the class which contains these public methods is annotated with #Configuration and that this configuration class is scanned by Spring Boot.
More details on bean declaration and dependency injection in the docs.
Unfortunately
#Autowire
private List<CCIntentHandler> allMycandidates;
is not
#Inject
private Instance<CCIntentHandler> allMycandidates;
because we can't select an instance from the list depending on type or annotation.
I've spent some time to find alternative in Spring, but looks like there is no equivalent...
We should defenetly bring that feature to Spring!
I am reading the spring 3.0.x reference documentation to understand Spring Autowired annotation:
3.9.2 #Autowired and #Inject
I am not able to understand the below examples. Do we need to do something in the XML for it to work?
EXAMPLE 1
public class SimpleMovieLister {
private MovieFinder movieFinder;
#Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
EXAMPLE 2
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
#Autowired
public void prepare(MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
How can the two classes be autowired implementing the same interface and using the same class?
Example:
class Red implements Color
class Blue implements Color
class myMainClass{
#Autowired
private Color color;
draw(){
color.design();
}
}
Which design method will be called? How do I make sure the design method of Red class will be called and not Blue?
TL;DR
The #Autowired annotation spares you the need to do the wiring by yourself in the XML file (or any other way) and just finds for you what needs to be injected where and does that for you.
Full explanation
The #Autowired annotation allows you to skip configurations elsewhere of what to inject and just does it for you. Assuming your package is com.mycompany.movies you have to put this tag in your XML (application context file):
<context:component-scan base-package="com.mycompany.movies" />
This tag will do an auto-scanning. Assuming each class that has to become a bean is annotated with a correct annotation like #Component (for simple bean) or #Controller (for a servlet control) or #Repository (for DAO classes) and these classes are somewhere under the package com.mycompany.movies, Spring will find all of these and create a bean for each one. This is done in 2 scans of the classes - the first time it just searches for classes that need to become a bean and maps the injections it needs to be doing, and on the second scan it injects the beans. Of course, you can define your beans in the more traditional XML file or with an #Configuration class (or any combination of the three).
The #Autowired annotation tells Spring where an injection needs to occur. If you put it on a method setMovieFinder it understands (by the prefix set + the #Autowired annotation) that a bean needs to be injected. In the second scan, Spring searches for a bean of type MovieFinder, and if it finds such bean, it injects it to this method. If it finds two such beans you will get an Exception. To avoid the Exception, you can use the #Qualifier annotation and tell it which of the two beans to inject in the following manner:
#Qualifier("redBean")
class Red implements Color {
// Class code here
}
#Qualifier("blueBean")
class Blue implements Color {
// Class code here
}
Or if you prefer to declare the beans in your XML, it would look something like this:
<bean id="redBean" class="com.mycompany.movies.Red"/>
<bean id="blueBean" class="com.mycompany.movies.Blue"/>
In the #Autowired declaration, you need to also add the #Qualifier to tell which of the two color beans to inject:
#Autowired
#Qualifier("redBean")
public void setColor(Color color) {
this.color = color;
}
If you don't want to use two annotations (the #Autowired and #Qualifier) you can use #Resource to combine these two:
#Resource(name="redBean")
public void setColor(Color color) {
this.color = color;
}
The #Resource (you can read some extra data about it in the first comment on this answer) spares you the use of two annotations and instead, you only use one.
I'll just add two more comments:
Good practice would be to use #Inject instead of #Autowired because it is not Spring-specific and is part of the JSR-330 standard.
Another good practice would be to put the #Inject / #Autowired on a constructor instead of a method. If you put it on a constructor, you can validate that the injected beans are not null and fail fast when you try to start the application and avoid a NullPointerException when you need to actually use the bean.
Update: To complete the picture, I created a new question about the #Configuration class.
Nothing in the example says that the "classes implementing the same interface". MovieCatalog is a type and CustomerPreferenceDao is another type. Spring can easily tell them apart.
In Spring 2.x, wiring of beans mostly happened via bean IDs or names. This is still supported by Spring 3.x but often, you will have one instance of a bean with a certain type - most services are singletons. Creating names for those is tedious. So Spring started to support "autowire by type".
What the examples show is various ways that you can use to inject beans into fields, methods and constructors.
The XML already contains all the information that Spring needs since you have to specify the fully qualified class name in each bean. You need to be a bit careful with interfaces, though:
This autowiring will fail:
#Autowired
public void prepare( Interface1 bean1, Interface1 bean2 ) { ... }
Since Java doesn't keep the parameter names in the byte code, Spring can't distinguish between the two beans anymore. The fix is to use #Qualifier:
#Autowired
public void prepare( #Qualifier("bean1") Interface1 bean1,
#Qualifier("bean2") Interface1 bean2 ) { ... }
Yes, you can configure the Spring servlet context xml file to define your beans (i.e., classes), so that it can do the automatic injection for you. However, do note, that you have to do other configurations to have Spring up and running and the best way to do that, is to follow a tutorial ground up.
Once you have your Spring configured probably, you can do the following in your Spring servlet context xml file for Example 1 above to work (please replace the package name of com.movies to what the true package name is and if this is a 3rd party class, then be sure that the appropriate jar file is on the classpath) :
<beans:bean id="movieFinder" class="com.movies.MovieFinder" />
or if the MovieFinder class has a constructor with a primitive value, then you could something like this,
<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
<beans:constructor-arg value="100" />
</beans:bean>
or if the MovieFinder class has a constructor expecting another class, then you could do something like this,
<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
<beans:constructor-arg ref="otherBeanRef" />
</beans:bean>
...where 'otherBeanRef' is another bean that has a reference to the expected class.