Deployment web-application on application server. Database access credentials - java

I have a web application which I deploy on Tomcat Server manually.
My property file with database credentials is not located in classpath. On startup I load it like this:
prop.load(new FileInputStream("C:\\application.property"));
Downback of this is that now I can move my code to linux based platform without changing the source.
If I put this file to classpath it will be packed inside war (with all credentials) and replaced every time I redeploy my application. Tomcat is deleting application dir and replace it with war content on redeploy.
The question is: How and where to put property file in classpath and ensure that this file will not be replaces/deleted by application server on application redeployment. And the file must not be inside war.

The thing which you are doing looks like anti-pattern. Do not store database connection credentials in external property file.
Database access credentials should be placed inside context.xml configuration file of your tomcat. This is called JNDI Resources and you can read about it, for example, here.

Related

How to know the location of a .properties file to read configurations when deploying a Java web application?

According to what I know Java Web applications are deployed on a server by deploying the .war file of the web application. Is this correct?
I have a Web application that has some configurations to allow the server administrator to configure the application at the time of deployment. Ex. Set the path where log files are to be saved, Set the location to store uploaded documents etc..
I defined such parameters in a .properties file and hardcode the path to it. Thereafter I was able to get the web application to read the values in the .properties file without recompiling the source code (as the .properties file path did not change).
Now I want to know how to do this without hardcoding the path to the .properties file so I can deploy this on any server without worrying about its directory structure.
So, is it possible to provide a .properties file along with the .war file when the web application is being deployed so that the server administrator can edit the .properties configuration file, deploy the .war file (without recompiling the web application) on a server and let it read the values in the .properties file?
If so how can the web application know where the .properties file is?
Best practise is to put the properties file at a location where it can be found on the classpath. Your application loads the file with
this.getClass().getClassLoader().getResourceAsStream( "myConfig.properties");
If the file is located in a non standard classpath location you can finetune your applications classpath using tomcats configuration possibilites. See e.g. Understanding The Tomcat Classpath

HSQLDB in resources within a WAR

I've developed a small application using Spring Boot, which uses HSQLDB as a database to store users, for the time being. What I want to do is store the database within Maven's resource folder. My application.properties file contains the following configuration:
#...
spring.datasource.url=jdbc:hsqldb:file:src/main/resources/database/dashboard
#...
So, whenever I start the application with Java (right click on my Application's main() and Run As Spring Boot App), the database is stored right.
But, after packaging a WAR file with mvn clean install spring-boot:repackage, deploying it into Tomcat, e.g., and running it, the database is not stored within the exploded WAR.
My question is how can I tell spring.datasource.url=jdbc:hsqldb:file:* property to store the database within Maven Resources directory (which will point still after exploding the WAR)? Could I use some sort of environment variable as used in pom.xml?
EDIT
Given the answers by #Steve C and #fredt, I've realised that the database shouldn't be stored within the war. Instead, I'll store it within the user's Home dir spring.datasource.url=jdbc:hsqldb:file:~/tomcat_webapp_data/dashboard/database.. Thank you so much!
The directories and contents of a WAR file are read-only.
You can set the read_only flag in the HSQLDB database .properties file before including in the WAR. You access this kind of database with a jdbc:hsqldb:res:<path> URL.
If you want to store data in a persistent and updatable database, connect to the (at first non-existent) database within your application and set up its tables if they don't yet exist with data from a resource. You can then store data. The database path should be outside the directories that are used for jars and resources.
Contrary to one of the comments, HSQLDB is not limited to storing data in memory and can have disk-based tables, called CACHED tables.
You can include a variable in the database URL to pick up a pre-defined property from the web server. For example:
jdbc:hsqldb:file:${mydbpath}
See http://hsqldb.org/doc/2.0/guide/dbproperties-chapt.html#dpc_variables_url
Maven's src/main/resources directory is a build time path, not a runtime path.
If you're building a jar file, then everything in src/main/resources is copied to the root of the jar.
If you're building a war file, then everything in src/main/resources is copied to the root of the /WEB-INF/classes directory in the war.
Now, your JDBC URL jdbc:hsqldb:file:src/main/resources/database/dashboard is indicating a file with a relative path. At runtime this path is relative to the current working directory - and it's unlikely to exist at runtime anyway.
If you really want to build the database within your WAR, then given:
you're deploying an exploded WAR file (it's impossible to write to the content of the WAR file itself);
you really really want to store the database within the exploded WAR;
you want to put it in WEB-INF/database/dashboard (there's security implications if you store outside of the WEB-INF directory);
then you can compute the JDBC url using something like:
...
String databaseDirectoryName = servletContext.getRealPath("WEB-INF/database");
File databaseDirectory = new File(databaseDirectoryName);
if (!databaseDirectory.exists()) {
if (!databaseDirectory.mkdirs()) {
throw new RuntimeException("Failed to create database directory");
}
}
File databaseFile = new File(databaseDirectory, "dashboard");
String jdbcURL = "jdbc:hsqldb:" + databaseFile.toURI();
...
Getting that into your Spring configuration is an exercise for you; but using #Configuration and #Bean springs to mind as a way to do this - you just need to get access to the servletContext at Spring configuration time.

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.

modify files in WEB-INF folder - tomcat as hot deployment

I have a application deployed in Tomcat7 server which deals with multiple database connections.
These database details are retrieved from 'database.properties' and it is referred in hibernate.xml file in WEB-INF folder. These database details are to be changed dynamically and the hibernate xml is also to be updated.
As for now, if I want to update the database details I need to modify the changes in the 2 files mentioned above and the war file needs to be deployed again.
I tried changing the files in tomcat without restarting. I verified that the 'reloadable' property in tomcat server.xml file is set to true. But still the changes are not reflected in the app without restarting the server.
Please let me know if any configurations to be done for modifying these files without restarting the tomcat server.....
--
Suriya
Look at WatchedResource tag. You need to add your files there.
WatchedResource - The auto deployer will monitor the specified static resource of the web application for updates, and will reload the web application if it is updated. The content of this element must be a string.
Look at the configuration in context.xml file
<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
Add more files, which you want to monitor the changes to redeploy.

deploying two projects in tomcat that needs connection to database with different URL

In my project a servlet has to connect to database (derby).I build my project into .war file.
Now before deploying the project in Tomcat , how do i tell the server the URL of the databsae,JNDI name,driverName etc etc. How do i do this ? I was told to add these into the context.xml file. Do i have to create this file myself ? Otherwise there is also a context.xml file in the conf directory of tomcat. I have to deploy one more project that also needs to connect to the database but has a different URL. So i think i can't add the details in the context.xml file in conf directory.
How do i deploy these two projects ? Do i need to make 2 different context.xml files ?
Put the configuration in a context.xml and put that file in the META-INF folder of your war. See tomcat context documentation on the tomcat website.
if you are using hibernate for persisting data to database then u need to mention the database url, name, password in hibernate.cfg.xml.
If you want to open database connection from Servlet itself.
then refer this http://www.roseindia.net/servlets/databaseconnectionservlet.shtml. i hope it would help you.

Categories