Bean-style Initialization With init
Resin

Change Log
Documentation

Orientation
Features
Installation
Configuration
Web Applications
JSP
Servlets and Filters
Databases
Admin (JMX)
Security
XML and XSLT
XTP
Resources (JNDI)
Performance
Protocols
Third-party
Troubleshooting

env
web-app
resin.conf
log
el vars
init
index
Common Tasks
Relax Schema
Config FAQ
Scrapbook
el vars
Configuration
index

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.

  1. Setting a single value
  2. Setting multiple values
  3. Type conversion
  4. init()
  5. Exceptions
  6. Sub beans
  7. Setting with the body text
  8. Returning a different object
  9. resin:type

    init

    child of: resource, access-log, authenticator, login-config, web-app, filter, servlet

    Configures Java Bean-style objects.

    Setting a single value

    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;
      }
       
    }
    

    Setting multiple values

    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);
      }
    
    }
    

    Type conversion

    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;
      }
    }
    

    init()

    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);
      }
    }
    

    Exceptions

    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
    

    Sub beans

    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) {
            }
          }
        }
      }
    
      ...
     
    }
    

    Setting with the body text

    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; }
      }
    }
    

    Returning a different object

    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

    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.


    el vars
    Configuration
    index
    Copyright © 1998-2003 Caucho Technology, Inc. All rights reserved.
    Resin® is a registered trademark, and HardCoretm and Quercustm are trademarks of Caucho Technology, Inc.