I\'m looking for a better understanding of this problem. A workaround is pretty simple, namely move the configuration data to another class that does not have proxies/advic
I figured it out. It was, indeed, too much magic.
I used Spring Roo in STS to generate the basic app framework, then factored out Roo using STS as we didn't want to stick with it.
One thing Roo does as a "best practice" is create two Spring contexts, one for the whole app, and one limited to the dispatcher servlet. Exactly why, I still haven't gotten to, but I guess they want to keep the presentation layer stuff, such as the Controllers, from creeping into the service layer that is shared. This was nicely explained by axtavt here. This was all hidden from me by STS.
In STS with Roo, the WEB-INF source is not where I expected it, under /src/main/resources (which is where the META-INF directory is) but instead under /src/main/webapp, which is not a Java source directory and thus shown completely separately, just above the /target directory, so I mistook it for an output folder.
In the applicationContext.xml, Roo had inserted the filter to prevent the application context from constructing Controllers, as explained in axtavt's post, but it also put in another filter to eliminate scanning Roo generated classes. I took both filters out at the same time, not really knowing what they were there for but thinking they were just Roo leftovers.
So now I've got the problem of the Controllers being created twice as explained before. And the one in the application context gets the property assigned, because it is using the applicationContext.xml and finding the properties file. But why weren't they both getting the properties set?
Which gets me back to the obscured webapps folder. Inside the WEB-INF folder Roo had placed the web.xml (naturally) and a spring folder containing a webmvc-config.xml file. This config file was set up to scan, create, and set up just the Controllers. The web.xml file sets up the web app to use the applicationContext.xml and the dispatcherServlet to use the webmvc-config.xml, so I should have left the filter in the applicationContext.xml to avoid the double creation.
The final piece of the puzzle was this webmvc-config.xml file. Since that is the context in which the Controllers get set up, that file needed to have the <context:property-placeholder/> configured as well so that it could find the properties file.
First of, the notation using the $ is correct, not the #
Now regarding the original poster, I think you have a conflicting behavior between the 2 annotations (@Controller and @Transactional).
Using the @Transactional annotation will proxify your implementation (I guess to detect an error and launch a rollback).
Now you are saying that you see 2 instances of your controller. That should not happen. Normally you should have only a single instance of a controller loaded in memory.
Could be related to your configuration files or due to the presence of @Transactional and its proxy nature?
As a side note, I never use @Transactional in the controllers themselves but either on a method of a service or dao. Since the actual process which can fail and need to be rollbacked is there, and can be access from different controllers/source.
Regards.
In my case I solve that this way:
in spring-servlet.xml
before <context:component-scan ... />
i put this:
<context:property-placeholder location="classpath:strings.properties"/>
While strings.properties
file I put to src/main/resources/
.
Note: context:property-placeholder
tag has limited visibility so i have read somewhere recommendation to duplicate it in every context file, where you use strings from it.
I had the same problem and it was the fact that I needed BOTH
To get these two senarios to work
I hope this helps.
Here is the web.xml.
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/spring-config/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Here is spring-servlet.xml: The key was to have BOTH util:properties and context:property-placeholder. Although they locate the same file, they serve different purposes.
<util:properties id="propSource" location="classpath:/properties/prop1.properties" />
<context:property-placeholder location="classpath:/properties/prop1.properties" />
<context:component-scan base-package="com.concurrent.controller" />
<context:annotation-config/>
<mvc:annotation-driven/>
Here is a snippet of my controller class:
@Controller
@RequestMapping("/fooController")
public class MyController {
@Value("${message1}")
public String message1;
@Inject
public ConfigProperties configProperties;
Lastly, here is my class that I inject the property into:
@Service
public class ConfigProperties {
@Value("${message1}")
public String message1;
}
That worked for me and will work for you. Good Luck!