Where should I put my properties file for tests? - java

I have a properties file that I currently have in this folder:
/src/webapp/WEB-INF/classes/my.properties
I am loading it using:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream is = classLoader.getResourceAsStream("/my.properties");
Properties props = new Properties();
try {
props.load(is);
} catch (IOException e) {
e.printStackTrace();
}
String test = props.getProperty("test");
Now this works fine in my Spring mvc application.
But when I created a test for this, it fails and I am assuming because the way the application loads it is not using web-inf/classes since it is just a class and not a spring web app.
So where do I put my properties file so that when my junit tests run, the properties file is picked up?
Also, for my web app, what other folders are in the default class path other than /web-inf/classes ?

If you put my.properties under /src/test/resources in maven, it will be available as a normal resource to your tests.

I would remove the path (/) in classLoader.getResourceAsStream("/my.properties"); since the classloader starts in the root of the application. Keep the file in the same location as it is. Then change to
String filename = "my.properties";
InputStream is = classLoader.getResourceAsStream(filename); //for web-app
if(is == null)
is = new FileInputStream (filename); //for testing

Normally i put the property files directly in the src folder.

Related

No such file or directory when reading Properties File in Java from one Class but not another

I am trying to read a properties folder from this path with respect to the repository root:
rest/src/main/resources/cognito.properties
I have a Class CognitoData from this path: rest/src/main/java/com/bitorb/admin/webapp/security/cognito/CognitoData.java which loads the Properties folder using this code, and it runs fine:
new CognitoProperties().loadProperties("rest/src/main/resources/cognito.properties");
#Slf4j
public class CognitoProperties {
public Properties loadProperties(String fileName) {
Properties cognitoProperties = new Properties();
try {
#Cleanup
FileInputStream fileInputStream = new FileInputStream(fileName);
cognitoProperties.load(fileInputStream);
} catch (IOException e) {
log.error("Error occured. Exception message was [" + e.getMessage() + "]");
}
return cognitoProperties;
}
}
However, when I call CognitoData from a test class located in rest/src/test/java/com/bitorb/admin/webapp/security/cognito/CognitoServiceTest.java , I get this error:
[rest/src/main/resources/cognito.properties (No such file or directory)]
Can anybody shed light on why this is happening?
File directory is not actually relative in that case. You need to provide appropriate file path for this. If you are already using spring boot, then
you can change your code to:
// this will read file from the resource folder.
InputStream inputStream = getClass().getClassLoader()
.getResourceAsStream("cognito.properties");
cognitoProperties.load(inputStream);
Otherwise you need to provide the full absolute path. new CognitoProperties().loadProperties("/absolutepath/..../cognito.properties")
I don't know what you're using for testing, but I suspect that the working directory when you run tests is not the project root.
One solution is to use an absolute path instead:
/absolute/path/to/project/rest/src/main/resources/cognito.properties
Or maybe check what is the working directory during testing and see if it can be changed to the project root.

Is there a simpler way to read off *.jar or filesystem?

I've developed a simple app using Sparkjava. I'm using Intellij, and when I run my tests, or run the app locally, all my resources are files.
However, when I deploy, the whole thing runs as a jar file. As such, I need a way to read my resources off the filesystem or the jar, depending on how the app is launched. The following code gets the job done, but it looks clumsy:
String startedOffFile = new java.io.File(Main.class.getProtectionDomain()
.getCodeSource()
.getLocation()
.getPath())
.getName();
InputStream inputStream;
if(startedOffFile.endsWith(".jar")) {
ClassLoader cl = PropertiesParser.class.getClassLoader();
inputStream = cl.getResourceAsStream("myapp.dev.properties");
} else {
inputStream = new FileInputStream(filename);
}
Is there a cleaner/simpler way?
Have your main create this class to determine if your java executable has defined a config.location parameter or will look on the classpath.
eg. java -Dconfig.location=/here/myapp.dev.properties -jar youapp.jar
public class ApplicationProperties {
public ApplicationProperties() throws IOException {
final Properties properties = new Properties();
String location = getProperty("config.location")
if(location != null) {
properties.load(new FileInputStream(getProperty("config.location", ENV_PROPERTIES_PATH)));
} else {
properties.load(Classname.class.getClassLoader().getResourceAsStream("myapp.dev.properties"));
}
}
public Properties getProperties() {
return properties;
}
}
If you're using Maven with IntelliJ, just put the configuration properties file inside the src/main/resources directory in the module. If you're not using Maven then put the properties file in the root of your source tree (outside any package - like: src/myapp.dev.properties).
After packaging/exporting of the JAR the file will be accessible with new Object().getClass().getClassLoader().getResourceAsStream("myapp.dev.properties") (the new Object()... is used, because in some cases/platforms the static ClassLoader is not defined).
The same classpath is used by the IntelliJ/Eclipse environment, which means there is no need for a special case for loading the files.
If you need to differentiate between development and production properties. You can use Maven profiles for build time packaging or you can load the properties with a variable using the -D switch.

writing to file in maven project

Hi i am using maven web project and want to write something to file abc.properties. This file in placed in standard /src/main/resource folder. My code is:
FileWriter file = new FileWriter("./src/main/resources/abc.properties");
try {
file.write("hi i am good");
} catch (IOException e) {
e.printStackTrace();
} finally {
file.flush();
file.close();
}
But it does not work as path is not correct. I tried many other examples but was unable to give path of this file.
Can you kindly help me in setting path of file which is placed in resources folder.
Thanks
I think you're confusing buildtime and runtime. During buildtime you have your src/main/java, src/main/resources and src/main/webapp, but during runtime these are all bundled in a war-file. This means there's no such thing as src/main/resources anymore.
The easiest way is to write to a [tempFile][1] and write to that file. The best way is to configure your outputFile, for instance in the wqeb.xml.
[1]: http://docs.oracle.com/javase/6/docs/api/java/io/File.html#createTempFile(java.lang.String, java.lang.String)
If your file is dropped under src/main/resources, it will end up under your-webapp/WEB-INF/classes directory if you project is package as a Web application i.e. with maven-war-plugin.
At runtime, if you want to files that are located under the latter directory, which are considered as web application resources, thus are already present in the application classpath, you can use the getResourceAsStream() method either on the ServletContext or using the current class ClassLoader:
From current thread context:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream is = classLoader.getResourceAsStream("abc.properties");
FileWriter file = new FileWriter(new File(new FileInputStream(is)));
// some funny stuff goes here
If you have access to the Servlet context:
ServletContext context = getServletContext();
InputStream is = context.getResourceAsStream("/abc.properties");
FileWriter file = new FileWriter(new File(new FileInputStream(is)));
// some funny stuff goes here
Notice the leading slash in the latter example.

How do I reference a file that is placed in the WEB-INF folder when using Arquillian?

I am using maven and the standard directory layout. So I have added a testdata.xml file in the src/test/resources folder, and I also added it as:
.addAsWebInfResource("testdata.xml", "testdata.xml")
in the deployment method, and I have confirmed that it is there. This will make the file appear in /WEB-INF/testdata.xml. Now I need to have a reference to this file in my code and I tried several different getClass().getResourceAsStream(...) and failing again and again so I need some advise now.
I need it for my DBUnit integration test. Is this not possible?
Option A) Use ServletContext.getResourceXXX()
You should have a Aquillarian MockHttpSession and a MockServletContext. E.g.:
#Test
public void myTest()
{
HttpSession session = new MockHttpSession(new MockServletContext());
ServletLifecycle.beginSession(session);
..testCode..
// You can obtain a ServletContext (will actually be a MockServletContext
// implementation):
ServletContext sc = session.getServletContext();
URL url = sc.getResource("/WEB-INF/testdata.xml")
Path resPath = new Path(url);
File resFile = new File(url);
FileReader resRdr = new FileReader(resFile);
etc...
..testCode..
ServletLifecycle.endSession(session);
}
You can create resource files & subdirectories in:
the web module document root - resources are accessible from the browser and from classes
WEB-INF/classes/ - resources are accessible to classes
WEB-INF/lib/*.jar source jar - accessible to classes
WEB-INF/lib/*.jar dedicated resource-only jar - accessible to classes
WEB-INF/ directly within directory - accessible to classes. This is what you are asking for.
In all cases the resource can be accessed via:
URL url = sc.getResource("/<path from web doc root>/<resourceFileName>");
OR
InputStream resIS = sc.getResourceAsStream("/<path from web doc root>/<resourceFileName>");
>
These will be packaged into the WAR file and may be exploded into directories on the deployed app server OR they may stay within the WAR file on the app server. Either way - same behaviour for accessing resources: use ServletContext.getResourceXXX().
Note that as a general principle, (5) the top-level WEB-INF directory itself is intended for use by the server. It is 'polite' not to put your web resources directly in here or create your own directory directly in here. Instead, better to use (2) above.
JEE5 tutorial web modules
JEE6 tutorial web modules
Option B): Use Class.getResourceXXX()
First move the resource out of WEB-INF folder into WEB-INF/classes (or inside a jar WEB-INF/lib/*.jar).
If your test class is:
com.abc.pkg.test.MyTest in file WEB-INF/classes/com/abc/pkg/test/MyTest.class
And your resource file is
WEB-INF/classes/com/abc/pkg/test/resources/testdata.xml (or equivalent in a jar file)
Access File using Relative File Location, via the Java ClassLoader - finds Folders/Jars relative to Classpath:
java.net.URL resFileURL = MyTest.class.getResource("resources/testdata.xml");
File resFile = new File(fileURL);
OR
InputStream resFileIS =
MyTedy.class.getResourceAsStream("resources/testdata.xml");
Access File Using full Package-like Qualification, Using the Java ClassLoader - finds Folders/Jars relative to Classpath:
java.net.URL resFileURL = MyTest.class.getResource("/com/abc/pkg/test/resources/testdata.xml");
File resFile = new File(fileURL);
OR
InputStream resFileIS =
MyTest.class.getResourceAsStream("/com/abc/pkg/test/resources/testdata.xml");
OR
java.net.URL resFileURL = MyTest.class.getClassLoader().getResource("com/abc/pkg/test/resources/testdata.xml");
File resFile = new File(fileURL);
OR
InputStream resFileIS =
MyTest.class.getClassLoader().getResourceAsStream("com/abc/pkg/test/resources/testdata.xml");
Hope that nails it! #B)
The way to access files under WEB-INF is via three methods of ServletContext:
getResource("/WEB-INF/testdata.xml") gives you a URL
getResourceAsStream gives you an input stream
getRealPath gives you the path on disk of the relevant file.
The first two should always work, the third may fail if there is no direct correspondence between resource paths and files on disk, for example if your web application is being run directly from a WAR file rather than an unpacked directory structure.
Today I was struggling with the same requirement and haven't found any full source sample, so here I go with smallest self contained test I could put together:
#RunWith(Arquillian.class)
public class AttachResourceTest {
#Deployment
public static WebArchive createDeployment() {
WebArchive archive = ShrinkWrap.create(WebArchive.class).addPackages(true, "org.apache.commons.io")
.addAsWebInfResource("hello-kitty.png", "classes/hello-kitty.png");
System.out.println(archive.toString(true));
return archive;
}
#Test
public void attachCatTest() {
InputStream stream = getClass().getResourceAsStream("/hello-kitty.png");
byte[] bytes = null;
try {
bytes = IOUtils.toByteArray(stream);
} catch (IOException e) {
e.printStackTrace();
}
Assert.assertNotNull(bytes);
}
}
In your project hello-kitty.png file goes to src/test/resources. In the test archive it is packed into the /WEB-INF/classes folder which is on classpath and therefore you can load it with the same class loader the container used for your test scenario.
IOUtils is from apache commons-io.
Additional Note:
One thing that got me to scratch my head was related to spaces in path to my server and the way getResourceAsStream() escapes such special characters: sysLoader.getResource() problem in java
Add this class to your project:
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
public class Init {
private static final String WEB_INF_DIR_NAME="WEB-INF";
private static String web_inf_path;
public static String getWebInfPath() throws UnsupportedEncodingException {
if (web_inf_path == null) {
web_inf_path = URLDecoder.decode(Init.class.getProtectionDomain().getCodeSource().getLocation().getPath(), "UTF8");
web_inf_path=web_inf_path.substring(0,web_inf_path.lastIndexOf(WEB_INF_DIR_NAME)+WEB_INF_DIR_NAME.length());
}
return web_inf_path;
}
}
Now wherever you want to get the full path of the file "testdata.xml" use this or similar code:
String testdata_file_location = Init.getWebInfPath() + "/testdata.xml";

How to load a text file from a class inside my EAR file?

I have a Java EE 5 project in Eclipse (actually, IBM RAD 7) running on WebSphere 7.
The workspace projects are laid out like this:
webapp <-- produces a WAR file
webappEAR <-- produces the EAR file
webappEJB <-- holds the Service and DAO classes
webappJPA <-- holds the domain/entity classes
webappTests <-- holds the JUnit tests
In one of my Service classes (in the webappEJB project) I need to load a text file as a resource.
I placed my text file in folder:
webappEAR/emailTemplates/myEmailTemplate.txt
So it appears in the EAR file here:
webappEAR.EAR
/emailTemplates/myEmailTemplate.txt
In my service class this is how I load it:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("emailTemplates/myEmailTemplate.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(input));
/* and so on */
The problem is input is always null -- it can't find the resource.
I tried a leading slash ("/emailTemplates/myEmailTemplate.txt") but that didn't work either.
Any ideas what I'm doing wrong? Or a better way to do this?
Thanks!
Rob
The EAR file hierarchy/content is not on your classpath; Jar files packaged within your EAR file may be on a module's classpath, per configuration.
So package the resource into any of the JAR files already on the classpath of of the module containing your "service class".
It's not unreasonable to create a new JAR for resources, particularly if you'll be updating them independently.
That code seems ok, in JBoss that works as a charm. It may happen that the class loader form the Thread class has a different classpath than the ear file.
Did you try using the same class you are coding to load the resource?
Try something like this:
ClassInsideEar.class.getResourceAsStream("/emailTemplates/myEmailTemplate.txt");
You may also try placing the folder inside the war or jar (EJB) to narrow down the issue.
I used this code for loading resources from ear.
Path is folder/file. Location of file is resources/folder/file.
private InputStream loadContent(String path) {
final String resourceName = path;
final ClassLoader classLoader = getClass().getClassLoader();
InputStream stream = null;
try {
stream = AccessController.doPrivileged(
new PrivilegedExceptionAction<InputStream>() {
public InputStream run() throws IOException {
InputStream is = null;
URL url = classLoader.getResource(resourceName);
if (url != null) {
URLConnection connection = url.openConnection();
if (connection != null) {
connection.setUseCaches(false);
is = connection.getInputStream();
}
}
return is;
}
});
} catch (PrivilegedActionException e) {
e.printStackTrace();
}
return stream;
}

Categories