Java tip for plugin-like architecture - java

My application will output a graph, for which the layout is to be defined by the user. The custom layout class should implement an interface defined by me.
How should I do this? Have a special folder where I look for layout classes? Have the user pass the class name as argument to the app?
Any help would be greatly appreciated.

Multiple approaches used at the same time usually give the best results here. Different users may choose different ways to configure your application. For example:
A default directory where users can put plugins. Or even a list of directories, which could include some subdirectory of the application folder, some system-wide directory in the platform-dependent "application data" place, some user-local directory.
A config file with some options to control plugins search and selection.
A Java system property which specifies a list of directories to search for plugins, like java -Dorg.something.appname.plugindirs=plugindir1;plugindir2.
A special command-line option or Java system property to select a particular plugin, possibly providing an absolute path or just a name to look up in the directories specified by the methods above.
I think that the more ways your application provide, the better. Of course, it should have some sort of default setup so users won't have to bother with all that stuff if they don't want to. Also, the order of using those options should be sensible: for example, it makes perfect sense for the user plugins to override the system ones, not the other way around.

The model chosen by toolkits years over, AWT, Swing, etc. is to be passed the layout as an argument to your API. Assuming you're being invoked from the commandline:
java -jar yourapp.jar;theirintf.jar yourapp org.example.theirintf
Don't try and be overly magical with special folders and conventions. Just take it as an argument. Please have a default value if the user choose not to create one of their own - your app should be usable on it's own.

Related

Retrieving and sorting list of files at runtime from Jar

I'm fairly new to Java (and stackoverflow for that matter) so I'll try my best to be on-point. I'm using Eclipse Juno and JavaSE 1.7.
I would like to create a data structure which allows me to dynamically sort and retrieve the files I'll need at runtime. These files will be scripts which are processed depending on "where" they were found, or what "type" they belong to. For example, a script relevant to processing commands from the command line would be a "command" script.
I've learned that "directories" in a Jar are more-or-less meaningless, so a clever usage of those proved useless. Although, there are some hacks to make it work, I'd like a more robust solution.
(I have seen the following threads questions and answers:
How do I list the files inside a JAR file? and
Listing the files in a directory of the current JAR file)
After some thought, I've decided I need to rethink how I'll retrieve these files and this is where I'm at a loss considering my underwhelming knowledge of Java still. I find myself hopping around the internet aimlessly looking for answers, which is when I decided I should ask the question directly.
My questions is this: What is the best approach to creating a meaningful file structure which allows me to retrieve (script) files relevant to how I want to process them at runtime?
There are many answers to this problem. The real question is how is this information going to be used by the target audience of this program? That is, are you aiming at developers who can whip up some code? Advanced users that just need to add some configuration? Or the general populace with no significant computer experience?
For the first, you could create your own annotations, and find all the classes in the class path that have the annotation. This would allow developers to add classes to your system just by adding some jars to the class path.
For the second, maybe you could have a plugin directory, and iterate over the files there to find the defined extensions? Or maybe have a configuration file that lists the plugins you should use?
Finally, for a general user, you should make it simple. Have the GUI allow the user to specify additional capabilities by location? or website? Like Firefox addins, maybe?

Is it correct for Java system properties to be used to set and get arbitrary program parameters?

It is possible using -Dproperty=value arguments to set arbitrary system properties (not some fixed set of system properties actually used by the JVM) and a program can get these properties later using System.getProperty("property"). Is it correct to do this?
I haven't found an authoritative answer on this, so that's why I'm asking here. It seems to me that program parameters should be set through command line arguments to the program, not to the JVM. However, perhaps this is an accepted practice that just isn't documented anywhere I've looked so far. I'd like to be sure. Thanks.
I think Java system properties are used to pass values from command line to libraries or plugins inside the execution. It is, that insider component has no direct way to receive the parameter from the main program that's executing it. So it reads it from a "context" that Java system properties are.
If we look at it as layers, command line arguments would be parameters for the inmediate lower layer, and system java properties are context for all the lower layers.
command line: arguments + properties
main program: uses arguments
some library/plugin: uses properties from context
If it's not this way the main program should have to carry all the parameters that user could set to the lower layers and it can be very cumbersome.
I don't like to depend on contextual properties so if I design a program I'd try to pass over all the properties in some non-global way. But it can be very handy some times (and using namespacing it's not probable they collide).
In my opinion this is not "incorrect" and there are programs and libraries that do use their own system properties for configuration.
However, it is probably more practical to put configuration parameters for your software in a configuration file (in whatever format you think is suitable - a .properties file, an XML file, or something else). It is cumbersome, especially if you have many configuration parameters, to have to put all those parameters on the command line with -Dname=value options.
You can use this method to set some of your application settings. I think of settings as a contrast to program arguments. For example. Let's think abount some file converter. It converts file A to B. So files A and B should be command line params. If you converter needs some temporary folder you can make id settable by -Dmy.package.tempfolder=\my\tmp\folder. But there should be a default setting for that and the program should work without this setting.
Think about it as an alternative to .properties file. .properties file will be more convinient of course.
You just have to know what you're doing. If your application is a standalone application, system properties provide an easy to use way to pass named arguments, in any order, to the program, and I don't see anything intrinsically bad in using them.
If your app is a webapp that must be deployed in a app server shared by multiple webapps, then it might not be a good idea, especially if you aren't allowed to change how the server is started, or if you have to deploy multiple versions of the same application.
From http://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html:
For example, the following invocation of getProperty looks up the
System property called subliminal.message. This is not a valid system
property, so instead of returning null, this method returns the
default value provided as a second argument: "Buy StayPuft
Marshmallows!"
System.getProperty("subliminal.message",
"Buy StayPuft Marshmallows!");
This implies that properties other than those used by the JVM are "invalid". However, later in the same document, it gives the example of loading a properties file containing the same property setting.
subliminal.message=Buy StayPuft Marshmallows!
It only advises "In general, be careful not to overwrite system properties."
So it seems that this is a supported use of System Properties. It looks like a case of misleading naming. When I hear "System Properties" I think "properties of the JVM" where the JVM is the system. While the properties are used for this, they can also be used for application settings. I think I'll make a mental note to think of this as "System and Application Properties".
Does anyone disagree with this?

Set System Property for an RCP Program

I have an RCP/Eclipse program and I want to provide it in 2 different flavors. Which flavor it is should be sort of hardcoded or provided as a conf setting that cannot be changed at runtime.
I was first thinking of having one specific class in my plugin duplicated and code the logic of the second flavor into that class and package it somehow as a second RCP program. Then I thought I can simple code the 2 different flavors in one class in the same plugin and differentiate by system property whether logic 1 or logic 2 is executed. Then I could've simply duplicated the RCP package and deliver one with an additional parameter in launcher.ini and the other without that parameter.
Problem is that I can't get a simple Java System Property set in an RCP program. I have tried launcher.exe -Dpropname=propvalue, I have tried adding it to launcher.ini, I have googled the web back and forth. There are lots of documents on the web explaining all the various configuration settings that you can provide as system property or as property to launcher.ini but none explains how to set custom properties.
Does anybody have an idea?
Many thanks,
Kai
go to the run configuration, you will get the arguments tab, there in VM Arguments block you can provide -Dpropname=propvalue. If you have more values you can enter with space or newline separating them.

Keeping i18n resources synced

I am looking for an editor/comparator for i18n property files that would help me keep different language files in sync.
Basically, something that would compare a bunch a of property files and show which keys are not present in a particular language.
a property would look something like
component.titlepage.title = hello world
A simple diff is not possible since the right-hand-side will be different from a language to another.
Our current infrastructure:
Java application
Built using maven2
Different i18n property files for different components of the system. (1 property file per language per component)
The Checkstyle tool, which I typically run as part of every continuous integration build which is done after every check-in to the main branch, will tell you if any given set of properties files has an inconsistent set of properties. When I first started using Checkstyle, I indeed found that a few of my properties files were missing a small number of properties.
This won't help on the editor end, but it will help you efficiently identify any gaps.
If you are using Eclipse, I find the ResourceBundle Editor plugin very handy. You can edit several properties files at the same time and you have warnings when a key is missing in one of the files.
There are also a number of web applications that allow you to do that (along with many other activities). To name a few:
Amanuens (disclaimer: my company builds this product)
Transifex
Get Localization

Encapsulating Java Preferences API

I used to have a custom preferences class for my applications. For my next hobby project i wanted to switch to the Preferences API. But the put and get functions require a default value and i do not want to spread default values all over the source files. Even though my project is small i can not imagine changing default values all over the source code. How do you guys use the api? I am thinking of wrapping the preferences api in another class but then what is the point of using the API because it only takes away the burden of saving the file to disk, which isn't that hard using serialization? Am i missing the point?
You're mixing a few concepts here. The default given in the code should be specific to the local situation as a 'reasonable default'. If you want to have application-wide defaults, then you need a preference-provider that allows you to hook in both the default preferences and an overlaid user-preferences. Something that may be a worthwhile project in itself.
Oh, and "reasonable defaults" is a great way to avoid configuration when it's not necessary but allow the user or packager to provide better values when needed.
#comment, I think I understand.
By 'local situation' I mean in the context of the code. For your GUI, you need a value for display that represents whatever the thread is using. Therefore I'd use something like Worker.DEFAULT_TIMEOUT. Your worker would use the same value internally as the default. That way you are retrieving the configured value or the worker's default when you are setting the worker's behavior.
then you might want to take full control over how Preferences should follow your desired storage by implementing AbstractPreferences. You can see a linux based implementation here:
http://www.docjar.com/html/api/java/util/prefs/FilePreferencesImpl.java.html
Good luck!
Would it be so hard to stick all your defaults in a single class so that they weren't littering your code?
I've used commons configuration in recent projects. I've looked into the Java Preferences API but I like the flexibility of the Commons project. And you don't have to specify default values!
You can put default values in .preferences file which you bundle in your .jar file (or in specialized class or interface with constants).
I use it for things like window positions/sizes, remembering default folder for choosing files, last opened files and such trivia. I can think of some interesting things you get "for free" with preferences API:
doing things in OS-recommended way; OS might not allow you to write "settings files" in your app folder, and users don't like to be asked where on disk they want to save settings, and you don't want to implement your custom logic for every platform
your data is saved for each OS user separately
a way to keep user data even if your application is uninstalled (or during an upgrade)
don't need database or access to file system
Also, I don't like serialization and don't recommend it for this. Serialization means you have to take care when changing your classes in new versions of your application.

Categories

Resources