spring beans configuration - java

I'm using Spring's dependency injection but I'm running into difficulty loading a resource in my Spring config file.
The resource is an XML file and is in a JAR file on my classpath. I try to access it as follows:
<import resource="classpath:com/config/resources.xml" />
however I keep getting encountering the following error:
Failed to import bean definitions from URL location [classpath:com/config/resources.xml]
The JAR file is on the classpath of a Java project, which is in turn used by my web app. Should I really be doing my Spring configuration in the web project as opposed the Java project, or does that matter?

If it needs to be in the classpath of your webapp, then you should stick the JAR containing the config file into your WEB-INF/lib directory.
If you're using a webapp, then the common convention is use a ContextLoaderListener to ensure a WebApplicationContext is inserted into a standard place in the ServletContext:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/com/config/resources.xml</param-value>
</context-param>
Then use WebApplicationContextUtils to fish the application context out of the servlet context using:
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());

I ran into a similar issue with a red5 plugin. I resolved it like so:
try {
subContext = new FileSystemXmlApplicationContext(new String[] { "classpath*:/myconfig.xml" }, true, context);
} catch (Exception fnfe) {
subContext = new FileSystemXmlApplicationContext(new String[] { "plugins/myconfig.xml" }, true, context);
}
This will look anywhere on the classpath first, including within the jar that contains my code. If an exception occurs the plugin directory is checked. It may not be the best solution but it works.

I don't really recall why this matters, but try putting an asterisk () in front of the colon (:) classpath:/ If this doesn't work, try the asterisk after the colon (classpath:*), although I think it was before the colon.

I've only used the <import> directive in J2SE and it works without the classpath: prefix, simply as <import resource="config/resources.xml" />. But in J2EE if all your files are inside WEB-INF, it should be similar, just import resource="bla.xml" and it should find it, although in J2EE you don't need to do this because in web.xml you can define several files in the contextConfigLocation context parameter inside web.xml, just separate them with spaces or newlines.

Related

java.io.FileNotFoundException: class path resource cannot be opened because it does not exist (even when kept in java folder) [duplicate]

I am trying to make my first bean in Spring but got a problem with loading a context.
I have a configuration XML file of the bean in src/main/resources.
I receive the following IOException:
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [src/main/resources/beans.xml]; nested exception is
java.io.FileNotFoundException: class path resource [src/main/resources/beans.xml] cannot
be opened because it does not exist
but I don't get it, since I do the following code test:
File f = new File("src/main/resources/beans.xml");
System.out.println("Exist test: " + f.exists());
which gives me true! resources is in the classpath. What's wrong?
Thanks, but that was not the solution. I found it out why it wasn't working for me.
Since I'd done a declaration:
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
I thought I would refer to root directory of the project when beans.xml file was there.
Then I put the configuration file to src/main/resources and changed initialization to:
ApplicationContext context = new ClassPathXmlApplicationContext("src/main/resources/beans.xml");
it still was an IO Exception.
Then the file was left in src/main/resources/ but I changed declaration to:
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
and it solved the problem - maybe it will be helpful for someone.
Edit:
Since I get many people thumbs up for the solution and had had first experience with Spring as student few years ago, I feel desire to explain shortly why it works.
When the project is being compiled and packaged, all the files and subdirs from 'src/main/java' in the project goes to the root directory of the packaged jar (the artifact we want to create). The same rule applies to 'src/main/resources'.
This is a convention respected by many tools like maven or sbt in process of building project (note: as a default configuration!). When code (from the post) was in running mode, it couldn't find nothing like "src/main/resources/beans.xml" due to the fact, that beans.xml was in the root of jar (copied to /beans.xml in created jar/ear/war).
When using ClassPathXmlApplicationContext, the proper location declaration for beans xml definitions, in this case, was "/beans.xml", since this is path where it belongs in jar and later on in classpath.
It can be verified by unpacking a jar with an archiver (i.e. rar) and see its content with the directories structure.
I would recommend reading articles about classpath as supplementary.
Try this:
new ClassPathXmlApplicationContext("file:src/main/resources/beans.xml");
file: preffix point to file system resources, not classpath.
file path can be relative or system (/home/user/Work/src...)
I also had a similar problem but because of a bit different cause so sharing here in case it can help anybody.
My file location
How I was using
ClassPathXmlApplicationContext("beans.xml");
There are two solutions
Take the beans.xml out of package and put in default package.
Specify package name while using it viz.
ClassPathXmlApplicationContext("com/mypackage/beans.xml");
src/main/resources is a source directory, you should not be referencing it directly. When you build/package the project the contents will be copied into the correct place for your classpath. You should then load it like this
new ClassPathXmlApplicationContext("beans.xml")
Or like this
new GenericXmlApplicationContext("classpath:beans.xml");
This is because applicationContect.xml or any_filename.XML is not placed under proper path.
Trouble shooting Steps
1: Add the XML file under the resource folder.
2: If you don't have a resource folder. Create one by navigating new by Right click on the project new > Source Folder, name it as resource and place your XML file under it.
use it
ApplicationContext context = new FileSystemXmlApplicationContext("Beans.xml");
You have looked at src directory. The xml file indeed exist there. But look at class or bin/build directory where all your output classes are set. I suspect you will need only resources/beans.xml path to use.
I suspect you're building a .war/.jar and consequently it's no longer a file, but a resource within that package. Try ClassLoader.getResourceAsStream(String path) instead.
Note that the first applicationContext is loaded as part of web.xml; which is mentioned with the below.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>META-INF/spring/applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>myOwn-controller</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>META-INF/spring/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Where as below code will also tries to create one more applicationContext.
private static final ApplicationContext context =
new ClassPathXmlApplicationContext("beans.xml");
See the difference between beans.xml and applicationContext.xml
And if appliationContext.xml under <META-INF/spring/> has declared with <import resource="beans.xml"/> then this appliationContext.xml is loading the beans.xml under the same location META-INF/spring of appliationContext.xml.
Where as; in the code; if it is declared like below
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
This is looking the beans.xml at WEB-INF/classes OR in eclipse src/main/resources.
[If you have added beans.xml at src/main/resources then it might be placed at WEB-INF/classes while creating the WAR.]
So totally TWO files are looked up.
I have resolved this issue by adding classpath lookup while importing at applicationContext.xml like below
<import resource="classpath*:beans.xml" />
and removed the the line ClassPathXmlApplicationContext("beans.xml") in java code, so that there will be only one ApplicationContext loaded.
In Spring all source files are inside src/main/java. Similarly, the resources are generally kept inside src/main/resources. So keep your spring configuration file inside resources folder.
Make sure you have the ClassPath entry for your files inside src/main/resources as well.
In .classpath check for the following 2 lines. If they are missing add them.
<classpathentry path="src/main/java" kind="src"/>
<classpathentry path="src/main/resources" kind="src" />
So, if you have everything in place the below code should work.
ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring-Module.xml");
Gradle : v4.10.3
IDE : IntelliJ
I was facing this issue when using gradle to run my build and test. Copying the applicationContext.xml all over the place did not help. Even specifying the complete path as below did not help !
context = new ClassPathXmlApplicationContext("C:\\...\\applicationContext.xml");
The solution (for gradle at least) lies in the way gradle processes resources. For my gradle project I had laid out the workspace as defined at https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_project_layout
When running a test using default gradle set of tasks includes a "processTestResources" step, which looks for test resources at C:\.....\src\test\resources (Gradle helpfully provides the complete path).
Your .properties file and applicationContext.xml need to be in this directory. If the resources directory is not present (as it was in my case), you need to create it copy the file(s) there. After this, simply specifying the file name worked just fine.
context = new ClassPathXmlApplicationContext("applicationContext.xml");
Beans.xml or file.XML is not placed under proper path. You should add the XML file under the resource folder, if you have a Maven project.
src -> main -> java -> resources
I did the opposite of most. I am using Force IDE Luna Java EE and I placed my Beans.xml file within the package; however, I preceded the Beans.xml string - for the ClassPathXMLApplicationContext argument - with the relative path. So in my main application - the one which accesses the Beans.xml file - I have:
ApplicationContext context =
new ClassPathXmlApplicationContext("com/tutorialspoin/Beans.xml");
I also noticed that as soon as I moved the Beans.xml file into the package from the src folder, there was a Bean image at the lower left side of the XML file icon which was not there when this xml file was outside the package. That is a good indicator in letting me know that now the beans xml file is accessible by ClassPathXMLAppllicationsContext.
This is what worked for me:
new ClassPathXmlApplicationContext("classpath:beans.xml");
If this problem is still flummoxing you and you are developing using Eclipse, have a look at this Eclipse bug: Resources files from "src/main/resources" are not correctly included in classpath
Solution seems to be look at properties of project, Java build path, source folders. Delete the /src/main/resources dir and add it again. This causes Eclipse to be reminded it needs to copy these files to the classpath.
This bug affected me when using the "Neon" release of Eclipse. (And was very frustrating until I realized the simple fix just described)
I was experiencing this issue and it was driving me nuts; I ultimately found the following lying in my POM.xml, which was the cause of the problem:
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
I was not sure to write it but maybe someone save a few hours:
mvn clean
may do the job if your whole configuration is already perfect!
I have stuck in this issue for a while and I have came to the following solution
Create an ApplicationContextAware class (which is a class that implements the ApplicationContextAware)
In ApplicationContextAware we have to implement the one method only
public void setApplicationContext(ApplicationContext context) throws BeansException
Tell the spring context about this new bean (I call it SpringContext)
bean id="springContext" class="packe.of.SpringContext" />
Here is the code snippet
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class SpringContext implements ApplicationContextAware {
private static ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
}
public static ApplicationContext getApplicationContext() {
return context;
}
}
Then you can call any method of application context outside the spring context for example
SomeServiceClassOrComponent utilityService SpringContext.getApplicationContext().getBean(SomeServiceClassOrComponent .class);
I hope this will solve the problem for many users
I am on IntelliJ and faced the same issue. Below is how i resolved it:
1. Added the resource import as following in Spring application class along with other imports: #ImportResource("applicationContext.xml")
2. Saw IDE showing : Cannot resolve file 'applicationContext.xml' and also suggesting paths where its expecting the file (It was not the resources where the file applicationContext.xml was originally kept)
3. Copied the file at the expected location and the Exception got resolved.
Screen shot below for easy ref:
But if you would like to keep it at resources then follow this great answer link below and add the resources path so that it gets searched. With this setting exception resolves without #ImportResource described in above steps:
https://stackoverflow.com/a/24843914/5916535
Sharing my case and how I debugged it, maybe helps someone:
this will only be relevant if you have first checked you actually have the resources folder in correct place and correctly named
create some temporary folder somewhere, preferably out of any git projects (e.g. mkdir playground) and move there (cd playground)
copy the java archive there (e.g. cp /path/to/java.war .) that is missing that beans.xml
unpack it (e.g. unzip java.war on ubuntu)
find if there's any .xml files in there (for example in WEB-INF/classes) (the unpacking process should show a list of files being unpacked, most of them will probably be other dependencies as archives, these are not relevant)
if you don't see a beans.xml, just read the other .xml files (e.g. cat root-config.xml), you might find something like root-config.xml there or similar, in there you might either have some other <import resource="somethingelse.xml"> records or nothing.
if this is the case, this means you do have that file (root-config.xml here) present in the project or if not, continue going up parent projects to where the archive is getting packaged from. Find that file, add <import resource="beans.xml"> and run mvn package.
Now verifying the fix by doing the steps in 1.-5. should result in that file (root-config.xml here) in the newly packaged archive having the beans.xml defined and once you deploy it, it should work.
Make sure that beans.xml is located in the resources folder.

How to specify a file path in web.xml file

i am developing an application in java and i am new to this java ee platform.I have a dataset file called "51Degrees-EnterpriseV3_2.dat" in my resource folder. how do i specify the path of this in my web.xml file and how do i retrieve the file in code?
In web.xml , you can add
<context-param>
<param-name>you can mention here localtion variable name</param-name>
<param-value>location here </param-value>
</context-param>
The other answer shows the correct way to add the parameter to your web.xml. Which for the 51Degrees V3.2 data file would look like this:
<context-param>
<description>The name of the device database.</description>
<param-name>BINARY_FILE_PATH</param-name>
<param-value>51Degrees-EnterpriseV3_2.dat</param-value>
</context-param>
As far as I know, there is not a way to get a resource which is located in the resources path (it's an XML file so the .getResource(name) method cannot be used). However, as you have a web.xml file, I assume this is a web project (i.e. .war rather than .jar)? If this is the case, then the WEB-INF directory is what you need. Files in here are also packaged up like resources, but can be more easily consumed by a .war package.
If you put your data file in src/main/webapp/WEB-INF/, which is used as the root by the web project. So the above XML example will work if the path to your data file is:
src/main/webapp/WEB-INF/51Degrees-EnterpriseV3_2.dat
As a sidenote, there is more documentation on configuring 51Degrees in a Java web app here

java.io.FileNotFoundException:for DispatcherServlet in WebApp

I have a program I'm running in a Spring project which always fails because of a java.io.FileNotFoundException, when it comes to locating the DispatcherServlet.
The DispatcherServlet lives in the \WEB-INF folder and is accessible to the rest of the project without incident.
So at the moment I'm forced to hardcode the path to the DispatcherServlet as follows:
File config = new File("C:\\project\\build\\web\\WEB-INF\\project-servlet.xml");
boolean exists = Misc.checkFileExists(config.getAbsolutePath());
if (exists) {
System.out.println("File: " + config.getAbsolutePath() + " found.");
}
ConfigurableApplicationContext context = new FileSystemXmlApplicationContext(config.getAbsolutePath());`
Which is not the best way at all.
But if I try to place the DispatcherServlet in a folder under \WEB-INF, e.g. \WEB-INF\resources to satisfy the CLASSPATH, the file is still not found. Because of this I can't use ClassPathXmlApplicationContext.
I have resolved this by setting my web.xml file as follows:
<servlet>
<servlet-name>project</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/project-servlet.xml</param-value>
</init-param>
</servlet>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/project-servlet.xml</param-value>
</context-param>
The application works as does the test program with:
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("project-servlet.xml");
I should add that I have a single project-servlet.xml file which configures everything.
The code makes no sense. ClassPathXmlApplicationContext, as its name indicates, is used to load an XML file from a classpath resource. But you're passing it the path of a file. Read the javadoc:
Standalone XML application context, taking the context definition files from the class path, interpreting plain paths as class path resource names that include the package path (e.g. "mypackage/myresource.txt")
What constitutes the classpath of a web application is the directory WEB-INF/classes, and all the jar files inside WEB-INF/lib. So, your XML file is not in the CLASSPATH, and can thus not be loaded using a ClassPathXmlApplicationContext.
If you want to load a context file from WEB-INF, use an XmlWebApplicationContext.
You should not have to do that manually anyway, since a Spring web application is typically configured using the web.xml file, or using JavaConfig, as explained in the documentation.

ClassPathXmlApplicationContext classpath notfound

I am newbie in Spring. I have problem with classpath as parameter of ClassPathXmlApplicationContext. I use Netbeans. The class where I use ClassPathXmlApplicationContext is in package cz.ryska.helloworld in Source Packages folder. Configuration XML file, name as Beans.xml is in WEB-INF folder.
But I don't know what way I can use. I try use f.e "WEB-INF\Beans.xml" or "/WEB-INF/Beans.xml" but file is not found. What way I can use or where I must move xml file?
Thanks
The project appears to be a J2EE web application, so you shouldn't need to create a new DI container with ClassPathXmlApplicationContext. Instead import beans.xml in your applicationContext.xml file, if it is already registered in web.xml.
In web.xml include:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
In applicationContext.xml include:
<import resource="Beans.xml"/>
This will cause the Beans.xml configuration to be added to the DI container.

Maven copying applicationContext.xml from src/main/resources to target/myproject/WEB-INF

At the moment, the default I think, it copies to
target/myproject/WEB-INF/classes
so when deploying it does not pick up the context.
Also, i want to reference a server specific config file database.properties, I want to put it in tomcat/conf and then reference it in applicationContext.xml, how can I do this ?
Also(2), I am under the impression that this is a fairly standard and decent way to set things up - please correct me if I am wrong.
edit
for the server specific config file I user this
<context:property-placeholder
location="file:${catalina.home}/conf/database.properties"
ignore-unresolvable="true"
/>
If you need to keep applicationContext.xml as a classpath resource, you can configure ContextLoaderListener to pick it from the classpath by adding the following lines to web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
It's much easier than configuring Maven to copy it to WEB-INF.
Regarding the second question, you can configure PropertyPlaceholderConfigurer or <context:property-placeholder> to load .properties file from a file system.
For your title question: Often in a .war maven module, you'll put web related resources under src/main/webapp instead of src/main/resources. Then the maven plugin will pick them up automatically because it matches convention. So, move your applicationContext.xml to src/main/webapp/WEB-INF
Another option is to configure the webResources as described in the documentation
For the second question you can look at a PropertyPlaceHolderConfigurer. You'll just have to get the path correct.

Categories

Resources