I have a code that deals with elasticsearch index. One of its steps, the program needs to read a jsonschema file in order to continue its execution. The code works well on my machine, but when I execute it as jar file inside a docker container, it gives me the following error:
java.io.FileNotFoundException: dm.jsonschema (No such file or directory)
the code that loads the schema is:
public class loadSchema {
private static final String JSON_SCHEMA_DOCUMENT = "dm.jsonschema";
....
public static JsonSchema tryLoadJSONSchema() {
JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
JsonNode cdmSchema = null;
try {
cdmSchema = JsonLoader.fromPath(JSON_SCHEMA_DOCUMENT);
} catch (IOException e) {
System.out.println(e);
System.exit(-1);
}
I placed the jsonschema file next to the jar file in the container, but it keeps giving me the same error. Any idea how to solve this problem?
The relative path of the File is resolved from wherever you are starting the java executable (mind the user.home), not from where the jar archive was located.
The best approach would be externalising this file location using a system property. For example if you define a jsonSchemaPath property:
String path = Sytem.getProperty("jsonSchemaPath");
JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
JsonNode cdmSchema = JsonLoader.fromPath(path);
Then you can change it in the java command:
java -jar yourcode.jar -DjsonSchemaPath=/path/to/dm.jsonschema
Related
I am trying to load and validate xml files from a directory in the class path at startup of a Spring Boot application. I am seeing the following error which indicates that I am trying to load files using absolute path and not class path:
java.io.FileNotFoundException: class path resource [converters/mapper.xml] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/opt/core/home/libexec/boss/core-service-2.0.0.jar!/BOOT-INF/lib/core-api-2.0.0.jar!/converters/mapper.xml
Below is a code snippet that loads the files:
..
#Autowired
public FieldsMapTypeConvertersRegistry(#Value("${core.files-location:converters}")
String mapperFilesLocation) {
this.mapperFilesLocation = mapperFilesLocation;
}
..
try {
// ToDo we need to replace this when we enable multi-tenancy
ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(classLoader);
Resource[] xmlResources = resolver.getResources(mapperFilesLocation + "/*.xml");
for (Resource xmlResource : xmlResources) {
File file = ResourceUtils.getFile(xmlResource.getURL());
registerTypeConverter(file);
}
} catch (IOException e) {
// do stuff
} catch (JAXBException e) {
//do stuff
}
I think the issue is in this statement in the code above:
File file = ResourceUtils.getFile(xmlResource.getURL());
but I am not sure what other ways I can do that. Any help is really appreciated.
I'm just wondering why you are using ResourceUtils.getFile(xmlResource.getURL()) when xmlResource.getFile() is already available to get the File Handle. Ideally speaking, you should be catching the FileNotFoundException inside the catch block and checking the detailed message wrapped inside the exception.
Edit:
The exception is being thrown because the xml is not found in classpath at runtime. Most probably, the file target/converters/mapper.xml is not available.
Try something like this MyService.class.getClassLoader().getResourceAsStream("/file.xml"); and then create File from stream.
Try using commons-io:commons-io:2.7 (Maven artifact) and use the following code:
InputStream inputStream = obj.getClass()
.getClassLoader()
.getResourceAsStream("converters/mapper.xml");
String data = IOUtils.toString(inputStream, "UTF-8");
With reference to the link: How do I read a resource file from a Java jar file?
I am trying using your code base and trying to read content of sample.csv which is residing in my project directory src/main/resources. I am unable to read the content, it says can not read file. Output:
[Can not read file: sample.csv]
//This is added within your while loop after this check /* If it is a directory, then skip it. */
I mean when file is detected then next is my below code snippet added to read the file content
if(entry.getName().contains("sample.csv")) {
File f1 = new File("sample.csv");
if(f1.canRead()) {
List<String> lines = Files.readAllLines(f1.toPath());
System.out.println("Lines in file: "+lines.size());
} else {
System.out.println("Can not read file: "+entry.getName());
}
}
Can anyone educate me what I am doing wrong here, how can I make it working?
My requirement is this:
(My micro-service) Service.jar imports Parser.jar library in its pom.xml
(My library) - Parser.jar has FnmaUtils-3.2-fieldMapping.csv file in src/main/resources directory
There is a FnmaUtils class that loads the FnmaUtils-3.2-fieldMapping.csv within its constructor, this class is part of Parser.jar - Here I am trying to read the content FnmaUtils-3.2-fieldMapping.csv, this step is keep failing with below error, tried all possible options shown in [How do I read a resource file from a Java jar file?
public FnmaUtils() {
String mappingFileUrl = null;
try {
Resource resource = new ClassPathResource("FnmaUtils-3.2-fieldMapping.csv");
mappingFileUrl = resource.getFile().getPath();
loadFnmaTemplate(mappingFileUrl);
} catch (Exception e) {
e.printStackTrace();
LOGGER.error("Error loading fnma template file ", e);
}
}
Getting error:
java.io.FileNotFoundException: class path resource [`FnmaUtils-3.2-fieldMapping.csv`] cannot be resolved to absolute file path because it does not reside in the file system: `jar:file:/home/ravibeli/.m2/repository/com/xxx/mismo/util/fnma-parser32/2018.1.0.0-SNAPSHOT/fnma-parser32-2018.1.0.0-SNAPSHOT.jar!/FnmaUtils-3.2-fieldMapping.csv`
at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:218)
at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:52)
at com.xxx.fnma.util.FannieMaeUtils.<init>(FannieMaeUtils.java:41)
at com.xxx.fnma.processor.FNMA32Processor.<init>(FNMA32Processor.java:54)
at com.xxx.fnma.processor.FNMA32Processor.<clinit>(FNMA32Processor.java:43)
What is going wrong here?
Try
InputStream in = this.getClass().getClassLoader()
.getResourceAsStream("SomeTextFile.txt");
Be sure the resource is in your classpath.
I need to catch some directory within the application. For that I have a small demonstration:
String pkgName = TestClass.class.getPackage().getName();
String relPath = pkgName.replace(".", "/");
URL resource = ClassLoader.getSystemClassLoader().getResource(relPath);
File file = new File(resource.getPath());
System.out.println("Dir exists:" + file.exists());
While running application from IDE I receive my goal and I can find my directory. But running application as JAR file, does not return a valid "file" (from Javas perspective) and my sout gives me back File exists:false. Is there some way to get this file? In this case, the file is a directory.
Java ClassPath is an abstraction that differs from a filesystem abstraction.
A classpath element may exist in two physical ways:
exploded with classpath pointing to the root directory
packed in a JAR archive
Unfortunatelly, the file.getPath does return a File object if classpath is pointing to file system but it does not if you refer to a JAR file.
In 99% of all cases you should read the contents of a resource using InputStream.
Here is a snippet, that uses IOUtils from apache commons-io to load the whole file content into a String.
public static String readResource(final String classpathResource) {
try {
final InputStream is = TestClass.class.getResourceAsStream(classpathResource);
// TODO verify is != null
final String content = IOUtils.toString(
is, StandardCharsets.UTF_8);
return content;
} catch (final IOException e) {
throw new UncheckedIOException(e);
}
}
My project structure looks like below. I do not want to include the config file as a resource, but instead read it at runtime so that we can simply change settings without having to recompile and deploy. my problem are two things
reading the file just isn't working despite various ways i have tried (see current implementation below i am trying)
When using gradle, do i needto tell it how to build/or deploy the file and where? I think that may be part of the problem..that the config file is not getting deployed when doing a gradle build or trying to debug in Eclipse.
My project structure:
myproj\
\src
\main
\config
\com\my_app1\
config.dev.properties
config.qa.properties
\java
\com\myapp1\
\model\
\service\
\util\
Config.java
\test
Config.java:
public Config(){
try {
String configPath = "/config.dev.properties"; //TODO: pass env in as parameter
System.out.println(configPath);
final File configFile = new File(configPath);
FileInputStream input = new FileInputStream(configFile);
Properties prop = new Properties()
prop.load(input);
String prop1 = prop.getProperty("PROP1");
System.out.println(prop1);
} catch (IOException ex) {
ex.printStackTrace();
}
}
Ans 1.
reading the file just isn't working despite various ways i have tried
(see current implementation below i am trying)
With the location of your config file you have depicted,
Change
String configPath = "/config.dev.properties";
to
String configPath = "src\main\config\com\my_app1\config.dev.properties";
However read the second answer first.
Ans 2:
When using gradle, do i needto tell it how to build/or deploy the file
and where? I think that may be part of the problem..that the config
file is not getting deployed when doing a gradle build or trying to
debug in Eclipse.
You have two choices:
Rename your config directory to resources. Gradle automatically builds the resources under "src/main/resources" directory.
Let Gradle know the additional directory to be considered as resources.
sourceSets {
main {
resources {
srcDirs = ["src\main\config\com\my_app1"]
includes = ["**/*.properties"]
}
}
}
reading the file just isn't working despite various ways i have tried (see current implementation below i am trying)
You need to clarify this statement. Are you trying to load properties from an existing file? Because the code you posted that load the Properties object is correct. So probably the error is in the file path.
Anyway, I'm just guessing what you are trying to do. You need to clarify your question. Is your application an executable jar like the example below? Are trying to load an external file that is outside the jar (In this case gradle can't help you)?
If you build a simple application like this as an executable jar
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class Main {
public static void main(String[]args) {
File configFile = new File("test.properties");
System.out.println("Reading config from = " + configFile.getAbsolutePath());
FileInputStream fis = null;
Properties properties = new Properties();
try {
fis = new FileInputStream(configFile);
properties.load(fis);
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
if(fis != null) {
try {
fis.close();
} catch (IOException e) {}
}
}
System.out.println("user = " + properties.getProperty("user"));
}
}
When you run the jar, the application will try to load properties from a file called test.properties that is located in the application working directory.
So if you have test.properties that looks like this
user=Flood2d
The output will be
Reading config from = C:\test.properties
user = Flood2d
And that's because the jar file and test.properties file is located in C:\ and I'm running it from there.
Some java applications load configuration from locations like %appdata% on Windows or /Library/Application on MacOS. This solution is used when an application has a configuration that can change (it can be changed by manually editing the file or by the application itself) so there's no need to recompile the application with the new configs.
Let me know if I have misunderstood something, so we can figure out what you are trying to ask us.
Your question is slightly vague but I get the feeling that you want the config files(s) to live "outside" of the jars.
I suggest you take a look at the application plugin. This will create a zip of your application and will also generate a start script to start it. I think you'll need to:
Customise the distZip task to add an extra folder for the config files
Customise the startScripts task to add the extra folder to the classpath of the start script
The solution for me to be able to read an external (non-resource) file was to create my config folder at the root of the application.
myproj/
/configs
Doing this allowed me to read the configs by using 'config/config.dev.properies'
I am not familiar with gradle,so I can only give some advices about your question 1.I think you can give a full path of you property file as a parameter of FileInputStream,then load it using prop.load.
FileInputStream input = new FileInputStream("src/main/.../config.dev.properties");
Properties prop = new Properties()
prop.load(input);
// ....your code
I have a certain requirement where I need to copy files from Unix server to Windows Shared Drive. I am developing the necessary code for this in Java. I am a beginner so please excuse me for this basic question.
I have my source path in my config file. So, I am using the below code to import my config file and set my variable. My Project has config.properties file attached to it.
public static String rootFolder = "";
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream("config.properties");
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("Config files not able to set properly for Dest Folder");
}
try {
prop.load(input);
rootFolder = prop.getProperty("Dest_Root_Path");
System.out.println("Destination Folder is being initialized to - "+rootFolder);
} catch (IOException e) {
e.printStackTrace();
System.out.println("Destination Path not set properly");
}
When I am doing this I am getting an error saying the file is not found.
java.io.FileNotFoundException: config.properties (No such file or directory)
at java.io.FileInputStream.<init>(FileInputStream.java:158)
at java.io.FileInputStream.<init>(FileInputStream.java:113)
Exception in thread "main" java.lang.NullPointerException
at java.util.Properties.load(Properties.java:357)
I am triggering this jar using a unix ksh shell. Please provide guidance to me.
Put your config file somewhere within the classpath. For example, if it's a webapp, in WEB-INF/classes. If it isn't a webapp, create a folder outside the project, put the file there, and set the classpath so the new folder is in it.
Once you have your file in the classpath, get it as a resource with getResourceAsStream():
InputStream is = MyProject.class.getResourceAsStream("/config.properties");
Don't forget the slash / before the filename.