| |
Application configuration files using a custom JNDI object |
A common requirement is the need to read, and possibly write,
configuration files for an application. An excellant way to
accomplish this is to implement a custom JNDI object, which is
easily configured and easily obtained from anywhere in the
application.
This implementation of the concept allows you to configure a base
directory for configuration files, and use the object obtained with a
jndi lookup to open files relative to the base directory.
The java code for a custom JNDI object |
A custom JNDI object is implemented similar to a java-bean. Setter
methods like setFoo(String foo) are used to set values
that are specified in the configuration.
In this case, a single setter is provided that matches the
configuration parameter "config-files-location"
package example;
import java.net.*;
import java.io.*;
import com.caucho.vfs.*;
public class AppConfig {
ConfigFilesLocation _cfl = null;
/**
* Set the base for subsequent call's to openConfigFileRead()
* and openConfigFileWrite()
*
* @param location a file path or url
*/
public void setConfigFilesLocation(String location)
throws Exception
{
_cfl = new ConfigFilesLocation();
_cfl.setLocation(location);
}
public void init()
throws Exception
{
if (_cfl == null)
throw new Exception("'config-files-location' must be set");
}
/**
* Create and return a ReadStream for a configuration file, with
* the file being relative to the base previously set with
* setConfigFilesLocation()
*
* @return a WriteStream, which can be treated as a
* java.io.InputStream if desired
*
* @see java.io.InputStream
*/
public ReadStream openConfigFileRead(String file)
throws IOException
{
return _cfl.openRead(file);
}
/**
* Create and return an WriteStream for a configuration file, with
* the file being relative to the base previously set with
* setConfigFilesLocation().
*
* @return a WriteStream, which can be treated as a
* java.io.OutputStream if desired
*
* @see java.io.OutputStream
*/
public WriteStream openConfigFileWrite(String file)
throws IOException
{
return _cfl.openWrite(file);
}
public static class ConfigFilesLocation {
Path _path; // com.caucho.vfs.Path
public void setLocation(String location)
{
_path = Vfs.lookup(location);
}
public ReadStream openRead(String file)
throws IOException
{
Path p = _path.lookup(file);
return p.openRead();
}
public WriteStream openWrite(String file)
throws IOException
{
Path p = _path.lookup(file);
return p.openWrite();
}
}
}
|
Configuring the custom JNDI object |
Configuration of the JNDI object is done with the
resource-ref tag.
The example here configures the location of the configuration files
as WEB-INF/config (which means you need to make
sure the directory exists for the example to work). It is good to
hide the files somewhere under WEB-INF, because a browser
will not be able to read the files, just the application.
<web-app>
<!-- make an example.AppConfig object, available with the
- JNDI name "java:comp/env/config/Application"
-->
<resource-ref res-ref-name='config/Application'
class-name='example.AppConfig'>
<!-- config-files-location
-
- set's the base for subsequent config file lookups.
-
- EL variables are very useful here, such as
- app.appDir, server.rootDir, host.rootDir
- See http://www.caucho.com/resin-3.0/config/el.xtp
-
- You can also use an http url, although you will not be able
- to write files then.
-->
<init-param config-files-location='${'${'}app.docDir}/WEB-INF/config'/>
<!-- <init-param config-files-location='http://gryffindor/config'/> -->
</resource-ref>
...
</web-app>
|
Obtaining and using the object |
An instance of the object is retrieved in the application using
JNDI. Since the configuration will not change, it is best to store the
results of the lookup.
In this example servlet, an instance of the object is retrieved in
the init() method and then used in the doGet() to open the
configuration files for reading and writing.
package example;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import javax.naming.*;
public class TestAppConfig extends HttpServlet {
AppConfig _appConfig;
final static String _jndi_name = "java:comp/env/config/Application";
public void init()
throws ServletException
{
try {
_appConfig = (AppConfig) new InitialContext().lookup(_jndi_name);
if (_appConfig == null)
throw new ServletException("`" + _jndi_name + "' is an unknown JNDI resource");
} catch (NamingException e) {
throw new ServletException(e);
}
}
public void doGet(HttpServletRequest req,
HttpServletResponse res)
throws IOException, ServletException
{
res.setContentType("text/html");
PrintWriter out = res.getWriter();
String inputFile = req.getParameter("inputFile");
String outputFile = req.getParameter("outputFile");
out.println("<html><head><title>TestAppConfig</title></head><body>");
if (inputFile != null && inputFile.length() > 0) {
// demonstration of reading a configuration file
out.println("<h2>inputFile: " + inputFile + "</h2>");
try {
// copy the input file to the output
InputStream is = _appConfig.openConfigFileRead(inputFile);
final int bufsz = 1024;
char[] buf = new char[bufsz];
int l;
Reader in = new BufferedReader(new InputStreamReader(is));
out.println("<pre>");
while ((l = in.read(buf,0,bufsz)) > 0) {
out.write(buf,0,l);
}
out.println("</pre>");
} catch (Exception ex) {
throw new ServletException(ex);
}
} else if (outputFile != null && outputFile.length() > 0) {
// demonstration of writing a configuration file
out.println("<h2>outputFile: " + outputFile + "</h2>");
try {
OutputStream os = _appConfig.openConfigFileWrite(outputFile);
PrintWriter outfile = new PrintWriter(os);
Date now = new Date();
outfile.print("Configuration file made from 'TestAppConfig' ");
outfile.println(now);
outfile.close();
} catch (Exception ex) {
throw new ServletException(ex);
}
String url = res.encodeURL(req.getRequestURI() + "?inputFile=" + outputFile);
out.println("The configuration file has been written.");
out.println("You can now <a href='" + url + "'>view it as an inputFile</a>");
} else {
outputFile = "test.txt";
String url = res.encodeURL(req.getRequestURI() + "?outputFile=" + outputFile);
out.println("Try <a href='" + url + "'>writing to a configuration file</a>");
}
}
}
|
To enable the servlet, you can add the following to
WEB-INF/web.xml, and the url will be (for example)
http://localhsot:8080/myapp/test
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>example.TestAppConfig</servlet-class>
</servlet>
<servlet-mapping>
<url-pattern>/test</url-pattern>
<servlet-name>test</servlet-name>
</servlet-mapping>
|
Copyright © 1998-2002 Caucho Technology, Inc. All rights reserved.
Resin® is a registered trademark,
and HardCoretm and Quercustm are trademarks of Caucho Technology, Inc. | |
|