When I run my application on tomcat the spring-context.xml file is located at
/WEB-inf/spring-context.xml
This is ok. But running a junit test I have to supply it with the location of my spring-test-context.xml like this:
#ContextConfiguration(locations={"classpath:/spring-test-context.xml"})
The only way this works is if the file is located in
/src/spring-context.xml
How can I get my application to find my spring-context files in the same location? So that it works with junit testes and deployed on tomcat?
I tried this and it gave me alot of errors about not finding any beans, but it didn't say it couldn't find the file..
classpath:/WEB-INF/spring-test-context.xml
As duffymo hinted at, the Spring TestContext Framework (TCF) assumes that string locations are in the classpath by default. For details, see the JavaDoc for ContextConfiguration.
Note, however, that you can also specify resources in the file system with either an absolute or relative path using Spring's resource abstraction (i.e., by using the "file:" prefix). You can find details on that in the JavaDoc for the modifyLocations() method in Spring's AbstractContextLoader.
So for example, if your XML configuration file is located in "src/main/webapp/WEB-INF/spring-config.xml" in your project folder, you could specify the location as a relative file system path as follows:
#ContextConfiguration("file:src/main/webapp/WEB-INF/spring-config.xml")
As an alternative, you could store your Spring configuration files in the classpath (e.g., src/main/resources) and then reference them via the classpath in your Spring MVC configuration -- for example:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/spring-config.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
With this approach, your test configuration would simply look like this (note the leading slash that denotes that the resource is in the root of the classpath):
#ContextConfiguration("/spring-config.xml")
You might also find the Context configuration with XML resources section of the reference manual useful.
Regards,
Sam
(author of the Spring TestContext Framework)
The problem is that /WEB-INF is not in the CLASSPATH for a web app. However, /WEB-INF/classes is.
Your problem with testing is that you aren't running in an app server, so WEB-INF/classes isn't part of the CLASSPATH by default. I'd recommend setting up your tests so that either WEB-INF/classes is in the test CLASSPATH or use a relative or absolute file path to find them.
Related
I have a war based spring web application project which internally has multiple jar files. I am using maven setup to build jars and war file. Each jar file has a set of beans that needs to be loaded and i am not able to do so.
In each of the jar file i have defined a beans.xml file . But the beans are not getting loaded automatically. I have tried loading the beans.xml file from:
a) src/main/resources
b) src/main/resources/META-INF
c) src/main/resources/META-INF/spring
It doesnt work.
My Question: How to prepare the application context for such scenarios? War based app with multiple jars.
If your are packaging your application as a webapp one, then you can simply add a file named yourservletname-servlet.xml and include all resources from your jar files using the <import /> element.
Spring, behind the scenes, will scan the file mentioned above by default including all beans declared in the files imported.
Here is how your servletname-servlet.xml should look like (xml namespace and schemas declaration are ommited for brevity sake):
<beans>
<import resource="classpath:/META-INF/beans.xml"/>
</beans>
I suggest the use of the META-INF as your context config files location.
This will scan all bean declaration files named beans.xml under META-INF folder under the root of your classpath, which assumes that those files must be under src/main/resources/META-INF/ in your project structure when using Maven as your build tool (so they can get copied directely under jar_root_path/META-INF/).
Otherwise, if you are not using the default -servlet.xml file, you can specify a custom application context descriptor using the contextConfigLocation as follows:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>application-context.xml</param-value>
</context-param>
Try simple
import resource="classpath*:/META-INF/beans.xml"/
Where each jar contains beans.xml file under META-INF folder.It will scan each jar and load beans.xml file and creates beans based on these XMLs files.
You mention beans.xml, is this a CDI project or a standard Spring project ?
Using maven, everything under src/main/resources gets packaged at the top level of your JAR. So if you had a file in src/main/resources/META-INF/beans.xml, then you should load it using "/META-INF/beans.xml" or define it in your spring context as "classpath:/META-INF/beans.xml".
I'm currently developing a Java Struts2 webapp (using Maven) and have successfully configured the use of datasources to connect with the database. Since May application needs the ability of being moved between environments (Development > Homologation > Production), it must use server config files to load paramenters (such as the datasources and log levels).
I can't find any references on how to configure a java webapp to use a log4j.xml file from outside the application (out of the WAR). With maven I simply put the log4j.xml inside my src/main/resources folder and it loads automatically. What should I do to ensure that my webapp loads a external log4j.xml file on deploy?
Maven by default places all files from src/main/resources into /WEB-INF/classes/. With log4j, you can specify where your configuration file is located with help of Web App Deployment Descriptor (web.xml). Simply, add log4j listener:
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
And context parameter:
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.xml</param-value>
</context-param>
classpath: is equivalent to /WEB-INF/classes, you may specify any path for example, with ${catalina.home}, a tomcat specific variable. Use it with file:// prefix
Is there a way to place applicationContext.xml into WEB-INF folder? I am specific to WEB-INF folder because I know that it can be placed into WEB-INF\classes folder.
As per the requirement, Clients should be able to configure applicationContext.xml according to their setup.
There is another option I thought of importing xml configuration files from WEB-INF folder to applicationContext.xml. But I didn't tried it yet and not sure how feasible it is.
From your requirement point of view, there is absolutely no difference between putting it in the WEB-INF or in WEB-INF/classes directory: Either way it needs to be accessed from the exploded WAR/EAR after deployment, which may not be possible if your app server don't explode it (ie, JBoss can work directly with the WAR).
IMO, the solution for you is to stop using the WebApplicationContext implementation. Use DefaultListableBeanFactory which should be initialized in a ServletContextListener, reading the configuration file manually. That way you can obtain the path to the applicationContextFile from the ApplicationServer environment (using JNDI or whatever method suits you), so it can be places anywhere in the machine where the Application Server resides.
At least that's what we did, for the very same reason you have.
Yes, you can do this, but the classpath is a pretty logical place to put them.
In your web.xml, in the definition for "contextConfigLocation", just add /WEB-INF/applicationContext.xml to the section.
If you add this in the web.xml then you can access the applicationContext
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
In short: I don't know which folder to place the "spring-context.xml" file in a WebApp when I'm doing this:
ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
In Long: I know what a classpath is basically. It used to be an environment variable that told the Java project where to look for jars and other resources. It doesn't seem to be used much. But in Eclipse, it talks about setting your classpath by going into your Java Build Path.
What I don't understand it when I want to find a Spring "spring-context.xml" file using the classpath (above) what that has to do with the Eclipse Java Build Path, if anything! What folders does a WebApp look in when I use the above statement? I usually hear people say, "In the classpath" but that doesn't tell me much since I don't want to use an environment variable and the Eclipse Java Build Path seems to have little to do with finding the spring-context.xml file.
More Detail
Initially I was afraid that more details would confuse the situation, but maybe they hold a key.
I am using Vaadin to create a web app. I'm following their direction for how to get a Spring context into Vaadin. I've created a Spring Helper class:
public SpringContextHelper(Application application) {
ServletContext servletContext = ((WebApplicationContext) application.getContext()).getHttpSession().getServletContext();
context = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
}
In the web.xml I have these sections:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring-context.xml</param-value>
</context-param>
I'm getting the error in the first line of SpringContextHelper(). I've broken the line down so I know it is this logic that is failing:
WebApplicationContext wac = (WebApplicationContext) application.getContext();
wac comes back null, presumably because is can't find the spring-context.xml file.
Essentially, the "Java Build path" you specify for a project is the CLASSPATH.
And files you put in the "src" root of your "Java Resources" project folder will automatically go in your web app's "classes" subdirectory (i.e will automatically be available as in the runtime CLASSPATH).
For example, if you have a custom log4j.properties file, then it can and should go in your Eclipse project's "src/" root.
As far as "where does spring-context.xml go?", I don't know. This link suggests it should go under META-INF/jsca (at least for WebLogic):
http://docs.oracle.com/cd/E15315_09/help/oracle.eclipse.tools.weblogic.doc/html/sca.html
How do I move my spring xml configuration outside of my java web application?
I'd like to store my spring.xml outside of my web application so I don't have to create a new build of my application to change the configuration.
What is the best way to do this?
As Rod Johnson explains it in this thread:
You can use the classpath: prefix to load from the classpath, with the normal Spring listener or startup servlet. This is made possible by Spring's Resource abstraction. You can freely mix and match resources from WEB-INF and classpath.
So, put the configuration files somewhere in the classpath outside the webapp and declare the following in the web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springContext*.xml</param-value>
</context-param>
I think that relying on the classpath is more portable than using an absolute file path.
You can move it to some folder (outside of webapp structure) and explicitly specify context location to point to context in that folder in your web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>file:/full/path/to/context.xml</param-value>
</context-param>
That said, the best way to do this may be to not do it at all :-) and instead reconsider how you deploy your application (e.g. you can create a "patch" or "upgrade" deployment unit that contains changes rather then full blown WAR). Specifying absolute paths tends to be more hassle than it's worth.
Why complicate you build for this, when it's a deployment problem. Most containers deploy WARs in an "exploded" form, which means that somewhere on you file system is the spring.xml file.
If you'd like to update that, you can simply locate the actual location and then copy your new spring.xml over the old one. Yet, at the same time, your WAR remains the de riguer "source of truth".
WARs tend to be very simple to use and deploy, so there's a benefit to bundling your configuration as best you can in the WAR.
So, you can update the spring.xml by going behind the back of the container, and editing it (or copying over) it directly.
Finally, having the spring.xml outside of your WAR means that's it's available to ALL of your WARs, and if you decide later to add another WAR to your system, you will likely have difficulty segregating the two files as they are no long anchored to a specific WAR.