Accessing and manipulating resource files in Maven project - java

I know that there already are many questions on this topic, but none of them seem to help. In my Maven Project I am trying to access the src/main/resource files, and i know that during runtime when I want to read a file and write to it i must access its class path or something.
I am really not sure how that works, I managed to write code to read from a file, but I don't know how to write code that writes to a file. Here it is what i have so far:
private File userFile;
private ObjectMapper om;
private InputStream is;
public UserService() {
om = new ObjectMapper();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
is = classLoader.getResourceAsStream("files/userJSON.json");
}
This constructor represents the UserService class which methods I use to access User Resoruces located in userJSON.json file. Here is a method I use for reading a file:
public List<User> readJSON() throws JsonParseException, JsonMappingException, IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(is));
List<User> list = om.readValue(br,new TypeReference<List<User>>(){});
return list;
}
How can I write to a file, and if possible to explain to me how this works. By that I mean how does Maven work with files during runtime and so on.

Just call this method it will read the file and convert it to JSONObject:
private static JSONObject readUserJSON() throws FileNotFoundException, IOException, ParseException {
String jarPath = (new File("")).getAbsolutePath();
JSONObject config = null;
JSONParser parser = new JSONParser();
config = (JSONObject) parser.parse(new FileReader(jarPath + "resource/files/userJSON.json"));
return config;
}
ADD this dependency in .pom file:
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple example</artifactId>
<version>1.1.1</version>
</dependency>
Using below statement you get Absolute path of file and you can write it using file writer :
String jarPath = (new File("")).getAbsolutePath();

Related

How do I make json file in src/main/resources/ accessable when spring application is hosted in a docker container?

I'm trying to read a json file that is located under src/main/resources, this works just fine locally but after having built docker-image the same code reports "IOException - File not found" when it's deployed.
Here is the code attempting to load in the class:
#Component
public class KontorAdmin {
List<KontorInfo> kontorer;
String filePath = "./src/main/resources/kontortoggle.json";
public KontorAdmin() throws IOException {
initKontor();
}
public void initKontor() throws IOException {
File file = new File(filePath);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
KontorWrapper kontorWrapper = objectMapper.readValue(file, KontorWrapper.class);
this.kontorer = kontorWrapper.getKontorer();
}
Here is the dockerfile:
FROM openjdk:11
VOLUME /tmp
ADD target/rek-service.jar rek-service.jar
EXPOSE 80:80
ENTRYPOINT ["java","-jar","rek-service.jar"]
I'm thinking I could ADD the file to docker, but how do I then make it pass unit tests locally which expects a different path to file?
Thanks for any help
Actually, the resource file is in your classpath.
You should try reading like this,
File file = ResourceUtils.getFile("classpath:kontortoggle.json");
or
File file = new File(getClass().getResource("kontortoggle.json").getFile());
You problem is your file access. When building the jar, your json file is moved as part of the jar file. Therefor you never may find this file by a simple file access by its name. Your resource json file is part of the rek-service.jar file. You have multiple opportunities to access this file.
In your use case you are using an fasterxml object mapper. This can be used with files or streams. I would suggest to use a stream by this code:
#Component
public class KontorAdmin {
List<KontorInfo> kontorer;
public KontorAdmin() throws IOException {
initKontor();
}
public void initKontor() throws IOException {
InputStream is = getClass().getResourceAsStream("kontortoggle.json");
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
KontorWrapper kontorWrapper = objectMapper.readValue(is, KontorWrapper.class);
this.kontorer = kontorWrapper.getKontorer();
}
But by the #Component annotation I suspect, that you are using spring. With Spring this is much easier to get the InputStream or File from class path. Then you should take a look at the ClassPathResource or the ResourceUtils. The ResourceUtils seems to be for internal use by JavaDoc, but anyone is using them in Spring.
new ClassPathResource("data/employees.dat", this.getClass().getClassLoader());
ResourceUtils.getFile("classpath:kontortoggle.json");
#Component
public class KontorAdmin {
List<KontorInfo> kontorer;
public KontorAdmin() throws IOException {
initKontor();
}
public void initKontor() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
KontorWrapper kontorWrapper = objectMapper.readValue(ResourceUtils.getFile("classpath:kontortoggle.json"), KontorWrapper.class);
this.kontorer = kontorWrapper.getKontorer();
}

How to get a File or Stream from a JSONObject?

How is a JSONObject from Twitter4J converted to an IOFile for use with the JsonParser from BaseX?
So, looking to use Twitter4J to get either a file or stream.
The JsonParser looks to work with a File fine:
JsonParser
public JsonParser(IO source,
MainOptions opts,
JsonParserOptions jopts)
throws java.io.IOException
Constructor.
Parameters:
source - document source
opts - database options
jopts - parser options
Throws:
java.io.IOException - I/O exception
although other IO works:
org.basex.io
Class IO
java.lang.Object
org.basex.io.IO
Direct Known Subclasses:
IOContent, IOFile, IOStream, IOUrl
How is a File acquired from a JSONObject here?
Snippet using Twitter4J:
private JSONObject jsonOps(Status status) throws JSONException, BaseXException {
String string = TwitterObjectFactory.getRawJSON(status);
JSONObject json = new JSONObject(string);
String language = json.getString("lang");
log.fine(language);
return json;
}
Writing a JSONObject to file file from Twitter4J seems to work, at least the file looks correct when opened manually:
public void writeJsonToFile(String fileName) throws FileNotFoundException, UnsupportedEncodingException, IOException {
FileOutputStream fileOutputStream = null;
OutputStreamWriter outputStreamWriter = null;
BufferedWriter bufferedWriter = null;
fileOutputStream = new FileOutputStream(fileName);
outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
bufferedWriter = new BufferedWriter(outputStreamWriter);
bufferedWriter.write(tweets.toString());
bufferedWriter.close();
outputStreamWriter.close();
fileOutputStream.close();
}
And once the file is written, it seems quite easy to "parse" the JSON, or at least instantiate a parser, as:
private void parseJsonFile(String fileName) throws IOException {
JsonParser jsonParser = new JsonParser(new IOFile(fileName), new MainOptions());
}
full code on github.
In no way is this a complete solution. In fact, it seems a kludge to write the JSON to a file at all -- but there it is.
Seems the only way to move JSON data from Twitter4J to BaseX, or at least most pragmatic. Other solutions appreciated.

How to get Maven to read a file from my resources folder

I have been happily using JUnit to run my tests and everything has been fine.
However, I now need to use Maven but for some reason it cannot find any of my resource files.
The files are in the expected place: src/main/resources
I am using the following code to try to read a file:
public Map<String, String> readCsv(String filename) {
Map<String, String> headersAsMap;
CSVDataManipulator csvDataManipulator = new CSVDataManipulator();
ClassLoader classLoader = getClass().getClassLoader();
String wrkbook = new File(classLoader.getResource(filename).getFile()).toString();
headersAsMap = csvDataManipulator.getAllRecordsAsMap(wrkbook);
return headersAsMap;
}
However, try as I might it cannot find the file.
I've tried lots of different code and tried moving the files to different locations but I cannot get Maven to find my resource files.
Any help would be greatly appreciated!
Thanks
To my understanding classLoader.getResource(..) expects the file to be in a folder structure matching the package of the class. So if the package of your class is com.matt.stuff, then you'll have to put the csv file in src/main/resources/com/matt/stuff.
Or you could just use this to grab your csv file:
private static String readFile(String fileName) throws IOException {
//filename can be src/main/resources/my-csv.csv
return new String(Files.readAllBytes(Paths.get(fileName)));
}
A File is indeed a file on the file system. For a resource which might be a file zipped in a jar, and has a path on the class path, you need something else.
Traditionally one would use a more general InputStream instead of a File.
InputStream in = getClass().getResourceAsStream("/.../x.csv"); // Path on the class path
With the new class Path, more general than File, you can deal with several (virtual) file systems:
URL url = getClass().getResource("/.../x.csv"); // Path on the class path
Path path = Paths.get(url.toURI());
Files.copy(path, Paths.get("..."));
With a bit of luck your CSVManipulator should besides being parametrized with a File, also with an InputStream or Reader (new InputStreamReader(in, "UTF-8"))
Here's my file structure of a Maven project built from the quick-start-archetype, with comons-io added as a dependency:
src
src/main
src/main/java
src/main/java/com
src/main/java/com/essexboy
src/main/java/com/essexboy/App.java
src/main/resources
src/main/resources/dir1
src/main/resources/dir1/test.txt
src/main/resources/dir2
src/main/resources/dir2/test.txt
src/main/resources/test.txt
src/test
src/test/java
src/test/java/com
src/test/java/com/essexboy
src/test/java/com/essexboy/AppTest.java
Here's my test
public class AppTest {
#Test
public void shouldAnswerWithTrue() throws Exception {
StringWriter writer = new StringWriter();
IOUtils.copy(getClass().getResourceAsStream("/test.txt"), writer, Charset.defaultCharset());
assertEquals("from root", writer.toString().trim());
writer = new StringWriter();
IOUtils.copy(getClass().getResourceAsStream("/dir1/test.txt"), writer, Charset.defaultCharset());
assertEquals("from dir1", writer.toString().trim());
writer = new StringWriter();
IOUtils.copy(getClass().getResourceAsStream("/dir2/test.txt"), writer, Charset.defaultCharset());
assertEquals("from dir2", writer.toString().trim());
}
}

Convert JSON to ORC using orc-tools

I am trying to convert JSON file using the orc tools jar mentioned on
https://orc.apache.org/docs/tools.html#java-orc-tools
I have imported this in my pom.xml
<dependency>
<groupId>org.apache.orc</groupId>
<artifactId>orc-tools</artifactId>
<version>1.3.1</version>
</dependency>
However, after the import, I am unable to see/import the class org.apache.orc.tools.json.JsonSchemaFinder which is used to infer the schema from JSON files.
Example using the above class can be seen in this commit.
https://github.com/apache/orc/pull/95/commits/2ee0be7e60e7ca77f574110ba1babfa2a8e93f3f
Am I using the wrong jar here?
This is scheduled to release in 1.4.0 version of ORC. Current version 1.3.x doesnt include these features.
You can still get the ORC git branch, copy out the org.apache.orc.tools.convert and org.apache.orc.tools.json to your repo and use these features. Alternatively, you can also make a jar from the ORC repo and use it too.
public static void main(Configuration conf,
String[] args) throws IOException, ParseException {
CommandLine opts = parseOptions(args);
TypeDescription schema;
if (opts.hasOption('s')) {
schema = TypeDescription.fromString(opts.getOptionValue('s'));
} else {
schema = computeSchema(opts.getArgs());
}
String outFilename = opts.hasOption('o')
? opts.getOptionValue('o') : "output.orc";
Writer writer = OrcFile.createWriter(new Path(outFilename),
OrcFile.writerOptions(conf).setSchema(schema));
VectorizedRowBatch batch = schema.createRowBatch();
for (String file: opts.getArgs()) {
System.err.println("Processing " + file);
RecordReader reader = new JsonReader(new Path(file), schema, conf);
while (reader.nextBatch(batch)) {
writer.addRowBatch(batch);
}
reader.close();
}
writer.close();
}

How to get files from resources folder. Spring Framework

I'm trying to unmarshal my xml file:
public Object convertFromXMLToObject(String xmlfile) throws IOException {
FileInputStream is = null;
File file = new File(String.valueOf(this.getClass().getResource("xmlToParse/companies.xml")));
try {
is = new FileInputStream(file);
return getUnmarshaller().unmarshal(new StreamSource(is));
} finally {
if (is != null) {
is.close();
}
}
}
But I get this errors:
java.io.FileNotFoundException: null (No such file or directory)
Here is my structure:
Why I can't get files from resources folder? Thanks.
Update.
After refactoring,
URL url = this.getClass().getResource("/xmlToParse/companies.xml");
File file = new File(url.getPath());
I can see an error more clearly:
java.io.FileNotFoundException: /content/ROOT.war/WEB-INF/classes/xmlToParse/companies.xml (No such file or directory)
It tries to find WEB-INF/classes/
I have added folder there, but still get this error :(
I had the same problem trying to load some XML files into my test classes. If you use Spring, as one can suggest from your question, the easiest way is to use org.springframework.core.io.Resource - the one Raphael Roth already mentioned.
The code is really straight forward. Just declare a field of the type org.springframework.core.io.Resource and annotate it with org.springframework.beans.factory.annotation.Value - like that:
#Value(value = "classpath:xmlToParse/companies.xml")
private Resource companiesXml;
To obtain the needed InputStream, just call
companiesXml.getInputStream()
and you should be okay :)
But forgive me, I have to ask one thing: Why do you want to implement a XML parser with the help of Spring? There are plenty build in :) E.g. for web services there are very good solutions that marshall your XMLs into Java Objects and back...
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("fileName").getFile());
you are suppose to give an absolute path (so add a loading ´/´, where resource-folder is the root-folder):
public Object convertFromXMLToObject(String xmlfile) throws IOException {
FileInputStream is = null;
File file = new File(String.valueOf(this.getClass().getResource("/xmlToParse/companies.xml")));
try {
is = new FileInputStream(file);
return getUnmarshaller().unmarshal(new StreamSource(is));
} finally {
if (is != null) {
is.close();
}
}
}

Categories