I have an application loading its Spring context with XML configuration.
Context files are stored in a jar's classpath (in the META-INF/context directory).
Introducing a new bean, I want to load a beanio mapping file from within the classpath of the same archive.
With Tomcat running within Eclipse it all works as a charm, but when I deploy a WAR file to our QA environment I get the application not starting.
Let me walk the code:
public class BeanIoParser implements Parser, Iterator<Message>, InitializingBean
{
private StreamFactory streamFactory;
private Resource resourceMapping; //Injected via Context
#Override
public void afterPropertiesSet() throws Exception
{
streamFactory = StreamFactory.newInstance();
streamFactory.load(resourceMapping.getFile()); //boom here
}
}
And then the context
<bean id="messagesParser" class="it.acme.BeanIoParser" scope="prototype">
<property name="resourceMapping" value="classpath:META-INF/mappings/messages-beanio.xml" />
</bean>
And then what? Uhm... I have double checked the built jar file by uncompressing the war file first. It all matches.
I can see my messages-beanio.xml file correctly.
But when I start the application I get the following root cause:
java.io.FileNotFoundException: class path resource [META-INF/mappings/messages-beanio.xml] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/C:/Program%20Files/Apache%20Software%20Foundation/Tomcat%208.0/temp/11-app/WEB-INF/lib/app-3.0.0.20151105.jar!/META-INF/mappings/messages-beanio.xml
I have also tried another way, by using classpath* (because we already faced this problem when loading Spring context from multiple jar files)
So if my bean declaration becomes
<property name="resourceMapping" value="classpath*:META-INF/mappings/messages-beanio.xml" />
My error becomes
java.io.FileNotFoundException: ServletContext resource [/classpath*:META-INF/mappings/messages-beanio.xml] cannot be resolved to absolute file path - web application archive not expanded?
How can I fix?
Solved differently. I programmatically instantiate the ClasspathResource with path starting with META-INF and not classpath:
Related
I am writing web app using spring. Which is created using standard web application.
I need ApplicationContext to be initialized using ClassPathXmlApplicationContext so i placed context.xml file in WEB-INF folder and created ApplicationContextusing following code.
ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
But I get FileNotFoundException saying context.xml is not found.
When i tried to initilize application using FileSystemXmlApplicationContext it works.
But i want ClassPathXmlApplicationContext
what can i do so that context.xml is located in classpath.
You need to place your context.xml inside classes folder or you can use
new ClassPathXmlApplicationContext("classpath:context.xml")
Read the below definition
ClassPathXmlApplicationContext will read files from your classpath. They must be in classes folder of your web application or in a jar in your libfolder.
FileSystemXmlApplicationContext can access all your file system, for example c:/config/applicationContext.xml.
XmlWebApplicationContext certainly can access to files contained in your web application.
I'm placing applicationContext.xml in the same directory and package as my Java classes.
Doing the following to read it:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Yet I am consistently met with:
IOException parsing XML document from class path resource [applicationContext.xml]; nested exception is java.io.FileNotFoundException
Which I do not get: The file is there, in the same directory as the classes. They're even compiled to /out and I can see it's all there.
I've tried putting it in src/resources/applicationContext.xml but to no avail.
Spring will look for it in the root of the classpath ...
The "same directory and package as my Java classes" is not at the root of your classpath
src/resources is not on your classpath at all
If you put it in src/main/resources then it will be (1) on your classpath and (2) in the root of your classpath.
I resolved this problem, as changing
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
to
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("packagename/applicationContext.xml");
My XML file also resides in the same package as my java classes exist.
I have encountered a problem when it comes to the Springs framework, which leads to that the communication between the server and the database does not work.
The project that I created is a Spring project, then refactored to Maven.
At this line in the code:
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("projectName/spring.xml");
I get this error:
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [projectName/spring.xml]; nested exception is java.io.FileNotFoundException: class path resource [projectName/spring.xml] cannot be opened because it does not exist
But it does exist. And I've tried solutions for this problem such as writing ClassPathXmlApplicationContext("spring.xml") instead. This doesn't help however, since then Spring automatically looks in the folder src/main/resources. This doesn't work for me since my project structure doesn't allow me to add this folder and put a XML-file in it. If I try to create this folder, then it is automatically put inside the Java-resources folder, and Eclipse won't allow me to put XML in there.
This is how my project looks:
enter image description here
Is there a way for me to declare where Spring should look for this spring.xml-file?
The ClassPathXmlApplicationContext assumes that the file is on your classpath (Javy describes how to do load a resource from your classpath).
If you want to load the configuration from your file system (as you're doing), you might want to consider using FileSystemXmlApplicationContext instead. Using this mechanism to load your context you can pass a file system location as you're currently doing.
new ClassPathXmlApplicationContext(this.getClass().getResource("/spring.xml").getPath())
try the code above
hope that helped
Spring doesn't look at the src/main/resources, it looks at the classpath.
If you write projectName/spring.xml you need to have this file in bin/projectName/spring.xml or build/projectName/spring.xml. Where bin or build your build folder.
If you build a jar, this file should be in the jar!projectName/spring.xml.
For the web-application this file should be in the WEB-INF/classes/projectName/spring.xml.
If you add src/main/resources at the class path, then content of this folder will be in the build folder. Maven adds src/main/resources at the class path automatically.
Sometimes you should rebuild (clean) your project in the IDE to have such files in the build folder.
Use "FileSystemXmlApplicationContext" as
ApplicationContext context = new FileSystemXmlApplicationContext("spring.xml");
How do I reference an external beans.xml file based on its relative location to where my jar file is deployed? This is what I have now, which doesn't work:
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("../beans.xml");
I want it out of the classpath so I can change things without redeploying, but relative to the deployed location of the jar so that it will work no matter where I put the jar and the beans.xml in the file system, as long as they are correctly situated relative to each other.
This is Spring btw, if that helps.
Thanks!
An application context file must be on the classpath to allow ClassPathXmlApplicationContext to work. To use a relative path you would have to use FileSystemXmlApplicationContext.
ApplicationContext context = new FileSystemXmlApplicationContext("../beans.xml");
You can import the external beans configuration file in your spring-config.xml you can import the extends
<beans ...>
<import resource="file:/path/to/external/config.xml"/>
</beans>
The above Spring config will import /path/to/external/config.xml. Having an external file will allow you to configure beans without having to rebuilding your main war/jar.
In your Java code, you can load it as follows:
ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
and the config.xml file should be in:
project-classpath/config.xml
More about loading external configuration files, you can find here
For some reason (a shiro filter) I saved my application context file in WEB-INF folder. Everything works when I run tomcat but, when I try to get an application context from a controller using :
context = new ClassPathXmlApplicationContext(fileContext);
I receive always this exception:
IOException parsing XML document from class path resource [applicationContext.xml]; nested exception is java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
It seems that under ecplise I'm not able to include WEB-INF under classpath. I took a look to a lot questions here in stackoverflow but I didn't find yet a solution.
If I move the applicationContext.xml file under src/main/java folder, I'm able to get the context but, the shiro filder defined into web.xml file is not able to see the shiro bean defined under applicationContext file (I double checked and the bean is correctly worked). How can I tell to web.xml to get content from src/main/java? Or, how can I reach the applicationContext.xml
WEB-INF is not in your CLASSPATH. WEB-INF/classes is. So why dont you put it in a source folder and package the application?
Do not create an instance of ApplicationContext in your controller. The spring DispatcherServlet already creates one for you. All you need to do is access all bean declarations in you application context file using #Autowired.
use
context = new FileSystemXmlApplicationContext(fileContext);
instead of
context = new ClassPathXmlApplicationContext(fileContext);
Problem has been solved moving all configuration file under WEB-INF/classes and adding the prefix classpath:
<import resource="classpath:spring-data.xml"/>
thanks to all for the help! I really appreciate that!
cheers, Andrea