Reading reloadable xml file from external Tomcat directory - java

Prerequisites
Apache Tomcat 7
Spring 3.2.11.RELEASE
Apache Camel 2.14.1
My Webapplication is deployed in ${catalina.home}/webapps/ as usual
Requirements
Reading xml file placed outside of war-Archive (for example from ${catalina.home}/myfolder/)
The xml file should be reloadable. So if the xml changes the new xml file should be available in my Webapplication
The xml file should be mapped to Java-Objects
First try
I have added the file to classpath via tomcat in catalina.home/conf/catalina.properties:
common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar,${catalina.home}/myfolder/
The file is placed here:
${catalina.home}/myfolder/myFile.xml
Reading and mapping the file to Java-Objects works via a timer in apache camel.
from("timer://myTimer?fixedRate=true&period=20000")
.setBody(simple("resource:classpath:myFile.xml"))
.unmarshal(myFileJaxbDataFormat)
.process(myFileTimerProcessor);
myFileTimerProcessor takes the mapped Objects and stores it to a Spring-Bean.
This Bean is used by other Camel-Routes to access the Data contained in the xml file.
Problem
As Claus Ibsen mentioned below the problem is that the ClassLoader caches the file. So the file is not read again if data in it has changed.
If the file ${catalina.home}/myfolder/myFile.xml changes it should be read again and the new values should be available to the timer so it can read the new values for the application.
Is there a possibility to read a xml file outside of war-Archive and reload it if it's content changes?
Is there a more common wary to do that?
Thanks in advance.
Regards,
Max
EDIT 1:
I have restructured the question to ask not only specific details.

The file is cached by the Java classloader, not something Camel can do anything about. You likely need to load the file using file resources instead of classpath.

Related

Setting up Custom class Object as Key/value in Apache Geode

I am using Apache Geode in one of my web applications.
I am using Custom class as a value-constraint in Apache Geode cache-server.xml file.
If value-constraint is not specified in the XML file, then I am able to start the server. But if value-constraint is specified then while running the server I am getting below error
Exception in thread "main" org.apache.geode.cache.CacheXmlException: While reading Cache XML file:/C:/localfolder/cache-server.xml. Could not load value-constraint class: myPackage.Test, caused by java.lang.ClassNotFoundException: myPackage.Test
Below is my startserver.bat file contents
gfsh start server --server-port=12000 --dir=C:\localfolder\server
--name=server123 --hostname-for-clients="someHost" --initial-heap=500m --max-heap=500m --bind-address="someAddress" --properties-file=gemfire.properties --server-properties-file=gfsecurity.properties --classpath="C:\localfolder\application.war"
Please let me know
How to provide a custom class objects as a key-value constraint in the XML file?
How to use war file, in the server start process?
The classpath (Gfsh option, and in general, to the java launcher) cannot refer to a WAR file; must be a JAR file (containing your application domain classes).
WAR files and JAR files have similar, but significantly different formats.

Reading a XML file from JAR within web application

I am trying to read XML file from JAR used as library in my web app. How can I achieve that? My directory structure for XML file is:
commons/resources/config.xml
where commons is a Java project for which I will create a JAR and place under
apache-tomcat-8.0.32/webapps/myWebApp-1.4/WEB-INF/lib
after building and deploying it.
You can read the XML file as resource from classpath this way: this.getClass().getResourceAsStream("/config.xml"). It returns a stream that you can use for reading the content of the file and do with it whatever you want. It is only possible within the webapp the jar belongs to because webapps are isolated with respect to classloading.

A static resource file?

Android uses a static resource file R. This file (at least in eclipse) is automatically updated when ever you add new id's of any sort. How can I create/implement the same feature in a normal java application? Is it as simple as just writing an xml parser and just updating the resource file after the xml is modified?
In a way, yes. You need to create a custom build script/program which runs at the start of each build (before anything else), scans your resource folder files (and if they are XML files it needs to read in the XML files and parse out the string resources or whatever from those), then write it all to a Java file in some manner (e.g. R.string_name = "string value").
Make sure the XML files aren't actually packaged in your .jar, since all that information will be stored inside your Java resources file now.
For things which aren't XML files you could just store the filename as a string in the Java resources file.
You didn't specified the type or the use of the resources. I don't know android, but I'll try to help; If you just need to access some resource in your application you can use properties or resource, there are some differences see this other question Properties vs Resource Bundle

netbeans and hibernate configuration

How can I load the configuration information for hibernate dynamically from a config file. Netbeans currently hard codes that information into an xml file that is then compiled into the jar. I'm a newbie to Java/Netbeans coming from PHP land and am use to a central bootstrap that pulls from a .ini or something similar, but netbeans tends to hardcode this information upon generation of the models,etc in an xml file that is then compiled in the jar. I'm looking for conventional methods of setting up configuration for various client machines using various database configurations. I don't want to have to compile the app on each machine it must be installed on.
The configuration file is read using the Configuration class. By default, it uses the hibernate.cfg.xml file found in the classpath, but you can use the configure method taking a file as parameter, and store the config file on the file system rather than in the jar.
You can also put the static mapping, which never changes between configs, in a file inside the jar, and put the varying config inside an external file. Look at the javadoc for Configuration to know how to add resources and config files to the configuration.

Java: Accessing properties file inside a war

I already searched StackOverflow for "properties inside war", but none of the results worked for my case.
I am using Eclipse Galileo and GlassFish v3 to develop a set of web services. I am using a "dynamic web project" with the following structure
Src
-java_code_pkg_1
-java_code_pkg_2
-com.company.config
--configfile.properties WebContent
-META-INF
-WEB-INF
--log4jProperties
--web.xml
--applicationContext.xml
--app-servlet.xml
I want to access the "configfile.properties" inside one of the source files in "java_code_pkg1". I am using the Spring Framework and this file will be instantiated once the application starts on the server.
I have tried the following with no luck
getResourceAsStream("/com.company.config/configfile.properties");
getResourceAsStream("/com/company/config/configfile.properties");
getResourceAsStream("com/company/config/configfile.properties");
getResourceAsStream("/configfile.properties");
getResourceAsStream("configfile.properties");
getResourceBundle(..) didn't work either.
Is it possible to access a file when it's not under the WEB-INF/classes path? if so then how?
Properties props = new Properties();
props.load(this.getClass().getResourceAsStream("/com/company/config/file.properties"));
works when I'm in debug mode. I can see the values in the debugger, but I get a NullPointerException right after executing the "props.load" line and before going into the light below it.
That's a different issue. At least now I know this is the way to access the config file.
Thank you for your help.
If you are in a war, your classpath "current directory" is "WEB-INF/classes". Simply go up two levels.
getResourceAsStream("../../com/company/config/configfile.properties");
It is horrible but it works. At least, it works under tomcat, jboss and geronimo and It works today.
P.S. Your directory structure is not very clear. Perhaps it is:
getResourceAsStream("../../com.company.config/configfile.properties");
Check the location of the properties file in WAR file.
If it is in WEB-INF/classes directory under com/company/config directory
getResourceAsStream("com/company/config/configfile.properties") should work
or getResourceAsStream(" This should work if the config file is not under WEB-INF/classes directoy
Also try using getClass().getClassLoader().getResourceAsStream.
Are you sure the file is being included in your war file? A lot of times, the war build process will filter out non .class files.
What is the path once it is deployed to the server? It's possible to use Scanner to manually read in the resource. From a java file within a package, creating a new File("../applications/") will get you a file pointed at {glassfish install}\domains\{domain name}\applications. Maybe you could alter that file path to direct you to where you need to go?
Since you are using Spring, then use the Resource support in Spring to inject the properties files directly.
see http://static.springsource.org/spring/docs/3.0.x/reference/resources.html
Even if the class that requires the properties file is not Spring managed, you can still get access to the ApplicationContext and use it to load the resource
resource would be something like, classpath:settings.properties, presuming that your properties file got picked up by your build and dropped in the war file.
You can also inject directly, from the docs:
<property name="template" value="classpath:some/resource/path/myTemplate.txt">

Categories