HotDeploy is a Java library which allows you to make plugins of your application hot deployable.
Assume you have an application which can be extended by means of plugins. A static approach would load these plugins at startup and to add, modify or remove a plugin you would have to restart your application. HotDeploy now allows you to dynamically change the deployed plugins.
What is a plugin? Technically speaking, for HotDeploy a plugin is a set of Java classes bundled into a jar file. Less formally, a plugin should bundle some functionality which may or may not be made available to an application at runtime.
How to write a plugin A plugin is recognized as such if one of its classes implements the Plugin interface. Therefore to code a plugin you simply derive one of its classes from the Plugin interface. Since the Plugin interface by itself does not offer any functionality (its an empty interface), it doesn't make much sense to only implement this interface. So in real life, you would create another interface (which is not empty) in the application where you want to use your plugins. This interface, which may be called MyPlugin, will extend the Plugin interface. Now whenever you write one of your plugins (which implements the MyPlugin interface) it will be recognized as a plugin by HotDeploy since it also implements the Plugin interface.
// from HotDeploy public interface Plugin {} // in your application public interface MyPlugin extends Plugin { ... } // one of your plugins public class APlugin implements MyPlugin { ... }
How to start/stop HotDeploy
start: Create plugins, put them in a directory and call PluginContainer.initHotDeployment() with appropriate configuration properties.
Map<String, String> properties = new HashMap<String, String>(); properties.put("pluginDir", "./plugins/"); properties.put("pluginScanInterval", "10000"); properties.put("runGCOnShutdown", "false"); PluginContainer.initHotDeployment(properties);
stop: Call shutdown.
PluginContainer.getInstance().shutdown();
Usage
After HotDeploy has been started, you may get a reference to a single plugin by using getPlugin() passing
it a classname.
To get all currently registered plugins, either call getClassnames() to get the all the classnames of
the plugins and afterwards call getPlugin() using some of the classnames, or use getPlugins()
to directly get references to all plugins.
Whenever a plugin is added, changed or removed in the plugin directory, HotDeploy will detect that change
and notify its registered observers. Therefore if you are interested in these changes, just register as an
observer.
To explicitly delete a plugin, either just remove the plugin jar or call deletePlugin().
Configuration Properties Properties which may be provided to PluginContainer.initHotDeployment():
HotTables is natural extension of HotDeploy which allows your plugins to define database tables.
When to use it?
Assume you have a set of plugins. Now the issue arises, that some of your plugins would like to store data into a database. Therefore each plugin should have a simple way do define the tables it wants to use. After the tables are defined, they should be automatically created.
If you run into such a case you might give HotTables a try - read on...
What HotTables does:
HotTables provides you with three interfaces (Table
, ForeignKey
, StorablePlugin
) which allow you to define database tables in your plugins. After the tables have been defined, the DbManager
can be used to create the tables. The DbManager
also does a regular backup (using BucketBackup) and enables access to the tables through an object oriented approach (using InfoAccess).
How to use it? A typical usage would look like this:
// hotdeploy config Map<String, String> properties = new HashMap<String, String>(); properties.put(PluginLoader.PLUGIN_DIR_PARAMNAME, "./plugins/"); properties.put(PluginLoader.SCAN_INTERVAL_PARAMNAME, "60000"); // hotdeploy init PluginContainer.initHotDeployment(properties); Set plugins = PluginContainer.getInstance().getPlugins(); log.info("Plugins: " + plugins.size() + " " + plugins); // hottables String driver = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://localhost/hottables_test?user=hottables&password=hottables"; int cacheExpireTime = 3600000; long interval = 3600000; String backupDir = "./backup/"; // hottables init DbManager dbm = DbManager.getInstance(); dbm.setInfoAccessProps(driver, url, cacheExpireTime); dbm.setBackupProps(interval, backupDir); dbm.setCoreTables(new ArrayList<Table>()); dbm.init(); // do something usefull try { log.info("Table names: " + dbm.getTableNames()); log.info("JDBC connection: " + dbm.getConnection()); log.info("InfoAccess: " + DbManager.getInfoAccess()); } catch (Exception e) { e.printStackTrace(); } // shutdown PluginContainer.getInstance().shutdown(); DbManager.getInstance().shutdown();
When HotTables is initialized, you may get the database table names getTableNames()
, get a plain JDBC connection getConnection()
or access the tables through InfoAccess getInfoAccess()
.
How to define tables?
Your plugin interface (e.g. MyPlugin
) should no loger extend Plugin
(as in the description for HotDeploy), but instead extend StorablePlugin
. This causes all your plugins to implement the getTables()
method. To a call to this method, return your table definitions. A possible hierarchy of interfaces and classes is shown below:
// from HotDeploy public interface Plugin {} // from HotTables public interface StorablePlugin extends Plugin { public List<Table> getTables(); } // in your application public interface MyPlugin extends StorablePlugin { ... } // one of your plugins public class APlugin implements MyPlugin { ... }
This small Java program allows to start a regularly executed database backup.
Its backup files are kept in a directory. To ensure that the number of backup files doesn't grow too large, it uses an idea of buckets to put the files in. Every bucket may contain only one file. BucketBackup loops over every file found in the backup dir. It then tries to put the backup file in the youngest bucket found which is older then the backup file. If this bucket already contains a file, the newer file of the two is deleted. The buckets are choosen in a way, that fewer backup files are kept, the older the files get.
Thus the older the backup files are, the fewer they become.
The backup files consist of simple SQL insert statements and stored in plain text. This might be not the most performant solution possible, but its easy to use and may work with many database vendors. Currently only java.sql.Types.INTEGER and columns which can be mapped to a String (e.g. dates) are supported. The best tested DBMS is MySQL.
Usage: There are at least two ways this program may be used - as a standalone application or as a library for another Java program.
Standalone:
java -cp <classpath> org.hotdeploy.bucketbackup.Main
(example shell script).
Java Library:
InfoAccess is an easy to use Java Library to access a database using Java objects. It is another abstraction layer above JDBC, which provides a more object oriented way of accessing the database. A typical usage example looks like this:
InfoAccess infoaccess = new SqlInfoAccess(props); InfoBean infobean = infoaccess.get(type, id, readOnly); Object value = infobean.getProperty(propname); Collection<InfoBean> beans = infoaccess.query(type, filter, ordering, readOnly);
InfoAccess has support to
InfoBean newbean = InfoAccess.create(String type);
InfoAccess.save(InfoBean bean, TransactionContext context);
InfoAccess.delete(InfoBean bean, TransactionContext context);