How to read resource file from unit test? - java

I have a Java-only module in my Android project. In that project I want to have a unit test that reads the contents from a local json file that is stored in the resources folder. Android Studio changes the icon of the resources folder, so I'd think it recognises it as the resources folder.
How I'm reading:
String json = Files.lines(Paths.get("file.json"))
.parallel()
.collect(Collectors.joining());
folder structure:
+project
+app (android)
+module (java only)
+src
+main
+java
+package
-the java file
+resources
-file.json
My question is how can I read the file?
updated below
URL resource1 = getClass().getResource("file.json");
URL resource2 = getClass().getClassLoader().getResource("file.json");
URL resource3 = Thread.currentThread().getContextClassLoader().getResource("file.json");
URL resource4 = ClassLoader.getSystemClassLoader().getResource("file.json");
All these are null.
I've copied the json file to resources/same.package.structure too, but to no success.

Don't need to do all this complicated stuff with ClassLoaders. You have access to test/resources directory from you /test/* classes.
UPD
This is how to deserialize file using its path using SimpleXML. So here source method param is your path to resource file

you should using Paths.get(URI) instead, for example:
ClassLoader loader = ClassLoader.getSystemClassLoader();
String json = Files.lines(Paths.get(loader.getResource("file.json").toURI()))
.parallel()
.collect(Collectors.joining());
this is because you run your tests in android platform, and the resoruces were packaged in a jar, please using BufferedReader.lines instead, for example:
ClassLoader loader = activity.getClassLoader();
BufferedReader in = new BufferedReader(new InputStreamReader(
loader.getResourceAsStream("file.json"),"UTF-8"
));
String json = in.lines()
.parallel()
.collect(Collectors.joining());

Apparently it was a bug, should be fixed now:
https://issuetracker.google.com/issues/63612779
Thank you all for your help

Related

JUnit5: create new file in build directory

I have a Spring Boot application that provides Open API specification by /api/open-api/v3 path. The idea is that I request the Open API JSON during test running and then write its content to the file in build folder. So, I could parse it later and generate documentation. I tried to do it like this:
Files.writeString(Path.of("src", "test", "resources", "open-api.json"), res.getBody());
It did write the the file to the src/test/resources folder but in the source code module itself. Not the result build folder. Is it possible to overcome this issue?
#Test
#DisplayName("Create a file on the build diretory")
void createFileOnBuildDir() throws IOException {
final URL buildRoot = getClass().getResource("/");
final Path jsonFile = Path.of(buildRoot.getPath(), "open-api.json");
Files.writeString(jsonFile, "{\"value\": 123}");
System.out.println(jsonFile);
}
result
/home/myuser/projects/testproject/build/classes/java/test/open-api.json
$ cat /home/myuser/projects/testproject/build/classes/java/test/open-api.json
{"value": 123}
But, I guess the best answer for your need is https://github.com/Swagger2Markup/spring-swagger2markup-demo project's https://github.com/Swagger2Markup/spring-swagger2markup-demo/blob/master/src/test/java/io/github/robwin/swagger2markup/petstore/Swagger2MarkupTest.java

Deployed WAR can't access a file

I have a spring application, and i'm trying to access a json file with the following code :
try (FileReader reader = new FileReader("parameters.json")) {
Object obj = jsonParser.parse(reader);
parameterList = (JSONArray) obj;
}
I have put the parameter.json file in the project folder and I'm accesing the file data from an angular app through a rest api, and that works fine when I run the application on local machine, but when I deploy the war file on tomcat, my application can't load the file, should I put parameter.json file somewhere else on tomcat or what is the best solution for it.
Your question states you are attempting to access a file called parameter.json, while your code excerpt shows parameters.json. Perhaps that discrepancy indicates a typo in your source code?
If not, there are various ways to access a file from the classpath in Spring, with the first step for each being to ensure the file is in the project's src/main/resources directory.
You can then use one of the Spring utility classes ClassPathResource, ResourceLoader or ResourceUtils to get to the file. The easiest approach, though, may be to put your properties in a .properties file (default file name application.properties) and access the values using Spring's #Value annotation:
#Value("${some.value.in.the.file}")
private String myValue;
You can use other file names as well by utilizing #PropertySource:
#Configuration
#PropertySource(value = {"classpath:application.properties",
"classpath:other.properties"})
public class MyClass {
#Value("${some.value.in.the.file}")
private String myValue;
...
}
Make sure your parameters.josn filename is exactly same in the code.
Move you parameters.json file in the resources folder and then use the classpath with the filename.
try (FileReader reader = new FileReader("classpath:parameters.json")) {
Object obj = jsonParser.parse(reader);
parameterList = (JSONArray) obj;
}
Try to put the file under resources folder in your spring project. You should be able to access the file from that location.
FileReader is looking for a full-fledged file system like the one on your computer, but when your WAR is deployed, there just isn't one, so you have to use a different approach. You can grab your file directly from your src/main/resources folder like this
InputStream inputStream = getClass().getResourceAsStream("/parameters.json");

Java: Getting resource path of the main app instead of jar's

A lot has been discussed already here about getting a resource.
If there is already a solution - please point me to it because I couldn't find.
I have a program which uses several jars.
To one of the jars I added a properties file under main/resources folder.
I've added the following method to the jar project in order to to read it:
public void loadAppPropertiesFile() {
try {
Properties prop = new Properties();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String resourcePath = this.getClass().getClassLoader().getResource("").getPath();
InputStream stream = loader.getResourceAsStream(resourcePath + "\\entities.properties");
prop.load(stream);
String default_ssl = prop.getProperty("default_ssl");
}catch (Exception e){
}
}
The problem (?) is that resourcePath gives me a path to the target\test-clasess but under the calling application directory although the loading code exists in the jar!
This the jar content:
The jar is added to the main project by maven dependency.
How can I overcome this state and read the jar resource file?
Thanks!
I would suggest using the classloader used to load the class, not the context classloader.
Then, you have two options to get at a resource at the root of the jar file:
Use Class.getResourceAsStream, passing in an absolute path (leading /)
Use ClassLoader.getResourceAsStream, passing in a relative path (just "entities.properties")
So either of:
InputStream stream = getClass().getResourceAsStream("/entities.properties");
InputStream stream = getClass().getClassLoader().getResourceAsStream("entities.properties");
Personally I'd use the first option as it's briefer and just as clear.
Can you try this:
InputStream stream = getClass().getClassLoader().getResourceAsStream("entities.properties")

Using getResourceAsStream after build isn't working?

In my Java project in netbeans I get a text files contents to populate some internal data structure using this:
InputStream PFile = this.getClass().getResourceAsStream("../../IISP Details/IISP.txt"); // Get File to create IISP's
String[] PStringArray = new Scanner(PFile, "UTF-8").useDelimiter("\\A").next().split("\\r?\\n");
But when I clean and build my project it isn't working.
Ideas?
Edit:
More info...
The code is called in the cs.analyser.gui.master package in the 'loadMaster' class.
The file is in cs.analyser.IISPDetails.
I can tell that it's not finding the file - are there any alternatives? Or anyways to make the file get bundled with it when I build it?
Try this
InputStream PFile = this.getClass().getResourceAsStream("IISP.txt"); // Get File to create IISP's
String[] PStringArray = new Scanner(PFile, "UTF-8").useDelimiter("\\A").next().split("\\r?\\n");
and add the IISP.txt to a location that it is in the CLASSPATH.
Don't know about classpath? http://docs.oracle.com/javase/tutorial/essential/environment/paths.html

How can I get real path for file in my WebContent folder?

I need to get real path for file in my WebContent directory, so that framework that I use can access that file. It only takes String file as attribute, so I need to get the real path to this file in WebContent directory.
I use Spring Framework, so solution should be possible to make in Spring.
If you need this in a servlet then use getServletContext().getRealPath("/filepathInContext")!
getServletContext().getRealPath("") - This way will not work if content is being made available from a .war archive. getServletContext() will be null.
In this case we can use another way to get real path. This is example of getting a path to a properties file C:/Program Files/Tomcat 6/webapps/myapp/WEB-INF/classes/somefile.properties:
// URL returned "/C:/Program%20Files/Tomcat%206.0/webapps/myapp/WEB-INF/classes/"
URL r = this.getClass().getResource("/");
// path decoded "/C:/Program Files/Tomcat 6.0/webapps/myapp/WEB-INF/classes/"
String decoded = URLDecoder.decode(r.getFile(), "UTF-8");
if (decoded.startsWith("/")) {
// path "C:/Program Files/Tomcat 6.0/webapps/myapp/WEB-INF/classes/"
decoded = decoded.replaceFirst("/", "");
}
File f = new File(decoded, "somefile.properties");
you must tell java to change the path from your pc into your java project so
if you use spring use :
#Autowired
ServletContext c;
String UPLOAD_FOLDEdR=c.getRealPath("/images");
but if you use servlets just use
String UPLOAD_FOLDEdR = ServletContext.getRealPath("/images");
so the path will be /webapp/images/ :)
In situations like these I tend to extract the content I need as a resource (MyClass.getClass().getResourceAsStream()), write it as a file to a temporary location and use this file for the other call.
This way I don't have to bother with content that is only contained in jars or is located somewhere depending on the web container I'm currently using.
Include the request as a parameter. Spring will then pass the request object when it calls the mapped method
#RequestMapping .....
public String myMethod(HttpServletRequest request) {
String realPath = request.getRealPath("/somefile.txt");
...
You could use the Spring Resource interface (and especially the ServletContextResource): http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/core/io/Resource.html
This approach uses the resource loader to get the absolute path to a file in your app, and then goes up a few folders to the app's root folder. No servlet context required! This should work if you have a "web.xml" in your WEB-INF folder. Note that you may want to consider using this solely for development, as this type of configuration is usually best stored externally from the app.
public String getAppPath()
{
java.net.URL r = this.getClass().getClassLoader().getResource("web.xml");
String filePath = r.getFile();
String result = new File(new File(new File(filePath).getParent()).getParent()).getParent();
if (! filePath.contains("WEB-INF"))
{
// Assume we need to add the "WebContent" folder if using Jetty.
result = FilenameUtils.concat(result, "WebContent");
}
return result;
}
my solve for: ..../webapps/mydir/ (..../webapps/ROOT/../mydir/)
String dir = request.getSession().getServletContext().getRealPath("/")+"/../mydir";
Files.createDirectories(Paths.get(dir));
try to use this when you want to use arff.txt in your development and production level too
String path=getServletContext().getRealPath("/WEB-INF/files/arff.txt");

Categories

Resources