Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring @Autowired messageSource working in Controller but not in other classes?

New updates: Dec 31 2010 8:15 PM
Very dirty fix but this is how I have temporarily made the messageSource to work. I changed my Controller class to pass the 'messageSource' to Message class and am able to retrieve the messages. Please review the class definition below and let me know any more info that you may need to help. I really appreciate all the help you are providing.

Dec 31 2010 3 PM
As I could not succeed in configuring messageSource through annotations, I attempted to configure messageSource injection through servlet-context.xml. I still have messageSource as null. Please let me know if you need any more specific info, and I will provide. Thanks for your help in advance.

servlet-context.xml
<beans:bean id="message"
    class="com.mycompany.myapp.domain.common.message.Message">
    <beans:property name="messageSource" ref="messageSource" />
</beans:bean>

Spring gives the below information message about spring initialization.

INFO : org.springframework.context.annotation.ClassPathBeanDefinitionScanner - JSR-330 'javax.inject.Named' annotation found and supported for component scanning

INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Overriding bean definition for bean 'message': replacing [Generic bean: class [com.mycompany.myapp.domain.common.message.Message]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\springsource\tc-server-developer-2.1.0.RELEASE\spring-insight-instance\wtpwebapps\myapp\WEB-INF\classes\com\mycompany\myapp\domain\common\message\Message.class]] with [Generic bean: class [com.mycompany.myapp.domain.common.message.Message]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in ServletContext resource [/WEB-INF/spring/appServlet/servlet-context.xml]]

INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring

INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1c7caac5: defining beans [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#0,org.springframework.format.support.FormattingConversionServiceFactoryBean#0,org.springframework.validation.beanvalidation.LocalValidatorFactoryBean#0,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#0,org.springframework.web.servlet.handler.MappedInterceptor#0,org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,org.springframework.web.servlet.resource.ResourceHttpRequestHandler#0,org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#0,xxxDao,message,xxxService,jsonDateSerializer,xxxController,homeController,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,tilesViewResolver,tilesConfigurer,messageSource,org.springframework.web.servlet.handler.MappedInterceptor#1,localeResolver,org.springframework.web.servlet.view.ContentNegotiatingViewResolver#0,validator,resourceBundleLocator,messageInterpolator]; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory@4f47af3


I have the below definition for message source in 3 classes. In debug mode, I can see that in class xxxController, messageSource is initialized to org.springframework.context.support.ReloadableResourceBundleMessageSource. I have annotated Message class with @Component and xxxHibernateDaoImpl with @Repository. I also included context namespace definition in servlet-context.xml. But in Message class and xxxHibernateDaoImpl class, the messageSource is still null.

Why is Spring not initializing messageSource in the two other classes though in xxxController classes, it initializes correctly?

@Controller
public class xxxController{
    @Autowired
    private ReloadableResourceBundleMessageSource messageSource;
}

@Component
public class Message{
 @Autowired
 private ReloadableResourceBundleMessageSource messageSource;
}

@Repository("xxxDao")
public class xxxHibernateDaoImpl{
 @Autowired
 private ReloadableResourceBundleMessageSource messageSource;
}

<beans:beans
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
            <beans:property name="basename" value="/resources/messages/messages" />
</beans:bean>   

    <context:component-scan base-package="com.mycompany.myapp"/>
</beans>
like image 489
Jayaprakash Avatar asked Dec 31 '10 01:12

Jayaprakash


Video Answer


2 Answers

Spring does not know about those classes that you are getting a null value field from. You can tell Spring about them by defining them as beans in your app context or annotating the classes as @Component

The reason why your first class is getting autowired correctly is because that class is correctly annotated as @Controller

like image 149
John Vint Avatar answered Nov 14 '22 04:11

John Vint


Try to refine your base-package. Don't let spring scan all your application class com.mycompany.myapp , (you will have a better startup time).

Suppose you have your controller class in a package : com.mycompany.myapp.controller and your service class (annotated with @component, @repository) in package com.mycompany.myapp.services

Add this to your [servlet-name]-servlet.xml (Dispatcher context file)

<context:component-scan base-package="com.mycompany.myapp.controller" />

In the other hand, open your servlet-context.xml (Supposed to be an application context loaded by contextloaderlistener) and add this :

<context:component-scan base-package="com.mycompany.myapp.services" />

followed by the declaration of your messageSource as you did.

You will have one messageSource injected every where it is autowired. It should work because stuff defined in Dispatcher-context-file can see other beans declared in application-context file(s) but not the opposite

like image 36
redochka Avatar answered Nov 14 '22 04:11

redochka