I am learning Spring MVC, and am trying to troubleshoot an issue with an #Autowired Service object. I have the following annotation:
#Autowired
private UserServiceBLInt userService;
This is within the context of a Controller class, and I get a NullPointerException when using the userService object. Nowhere in the class am I manually instantiating the userService object, since my understanding is that for #Autowired to work, I have to let spring be responsible for creating the object.
My suspicion is that in the spring configuration file, the component-scan base-package declared incorrectly, so Spring doesn't know where to find the classes.
<context:component-scan base-package="com.app.service.**" />
The UserServiceBLInt is in com.app.service.int
The concrete implementation is in com.app.service.impl
Is the ** notation correct?
The example in the Spring reference doc does not use .**:
<beans>
<context:component-scan base-package="com.acme"/>
</beans>
So most likely, this is your problem.
Don't use the .** ind base package declartion. just specify the package name whose Bean you want to autowire by Spring, you can use comma separated values for package name as well.
Related
I want to create a simple app built on Spring Boot. I don't have experience with the framework, and this issue is beyond me.
I want to use the Security module in my app, particularly the org.springframework.security.authentication.encoding.ShaPasswordEncoder class. I want to get this autowired as a bean.
How do I define that in Spring Boot? For instance, this answer explains how to use it in "regular" Spring - defining the bean in a XML file. However, when I was reading the Boot overview, it stated that there is no need for XML setup, so is it possible to somehow do this in code, not configuration? What is the Boot-ish way?
I have tried just using this code to get the encoder class.
#Autowired
private ShaPasswordEncoder passwordEncoder;
But I get an exception: org.springframework.beans.factory.NoSuchBeanDefinitionException -- it's not defined, but how do I define it?
Thanks
The beans can be defined in-code like this:
#Bean
public ShaPasswordEncoder passwordEncoder() {
return new ShaPasswordEncoder();
}
This method will create a bean named "passwordEncoder" which will be managed by Spring. It is the equivalent of the XML-styled
<bean class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" id="passwordEncoder" />
You can put this method in the #SpringBootApplication-annotated class, or any class annotated with #Configuration.
More info here
I'm trying to get a better understanding of the #Autowired annotations component scanning, but all the examples I found so far use context.getBean(..) at some point to get at least one Bean to start with.
I also read that doing that is considered bad practice , but I can't seem to find any information on how to do it without context.getBean(..)
Could somebody please enlighten me with an example and information on how to do this ?
Define your bean in xml and use
<context:component-scan base-package="com" />
<mvc:annotation-driven />
Bean def
<bean id="processEngine" class="com.processEngine">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
now you can get bean as following
#Autowired
private ProcessEngine processEngine;
how it works
spring scans the bean's recipes either from xml or java configuration. then spring creates a beanDefinitions which are 'loaded' into BeanFactory. BeanFactory triggers a set of BeanPostProcessors (BPP) which are scanning classes for particular annotations like Autowired/Resource/PostProcessor and etc. and do appropriate actions. in case when your class contains #Autowired annotation, AutowiredAnnotationBeanPostProcessor would auto wire required field (dependencies), and when creation of an object is done and all BPP worked out, object is ready to be used by the app, from this point your code can get 'ready' objects from container.
there are some cases when you would need to access this beans from the code which is out of spring's control and not managed by container. in order to do so, you would need to get the ApplicationContext (container) and call #getBean specifying either name or type. using applicationContext directly is not a good practice because there are some problems that you can come to, f.ex. id of a bean might be changed and if you refer to bean by id then NPE would be thrown.
configuration
there are several approaches to configure spring to scan the classes for finding bean recipes. one would be defining component-scan, in this case classes which are located in the path that you've set and having any of valid spring annotations like #Component, #Service, #Repository, #Controller (for web container) would be considered. another way would be specifying each bean separately using <bean> or #Bean.
examples.
if you want to create a web app then you should see DispatcherServlet with ContextLoaderListener classes. this classes would boot your app and load everything according to configuration. f.ex. here,
but if you want to create a desktop app, then you would end up with something like this
From time to time (usually when not using Spring Boot), I use something along the lines of the following code:
public static <T> T autowire(ApplicationContext ctx, T bean) {
ctx.getAutowireCapableBeanFactory().autowireBean(bean);
return bean;
}
In my main, I create an instance of the main application class that contains a few #Autowired annotations for the main services / entry points to my Spring application.
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.
Maybe, because of my wrong English, I couldn't understand the benefit of using #Autowired annotation.
According to the tutorial we can simplify the first(I.) case to second case(II.) by means of #Autowired.
My question is, what is the meaning of the #Autowired ? Because it doesnt tell any more, since without using #Autowired the compiler can figure out that "EmpDao emDao" and "EmpManager" are closely related according the declaration.
code cited from here
I.
<bean id="empDao" class="EmpDao" />
<bean id="empManager" class="EmpManager">
<property name="empDao" ref="empDao" />
</bean>
public class EmpManager {
private EmpDao empDao;
public EmpDao getEmpDao() {
return empDao;
}
public void setEmpDao(EmpDao empDao) {
this.empDao = empDao;
}
...
}
II.
<context:annotation-config />
<bean id="empManager" class="autowiredexample.EmpManager" />
<bean id="empDao" class="autowiredexample.EmpDao" />
import org.springframework.beans.factory.annotation.Autowired;
public class EmpManager {
#Autowired
private EmpDao empDao;
}
#Autowired is spring-specific. #Inject is the standard equivallent. It is an annotation that tells the context (spring, or in the case of #Inject - any DI framework) to try to set an object into that field.
The compiler has nothing to do with this - it is the DI framework (spring) that instantiates your objects at runtime, and then sets their dependencies at the points you have specified - either via XML or via an annotation.
I agree it is a possible scenario for a DI framework to try to inject dependencies into all fields, even if they are not annotated. (And if you want to exclude a particular field, to annotate it). But they chose the other strategy (configuration-over-convention). By the way:
if using xml config and choose some form of autowiring, the dependencies of the bean will be automatically autowired without the need to specify anything
you can specify per-context autowiring settings.
When the server bootstraps itself. It finds
<context:annotation-config />
in the application context and then goes through the classes defined in the contexts. If there are any beans that are autowired, it injects that into the class by referring the context file.
Basically, it promotes convention over configuration. That's what most frameworks do these days to reduce the development time.
the #Autowired Spring annotation tells Spring to for a bean named 'empDao' and inject it into the EmpManager class, without you having to add the empDao bean as a property in your spring config file.
#Autowired tells Spring to find a bean of the declared type and wire in that bean, rather than requiring an explicit lookup by bean name. It can, under certain circumstances, make configuring applications easier if you only have one implementation of your types in a given Spring context.
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);