How to inject spring injection manually if not done automatically - java

My spring dependencies are working fine but there one class
CustomUserDetaisls where i need the Autowired dependency called
#Autowired Private UserDAO userDAO
to match with username and password
But my spring injection is not working here as this class implements the userDetailsSerivce . However injection works if i remove the implements.
I have submitted the question to ask why in this question, but no one gave me answer so i decided to use the DAO with new operator
private UserDAO userDAO = new UserDAO();
But that userDAO in turn depends on session Factory which is a spring bean.
Then i again decided to get sessionfactory from java code rather than spring using following code
SessionFactory sessionFactory = new AnnotationConfiguration()
.configure("com/vaannila/service/hibernate.cfg.xml")
.buildSessionFactory();
But again i have several bean in hibernate-context like datasource , properties file and i am finding it very hard to re-write all the things.
Is there any way that I can manually inject userDAO so that all the related spring injection like sessionFactories works

If you have access to the spring context, you can retrieve an AutowireCapableBeanFactory which you can then use on any bean like this:
ApplicationContext springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContextEvent.getServletContext());
AutowireCapableBeanFactory factory = springContext.get(AutowireCapableBeanFactory.class);
// this would instantiate and autowire a bean:
UserDAO userDAO = factory.createBean(UserDAO.class);
// this will autowire an already existing bean:
UserDAO manualUserDAO = new UserDAO();
factory.initializeBean(manualUserDAO, "beanNameIfNeeded");
However, if a bean requires that it be autowired before it can be used, I prefer to use the first mechanism and mark the constructor as private/protected to make sure that it cannot be created via 'new' and force it to be created via a factory like above.
UPDATE 11/27/17
I personally didn't like to have to use the factory every time I wanted to create an autowired instance. Particularly if some other process was creating the instance, such as deserializing from a database, etc.
I ended up creating a aspect to automatically handle the autowiring.
First, I created an annotation to flag classes that I wanted automatically autowired:
#Documented
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Inherited
public #interface AutowireAfterCreation {
}
Then I created an aspect that uses an 'after construction' point cut to do the autowiring. Unfortunately, I was unable to figure out a point cut that was only called after the 'last' constructor was finished, but it doesn't seem to hurt to autowire multiple times, at least in my case.
public aspect AutowiringAfterCreation {
#Autowired
private AutowireCapableBeanFactory beanFactory;
/**
* After construction, autowire the instance.
* #param o Newly created object to be autowired.
*/
after(Object o) returning : target(o) && initialization((#AutowireAfterCreation *).new(..)) {
// this aspect will actually autowire the instance multiple times if the class is part of an inheritance
// Hierarchy. This is not optimal, but it should not hurt anything to autowire more than once.
// FUTURE: modify the aspect so it only runs once, regardless of how many constructor calls are necessary.
beanFactory.autowireBeanProperties(o, AutowireCapableBeanFactory.AUTOWIRE_NO, false);
beanFactory.initializeBean(o, "unused");
}
}
Then I had to tell Spring about the aspect so the factoryBean is autowired into the aspect itself:
<bean class="AutowiringOnDemand" factory-method="aspectOf"/>
Now I can create any instance and have it automatically autowired simply by attaching the annotation:
#AutowireAfterCreation
public class TestEntity {
#Value("${some.config.value}")
private String value;
#Autowired
private TestRepository repository;
}
Finally, all you have to do is create an instance, and it is automatically autowired after the completion of the constructors:
TestEntity entity = new TestEntity();
UPDATE 1/2/2018
The interface ApplicationContext has changed, and get() has been removed, but you can still use the first mechanism, but you need to call getAutowireCapableBeanFactory() instead.
So the first two lines in the example at the top for this answer would now look like:
ApplicationContext springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContextEvent.getServletContext());
AutowireCapableBeanFactory factory = springContext.getAutowireCapableBeanFactory();

You can take a look at spring java configuration.
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java
In example below all dependencies of UserDAO will be automatically set by spring.
It should be something like this:
#Configuration
#PropertySource("classpath:configuration.properties")
public class ApplicationConfig {
#Bean
public UserDAO userDAO() {
return new UserDAO();
}
#Bean
public CustomUserDetails customUserDetails (UserDAO userDAO) {
CustomUserDetails customUserDetails = new CustomUserDetails ();
customUserDetails.setUserDAO(userDAO());
return customUserDetails;
}
}

Related

How to autowire a bean into a 2 different controllers (Spring)

I am learning spring and i have a problem that i do not know how to solve.
#Service
#Transactional
public class SchoolService {
#Autowired
private CourseDao courseDao;
#Autowired
private EducationDao educationDao;
#Autowired
private StudentDao studentDao;
#Autowired
private TeacherDao teacherDao;
#Autowired
private StatisticsDao statisticsDao;
............
}
This code is injecting my DAOS into this service class but then i need to inject the class above into two controllers.
One way i have tried was with this code but that did not work.
#Autowired
SchoolService sm;
How would i inject it into my controller class. I have tried making the controller class a #Component but nothing seems to work.
ClassPathXmlApplicationContext container = new ClassPathXmlApplicationContext("application.xml");
SchoolService sm = container.getBean(SchoolService.class);
This way works but i do not want to create a new applicationcontext for each time i want to get that bean.
Yes i am using xml at the moment, please don't shoot me :D
Thanks.
Try creating the controller bean in the application.xml file instead of annotating the controller.
Since its obviously an educational question, I'll try to provide a very detailed answer as much as I can:
Once basic thing about spring that all the auto-wiring magic happens only with beans that are managed by spring.
So:
Your controllers must be managed by spring
Your service must be managed by spring
Your DAOs must be managed by spring
Otherwise, autowiring won't work, I can't stress it more.
Now, Think about the Application Context as about the one global registry of all the beans. By default the beans are singletons (singleton scope in terms of spring) which means that there is only one object (instance) of that bean "retained" in the Application Context.
The act of autowiring means basically that the bean (managed by spring) - controller in your case has dependencies that spring can inject by looking in that global registry, getting the matching bean and setting to the data field on which the #Autowired annotation is called.
So, if you have two controllers (again, both managed by spring), you can:
#Controller
public class ControllerA {
#Autowired
private SchoolService sm;
}
#Controller
public class ControllerB {
#Autowired
private SchoolService sm;
}
In this case, the same instance of school service will be injected into two different controllers, so you should good to go.

Spring dependency injection #Autowired VS dependency injection of an object without #Autowired

what is the main difference between injecting objects with #Autowired and injecting without it ?
I know that spring will initialize the bean , but what it is really offering ?
There are several ways to configure Spring beans and inject dependencies using Spring. One way is by using constructor injection, where the constructor of your Spring bean has arguments which are the dependencies that should be injected:
#Component
public class MyBean {
private final SomeDependency something;
#Autowired
public MyBean(SomeDependency something) {
this.something = something;
}
}
However, since Spring 4.3, it is not necessary anymore to use #Autowired on such a constructor (click link for Spring documentation). So you can write it without the #Autowired:
#Component
public class MyBean {
private final SomeDependency something;
public MyBean(SomeDependency something) {
this.something = something;
}
}
This will work exactly the same as the code above - Spring will automatically understand that you want the dependency to be injected via the constructor. The fact that you can leave out #Autowired is just for convenience.
So, to answer your question: there is no difference.
#Autowired (so the injection) in some situation cannot be used, an example is if your autowired bean not ready because of some async stuff but in the target bean you want to use that.
So in this situation do not use inject (#Autowired) it is better to inject the ApplicationContext and in the exact moment get your bean from there by name or by class (there is a lot off possibilities there).
You can consider the #Autowired with the #Lazy annotation too.

Class instantiation using the Autowired annotation

Is its advisable to instantiate the class using #Autowired annotation like below.
#Autowired
public static Car = new Car();
Case 1
If you are trying to autowire an attribute like following:
#Autowired
public Car car;
then Spring will try to search for a Bean definition in Spring context and will also instantiate it, hence no need to again invoke constructor.
Case 2
If you are getting confused with constructor autowire like following:
#Autowired
public Driver(License license){
this.license = license;
}
Here, it is trying to get the Bean of "License" class autowired, and it is not autowireing Driver.
In your case, I feel it is case 1.
If you are trying to set it manually cause you are seeing it as not initialized, then check the spring application context configuration file/class. You will need to have something like following in it:
<context:component-scan base-package="com.test.packagename" />
If using AppConfig class then:
#Configuration
#ComponentScan("com.test.packagename")
public class AppConfig {
}
Also, make sure that your spring core is deployed in lib where it is executing.
Also check that you are instantiating the class by using Spring application context as follows:
AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Car car= (Application)context.getBean("car");
Try to refer this: http://websystique.com/spring/spring-dependency-injection-annotation-beans-auto-wiring-using-autowired-qualifier-resource-annotations-configuration/
Happy coding DBZ fan :-)

spring - ApplicationContext registerBean autowiring fails but getBean works in Spring 5

I'm using a configuration class that uses dynamic bean registration:
#Configuration
public class ConfigClass {
#Autowired
private GenericApplicationContext applicationContext;
#PostConstruct
private void init() {
System.out.println("init");
applicationContext.registerBean("exService", ExecutorService.class, () -> Executors.newFixedThreadPool(10), bd -> bd.setAutowireCandidate(true));
System.out.println("init done");
}
}
If I try to autowire the bean, application startup fails with error Field exService in com.example.DemoApplication required a bean of type 'java.util.concurrent.ExecutorService' that could not be found.
From the logs I can see that the init method on config class wasn't called before the error as the two system out statements were not printed out.
However, when I use applicationContext.getBean(ExecutorService.class) it does work without any issues.
Anyway I can get the bean to Autowire?
I'm deliberately not using the #Bean annotation because I need to register the beans dynamically based on certain conditions.
It could be because you are registering your bean in the middle of the context initialization phase. If your target bean initializes and auto-wires ExecutorService before ConfigClass #PostConstruct is invoked there simply is no bean available.
You can try forcing the initialization order:
#Component
#DependsOn("configClass")
public class MyComponent
#Autowired
private ExecutorService executorService;
However it would be cleaner to register a bean definition using BeanFactoryPostProcessor with BeanDefinitionBuilder:
#Component
public class MyBeanRegistration implements BeanFactoryPostProcessor {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) {
BeanDefinitionRegistry reg = (BeanDefinitionRegistry) bf;
reg.registerBeanDefinition("exService",
BeanDefinitionBuilder
.rootBeanDefinition(ExecutorService.class)
.setFactoryMethod("newWorkStealingPool")
.getBeanDefinition());
}
}
You can do like this:
#Resource
#Lazy
private ExecutorService executorService;
It works.
Actually, I wrote the small infrastructure that deals with such issues. Here is the idea how to do this:
Create a class (lets call it MyClass) that incapsulates ExecutorService.class as a property and declare it as Bean (#Component). Even before that create an Interface (Lets call it MyInterface) that your new class would implement
Create a factory class (Lets call it MyFactory) with method MyInterface getInstance(String) that returnce an instance of your interface. In that factory crate a static property Map[String, MyInterface] and public static method that allows you to add instances of the interface to this map
In MyClass create a constructor that at the end will place newly created instance of itself into that map in the factory with the key of your class name ("MyClass")
Now The trick is that when Spring starts and initializes it creates all its beans. As your MyClass will be created its constructor will place its instance into a factory. So now anywhere in your code you can call:
MyInterface myInterface = MyFactory.getInstance("MyClass");
And you get your bean without worrying about instantiating it. Spring already did it for you. Big extra bonus is non-intrucivness - you don't have to explicitely work with Spring classes

Support for autowiring in a class not instantiated by spring (3)

I realize this should be really basic but I haven't found a second step example after Helloworld
So what I have is:
spring config xml called spring-beans.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config />
<context:component-scan base-package="org" />
</beans>
A spring context initialized class:
public static void main(String[] args) {
// initialize Spring
ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring-beans.xml");
App app = (App) context.getBean("app");
app.run();
}
Relevant details of AppImpl class:
#Component("app")
public final class AppImpl implements App{
// focus of question: This autowiring works
#Autowired
private DAO1 dao1;
public void run() {
//focus of question: This works as daoclass is instantiated properly
obj1s = dao1.myFind();
badJobs = runJobs(obj1s);
}
private List<Obj1> runJobs(final List<Obj1> obj1s) {
List<Obj1> jobsGoneBad = new ArrayList<Obj1>();
for (Obj1 next : obj1s) {
// focus of question: usage of new keyword, thus not spring container managed?
Job job = new JobImpl(next);
job.run();
}
return jobsGoneBad;
}
}
Relevant details of JobImpl:
public class JobImpl implements Job {
private Obj1 obj1;
// focus of question: can't autowire
#Autowired
private DAO2 dao2;
#Override
public void run() {
//focus of question: opDAO == null - not initialized by #Autowired
Obj2 obj2 = dao2.myFind();
}
}
Relevant details of DAO1:
#Repository("DAO1") //Focus of question: DAO1 is a repository stereotype
public class DAO1 {
myfind() { ...}
}
Relevant details of DAO2:
#Repository("DAO2") //Focus of question: DAO2 is a repository stereotype
public class DAO2 {
myfind() { ...}
}
Right, so I initialize the App through a springcontext call and then succesfully instantiate a DAO1 instance through the use of #Autowired.
Then I create an unmanaged instance of Job and want to inject "singeltonish" dependencies in that class too by using #Autowired
Both Dao classes are spring stereotypes and scanner finds them fine.
So my question is basically, how should I instantiate the job instance so that I can use #Autowired concept inside it?
If I need a globally accessible applicationcontext, how do I best introduce that?
You can use Spring Bean functionality like injection only in spring managed beans!
But you can use the #Configurable Annotation, but this requires that you use REAL AspectJ.
If a class is annotated by #Configurable (and you use AspectJ) then you can use Springs Injection Annotations even if this class is created by a normal new.
#See
Spring Reference: Chapter 8.8.1 Using AspectJ to dependency inject domain objects with Spring
Spring autowiring using #Configurable
Spring beans are singletons by default. However, what you need there are multiple instances, and on top of that, multiple instances created runtime.
One possibility is to use method injection for this. You'd create a container aware job factory that would request new instances from the container.
(I think it is a bit fishy that you'd need a DAO reference injected in those runtime instances... I would maybe try rethinking the logic. Why couldn't you just provide the DAO reference in a constructor argument, for example, or use it from somewhere else altogether. You could have a method in the dao that would accept a Jobs instance, or a runWith(DAO2 dao) stuff in the JobImpl that would be satisfied with a class injected elsewhere, or a JobProcessor service that would have the daos injected and would ask the relevant info from Jobs instance...)
#Autowired isn't working because your JobImpl object isn't managed by spring so it never has a chance to inject it. Spring managed beans are those where instances are created during component scan or in XML definition. JobImpl in your case is being instantiated as a normal Java object.
One solution would be to replace the auto-wiring with a manual lookup in the spring context.
private DAO2 dao2 = SpringApplicationContext.getApplicationContext ().getBean (DAO2.class);
#Autowired is working in #AppImpl because it's annotated as #Component. This flags it up for spring during its classpath scan where it will create an instance of this class and perform any autowiring/injections.
Add #Component annotation to your JobImpl class. Add component scan for this class in xml and your autowiring will work for dao2(provide getter-setter methods).

Categories

Resources