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
Related
below is the class which has constructor args which gets autoWired, but what i don't understand is that how the constructor gets autowired here without specifying any annotation or without mentioning it in any xml file.
I am kind of baffled with the code.
#Loggable
#Slf4j
public class DefaultDirectPlusService extends AbstractDnBDirectPlusService implements DirectPlusService {
public DefaultDnBDirectPlusService(String baseURL, RestTemplate restTemplate, DnBMetricsRepository dnbMetricsRepository, Environment env) {
super(restTemplate, dnbMetricsRepository, env);
this.baseURL = baseURL;
}
Here the question is how does baseURL gets populated without any annotations or the xml configuration?
As specified in the documentation (https://docs.spring.io/spring/docs/5.1.9.RELEASE/spring-framework-reference/core.html#beans-autowired-annotation), starting with Spring 4.3, if a class has only one constructor, Spring will automatically use that constructor for autowiring.
If you would have more than one constructor (you can try it out), you need to add the #Autowired annotation to the constructor which you want Spring to use.
THis should be easy, but doesn't work.
I have spring-boot-actuator activated in my Spring Boot (2.0.1-RELEASE) application.
The Actuator-Endpoint /actuator/info works as expected and also shows the correct version info. The file build-info.properties is present.
When trying to access the version property with (e.g. in my Spring-Controller-Class):
#Value("${build.version}) private String version;
The action fails with the error Could not resolve placeholder 'build.version' in value "${build.version}".
ANy suggestions?
With spring expression language it is pretty simple and clean.
#Value("#{buildProperties.get('version')}") // not 'build.version'
private String myAppBuildVersion;
Or better, Autowire the buildProperties bean directly to your components so you can play with it as you want.
#Autowired
private BuildProperties buildProperties;
NOTE: The autoconfiguration strips off the build. prefix. So your
SpEL expressions should use version as key. Not build.version.
I needed to add the file build-info.properties as #PropertSource
#SpringBootApplication()
#PropertySource("classpath:META-INF/build-info.properties")
public class MyApp implements WebMvcConfigurer {
[...]
}
Then you can use the build-info in annotations
#SomeAnnotation(value = "${build.version}")
public class someClass { ... }
In your #Service, put the #Value in the constructor, as a parameter of the constructor. Don't use a standalone value and try to reference it.
like this:
#Service
public class myService {
public myService(#Value("${my.param}") String myParam) {
client.withParam(myParam).build();
}
}
Where your application.properties has a value like:
my.param=http://google.com
I have tried other implementations and they do not work. for example,
#Service
public class myService {
#Value("${my.param}")
String myParam;
public myService() {
client.withParam(myParam).build();
}
}
Does not work.
In this case, the service will be initialized, but the string will be null. I can't explain it. Something to do with param construction and bean initialization timing, I guess.
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();
This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 6 years ago.
I was able to use RestTemplate and autowire it. However I want to move my rest template related part of code into another class as follows:
public class Bridge {
private final String BASE_URL = "http://localhost:8080/u";
#Autowired
RestTemplate restTemplate;
public void addW() {
Map<String, String> x = new HashMap<String, String>();
W c = restTemplate.getForObject(BASE_URL + "/device/yeni", W.class, x);
System.out.println("Here!");
}
}
And at another class I call it:
...
Bridge wb = new Bridge();
wb.addW();
...
I am new to Spring and Dependency Injection terms. My restTemplate variable is null and throws an exception. What can I do it how to solve it(I don't know is it related to I use new keyword)?
Using Bridge wb = new Bridge() does not work with dependency injection. Your restTemplate is not injected, because wb in not managed by Spring.
You have to make your Bridge a Spring bean itself, e.g. by annotation:
#Service
public class Bridge {
// ...
}
or by bean declaration:
<bean id="bridge" class="Bridge"/>
Just to add further to Jeha's correct answer.
Currently, by doing
Bridge wb = new Bridge();
Means that, that object instance is not "Spring Managed" - I.e. Spring does not know anything about it. So how can it inject a dependency it knows nothing about.
So as Jeha said. Add the #Service annotation or specify it in your application context xml config file (Or if you are using Spring 3 you #Configuration object)
Then when the Spring context starts up, there will be a Singleton (default behavior) instance of the Bridge.class in the BeanFactory. Either inject that into your other Spring-Managed objects, or pull it out manually e.g.
Bridge wb = (Bridge) applicationContext.getBean("bridge"); // Name comes from the default of the class
Now it will have the dependencies wired in.
If you want to use new operator and still all dependency injected, then rather than making this a spring component (by annotating this with #Service), make it a #Configurable class.
This way even object is instantiated by new operator dependencies will be injected.
Few configuration is also required. A detailed explanation and sample project is here.
http://spring-framework-interoperability.blogspot.in/2012/07/spring-managed-components.html
Let's say we have a class:
public class MyClass {
#Autowired private AnotherBean anotherBean;
}
Then we created an object of this class (or some other framework have created the instance of this class).
MyClass obj = new MyClass();
Is it possible to still inject the dependencies? Something like:
applicationContext.injectDependencies(obj);
(I think Google Guice has something like this)
You can do this using the autowireBean() method of AutowireCapableBeanFactory. You pass it an arbitrary object, and Spring will treat it like something it created itself, and will apply the various autowiring bits and pieces.
To get hold of the AutowireCapableBeanFactory, just autowire that:
private #Autowired AutowireCapableBeanFactory beanFactory;
public void doStuff() {
MyBean obj = new MyBean();
beanFactory.autowireBean(obj);
// obj will now have its dependencies autowired.
}
You can also mark your MyClass with #Configurable annotation:
#Configurable
public class MyClass {
#Autowired private AnotherClass instance
}
Then at creation time it will automatically inject its dependencies. You also should have <context:spring-configured/> in your application context xml.
Just got the same need and in my case it was already the logic inside non Spring manageable java class which had access to ApplicationContext. Inspired by scaffman.
Solved by:
AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory();
factory.autowireBean(manuallyCreatedInstance);
I used a different approach. I had spring loaded beans that I wanted to call from my extended classes of a third-party library that created its own threads.
I used approach I found here https://confluence.jaytaala.com/display/TKB/Super+simple+approach+to+accessing+Spring+beans+from+non-Spring+managed+classes+and+POJOs
In the non-managed class:
{
[...]
SomeBean bc = (SomeBean) SpringContext.getBean(SomeBean.class);
[...]
bc.someMethod(...)
}
And then as a helper class in the main application:
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
#Component
public class SpringContext implements ApplicationContextAware
{
private static ApplicationContext context;
public static <T extends Object> T getBean(Class<T> beanClass)
{
return context.getBean(beanClass);
}
#Override
public void setApplicationContext(ApplicationContext context) throws BeansException
{
SpringContext.context = context;
}
}
I wanted to share my solution that follows the #Configurable approach as briefly mentioned in #glaz666 answer because
The answer by #skaffman is nearly 10 years old, and that does not mean not good enough or does not work
The answer by #glaz666 is brief and didn't really help me solve my problem but, did point me in the right direction
My setup
Spring Boot 2.0.3 with Spring Neo4j & Aop starts (which is irrelevant anyway)
Instantiate a bean when Spring Boot is ready using #Configurable approach (using ApplicationRunner)
Gradle & Eclipse
Steps
I needed to follow the steps below in order to get it working
The #Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false) to be placed on top of your Bean that is to be manually instantiated. In my case the Bean that is to be manually instantiated have #Autowired services hence, the props to above annotation.
Annotate the Spring Boot's main XXXApplicaiton.java (or the file that is annotated with #SpringBootApplication) with the #EnableSpringConfigured and #EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
Add the dependencies in your build file (i.e. build.gradle or pom.xml depending on which one you use) compile('org.springframework.boot:spring-boot-starter-aop') and compile('org.springframework:spring-aspects:5.0.7.RELEASE')
New+up your Bean that is annotated with #Configurable anywhere and its dependencies should be autowired.
*In regards to point #3 above, I am aware that the org.springframework.boot:spring-boot-starter-aop transitively pulls the spring-aop (as shown here mavencentral) but, in my case the Eclipse failed to resolve the #EnableSpringConfigured annotations hence, why I explicitly added the spring-aop dependency in addition to the starter. Should you face the same issue, just declare the dependency or go on adventure of figuring out
Is there a version conflict
Why the org.springframework.context.annotation.aspect.* is not available
Is your IDE setup properly
Etc etc.
This worked for me:
#Configuration
public class AppConfig {
#Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}
See more information: https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html
Found the following way useful for my use case. Sharing here for reference, credit goes to the blogger entirely. This creates a static field and populates that from Spring and then provides a public static method which returns the field populated above.
https://sultanov.dev/blog/access-spring-beans-from-unmanaged-objects/