With Resin, the init tag configures Java Bean-style objects.
A "Java Bean" is just a Java class that follows a simple set of rules.
Because Resin can find the bean-style setters from looking at the
class, it can configure those setters in a configuration file like the
web.xml.
init
child of: resource, access-log, authenticator, login-config, web-app, filter, servlet
Configures Java Bean-style objects.
Each configuration parameter foo has a corresponding setter method
setFoo with a single argument for the value. Resin
looks at the class using Java's reflection to find the setFoo
method.
Bean-style configuration for a single value setter
<init>
<greeting>Hello, World!</greeting>
<another-greeting>Hello, Mom!</another-greeting>
</init>
|
Bean-style java code for a single value setter
public class MyBean {
private String _greeting;
private String _anotherGreeting;
public void setGreeting(String greeting)
{
_greeting = greeting;
}
public void setAnotherGreeting(String anotherGreeting)
{
_anotherGreeting = anotherGreeting;
}
}
|
A setter method addFoo allows multiple values to be
specified from the configuration.
Bean-style configuration for setting multiple values
<init>
<greeting>Hello, World!</greeting>
<greeting>Hello, Mom!</greeting>
</init>
|
Bean-style java code for setting multiple values
public class MyBean {
private LinkedList _greetings = new LinkedList();
public void addGreeting(String greeting)
{
_greetings.add(greeting);
}
}
|
A setter can have a parameter that has a type other than
String. Resin will perform any type conversion
necessary, so you can use integers and doubles as well as strings.
Bean-style configuration for type conversion
<init>
<host>www.gryffindor.com</host>
<port>80</port>
</init>
|
Bean-style java code for type conversion
public class MyBean {
private String _host;
private int _port;
public void setHost(String host)
{
_host = host;
}
public void setPort(int port)
{
_port = port;
}
}
|
After all of the setters have been called, the init() method is
called, if it exists.
Bean-style init()
public class MyBean {
private String _language;
private String _country;
Locale locale;
public void setLanguage(String language)
{
_language = language;
}
public void setCountry(int country)
{
_country = country;
}
public void init()
{
locale = new Locale(language,country);
}
}
|
If an exception is thrown from any of the methods in the bean,
Resin will attach a file name and line number that correspond to the
configuration file.
Bean-style exceptions
public class MyBean {
private String _language;
private String _country;
Locale _locale;
public void setLanguage(String language)
throws Exception
{
if (language.length() != 2)
throw new Exception("'language' must be a two-character string");
_language = language;
}
public void setCountry(int country)
throws Exception
{
if (country.length() != 2)
throw new Exception("'country' must be a two-character string");
_country = country;
}
public void init()
{
if (_country == null)
throw new Exception("'country' is required");
if (_language == null)
throw new Exception("'language' is required");
_locale = new Locale(language,country);
}
}
|
500 Servlet Exception
WEB-INF/web.xml:9: java.lang.Exception: 'country' must be a two-character string
|
Beans can be nested, allowing a bean to have setters that have
other sub-beans as the type.
Bean-style configuration for sub-beans
<init>
<table>
<name>Foo</name>
<timestamp-field>tstamp</timestamp-field>
</table>
<table name="Bar" timestamp-field="ts"/>
</init>
|
Bean-style java code for sub-beans
// a class to periodically clean old log records from the database
public class LogCleaner {
List _logTables = new LinkedList();
// the createXXX method is optional, and allows use something other than
// the default constructor for a sub-bean
public LogTable createTable()
{
return new LogTable();
}
// you could also use setTable(LogTable logTable)
public void addTable(LogTable logTable)
{
_logTables.add(logTable);
}
public class LogTable {
String _name;
String _timestampField;
public void setName(String name)
{
_name = name;
}
public void setTimestampField(String timestampField)
{
_timestampField = timestampField;
}
public void init()
throws Exception
{
if (_name == null)
throw new Exception("'name' is required");
if (_timestampField == null)
throw new Exception("'timestamp-field' is required");
}
public void cleanTable(DataSource pool)
{
Connection conn = null;
try {
conn = pool.getConnection();
...
} catch (SQLException e) {
throw new ServletException(e);
} finally {
try {
if (conn != null)
conn.close();
} catch (SQLException e) {
}
}
}
}
...
}
|
The addText() method will capture the body of the tag
for a bean setter.
Bean-style configuration for setting with the body text
<init>
<message>This is the message</message>
</init>
|
Bean-style java code for setting with the body text
public class MyBean {
Message _msg;
public Message createMessage() { return new Message(); }
public void setMessage(Message msg) { _msg = msg; }
public class Message {
String _text;
public void addText(String text) { _text = text; }
public String getText() { return _text; }
}
}
|
There are some unusual cases where the configured bean is just a
configuration object and you want to return a different bean. The
bean can implement a method Object replaceObject() to return a
different object. Called after the init().
resin:type
This special attribute can be used with all sub-beans to
instantiate a different bean class than the one defined in the parent
bean.
If a sub-bean is returned from method like SubBean
createSubBean() then resin:type cannot be used. A
void setParent(Object obj) method in the sub-bean, which
is called before the other setters, provides an opportunity for the
sub-bean instance to know it's enclosing object.
The resin: in resin:type is a namespace prefix automatically
mapped to http://caucho.com/ns/resin. You could use another namespace
prefix, for example if you defined
xmlns:foo="http://caucho.com/ns/resin", you could use foo:type.
Bean-style configuration for using resin:type
<resource jndi-name="env/message">
<type>example.MessageBean</type>
<init>
<message>This is message 1</message>
<message>This is message 2</message>
<message resin:type="example.CustomMessage">This is message 3</message>
</init>
</resource>
|
MessageBean.java
package example;
import java.util.*;
public class MessageBean {
List _msgs = new LinkedList();
public void addMessage(Message msg)
{
_msgs.add(msg);
System.out.println("MessageBean.addMessage(): " + msg);
}
// this never get's called, because MessageBean has no parent
public void setParent(Object obj)
{
System.out.println("MessageBean.setParent(): " + obj);
}
}
|
Message.java
package example;
public class Message {
String _text;
public void addText(String text)
{
_text = text;
System.out.println("Message.addText(): " + text);
}
public void setParent(Object obj)
{
System.out.println("Message.setParent(): " + obj);
}
public String toString()
{
return super.toString() + ": " + _text;
}
}
|
Message.java
package example;
public class CustomMessage extends Message {
public void addText(String text)
{
_text = text;
System.out.println("CustomMessage.addText(): " + text);
}
public void setParent(Object obj)
{
System.out.println("CustomMessage.setParent(): " + obj);
}
}
|
Message.setParent(): example.MessageBean@ffb35e
Message.addText(): This is message 1
MessageBean.addMessage(): example.Message@1591b4d: This is message 1
Message.setParent(): example.MessageBean@ffb35e
Message.addText(): This is message 2
MessageBean.addMessage(): example.Message@10f965e: This is message 2
CustomMessage.setParent(): example.MessageBean@ffb35e
CustomMessage.addText(): This is message 3
MessageBean.addMessage(): example.CustomMessage@12164ea: This is message 3
|
In practice, it may make more sense to use createSubBean or
addSubBean to set a parent-child relationship for beans, instead
of setParent. The possible issue with addSubBean is that init() is
called before addSubBean. The possible issue with createSubBean is that it's
not possible to use a resin:type with createSubBean. So the setParent is
useful when the init() needs the parent, and you need to use
resin:type.
Copyright © 1998-2003 Caucho Technology, Inc. All rights reserved.
Resin® is a registered trademark,
and HardCoretm and Quercustm are trademarks of Caucho Technology, Inc. |  |
|