cannot find files while app running on cloud foundry - java

When running the app locally, it works. However, after I build a jar with maven and push it to cloud foundry, it cannot find the krb5.keytab file through the local absolute file path
The krb5.keytab's path are setting in my application.yml file. e.g
keytab:
key: krb5.keytab
file: C:\Users\Documents\WorkSpace\MyProject\kafkatool\krb5.keytab
How do I need to change the file path of krb5.keytab so when it's running on cloud foundry the app can still find the keytab?

When your Java application runs on CloudFoundry, it's running in a remote Linux container. It does not have access to your local file system and any files you reference need to be within the Linux container's filesystem, thus no c:\ Windows-style paths are going to work.
Your application, when running on CF, lives in the /home/vcap/app directory (there's also a symlink at /app which points to /home/vcap/app that you can use if you want).
In addition, your application will be executed out of the /home/vcap/app directory so the current working directory will be /home/vcap/app.
Thus, if you need to reference files you can either reference them relative to the /home/vcap/app directory or you can prefix the /home/vcap/app to all paths and use a full path to the file.
If you don't like the idea of hard-coding /home/vcap/app into your application, you can fetch this directory dynamically by looking at the HOME environment variable. When your application runs, the HOME env variable points to /home/vcap/app.

Related

Read external .properties file from the install directory (not the current directory)

I am distributing a Spring Boot application as a zipped "bootJar" using the Gradle Application plugin and the "distZip" task. The end-user will get the zip file, unzip it, and run it by just typing "myApp" (a shell script nicely created by the plugin).
I would like the end-user to create a "myapp.properties" file (a name I chose) and put it in the installation directory, or a "config" directory under the installation directory.
Suppose I set up my embedded (in the jar) application.properties file as follows:
spring.config.import = file:./myapp.properties will only read from the current directory
spring.config.import = file:/etc/myapp.properties will read from the specified directory -- but I don't know what this is at build time (the end-user determines it at installation time)
How can I set up my application so that Spring Boot can read properties from an external file whose location is specified later?
NOTE: I know I can play around with the generated scripts to pass in environment variables or Spring Boot properties, but I was hoping to do this completely within Spring Boot so I don't need to modify the nicely generated shell scripts.
spring.config.import = file:./myapp.properties will only read from the
current directory spring.config.import = file:/etc/myapp.properties
will read from the specified directory -- but I don't know what this
is at build time (the end-user determines it at installation time)
Why overcomplicate this.
Place inside the jar all the properties that you want to be statically configured as default values when you build the application.
Embedded application.properties
server.port = 8080
prop1.element = something
Then the client can create another file application.properties and place it in the same directory with the jar and define more properties which are not already defined.
prop2.element = something2
prop3.element = something3
By default Spring Boot will load properties both from the embedded file as well from the file in the current directory where the jar is placed during startup.
In the external application.properties you can also overwrite properties existing in the embedded application.properties. So if the external file in the current directory same as the jar is the following
prop2.element = something2
prop3.element = something3
prop1.element = something4 <--- this value here will overwrite the value 'something' from embedded file
According to spring doc
SpringApplication will load properties from application.properties
files in the following locations and add them to the Spring
Environment:
/config subdirectory of the current directory.
The current directory
classpath /config package
The classpath root The list is ordered by
Precedence (properties defined in locations higher in the list
override those defined in lower locations).
After having more input from the comments, it seems that you face another issue as well. You start the application from command line from another directory so that is counted as the directory where spring will look for the external configuration instead of where the jar is placed.
So for example let's say that the jar is placed inside the target folder that exists in current directory. You start the application using the following command:
java -jar target/demo-0.0.1-SNAPSHOT.jar
But then the external application.properties existing inside target folder is not loaded from spring because you executed the command from another directory. This can be solved if you start the application in the following way
java -jar -Dspring.config.additional-location=./target/ target/demo-0.0.1-SNAPSHOT.jar
This should not be difficult as you already provide the path where the jar exists in the command line.

How to force Tomcat doesn't write data (like logs, temp, ets) to its own root folder?

I'd like to create a desktop standalone application from my Java/Spring web application. I created MSI-installer that copy all required files to C:\Program Files (x86)\App. But tomcat doesn't have permission and can't write to its own folder. How I can configure tomcat so it would write all app-specific data to other folder? I wouldn't like to install my app to C:\App or user dir.
java.io.FileNotFoundException: C:\Program Files (x86)\App\tomcat\logs\catalina.2016-06-18.log (Access denied)
By setting the environment variable CATALINA_BASE to another directory in your tomcat start script you can configure Tomcat to read/put the working data, configuration and stuff from/to another location. If CATALINA_BASE is set, Tomcat will use the folders %CATALINA_BASE%/bin, %CATALINA_BASE%/conf, %CATALINA_BASE%/logs, %CATALINA_BASE%/temp, etc. for the current instance of Tomcat. This is described in more detail in the Advanced Configuration - Multiple Tomcat Instances section of the RUNNING.txt file in Tomcat's root folder.
If you are planning to ship Tomcat with your application and put all Tomcat files to some user choosable folder you should set CATALINA_HOME to this folder. Tomcat will then use this folder as base directory for everything.
However I think, as you mentioned to ship a standalone application based on Spring, you should seriously take a look at Spring Boot. This will allow you to ship a single fat jar containing all of your application's dependencies (including Tomcat). And this application can simply be started by executing the jar file.
If it's just about the log and temp files, you can set the Java system properties java.util.logging.config.file and java.io.tmpdir in the setenv.bat file under %CATALINA_BASE%/bin to make Tomcat use a custom logging configuration and a different temp dir, respectively. That is the file would look something like this:
set CATALINA_OPTS="-Djava.util.logging.config.file=file:///c:/path/to/log/config.properties"
set CATALINA_OPTS="%CATALINA_OPTS% -Djava.io.tmpdir=c:/path/to/temp/dir"
Find and update all occurrences of "$CATALINA_BASE"/logs/catalina.out to custom path in catalina.sh script.

Run a jar from shared folder from a server, and the jar need to read a file from the server

Bear with me cause I'm new to java and stackoverflow.
Problem:
I have a jar that is reading a file from the environment variable of its machine(Server A).
If I remote Server A and run this jar, the file reading is ok.
But I needed to put this jar and a batchfile to execute it in a SHARED FOLDER to be able to access it without the need to remote Server A.
For the batchfile in the shared folder with "java -jar "%~dp0MYJAR.jar"
Adding %~dp0 in front of jar name in batchfile allowed me to call the jar in shared folder. [source in link below]
Can I run a jar file from shared folder of remote system just by double clicking from my system?
But when running the jar, the jar was not able to locate the file its reading in Server A. Here's the code on reading the file.
Properties prop2 = new Properties();
String propFile=System.getenv("OTHERS_HOME") + "\\conf\\FILE_TO_READ.txt";
upon printing the current directory when the jar is running.
When remote access to Server A i got E:\ISO_Tester. This is the correct path.
But when running in my machine from a shared folder of Server A i got C:\Windows which I think is from my local machine instead of Server A.
The best part is that you should be sharing from server A the JAR file and the required files as well and write/execute the code with respect to the relative path of file
It is because the batch will not access the properties of server A, instead takes whatever available from machine where it is being executed
If you want to read more please refer this link for Get remote env vars using Windows Powershell

Accessing files in Play dev and prod mode

I'm having a trouble accessing some files in universal way across app run modes.
I have folder "resources" in app root folder, which contains some crucial files.
When I run in dev mode, I access them in simple manner, like:
Play.application().path().getAbsolutePath()+"/resources/file.file";
But after I package my app via dist commmand (I've modified build.sbt so that "resources" folder is copied near conf and lib folders), the code above stops working, due to this line
Play.application().path().getAbsolutePath()
now returns a path to bin folder, in which app.bat is ran from. So if in dev mode, the code above returns correct path like X:/app/resources/file.file, in prod mode it's like X:/app/bin/resources/file.file which is incorrect.
P.S. I absolutely can't put my files in conf folder and access them as a resource from a classloader because of numerous reasons which are actually not important.
So the question is simple as that: how to access these file resources in a universal manner across modes, without any hardcoding.
TY in advance.
There is a method on Application which lets you access files in the application root.
https://playframework.com/documentation/2.4.x/api/java/play/Application.html#getFile-java.lang.String-
default java.io.File getFile(java.lang.String relativePath)
Get a file relative to the application root path.
Parameters: relativePath - relative path of the file to fetch
Returns: a file instance - it is not guaranteed that the file exists
Since you already have the application, you should be able to use this method to directly access the file.

user.dir is incorrect while using tomcat web app in eclipse

I have a configuration project that few projects are using it.
All of my project under the same workingspace.
workingspace/configuration
workingspace/webapp1
workingspace/mongoDB
workingspace/model
mongoDB and the model project are using the configuration jar project and able to read the xml files using relative path ../configuration/conf/....xml
when using the
System.out.println("Working Directory = " +
System.getProperty("user.dir"));
inside both of them, I'm getting the correct path (workspace)
while trying to do it from the web app servlet i'm getting the folder of eclipse.exe that causing some problems.
How can i fix the user.dir defalte path for the web app?
At runtime, e.g. when you're not running from inside eclipse, you probably want to work in a defined directory as well - I'd suggest to explicitly configure a specific directory. When you're running within an appserver, you might run as an unpriviledged user that doesn't have a home directory writeable at all (when the account is properly administered with minimal permissions). This differs from applications that are launched ad hoc. In fact, you probably can't assume that your application server runs as the same user as your standalone apps do.
Another alternative is to utilize the system's temp directory - if these are truly temporary files. This could be assumed writeable, or complaints if it isn't do make sense.

Categories