Liquibase won't find changelog files - java

I'm trying to call liquibase programmatically.
For that I use the following code :
val database = DatabaseFactory.getInstance()
.findCorrectDatabaseImplementation(JdbcConnection(connection))
Liquibase(pathToChangelog, ClassLoaderResourceAccessor(), database)
.update(Contexts(), LabelExpression())
Liquibase managed to connect to the database and to acquire the lock, but it fails when parsing the pathToChangelog with a path/to/changelog does not exist error.
Here is my WAR file structure :
WEB-INF
\ changelog
\ db.changelog-master.xml
I tried
"WEB-INF/changelog/db.changelog-master.xml"
"/WEB-INF/changelog/db.changelog-master.xml"
"changelog/db.changelog-master.xml"
System.getProperty("user.dir") + "/WEB-INF/changelog/db.changelog-master.xml"
and certainly some other stuff, to no avail. It keeps on telling me that the file does not exist.
Am I doing something wrong ?

Found the answer by looking at the source code. The files have to be placed inside the WEB-INF/classes directory provided path has to be a relative path starting from there.
For instance, if you put your master file here :
WEB-INF/classes/changelog/db.changelog-master.xml
the pathToChangelog parameter should simply be changelog/db.changelog-master.xml.
In fact, this seems to be the default target location for the resources copied by the maven-war-plugin for instance.

Related

Playframework 2.5 : unable to access SQLite db file in stage mode

I have an application.conf file with my database configuration : db.default.url = "jdbc:sqlite:public/db/mydatabase.db". This works fine in development mode.
When I try to deploy in production, after done ./activator clean compile stage and ./activator start the application try to connect to the database during 30 seconds and finally exits with an exception :
java.sql.SQLException: path to 'public/db/mydatabase.db': '/path/to/app/target/universal/stage/public' does not exist
I tried to specify absolute path with a specific prod.conf including application.conf and overriding db.default.url. I tried also to start with an argument to the command line (-Ddb.default.url="jdbc:sqlite:public/db/mydatabase.db") the output is always the same.
How can I solve this problem ?
EDIT : the prod.conf configuration doesn't seem to override the application.conf statements... When I change directly the application.conf file with production specific properties, it works.
Play does not package the assets in the stage/dist tasks. In production, the assets are in a jar that is loaded when you start the app and not in the filesystem (ie a "public" folder). so you can't load it that way.
Move your SQLite file to the conf directory and change the db.default.url line to match the new path.

How to specify a relative file path in a standard Maven project

My Maven project needs to load data to database, and the import.sql contains the following:
LOAD DATA LOCAL INFILE
`'/home/jack/ubuntu/bword/src/main/resources/Term.txt' INTO TABLE Term FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' (id,name);`
The path used here is the absolute path on my machine. How can I specify a relative path to make it work? I tried these:
/bword/src/main/resources/Term.txt
../bword/src/main/resources/Term.txt
../bword/src/main/resources/Term.txt
../src/main/resources/Term.txt
None of these work. The file is located at src/main/resources, a default directory in a Maven directory.
I am using JBoss and hibernate, JPA.
IMHO you can't do it.
Your application is web application (I take a look on chat). Maven can package import.sql and Term.txt into the application. Both files are visible on classpath. Hibernate scans classpath, finds import.sql and execute it.
But when import.sql is proceed, the command
LOAD DATA LOCAL INFILE 'file_name' ...
is executed. 'file_name' is resolved against current working dir.
Is Term.txt visible in filesystem? I don't think so.
Does you application control current directory of JBoss process? No
Summary:
Term.txt is not visible as file on JBoss filesystem
LOAD DATA LOCAL INFILE needs file on JBoss filesystem

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.

cloudbees & ESAPI - how do I point to the ESAPI directory?

I'm using ESAPI for my project, and added the ESAPI configuration directory to src/main/resources so it is copied to my WAR file (I downloaded the WAR from cloudbees, I can see it was put in WEB-INF/classes/esapi/ directory)
Locally, I just point to where the directory is and all works fine, but on cloudbees it just doesn't work for me.
In order to access its properties, ESAPI project tries all kinds of stuff, including checking the org.owasp.esapi.resources system property, so I've added the following code to cloudbees-web.xml:
<sysprop name="org.owasp.esapi.resources" value="WEB-INF/classes/esapi/" />
and I can see that the system property value is found because of the following error in the logs:
Not found in 'org.owasp.esapi.resources' directory or file not readable: /var/genapp/apps/akld3873/WEB-INF/classes/esapi/ESAPI.properties
so it finds the system property (because the path is like I've specified), but when it looks for the actual directory and files in it, I guess the directory is either not there or not readable.
Do I need to move it somewhere else? Inside the WEB-INF directory maybe? Is the setting not right? I've read that others solved similar issues by building a JAR just for this directory, but this doesn't seem like a good solution, there must be a simple setup that will work for cloudbees.
Design for ESAPI lib to require a directory access to configuration is not very flexible.
A general purpose option is to use ServletContext.getRealPath to resolve the absolute filesystem path to this directory and pass it to ESAPI.
Another option is for you to have some init code to copy WEB-INF/classes/esapi content in a temporary directory (using java.io.temp system property to point to the currently configured temp dir for your app) and point ESAPI lib to this path.
Ok so after searching and testing, I finally figured it out.
Cloudbees deploys your web app to the following directory:
staxcat/install/webapp.war/
notice that this is a relative path, with prefix of this path attached it looks something like this:
/var/genapp/apps/xxxxxxxx/staxcat/install/webapp.war/WEB-INF/esapi/ESAPI.properties
so, in order to get ESAPI to work, I had to set the following in cloudbees-web.xml:
<sysprop name="org.owasp.esapi.resources" value="staxcat/install/webapp.war/WEB-INF/esapi" />
this will enable ESAPI to find the directory if in your project it is located under:
src/main/webapp/WEB-INF/esapi
and you should get the following log line:
Found in 'org.owasp.esapi.resources' directory: /var/genapp/apps/xxxxxxxxx/staxcat/install/webapp.war/WEB-INF/esapi/ESAPI.properties

Config files - where to put them in Java?

I have a java desktop app and the issue of config files is vexing me.
What I want is for my distributable application folder to look like this:
MyApp/Application.jar
MyApp/SpringConfig.xml
MyApp/OtherConfig.xml
MyApp/lib
But at the moment SpringConfig.xml is inside Application.jar and I can't even find OtherConfig.xml programmatically.
I don't care how I set up the various files in my compilation path, so long as they end up looking like the above.
So..
where do i put the files in my dev setup?
and how do i access them programmatically?
thanks
the spring config file is related to the code and wiring of your application, hence it'd better be inside the jar, and should be subject to change by the users
(new File(".")).getAbsolutePath(); returns the absolute path of your jar - then you can load the OtherConfig.xml by a simple FileInputStream
if the SpringConfig.xml contains configuration data like database credentials, put them in an external application.properties and use a custom PropertyPlaceholderConfigurer to load the external file.
Answering the question "where do I put the files in my dev setup" is not possible because we don't know your environment.
Actually, if you want to be able to edit the config yourself (and not necessarily end-users), you can open the jar with any zip software (WinRAR for instance) and edit the config file from within the jar.
Update: as it seems you can't make the config files to be places out of the jar. Well, for a start, you can do it manually - whenever the .jar is complete, just remove the config file from inside and place it outside.
I typically create a structure where I have a src/ directory and then other directories exist at the same level. Some of those directories include:
lib/ - External Libraries
config/ - Configuration Files
resources/ - Various resources I use (images, etc)
At that same level, I then create an Ant script to perform my build so that the appropriate config files, resources, lib, etc are copied into my JAR file upon build. It has worked great for me up to this point and is a fairly easy to understand organizational structure.
Update: Accessing my config files is done, typically, by knowing their location and opening them up and reading them in the code. Because I use Ant to build, I make sure that my config files are in a location that I expect. So, for example, in a recent application I created, when I compile, my JAR file is in the top level directory (relative to the application release structure). Then, there is a "main" config file at that same level. And there is a "theme" config file that is in a themes folder.
To read the various files, I just open them up as I would any other file and read them in and go from there. It's nothing particularly fancy but it works well and it makes it easy to manually change configurations if I need to do so.
In dev mode, put them in source dir and they will be copied to your classes folder, you can then access them using classloader.
Example:
URL url = ClassLoader.getSystemResource("test.properties");
Properties p = new Properties();
p.load(new FileInputStream(new File(url.getFile())));
In Prod mode, you can make them part of your jar.

Categories