Caucho Technology
  • resin 4.0
  • injection-based resource configuration (candi)


    Resin's configuration uses a powerful, general dependency injection system (CanDI) to configure servlets, Resin resources, databases, application components, third-party libraries and drivers. By understanding a few rules matching the XML to the configured resources, an administrator can have full control over the application server behavior.

    Because of the importance of verifying and debugging configuration, Resin's configuration is stateless, meaning that the XML files fully describe the configuration of the system. Resin avoids hidden state by avoiding deployment tools and internal, hidden database configuration.

    Overview

    Because Resin's configuration (CanDI) creates and updates Java objects, each XML tag exactly matches either a Java class or a Java property. For security and rewrite rules, the JavaDoc helps document the configuration. Your own application's configuration can use its JavaDoc to describe the XML tags, and Resin's configuration files like the META-INF/resin-web.xml to customize your application.

    • Selecting drivers and services: by specifying the Java class, like choosing a JDBC database driver, or application services. The Java classes should be self-documented in the application's JavaDoc.
    • Configuring properties: with XML values for each important property of the Java class, like setting URLs, timeouts, and connection limited. More complicated configuration is supported allowing configuration similar to domain-specific languages, for example Resin's rewrite rules and security configuration.
    • Registration for the application: the application looks up configured resources either through Java Injection or in JNDI. The application will already have defined names and binding types for the XML configuration to use.
    • Linking references: in some more complicated applications, the configuration can link resources and services together using the JSP expression language, specifying resources by name like #{myResource}.

    XML configuration

    Services, drivers, and third-party libraries are registered and configured using the standard Resin configuration files resin.xml or resin-web.xml files as well as the META-INF/beans.xml. Application services and libraryes are treated as first-class components just like Resin-internal resources, because Resin's own configuration uses the same CanDI configuration. Even standard JavaEE configuration like servlets, JSP .tld files, and EJBs are configured with CanDI.

    The configuration in Resin is smaller than some other dependency frameworks because only components which need customization need to be in the XML. If your application is using Java Injection internally, most of the wiring occurs automatically through Java code annotations instead of being configured in XML. The annotation focus makes the Java code self-describing, and also simplifies the management by shrinking the needed XML.

    The XML-configuration lets you customize your application for a particular environment, e.g. setting configuration parameters. For example, Resin's <database> needs to select a database driver and configure the URL, user and password of the database as well as configuring connection pooling parameters. Some application services will also need configuration.

    In addition, the XML-configuration documents the services you've enabled. For heavyweight services, this documentation is critical, while lightweight components do not need this extra housekeeping overhead.

    Component overview

    Component/Bean configuration template
    <web-app xmlns="http://caucho.com/ns/resin"
             xmlns:mypkg="urn:java:com.mycom.mypkg">
    	   
      <mypkg:MyBean>
        [class annotations, service, and registration]
        
        [bean constructor args]
        
        [property configuration]
        
        [method annotation configuration]
      </mypkg:MyBean>
      
    </web-app>
    
    1. The Bean/Component name and package is the Java class which implements the resource you're configuring, either your own application class, or a library class.
    2. The class annotations register up the bean using a binding-type, or a name and may register the bean as a service, like a servlet, or EJB or remote service.
    3. The optional bean constructor args are needed for some specialized beans. The application or library JavaDocs will document if you need to use the constructor.
    4. The properties configure the bean, like setting a database's url or max-connections. Each XML tag represents a bean property, and matches exactly with the bean's JavaDoc.
    5. The optional and rare method annotations are for special cases like aspect-oriented interception. Typically, these annotations are configured by the library developers.

    Service and component registration

    The <my:MyBean> tags register application classes with Resin. The default scope of a <my:MyBean> is @Dependent. A <my:MyBean> will create a new instance each time it's injected or referenced.

    Example: bean and component META-INF/beans.xml
    <Beans xmlns="urn:java:ee" xmlns:example="urn:java:example">
    
      <example:MyService>
        <ApplicationScoped/>
      </example:MyService>
    
      <example:MyComponent>
      </example:MyComponent>
    
    </Beans>
    

    The <my:MyBean> tags can configure fields and annotations:

    XML annotations
    ATTRIBUTEDESCRIPTION
    <Named>the @javax.enterprise.inject.Named annotations for EL naming
    <BindingType>any @javax.enterprise.inject.BindingType annotations for injection
    my:myFieldoptional configuration, using bean-style assignment
    <SessionScoped>specifies scope of the instances: request, conversation, session, application, or singleton

    References and EL Expressions

    Some services and components need a name because they're used as a JSP or JSF reference, or because the configuration needs a reference to the component. Resin configuration files can use EL expressions to get references to resources, beans, system properties, and calculate generatal expressions based on those values. Because all Resin's resources are added to the CanDI registry automatically, application components have access to anything they need.

    Both the JSP immediate syntax and deferred syntax are supported (${...} vs #{...}). Currently, there is no distinction between the two, but the deferred syntax is preferred, because CanDI initializes beans lazily to handle circular references.

    Example: circular references in resin-web.xml
    <web-app xmlns="http://caucho.com/ns/resin"
           xmlns:qa="urn:java:qa">
    
      <qa:FooBean>
        <Named>a</Named>
        <qa:bar>#{b}</qa:bar>
      </qa:FooBean>
    
      <qa:FooBean>
        <Named>b</Named>
        <qa:bar>#{a}</qa:bar>
      </qa:FooBean>
    
    </web-app>
    

    You can also use beans as factories in the EL expressions, because Resin's EL implementation allows method expressions. If the bean's create method is named create(), the EL expression will look something like #{foo.create()}.

    Property configuration

    Resin's Java Injection configuration uses the standard JavaBeans patterns to configure properties. Resin uses the same mechanism for all of its own configuration parsing, including every JavaEE configuration file, the resin-web.xml and the resin.xml itself. So your application will have all the configuration flexibility it needs.

    Since the component beans can use Java Injections, injected components are typically not configured in the resin-web.conf, avoiding the need for tags like <ref>.

    Example: Hello.java
    package example;
    
    public class Hello {
      public void setGreeting(String greeting);
    }
    

    The basic example sets a greeting property of a hello, world bean. Resin will apply the configuration to the instance as part of the creation process.

    Example: META-INF/beans.xml configuring a singleton
    <Beans xmlns="urn:java:ee" xmlns:example="urn:java:example">
    
      <example:Hello>
        <example:greeting>Hello, World</example:greeting>
      </example:Hello>
    
    </Beans>
    

    primitive conversions

    Resin automatically converts XML values to the Java property types for most primitive values. For other primitive types, it also supports the JavaBeans PropertyEditor and custom converters.

    Built-in String Converters
    TYPEEXAMPLES
    Stringhello, world
    booleantrue, false
    numbers3, -4, 3.14, 9.3e-20
    chara, b
    String[]foo, bar, baz
    Classcom.foo.MyBean
    Pathfile:/var/data/file
    File/var/data/file
    URLhttp://hessian.caucho.com/test
    Patterna+[bcd]*
    Date2009-07-14 10:13
    Propertiesa=value
    EnumerationRED, BLUE

    enumerations

    Enumerations are automatically converted from their string representation.

    compound types

    Full sub-bean configuration is also available when a service needs a more complicated configuration than primitives allow. The service class can add sub-beans as properties and the sub-beans themselves are configured recursively using Resin's configuration. Since all JavaEE configuration files like the web.xml and the *.tld files are configured using Resin's recursive sub-bean configuration, your application has full access to a powerful recursive configuration.

    A sophisticated application can use Resin's sub-bean configuration to create a full domain-specific language, allowing extensive user control of the application.

    custom sub-beans

    Example: sub-bean configuration example
    <web-app xmlns="http://caucho.com/ns/resin">
    
      <example:Theater xmlns:example="urn:java:example">
        <example:name>Balboa</example:name>
    
        <example:movie title="The Princess Bride"/>
    
        <example:movie title="The Maltese Falcon"/>
      </example:Theater>
    
    </web-app>
    

    In this example, the Theater is configured with multiple Movie classes, each added with the addMovie method.

    Example: Theater.java
    public class Theater {
      public void setName(String name);
    
      public void addMovie(Movie movie)
    }
    
    Example: Movie.java
    public class Movie {
      public void setTitle(String title);
    }
    

    list

    Setters taking a List or array argument can be configured with list values.

    List items are specified directly with <value> elements. There is no extra <list> element required. The <list> element is only used when creating a sub-list or sub-element (see below.)

    Example: MyBean.setValues(List)
    <my-bean>
      <values>
        <value>a</value>
        <value>b</value>
        <value>c</value>
      </values>
    </my-bean>
    
    Example: MyBean.setValues(String [])
    <my-bean>
      <values>
        <value>a</value>
        <value>b</value>
        <value>c</value>
      </values>
    </my-bean>
    

    In the following example, the argument is an object, so we need a <list> element to tell Resin to create a list. The object created will be an ArrayList.

    Example: MyBean.setValues(Object)
    <my-bean>
      <values>
        <list>
          <value>a</value>
          <value>b</value>
          <value>c</value>
        </list>
      </values>
    </my-bean>
    

    Resin can always use the addXXX pattern to add a variable number of items. Normally, the addXXX pattern is easier and more maintainable than the addList pattern. In particular, validation of the item values is quicker and more accurate with addXXX.

    Example: MyBean.addValue(String)
    <my-bean>
      <value>a</value>
      <value>b</value>
      <value>c</value>
    </my-bean>
    

    map

    Generic maps can use an <entry> syntax to define property values.

    Example: MyBean.setValues(Map)
    <my-bean>
      <values>
        <entry key="a" value="one"/>
        <entry key="b" value="two"/>
        <entry key="c" value="three"/>
      </values>
    </my-bean>
    

    Constructors

    Some beans require constructor configuration because the service or library designer prefers constructors to method configuration. Resin's configuration can support these constructor beans with the <new> syntax.

    Example: MyBean configuration
    <web-app xmlns="http://caucho.com/ns/resin"
                xmlns:example="urn:java:example">
    	    
      <example:MyBean>
        <new>
          <value>first arg<value>
          <value>second arg<value>
        </new>
      </example:MyBean>
    
    </web-app>
    
    Example: MyBean with constructor
    public class MyBean {
      public MyBean(String a, String b)
      {
        ...
      }
    }
    

    Single constructor

    As a convenience, Resin provides short form of the constructor configuration if there's only a single argument. You can either omit the <value> and just use the <new> tag, or you can even omit the <new> tag entirely.

    Example: MyBean short form
    <web-app xmlns="http://caucho.com/ns/resin"
                xmlns:example="urn:java:example">
    	    
      <example:MyBean>
        <new>single arg</new>
      </example:MyBean>
    
    </web-app>
    
    Example: MyBean ultra-short form
    <web-app xmlns="http://caucho.com/ns/resin"
                xmlns:example="urn:java:example">
    	    
      <example:MyBean>single arg<example:MyBean>
    
    </web-app>
    

    valueOf

    For classes which implement a static valueOf(String) method, Resin will automatically convert to the given type using the valueOf method.

    Example: MyBean with valueOf
    public class MyBean {
      ...
    
      public static MyBean valueOf(String text)
      {
        MyBean bean = new MyBean();
        bean.setTextValue(text);
        bean.init();
        return bean;
      }
    }
    

    setValue

    For objects with a setValue or addText method and a zero-argument constructor, Resin-IoC will convert using the following steps:

    1. Create the object
    2. Inject any dependencies
    3. Call setValue or setText with the string
    4. Call any @PostConstruct
    5. Return the configured bean

    Custom Services

    Some of your application's beans will be configured as custom services, like Java servlets or Hessian services, using CanDI to configure a service annotation. These custom services combine your own Java code with Resin capabilities, usually to expose them as external web services.

    Custom Service Configuration
    ANNOTATIONDESCRIPTIONSAMPLE
    @BamServiceBAM service
    
    <mypkg:MyBean>
      <resin:BamService name="my-service"/>
    </mypkg:MyBean>
    
    @HessianClientHessian client proxy
    
    <mypkg:MyApi>
      <resin:HessianClient
                   url="http://localhost:8080/test"/>
    </mypkg:MyApi>
    
    @HessianServiceHessian service
    
    <mypkg:MyBean>
      <resin:HessianService urlPattern="/test"/>
    </mypkg:MyBean>
    
    @JmsListenerJMS based EJB message driven bean
    
    <mypkg:MyBean>
      <resin:JmsListener destination="my_queue"/>
    </mypkg:MyBean>
    
    @MessageDrivenEJB message driven bean
    
    <mypkg:MyBean>
      <ee:MessageDriven>
        <ee:activationConfig
                   propertyName="destination"
                   propertyValue="my_queue"/>
      </ee:MessageDriven>
    </mypkg:MyBean>
    
    @StartupStart on initialization
    
    <mypkg:MyBean>
      <ee:Startup/>
    </mypkg:MyBean>
    
    @StatefulEJB stateful session bean
    
    <mypkg:MyBean>
      <ee:Stateful/>
    </mypkg:MyBean>
    
    @StatelessEJB stateless session bean
    
    <mypkg:MyBean>
      <ee:Stateless/>
    </mypkg:MyBean>
    
    @WebServletServlet mapping
    
    <mypkg:MyServlet>
      <ee:WebServlet value="/test"/>
    </mypkg:MyServlet>
    

    Copyright © 1998-2009 Caucho Technology, Inc. All rights reserved.
    Resin ® is a registered trademark, and Quercustm, Ambertm, and Hessiantm are trademarks of Caucho Technology.