i have the following in my app-servlet.xml
<mvc:annotation-driven />
<context:component-scan base-package="com.merc.myProject.web.controllers"/>
<context:component-scan base-package="com.merc.myProject.web.forms"/>
what ever I have in my controller package gets injected but the same thing in the forms package is always null.
my form looks something like this
public class SelectDatesForm {
#Inject IUserService userService;
.....
}
my controllers looks like this
#Controller
public class SelectDates {
#Inject IUserService userService;
.....
}
somebody please help
<context:component-scan> looks for classes annotated with things like #Component, #Controller, #Service, and so on, and configures those as beans. If those classes have properties injected with #Inject or #Resource, then those will be processed also.
However, if your class isn't annotated to start with, then #Inject will not be processed. This is the case for SelectDatesForm. If you annotate this with #Component, it should get picked up.
I'd be a bit careful here, though - forms are generally not good candidates for Spring beans, since they tend to be throw-away, transient objects.
I guess your SelectDatesForm is instantiated manually with new rather than obtained from the Spring context. In this case it is not a Spring bean and therefore not a subject for dependency injection.
Usually you don't need to inject dependencies into manually created objects. If you actually need to do so, you have several options:
Declare your SelectDatesForm as a prototype-scoped bean and obtain a fresh instance of it from Spring context instead of creating it with new:
#Component #Scope("prototype")
public class SelectDatesForm { ... }
and when you need to obtain a new instance of it:
SelectDatesForm newForm = applicationContext.getBean(SelectDatesForm.class);
However, this approach couples your code with Spring's ApplicationContext.
If your have no control over instantiation of SelectDatesForm (i.e. it happens outside of your code), you can use #Configurable
Also you can manually facilitate autowiring of the object created with new:
SelectDatesForm newForm = new SelectDatesForm();
applicationContext.getAutowireCapableBeanFactory().autowireBean(newForm);
Related
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.
I understand that a managed bean works like a controller, because your only task is "link" the View Layer with Model.
To use a bean as a managed bean I must declare #ManagedBeanannotation, doing that I can communicate JSF with bean directly.
If I want to inject some component (from Spring) in this managedBean I have two possibles ways:
Choose the property in ManagedBean (like "BasicDAO dao") and declare #ManagedProperty(#{"basicDAO"}) above the property. Doing it, i'm injecting the bean "basicDAO" from Spring in ManagedBean.
Declared #Controller in ManagedBean Class, then i'll have #ManagedBean and #Controller annotations, all together. And in property "BasicDAO dao" i must use #Autowired from Spring.
Is my understanding correct?
#ManagedBean vs #Controller
First of all, you should choose one framework to manage your beans. You should choose either JSF or Spring (or CDI) to manage your beans. Whilst the following works, it is fundamentally wrong:
#ManagedBean // JSF-managed.
#Controller // Spring-managed.
public class BadBean {}
You end up with two completely separate instances of the very same managed bean class, one managed by JSF and another one managed by Spring. It's not directly clear which one would actually be used in EL when you reference it as #{someBean}. If you have the SpringBeanFacesELResolver registered in faces-config.xml, then it would be the Spring-managed one, not the JSF-managed one. If you don't have that, then it would be the JSF-managed one.
Also, when you declare a JSF managed bean specific scope, such as #RequestScoped, #ViewScoped, #SessionScoped or #ApplicationScoped from javax.faces.* package, it will only be recognized and used by #ManagedBean. It won't be understood by #Controller as it expects its own #Scope annotation. This defaults to singleton (application scope) when absent.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
#Controller // Spring-managed (without own scope, so actually becomes a singleton).
public class BadBean {}
When you reference the above bean via #{someBean}, it would return the Spring-managed application scoped bean, not the JSF-managed view scoped bean.
#ManagedProperty vs #Autowired
The JSF-specific #ManagedProperty works only in JSF-managed beans, i.e. when you're using #ManagedBean. The Spring-specific #Autowired works only in Spring-managed beans, i.e. when you're using #Controller. Below approaches are less or more equivalent and cannot be mixed:
#ManagedBean // JSF-managed.
#RequestScoped // JSF-managed scope.
public class GoodBean {
#ManagedProperty("#{springBeanName}")
private SpringBeanClass springBeanName; // Setter required.
}
#Component // Spring-managed.
#Scope("request") // Spring-managed scope.
public class GoodBean {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
}
Do note that when you have the SpringBeanFacesELResolver registered in faces-config.xml as per the javadoc,
<application>
...
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
and thus you can reference Spring managed beans in EL via #{springBeanName}, then you can just reference them in #ManagedProperty too, as it basically sets the evaluated result of the given EL expression. The other way round, injecting a JSF managed bean via #Autowired, is in no way supported. You can however use #Autowired in a JSF managed bean when you extend your bean from SpringBeanAutowiringSupport. This will automatically register the JSF managed bean instance in Spring autowirable context during constructor invocation, which means that everything #Autowired will be available in #PostConstruct and later.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport implements Serializable {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
// springBeanName is now available.
}
}
Or when your architecture doesn't allow extending beans from a different base class, then you can always manually register the JSF managed bean instance in Spring autowirable context as below. See also How to integrate JSF 2 and Spring 3 (or Spring 4) nicely for the trick.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
FacesContextUtils
.getRequiredWebApplicationContext(FacesContext.getCurrentInstance())
.getAutowireCapableBeanFactory().autowireBean(this);
// springBeanName is now available.
}
}
#XxxScoped vs #Scope
Spring's #Scope has limited support for JSF scopes. There's no equivalent for JSF's #ViewScoped. You'd basically either homegrow your own scopes, or stick to manually registering the JSF managed bean instance in Spring autowirable context as shown above.
And, from the other side on, Spring WebFlow was taken over in JSF 2.2 via new #FlowScoped annotation. So if you happen to be on JSF 2.2 already, then you don't necessarily need to use Spring WebFlow if you solely want the flow scope.
CDI - trying to unify it all
Since Java EE 6, CDI is offered as standard alternative to Spring DI. It has respectively #Named and #Inject annotations for this and also its own set of scopes. I'm not sure how it interacts with Spring as I don't use Spring, but #Inject works inside a #ManagedBean, and #ManagedProperty inside a #ManagedBean can reference a #Named bean. On the other hand, #ManagedProperty doesn't work inside a #Named bean.
The purpose of CDI is to unify all different bean management frameworks into only one specification/inteface. Spring could have been a full CDI implementation, but they choosed to only partially implement it (only JSR-330 javax.inject.* is supported, but JSR-299 javax.enterprise.context.* not). See also Will Spring support CDI? and this tutorial.
JSF will be moving to CDI for bean management and deprecate #ManagedBean and friends in a future version.
#Named // CDI-managed.
#ViewScoped // CDI-managed scope.
public class BetterBean implements Serializable {
#Inject
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
// springBeanName is now available.
}
}
See also:
When is it necessary or convenient to use Spring or EJB3 or all of them together?
JSF Service Layer
Backing beans (#ManagedBean) or CDI Beans (#Named)?
Using JSF as view technology of Spring MVC
How to install and use CDI on Tomcat?
There is another way to use Spring-managed beans in JSF-managed beans by simply extending your JSF bean from SpringBeanAutowiringSupport and Spring will handle the dependency injection.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
// springBeanName is now available.
}
The easy way to do this is via XML. I used #Component in already made jsf managed bean but #Autowired did not work because managed bean was already there in faces-config.xml. If it is mandatory to keep that managed bean definition along with its managed property in the xml file then it is suggested to add the spring bean as another managed property inside the managed bean tag. Here the spring bean is there defined in spring-config.xml(can be autowired somewhere alternately). please refer
https://stackoverflow.com/a/19904591/5620851
edited by me. I suggest to either implement it altogether through annotation #Managed and #Component or via xml for both.
You can autowire individual beans without #Autowired by leveraging getBean of the current WebApplication context.
Please refer to #BalusC's answer for more details. This is just a slight modification over his example:
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {
// #Autowired // No Autowired required
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
WebApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
this.springBeanName = ctx.getBean(SpringBeanClass.class);
// springBeanName is now available.
}
}
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.
I use Spring 3 to make a simple configuration.
I have an XML file called PropertyBeans.xml like that :
<bean id="propertyBean" class="com.myapp.PropertyBean">
<property name="rootDirLogPath" value="C:\Users\dede" />
</bean>
I have the bean which match this XML and then I want to use this bean with the value injected. Actually I have :
ApplicationContext context = new ClassPathXmlApplicationContext("AppPropertyBeans.xml");
PropertyBean obj = (PropertyBean) context.getBean("propertyBean");
String rootDirLogPath = obj.getRootDirLogPath();
This works great but I want to know if there's a way to avoid the instantiation of ApplicationContext at each time I want to use a bean. I've heard about BeanFactory is that a good idea? Which are the others solutions?
In other words: Am I supposed to called this Application context instanciation in every Controller in spring MVC?
If you want to use spring beans in controllers, add line to applicationContext.xml:
<context:spring-configured/>
<task:annotation-driven/>
<context:component-scan base-package="by" />
Then write your controller following way:
#Controller
public class IndexController {
#Autowired
private UserService userService;
#Autowired
private GroupService groupService;
// methods with #RequestMapping annotation
}
This is trivial thing, so If you have questions it is strongly recommended to read "Spring in action book", chapter 7: Building web applications
The whole idea of the ApplicationContext is that there is one (hence the name, context of the application).
So if you're creating a new one every time, you're doing it wrong.
If you use dependency injection properly, the object containing that code will already be instantiated by the injection container (Spring) and the propertyBean will have been injected.
Use autowiring or implements the InitializingBean interface.
You can simply add the context as member in your class like:
private ApplicationContext context;
and instanciate it in the constructor or an init() method.
I am working on a core java framework. I don't want to create instances directly inside the class which is why I want to use dependency injection.
I am thinking of declaring my custom annotations on the fields to be instantiated. And having a call back function which would create an instance and inject it into the field.
I had tried to create a custom annotation. But looks like there's no direct way to get a callback on the declared annotation. So, I was trying to scan the classes for that. But I ended up with this problem
Java Scanning Class for Annotation using Google Reflections
Please let me know if this is the right way of achieving this.
Since your question is tagged 'Spring', you can use Spring Framework's bean annotations (#Component / #Service / #Repository / ...), classpath scanning and #Autowired.
For example:
Setup classpath scanning on your spring config xml:
<context:component-scan base-package="com.mycompany.myapp" />
Create your bean to be scanned. Spring container will automatically create a singleton instance of this bean using default constructor:
#Repository
public class FooDAO {
...
}
Inject reference to above DAO instance using DI + autowiring
#Service
public class FooService {
#Autowired private FooDAO fooDAO;
...
}