Grant Gochnauer opened SPR-6531 and commented
For some reason, when my controllers are trying to auto-wire my "MessageSource" I'm getting an error about no matching type found.
What's interesting is that I have my message source defined in my applicationContext.xml but when it's autowired in a controller it cannot be found.
When I copy the definition of the message source into my spring-servlet.xml, the controller can find the bean. I found this error while upgrading our 30+ web app enterprise application to Spring 3.0RC3 from 2.5.6
I have my message source defined like:
\
\
\
Affects: 3.0 RC3
Comment From: spring-projects-issues
Grant Gochnauer commented
Controllers auto-wire the bean like:
@Autowired
@Qualifier("cwpwebcomponents")
protected MessageSource messageSource;
The way the application layout is setup is like: EAR/ /JAR which contains all the applicationContext.xml beans /webapp1 /webapp2
Both web app's applicationContext.xml load the applicationContext.xml provided by the JAR living in the EAR.
The messagesource is defined in the JAR which is deployed in the EAR
Comment From: spring-projects-issues
Juergen Hoeller commented
So you're saying that "@Autowired MessageSource messageSource" (in a controller bean) works when the MessageSource is defined in the same context but not when it's defined in a parent context?
Juergen
Comment From: spring-projects-issues
Grant Gochnauer commented
It works when I define the message source bean in the spring-servlet.xml instead of the applicationContext.xml.
It's like the servlet context can't see the bean defined in the application context -- but just that MessageSource bean since my controller is autowiring other beans defined in the applicationContext.xml. I got it to work by copying and pasting the MessageSource bean definition in both my applicationContext.xml and spring-servlet.xml.
None of the beans in question with this issue are being loaded in the ear.context.
Grant
Comment From: spring-projects-issues
Grant Gochnauer commented
Something definitely seems weird. I have a workaround by defining the bean twice (once in applicationContext.xml and once in spring-servlet.xml) but IntelliJ is now complaining hehe.
For more detail, here's how I have my application structured:
/myear.ear ./mywar1.war ../applicationContext.xml - import via classpath:/ the applicationContext.xml in globalbeans.jar ../spring-servlet.xml - import via classpath:/ the shared-servlet-beans.xml ./mywar2.war ../applicationContext.xml - import via classpath:/ the applicationContext.xml in globalbeans.jar ../spring-servlet.xml - import via classpath:/ the shared-servlet-beans.xml ./mywar3.war ../applicationContext.xml - import via classpath:/ the applicationContext.xml in globalbeans.jar ../spring-servlet.xml - import via classpath:/ the shared-servlet-beans.xml ./globalbeans.jar ../applicationContext.xml -- MessageSource defined here ./mvcbeans.jar ../shared-servlet-beans.xml
This is how this was working in Spring 2.5.
Now in spring 3.0RC3, I've had to copy the messageSource bean definition listed above into the ./mvcbeans.jar's shared-servlet-beans.xml. This means I have this bean defined twice in JARs in the EAR.
Comment From: spring-projects-issues
Grant Gochnauer commented
I should also note that ALL spring JARs are packaged at the EAR level and the web apps add them to their classpath via the manifest.mf file
Comment From: spring-projects-issues
Grant Gochnauer commented
Hi Juergen,
I thought occurred to me this morning. I wonder if this problem isn't a MessageSource issue per se but an issue with the way my JARs which live in my EAR are importing other spring XML files.
For example, my web apps include one XML file via classpath: reference which live in the JARs in the EAR. Then the JAR files which live in the EAR have a "master" applicationContext.xml which in turn includes many other XML files within that JAR. The applicationContext.xml in the globalbeans.jar doesn't use a classpath: reference to import but a relative path like: \
I'm going to play around with the way I'm defining imports and see if that actually may be the issue.
Grant
Comment From: spring-projects-issues
Juergen Hoeller commented
Ah, maybe this is related to #11159: Relative resources suddenly got resolved in the local directory only rather than relative to the abstract classpath location, which exactly affects imports like yours.
You might want to the give the latest snapshot a try and see whether the problem remains...
Juergen
Comment From: spring-projects-issues
Grant Gochnauer commented
Juergen,
That could be it :). I tried to grab a snapshot from: http://static.springsource.org/downloads/nightly/snapshot-download.php?project=SPR
but it appears it's from 12/2/2009. Is there a place I can grab a snapshot from last night's build?
thanks
Comment From: spring-projects-issues
Juergen Hoeller commented
Grant, it seems that the download page is stale. The direct link for the latest snapshot does work:
http://s3.amazonaws.com/dist.springframework.org/snapshot/SPR/spring-framework-3.0.0.CI-493.zip
Comment From: spring-projects-issues
Grant Gochnauer commented
Hi Juergen,
It seems the snapshot didn't help resolve the issue.
I've also tried including resources using both "classpath:com/.." and "classpath*:com/.." but neither seem to work.
What other information can I provide to help diagnose?
Thanks
Comment From: spring-projects-issues
Juergen Hoeller commented
Hmm, in the meantime, are you sure that this is actually caused by some XML files not being loaded? That should become obvious when looking at the debug log for the org.springframework.beans.factory.xml package, for example.
Juergen
Comment From: spring-projects-issues
Grant Gochnauer commented
I am seeing it being loaded:
I'm seeing this: [12/8/09 13:27:17:470 CST] 00000028 DefaultListab I org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5c005c0: defining beans [ ... ,messageSource, ...]
The error about not finding it is later.
I'm still trying to debug.
Comment From: spring-projects-issues
Grant Gochnauer commented
So I took out my controllers by commenting out the component scan for them and now I'm getting other auto-wiring issues for MessageSource in my services.
So it appears that anytime I define messageSource in my applicationContext, I can't autowire it..
Let me try taking off the qualifier.
Comment From: spring-projects-issues
Grant Gochnauer commented
Juergen --
I removed the @Qualifier and everything is working now... It seems something broke when using the @Qualifier with the messageSource.
BTW, I have 2 different types of beans with a qualifier value of "cwpwebcomponents" -- a messageSource and a freemarker configurer. Could it be that by re-using the same qualifier value screwed something up? This definitely worked on Spring 2.5.6.
Strange.
Grant
Comment From: spring-projects-issues
Juergen Hoeller commented
Using the same qualifier on different kinds of beans should work fine, since qualifiers only apply within the set of matches by type. I'll check our qualifier resolution process there, which indeed did change a bit since 2.5...
Juergen
Comment From: spring-projects-issues
Juergen Hoeller commented
Actually, your case is a bit special since it uses the default "messageSource" bean: If you aren't defining such a bean in your servlet-level context, there will be an implicit "messageSource" bean registered there - delegating to the parent context's MessageSource.
So you'll effectively have two "messageSource" beans: one at the global level and one at the servlet level, using the same bean name - which means that the implicit servlet-level "messageSource" bean effectively overrides the global-level "messageSource" bean in terms of visibility in the child context.
As a consequence, autowiring within the servlet-level context can only ever detect the local implicit "messageSource" bean which doesn't have any qualifiers associated with it. The qualified "messageSource" bean in the parent context isn't visible at that level and hence not available for autowiring either.
However, if the above is what you're affected by, why did this work with Spring 2.5? The rules were the same there, and the relevant code for this specific visibility checking hasn't changed either...
Juergen
Comment From: spring-projects-issues
Grant Gochnauer commented
Interesting. I'm not sure how this worked in Spring 2.5 :)
So when I removed my @Qualifier on my MessageSource, the implicitly defined messageSource bean in the servlet context "sees" the messageSource bean defined in the parent application Context and essentially "extends" that? Now that I removed the @Qualifier, auto-wiring the MessageSource object in my controllers does seem to be able to read from the resource bundles only defined in the parent context.
Thanks
Comment From: spring-projects-issues
Juergen Hoeller commented
Indeed, MessageSources have a parent detection model built in: The implicit MessageSource will automatically delegate to the parent ApplicationContext as its parent MessageSource. This is why message resolution will work if your MessageSource is defined in the global context... even if the global MessageSource bean itself is not directly available.
Do you actually have multiple MessageSource beans defined, since you were using qualifiers there? With one of them being named "messageSource" (as the context's MessageSource) and the others having different names and different qualifiers?
I'm still trying to find out why this could possibly have worked in Spring 2.5... and trying to make up my mind whether we should make this work in 3.0 at all.
Juergen
Comment From: spring-projects-issues
Grant Gochnauer commented
Feel free to push to 3.0.1 because it's working for us now that we removed the @Qualifier. I can keep debugging later but probably won't have time until next week.
Comment From: spring-projects-issues
Juergen Hoeller commented
Closing groups of outdated issues. Please reopen if still relevant.
Comment From: tshavkat
what is the solution?