How to inject static field in static class in spring - java

I have the service MyStaticService which is doing some calculations using a DAO.
How can I inject the MyDao object into the class field?
I've tried to implement the setter with #Autowired but when I call doCalculations(..) the DAO is null. What am I doing wrong?
public class MyStaticService
{
private static MyDao dao;
public static int doCalculations(..){
dao.doSmth()
// omitted
}
}

First of all you cannot Autowire Spring beans inside classes that are not managed by Spring.
Hence in your example even if you DAO is a valid Spring managed bean, you cannot inject that in your MyStaticService. Of course it will always be null. Spring wouldn't be able to know what dependencies to scan and inject if your static service class is itself not a Spring Component
Spring dependency injection is meant to work only in classes managed by the Spring IOC container.
Your StaticService class makes more sense to be of a Singleton Class, hence there is no harm in declaring it as a Spring component.
#Component
public class MyStaticService
Then you can Autowire your DAO classes.
Service classes should ideally be Singletons with other singletons dependencies like your DAOs.

You need initialize your object for you to access the functions of MyDao() class like this:
dao = new MyDao();
or while you create the instance
private static MyDao dao = new MyDao();
else it will always show null

Related

DI & Autowiring vs instantiation in Spring [duplicate]

I've started to use Spring recently. And I'm making spring mvc project. So my question is if it's preferred to make interfaces and autowire it with particular implementation by spring or just use class instances in case when I have only one implementation of that interface?
For example:
#Controller
public class MyController {
#Autowired
MyService myService;
#RequestMap("/")
public String mainPage() {
...
}
}
or
#Controller
public class MyController {
#RequestMap("/")
public String mainPage() {
MyService myService = new MyServiceImpl();
...
}
}
if there is only one implementation of MyService interface?
In most cases you should go with injection because:
It eases unit testing (you can inject mock or different implementation)
Spring can inject some dependencies into MyServiceImpl as well because it manages this object
You are not coupling your controller with particular implementation
Even if your service does not have an interface, because of the second reason you should consider injection.
The only case when you might want to skip Spring is when the class does not have any dependencies and is stateless. But most likely such a class is a utility that does not need any an instance at all because it has only static members.
It will depend on whether MyService is a bean that holds a state or not. If MyService does not hold state, then you don't need to create new instances and you can let Spring to inject it having the advantages above described

#Autowired does not create members in constructor

I have a bean that is created from context, after which a autowired member is created:
#Service
public class FileDownloadService extends WFWFileDownloadService {
#Autowired
ConfigurationManager configurationManager;
When I use in code manual constructor call:
FileDownloadService fileDownloadService = new FileDownloadService();
I see configurationManager is null, so I have to make manual wiring:
public FileDownloadService() {
configurationManager = new ConfigurationManagerImpl();
}
What am I doing wrong to make autowiring working with manual creating?
When you call the constructor directly, you're just creating an object and not a bean. The support of the #Autowired annotation is a feature of bean.
Ask the Spring context for the bean.
If you attempt to get the bean by using new operator, you will get all autowired beans inside that class as null.
Your service class is annotated with #Service, so to use it you should autowire this service class also.
Sample code to access service bean in other classes is :
#Controller or #Component
public class OtherClass {
#Autowired FileDownloadService fileService;
public void download() {
fileService.downloadFile();
}
}
In order this class to be able to autowire other beans, this class itself should be annotated with #Controller or #Component.
The Answer is simple:
If you manually create the Object, there is no wiring involved. How should Spring know, that you are in need for wiring? Instead of using new, you could use the getBean() method of the application context (Bean Factory). http://static.springsource.org/spring/docs/current/javadoc-api/index.html?org/springframework/beans/factory/BeanFactory.html
http://static.springsource.org/spring/docs/current/javadoc-api/index.html?org/springframework/beans/factory/BeanFactory.html

Spring - creating objects with new operator using #Configurable & #Value annotations

Is it possible to use #Configurable on a class that's weaved using AspectJ and get Spring to load in values on fields/methods which are annotated with #Value?
I know its possible with #Autowired and #Resource etc... Are there any others.
e.g.
#Configurable
public Class MyObj{
#Value("$(my.prop)")
private String aField;
public String getAField(){
return aField;
}
}
And then have something like
public aMethodSomewhereElse(){
MyObj obj = new MyObj()
assertNotNull(obj.getAField());
}
Are there any alternatives to being able to create MyObj with the new operator and still get spring to handle the annotations?
--EDIT:--
It IS possible to do this using new when using #Autowired, have a look at some Hibernate and JPA stuff with Spring and AOP... I've used this in the past to do some profiling of Java code. But I really want to use SPEL and #Value before I mock up a full example I was hoping to find the answer here. FYI - if you don't belive me the Spring Manual even says it is possible to do this, what I want to know is if its possible to use #Value annotations in the same scope...
The Spring container instantiates and configures beans defined in your
application context. It is also possible to ask a bean factory to
configure a pre-existing object given the name of a bean definition
containing the configuration to be applied. The spring-aspects.jar
contains an annotation-driven aspect that exploits this capability to
allow dependency injection of any object.
And...
Using the annotation on its own does nothing of course. It is the
AnnotationBeanConfigurerAspect in spring-aspects.jar that acts on the
presence of the annotation. In essence the aspect says "after
returning from the initialization of a new object of a type annotated
with #Configurable, configure the newly created object using Spring in
accordance with the properties of the annotation". In this context,
initialization refers to newly instantiated objects (e.g., objects
instantiated with the 'new' operator) as well as to Serializable
objects that are undergoing deserialization (e.g., via readResolve()).
http://static.springsource.org/spring/docs/3.0.0.RC2/reference/html/ch07s08.html
Cheers.
You are absolutely right - #Autowired fields will be wired in an #Configurable annotated class even outside of a Spring container, assuming that you have a AspectJ infrastructure in place.
You have noted a good catch though, #Value fields are processed by a Spring bean post processor(AutowiredAnnotationBeanPostProcessor), which resolves the #Value annotated fields. It does not act on objects instantiated outside of the container though - so in short, the #Autowired fields should get wired in, but #Value properties will not.
Doing
MyObj obj = new MyObj()
means that obj is not managed by spring, so it will not do autowiring.
Only way to do that is to obtain instance from an application context. For example:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyObj obj = context.getBean("myBean");
I don't think it is possible to use new operator and ask spring to autowire properties. I think 1 way to solve this is to get a static reference to applicationContext and create a prototype scoped bean.
#Component
public class ApplicationContextLocator {
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public ApplicationContextLocator() {
super();
}
#Autowired
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextLocator.applicationContext = applicationContext;
}
}
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Component
public class MyObj {
.....
}
public aMethodSomewhereElse(){
MyObj obj = ApplicationContextLocator.getApplicationContext().getBean(MyObj.class)
assertNotNull(obj.getAField());
}

Autowiring vs instantiating in Spring

I've started to use Spring recently. And I'm making spring mvc project. So my question is if it's preferred to make interfaces and autowire it with particular implementation by spring or just use class instances in case when I have only one implementation of that interface?
For example:
#Controller
public class MyController {
#Autowired
MyService myService;
#RequestMap("/")
public String mainPage() {
...
}
}
or
#Controller
public class MyController {
#RequestMap("/")
public String mainPage() {
MyService myService = new MyServiceImpl();
...
}
}
if there is only one implementation of MyService interface?
In most cases you should go with injection because:
It eases unit testing (you can inject mock or different implementation)
Spring can inject some dependencies into MyServiceImpl as well because it manages this object
You are not coupling your controller with particular implementation
Even if your service does not have an interface, because of the second reason you should consider injection.
The only case when you might want to skip Spring is when the class does not have any dependencies and is stateless. But most likely such a class is a utility that does not need any an instance at all because it has only static members.
It will depend on whether MyService is a bean that holds a state or not. If MyService does not hold state, then you don't need to create new instances and you can let Spring to inject it having the advantages above described

Can #Autowire #Service beans but not members of a class instantiated with "new" keyword - even with context scanning configured

I have an app that's been working well with #Autowired #Service beans.
Now I'm adding a Validator class which is instantiated in the Controller:
BlueValidator validator = new BlueValidator(colors);
validator.validate(colorBlend, bindResult);
In the BlueValidator class I'm trying to #Autowire the blendService which is working as an #Autowired field elsewhere in the app:
public class BlueValidator implements Validator {
#Autowired
private BlendService blendService;
private Colors colors;
But for some reason after instantiating the BlueValidator, I keep getting NullPointerExceptions for the blendService.
Of course I've added the necessary context scanning:
<context:component-scan
base-package="com.myapp.controllers, com.myapp.services, com.myapp.validators" />
I also tried adding the#Autowired annotation to the constructor but that didn't help:
#Autowired
public BlueValidator(Colors colors) {
this.colors = colors;
}
Should I just pass the blendService to the BlueValidator and forget about the Autowiring or is there something obvious missing here?
If you just instantiate an object with new, Spring is not involved, so the autowiring won't kick in. Component scanning looks at classes and creates objects from them - it doesn't look at objects you create yourself.
This can be made to work, using Spring's AspectJ support, but it takes some effort.
Otherwise, you need to let Spring instantiate your objects if you wan autowiring to work.
Should I just pass the blendService to the BlueValidator and forget about the Autowiring
In your situation, I'd say yes, this is the least effort solution.
When you instantiate objects spring cannot do anything for them, so it does not get the dependencies injected (article).
In your case, you have a couple of options:
pass dependencies to the validator from the controller (where you can inject them)
make the validator a spring bean and inject it, instead of instantiating it
use #Configurable, which, via AspectJ, enables spring injection even in objects created with new
#Autowired is being used by Spring's ApplicationContext to populate those fields on creation. Since the ApplicationContext is not the one creating these beans (you are because of the keyword 'new'), they are not being autowired. You need to pass it in yourself if you are creating it.
Don't create validator manually -- allow to Spring do this work for you:
#Controller
class Controller {
#Autowired
BlueValidator validator;
void doSomething() {
...
validator.validate(colorBlend, bindResult);
...
}
}
Also pay attention that adding package com.myapp.validators to context:scan-packages not enough, you also should annotate your validator class with #Component annotation:
#Component
public class BlueValidator implements Validator {
#Autowired
private BlendService blendService;
(BTW this solution works in my project.)

Categories