Felix ConfigAdmin (File) | Does my file needs to include service.pid? - java

I'm using Felix ConfigurationAdmin 1.8.6 (which is included in OSGI enRoute) and i'm not able to get it working with files in a folder.
I downloaded the sources to see what's going on, but i still can't figure out...
First, I added the run property felix.cm.dir, specifying the folder I want to configure my services. From what i see debugging, it's working fine, but my managed service get a null properties map.
Next, i discovered my properties must have the following format to be read (with doublequotes):
key="value"
Still, i get a null properties map...
Then i discovered that after reading my properties, the FilePersistenceManager.seek() only returns the Dictionary if it DOESN'T contains service.pid property, OR it contains that property and it equals the filename. Before comparing, it replaces the dots with slashes, so it never equals... I better not specify service.pid property anyway, i don't see the point.
When the Dictionary comes back to CachingPersistenceManagerProxy, it only get cached if the Dictionary contains the service.pid ou factory.pid property; which never happens.
Am i missing something?

I don't know if enRoute brings Apache Felix FileInstall with it, but without this bundle configuration admin services doesn't pick up configuration files. FileInstall usually takes care of that. And in that case, yes you'll need to make sure your cfg file does have a name matching your PID.
So for a configuration with pid: my.conf.foo you'd need a file my.conf.foo.cfg in a folder monitored by the FileInstaller Bundle. It'll pick up this file and make sure your configuration is updated with the content of the file.

Related

update properties file at runtime

I have one Project (say A) which uses Spring. Project A internally depends on other project (Say B) for few Task. So B Project URL is configurable in server.properties file of A Project.
So now each time URL for B project get changed then I have to shutdown A Project, change the URL in server.properties file and then again start the server.
So I have requirement as to ask user to enter the new URL using GUI and change the URL at runtime.
I know it is possible to change the value of the property at runtime but it will be set only for that session and not an actual modification to properties file, and once the server is restarted again it will refer to old URL because actual changes are present in Session and not to actual Properties file.
my actual need is that changes should be reflected in properties file(for future restart of server it should work) as well as in beans configuration File(for current session - I am aware of how to do.)
Now my requirement is, whenever any changes comes in configuration then it should also physically change the properties file...is there any neat way to do this instead of reading File and search for that key and then replace substring.
Is there any third party api to do this nicely.
You can look at commons configuration. See file based save and reload here.
You can update properties file at runtime by using Commons Configuration API then get value by key. Here is good working example update and read properties
Hope this help!

Is this the best way to keep .properties file out of WAR file?

To externalize a .properties file, currently I am keeping it in a file system say
C:\test\UI\properties
and I have created a Environment variable $PROP_LOCATION which points to above file location. So whenever I need to change properties, just I go to that location edit properties and refresh the application. It works like a charm.
So is this the best way? Or is there any other way you professionals suggest me to keep properties file out of war file?
Note: The above thing works fine in both unix and windows environment as I have a "if" condition, if one of the environment variable not found I will check for another environment variable.
I agree that just packaging the properties file with your application makes the most sense. If you have some valid reason not to do that, your solution seems fine as long as in deployment the file is placed in a location that your application has access to and is not exposed to the Internet.
I am doing something somewhat analagous to you. In an application I'm running, there is a page of announcements and other messages that I want users to see, but to make it easier for me and others to edit these messages, they are loaded from another place on the server, not even in the Tomcat folder. I can then easily edit the messages without even re-deploying.
I usually reference external properties files by adding the directory to the classpath.
For example, if example.properties is in path C:\test\UI\properties directory, I call JVM as follows:
java -classpath C:\test\UI\properties MyJavaProgram
Inside the Java code, you can load the properties via the following mechanism:
Properties p = new Properties();
p.load(getClass().getClassLoader().getResourceAsStream("/example.properties"));
I suggest to use the ReloadableResourceBundleMessageSource of spring
Check it out: http://static.springsource.org/spring/docs/1.2.9/api/org/springframework/context/support/ReloadableResourceBundleMessageSource.html
And as for placing the properties files, I don't think keeping them outside application is good idea. You should package them in war anyway, as they are logically part of your application.
And since you are reloading the application, you can use maven task to build, deploy and reload the app on server everytime the properties change.

How make working directory files available to WebStart application?

We have to make a Java application demo available on Internet using JWS. It goes pretty well; all that's missing is making working directory files available for the application.
We know about the getResource() way... The problem is that we have different plugins for the same application and each one require different files (and often different versions of the same files) in their working directory to work properly. So we just change the working directory when we want the application to have a different behavior.
Currently, the demo is packaged in a signed jar file and it loads correctly until it requires a file from the working directory. Obviously, the Internet users of this demo don't have the files ready. We need a way to make these files available to the WebStart application (read/write access) in its working directory.
We've thought of some things, like having the application download the files itself when it starts, or package them in the jar and extract them on startup.
Looking for advices and/or new ideas. I'll continue working on this... I'll update if I ever find something reliable.
Thank you very much!
I said I would share what I found in my research for something that would fit my needs. Here's what I have so far.
I have found that the concept of current working directory (CWD) does not really make sense in the context of a Java Web Start (JWS) application. This had for effect that I stopped trying to find the CWD of a JWS and started looking for other options.
I have found that (no, I didn't know that) you can refer (using getResource()) to a file in the root directory of a JAR file by simply adding a '/' in front of its name. ("/log4j.properties", for example.) The impact of this is that I can now take any file which is only referred to in a read-only manner in the root of that JAR file (which is really only a ZIP file). You can refer to any file in the root of the JAR file using AnyClass.class.getResourceAsStream. That rules out the problem with read-only files required to run the application, at the cost of a switch in the code telling whether the application is run from a valid CWD or from a JWS context. (You can very simply set a property in the JNLP file of the JWS application and check if that property is set or not to know where to look for the file.)
For write-only files (log files in my case), I used the property , adding a directory with the name of the application: <user.home>/.appname and added log files to it.
Read/write files (which I don't have in my case) would probably simply go at the same place than write-only files. The software could deal with uploading them somewhere if needed, once modified, I guess.
That's the way I deal with the problem for now.
Note there is a service you can explicitly ask for, to get file access to the computer (unless you go all the way and ask for full access (which requires signed jar files)).
Then you need to determine where these files need to go - basically you have no idea what is where and whether you may actually write anywhere. You can create tmp-files but those go away.
Would a file system abstraction talking to the JNLP-server do so you store the users data on the server?

JBoss/EJB - location of custom configuration file

I'm implementing an EJB-based system in JBoss.
One of my message driven beans will be responsible for sending emails. I want the email template to be stored externally (probably as XML) so that it can easily be changed without having to change the code/redeploy the bean, etc.
Where should this file be placed and how do I reference it?
The JBoss documentation specifies that the environment variable jboss.server.data.dir is the "location available for use by services that want to store content in the file system". See here for more details.
You can get the value of the variable by
System.getProperty("jboss.server.data.dir");
And, as shown in the link, the location of the server/[config]/data directory will be returned. Store the template file there when you deploy your app, and instruct your admins to modify it there.
This question and this blog post refer to property files, but what is discussed also applies for other kind of files. One solution would be to place the XML file in a standard location and read it like this (code taken from the link above):
String path = System.getProperty("catalina.base")
+ System.getProperty("file.seperator")
+ "YOUR_FILE.properties";
FileInputStream fis = new FileInputStream(path);
Instead of catalina.base you can use user.dir or even define your own environmental variable (mypath_to_xml_file) and read it with System.getProperty.
Another solution would be to use JNDI to define the path to the file.
Or put it in a database where you can get at it via SQL client. Load it on startup or maybe poll to check for timestamp changes and reload it.
What kind of template do you mean? Is it a Velocity template that you populate in a mail merge fashion?
One thing that I like about the database design is that you can add so much more information to the schema that's over and above a mere file. You can include timestamp, user ID of the person who updated the template, version, meta data, system name, a boolean to indicate "live" or "dormant", etc. Your EJB can be really smart about which template it chooses. You might find yourself with even more options than you'll have if you simply park files on the server drive. They'll be available to other apps that way as well. Could be a nice design if you run with it a little bit.
If you add it to the WEB-INF/classes directory of an exploded deployment you can easily reference it using "getResourceAsStream()". Add a polling feature if you don't want to have to bounce the server.

What is the best place to store a configuration file in a Java web application (WAR)?

I create a web application (WAR) and deploy it on Tomcat. In the webapp there is a page with a form where an administrator can enter some configuration data. I don't want to store this data in an DBMS, but just in an XML file on the file system. Where to put it?
I would like to put the file somewhere in the directory tree where the application itself is deployed. Should my configuration file be in the WEB-INF directory? Or put it somewhere else?
And what is the Java code to use in a servlet to find the absolute path of the directory? Or can it be accessed with a relative path?
What we do is to put it in a separate directory on the server (you could use something like /config, /opt/config, /root/config, /home/username/config, or anything you want). When our servlets start up, they read the XML file, get a few things out of it (most importantly DB connection information), and that's it.
I asked about why we did this once.
It would be nice to store everything in the DB, but obviously you can't store DB connection information in the DB.
You could hardcode things in the code, but that's ugly for many reasons. If the info ever has to change you have to rebuild the code and redeploy. If someone gets a copy of your code or your WAR file they would then get that information.
Putting things in the WAR file seems nice, but if you want to change things much it could be a bad idea. The problem is that if you have to change the information, then next time you redeploy it will overwrite the file so anything you didn't remember to change in the version getting built into the WAR gets forgotten.
The file in a special place on the file system thing works quite well for us. It doesn't have any big downsides. You know where it is, it's stored seperatly, makes deploying to multiple machines easy if they all need different config values (since it's not part of the WAR).
The only other solution I can think of that would work well would be keeping everything in the DB except the DB login info. That would come from Java system properties that are retrieved through the JVM. This the Preferences API thing mentioned by Hans Doggen above. I don't think it was around when our application was first developed, if it was it wasn't used.
As for the path for accessing the configuration file, it's just a file on the filesystem. You don't need to worry about the web path. So when your servlet starts up it just opens the file at "/config/myapp/config.xml" (or whatever) and it will find the right thing. Just hardcodeing the path in for this one seems pretty harmless to me.
WEB-INF is a good place to put your config file. Here's some code to get the absolute path of the directory from a servlet.
public void init(ServletConfig servletConfig) throws ServletException{
super.init(servletConfig);
String path = servletConfig.getServletContext().getRealPath("/WEB-INF")
Putting it in WEB-INF will hide the XML file from users who try to access it directly through a URL, so yes, I'd say put it in WEB-INF.
I would not store it in the application folder, because that would override the configuration with a new deployment of the application.
I suggest you have a look at the Preferences API, or write something in the users folder (the user that is running Tomcat).
The answer to this depends on how you intend to read and write that config file.
For example, the Spring framework gives you the ability to use XML configuration files (or Java property files); these can be stored in your classpath (e.g., in the WEB-INF directory), anywhere else on the filesystem, or even in memory. If you were to use Spring for this, then the easiest place to store the config file is in your WEB-INF directory, and then use Spring's ClassPathXmlApplicationContext class to access your configuration file.
But again, it all depends on how you plan to access that file.
If it is your custom config WEB-INF is a good place for it. But some libraries may require configs to reside in WEB-INF/classes.

Categories

Resources