How To Manage Your Application Properties using WebDAV

Managing the configuration of an application is a consistent pain-point for developers, administrators, and business analysts.

Often in production environments, configuration is isolated as files on the local disk, limiting easy access by all but administrators. Another common approach is to store configuration in a database or LDAP. While this have benefits of a local disk file, it lacks the ability to manage properties as naturally as a file.

The solution proposed uses a database and WebDAV to help resolve many negatives to do with application configuration in both a simple and lightweight way.
In the first blog in the WebDAV series, we discussed a simple example of how you can use WebDAV to create an online network drive, to illustrate how WebDAV can quickly enhance your application. I recommend reading it first before moving onto this blog.

Solution Features

We can help resolve those pains and have added benefits just by using a database and WebDAV. This approach allows for accessibility (both read & read/write) for a larger set of user types, and allows those users the ability to:

view and edit individual properties from their favorite text editor

backup & restore property files quickly, by just zipping them up for example

migrate property files from one environment to another by copying over a folder

All this is packaged as a simple add-on that can be quickly integrated to your existing web application.

Design

File & Folder Structure

This is an example of how the mapped drive would appear when mounted:

Folders are nested and can be named accordingly to the type of properties that are held. Property files appear as you would expect under folders (or at the root level as well). Here we have put configuration specific to countries under the “country configs” folder with the country in the name of the file.

Schema

Below is the simple schema that is used:

It allows having a recursive tree structure by the self-referencing folder table. Files contain a set of properties and existing within a folder. Properties are stored in the property table as String key-value pairs. Basic DAO classes facilitate CRUD operations on the files and folders.

Properties to File and File to Properties Transformation

To keep things simple and consistent, we use the existing methods present in the Properties class to generate a file from properties and vice versa. By using this method, properties appear in the file content as key-value pairs, one per line separated by ‘=’ as you commonly see String properties represented.

Usage

Of course, having your application read these properties is vital. To that effect, there is a class called WebDAVProperties where your application can both read and write properties:

Properties WebDAVProperties.getProperties(String path) where path is the fully qualified path of the properties resource.

void WebDAVProperties.saveProperties(String path, Properties props) where path is the fully qualified path of the properties resource.

Saving the properties using the above method calls the necessary DAOs to persist the properties in the schema.

Implementation

Class Diagram

Model Objects

There are 2 model objects in use in this approach (besides the java.util.Properties object). Both are under the package com.northconcepts.webdav.model.

The FolderInfo self-references to allow it to keep track of it’s parent. For each FolderInfo, there can be any number of FileInfos, directly mapping to a typical file systems model. Each FileInfo has a Properties class to maintain the contents of the file.

DAO

Under the package com.northconcepts.webdav.dao you will see 3 DAO classes: FileDAO, FolderDAO, and PropertyDAO.

FileDAO

List<FileInfo> getFilesInFolder(FolderInfo fi) – gets the list of files that are in the specified folder

FolderInfo createFolder(final String name, final FolderInfo parentFolder) – persists a folder based on the specified values and returns that folder

void deleteFolder(final int id) – deletes the folder by it’s id

void moveFolder(final int id, final int destFolderId, final String name) – moves the folder of the specified id to below the specified destination folder id and rename the folder to the new name

PropertyDAO

Properties getProperties(final int fileId) – gets all the property key-value pairs for the given file’s id

FileInfo createProperties(final String name, final Properties props, final FolderInfo folder) – persists a properties based on the specified key-value pairs, name and folder location

WebDAV Implementation

For a simple Milton Java WebDAV Server Library in-memory implementation example with just a single file and no folders, please review the previous blog post. Similar to the aforementioned model objects, we have 2 classes implementing the various WebDAV Resource interfaces: DavFolder and DavFile.

WebDAV Resource Interfaces

Key to this part of the implementation is understand the behavior implications by implementing specific Resource interfaces.

GetableResource – allows the content of the resource can be retrieved

DeletableResource – allows the resource to be deleted

CollectionResource – the resource to have children implying the directory behavior

PutableResource – allows file resources to be created as children below it

MakeCollectionableResource – allows folder resources to be created as children below it

MoveableResource – allows the resource to be moved to a child of another folder

Properties Processing

Since we want to be able to read the contents of a file as well as delete the file, we need to implement the interfaces GetableResource and DeletableResource.
Below is the sendContent(...) method of the DavFile class, required by the GetableResource interface:

This method is using the existing list method of the Properties class to render the content of the file.
The opposing act of persisting properties by file creation, that is driven by the createNew(...) method of the DavFolder class:

log.debug("attempting to create a new file in this folder name={} length={} contentType={}",newObject[]{name,length,contentType});

//CHECK IF INVALID NAME

if(Util.isEmpty(name)){

log.error("bad request when creating a file");

thrownewBadRequestException(this);

}

//ASSERT NO CONFLICT WITH THE NAME

assertNoConflict(name);

//LOAD STREAM TO A PROPERTIES OBJECT

Propertiesp=newProperties();

p.load(is);

//PERSIST THE PROPERTIES AND RETURN THE DAV-WRAPPED NCPROPERTIES

returnnewDavFile(PropertyDAO.createProperties(name,p,f));

}

Once again we are using a provided method in the Properties class to parse and load the properties coming from the input stream.

MyResourceFactory Implementation

Finally, to be able to produce the file system structure as designed, the class implementing the ResourceFactory uses recursion to determine, based on the path, whether to offer back a appropriate folder, or the appropriate file.

The recursive search, shown below, essentially works by iterating through the path, where each part of the path is determined if it’s a folder or a file; if its a folder and there are more path parts then we recursively search within that folder with the remainder of the path.

Download & Install

Step 1

The WebDAV download contains the entire source code (including Eclipse project). The source code is licensed under the terms of the Apache License, Version 2.0. Download this source code and import the project to your Eclipse workspace.

Step 2

Run the MySQL create_script.sql script located in the project folder src-database/scripts in your MySQL database. If you are using another type of DB other than MySQL, please refer to the schema diagram under src-database/model to create the three necessary tables as illustrated.

Step 3

Add a Resource to define a data source for the application to use in your Tomcat context.xml file. Below is an example:<Resource name="jdbc/MySQLDB" auth="Container" type="javax.sql.DataSource" username="root" password="password" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/test?autoReconnect=true"/>

Step 4

Create, if it doesn’t already exist, a Apache web server instance in Eclipse and publish the application to that server. Then start the application server.

Step 5

Concluding Thoughts

Certainly we have all felt the pain of managing application configuration from development environments through to production. This approach attempts to solve some of this pain. The example code provided can be plugged into your application to allow you to quickly move forward on improving the configuration efficiency and accessibility. More valuable, the design and implementation could inspire you to consider other objects your application uses or persists which can be expressed as a file system, giving you unprecedented accessibility.

Hello Kuhan,
thanks for the easy to user WebDAV server code. The only problem I have is to create folders and/or files. The Mac OS file systems somehow seems to be read only – although it is not normally -.
So I had to enter the folders and files records by hand in MySql.
My example-2 web app then can read and shows the folders and fields using my finder Mac file system app.
Can you please give me a hint what I need to do to get writer and delta permissions?