Caucho Technology
  • resin 4.0
  • resin ioc


    Resin is designed around the Java Dependency Injection specification (JSR-299), an inversion-of-control framework used for all configuration and resources including servlets, EJBs, messaging, remoting, and databases. Applications can take advantage of Java Injection using standard annotations and interfaces.

    Since Resin-IoC is used for servlets, WebBeans and EJBs, any application bean can use EJB annotations like @TransactionAttribute or WebBeans @InterceptionTypes or event @Observes capabilities, in addition to the dependency injection and IoC configuration.

    The dependency injection framework is type-safe, meaning the registry is organized around Java types, not a flat namespace, which gives more power and flexibility for component assembly. Since injection is annotation-based, most components can avoid XML configuration, while XML is still available for components.

    See Also

    • The Resin EJB page gives more information about the EJB bean lifecycles and their integration with Resin IoC.
    • The Resin messaging page gives more information about the message bean and its integration with Resin IoC.
    • The Resin remoting page shows Resin's remoting integration.
    • All Resin configuration, including all JavaEE specified files uses Resin-IoC as the configuration engine.

    Overview

    Resin's Java Injection support is integrated with EJB 3.0 and the core components like Servlets, Filters and remote objects. This integration means plain Java beans can use EJB annotations and interception, EJBs can use Java Injection annotations, and both kinds of beans can be configured directly from the resin-web.xml or discovered by classpath scanning.

    So it's best to think of Java Injection as a set of orthogonal capabilities that are available to any registered bean. The basic capability types are:

    • Lifecycle model: Java, @Stateless, @Stateful, or @MessageDriven. Resin-managed objects like Servlets and Filters are Java model beans.
    • Dependency injection: injection annotations from javax.inject: @Current, @Named, @BindingType, @EJB, @PersistenceUnit, etc are available to all beans.
    • Registration: all beans are registered in a unified typed-namespace registry (i.e. the registration half of dependency injection.)
    • Lifecycle events: the @PostConstruct and @PreDestroy
    • Predefined aspects: the @TransactionAttribute, @RunAs, @RolesAllowed, etc. annotations are available to all beans.
    • Custom interceptors: EJB-style @AroundInvoke, and @Interceptors, as well as Java Injection @Interceptor, @InterceptorBindingType, and @Decorator are available to all beans.
    • Event handling: the Java Injection javax.event, @Observes capability is available to all beans.

    Injecting Resources

    Before dependency injection, applications needed to use JNDI to grab resources managed by Resin: database connections, JMS queues, JCA EntityManagers, timers, UserTransaction, the JMX MBeanServer, etc. The JNDI lookup had two main flaws: it required a good chunk of boilerplate code to solve a simple problem, and it was untyped. Since JNDI is essentially a big HashMap, the only way of making sure your DataSource name didn't conflict with your JMS Queue was strictly structuring the JNDI names with patterns like java:comp/env/jdbc/foo.

    With dependency injection, Resin will lookup, verify and inject the resource when it creates your managed class, for example when creating a servlet. In the following example, when Resin creates MyServlet, the @In annotation tells it to look for a UserTransaction and DataSource and use reflection to set the fields, before calling the servlet's init() method.

    Example: DataSource and UserTransaction
    import javax.sql.DataSource;
    import javax.transaction.UserTransaction;
    import javax.inject.Current;
    
    public class MyServlet extends GenericServlet {
      @Current private DataSource _ds;
      @Current private UserTransaction _ut;
    
      ...
    }
    

    @Named and bindings

    Since many applications use multiple resources like named databases, your injection may need to specify a name or other binding to uniquely identify the resource you want. In the case of a unique resource like UserTransaction or MBeanServer or an application with a single DataSource, the @Current is enough information. When you have multiple databases, you'll want to use @Name to specify the database name.

    Example: @Name with DataSource
    import javax.sql.DataSource;
    import com.caucho.config.Name;
    
    public class MyServlet extends GenericServlet {
      @Name("foo")
      private DataSource _ds;
    
      ...
    }
    
    Example: resin-web.xml database configuration
    <web-app xmlns="http://caucho.com/ns/resin">
    
      <database>
        <name>foo</name>
        <driver type="org.gjt.mm.mysql.Driver">
          <url>jdbc:mysql://localhost:3306/foo</url>
        </driver>
      </database>
    
      <database>
        <name>bar</name>
        <driver type="org.gjt.mm.mysql.Driver">
          <url>jdbc:mysql://localhost:3306/bar</url>
        </driver>
      </database>
    
    </web-app>
    

    Injection using a @Name binding annotation is still typed. You can have a database with @Name("foo") and a JMS queue with @Name("foo"), i.e. each type has its own namespace. The typed injection is a big improvement from the JNDI java:comp/env/jdbc/foo vs java:comp/env/jms/foo conventions.

    Although many applications will just use @In and @Name, you can also create your own @BindingType annotations to match resources and components.

    field, method, and constructor injection

    Since Resin implements all three flavors of dependency injection: field, method and constructor, the choice of style is up to you.

    You can mark any field with @Current, @New, @Name or any other @BindingType to tell Resin to inject the field. When a @BindingType is used, Resin will only match components configured with that binding type.

    Example: field injection with @Name
    import com.caucho.config.Name;
    
    public class MyBean {
      @Name DataSource _ds;
      ...
    }
    

    Method injection can use any binding annotation on any of the parameters. When Resin introspects the component class and it finds any @BindingType or @Current parameter on a method, it will schedule that method to be injected. Method parameters can also use @New. The method does not need to follow bean-style setting conventions; any method will work.

    Example: method injection with @Named
    import com.caucho.config.Name;
    
    public class MyBean {
      void foo(@Name("jdbc/foo") DataSource myDataSource) { ... }
      ...
    }
    

    Construction injection is available for components and singleton beans. Like method injection, the @BindingType values like @Name assigned to the parameters determine the values to be injected.

    If the bean has multiple constructors, exactly one must be marked @Current or have a @BindingType value.

    Example: constructor injection
    import javax.inject.Current;
    
    public class MyBean {
      @Current
      public MyBean(DataSource myDataSource) { ... }
      ...
    }
    

    Java Injection simple beans (injectable objects)

    Any Resin-managed object can use the entire Java Dependency-Injection system and all of the managed objects, while objects you create using new are still plain Java objects. Once you've got a root object managed by the system, any futher Java injection components or singletons you bring in will also be managed. The starting set of managed objects is pretty broad and includes:

    • <my:MyBean> (simple beans) defined in the META-INF/beans.xml, resin.xml or resin-web.xml
    • EJB message-driven beans
    • EJB session beans
    • Filters (servlet)
    • JSF resources (currently only model beans)
    • JSP pages
    • JSP tag libraries
    • Servlets
    • Servlet Listeners defined in the web.xml
    • Simple beans discovered through the classpath scan (see below)
    • Java Injection simple beans injected with @New (see below)
    • Remote services defined by <servlet> (e.g. Hessian or SOAP).

    Resin global resources

    Resin automatically provides several global resources to any injectable code. Since these resources are unique, your application will use @Current as the annotation.

    javax.inject.manager.Manager provides a reference to the Java Injection manager itself. Applications can use the Manager to raise javax.event events, and lookup components programmatically.

    javax.context.Conversation injects the Java Injection conversation scope for a JSF application. The conversatio scope lets JSF views store data local to the page itself, separate from the HTTP session scope.

    javax.management.MBeanServer injects the JMX management server. JMX manages Resin's resources, so an application can use JMX to view the current state of Resin. See the JavaDoc for an overview of Resin's resources.

    javax.transaction.TransactionManager injects the XA transaction manager. Advanced applications which want to add their own XAResource or Synchronization objects to an active transaction can use @Current TransactionManager.

    javax.transaction.UserTransaction injects the XA user transaction manager. Applications controlling XA transactions programmatically will use the UserTransaction to begin(), rollback(), and commit() distributed transactions.

    java.util.concurrent.ScheduledExecutorService lets applications schedule threads and timed events controlled by Resin's thread pool, and restricted by the thread-max configuration in the resin.xml. This ScheduleExecutorService is classloader-safe, so Resin will automatically close your scheduled tasks when restarting a web-app.

    Resin configured resources

    All Resin configured resources are available through WebBeans, since Resin uses WebBeans as its internal registry.

    <my:MyBean> is an application-specific custom bean. They can either use Java Inject annotations or just be POJO objects. The simple beans default to @Dependent scope, which means a new instance is created each time they're referenced or injected. The injected type will depend on the class attribute of the bean.

    <database> is a JDBC pooled database. The name attribute is assigned to the @com.caucho.config.Name binding. Databases are injected as javax.sql.DataSource types.

    EJB stateless beans are automatically registered with Java Injection. The Resin @Name value is the ejb-name. Stateless beans can use the <Stateless> annotation for custom configuration, or rely on the standard EJB discovery mechanism. Each EJB 3.0 @Local interface is registered separately in the Java Injection registry.

    EJB stateful beans are automatically registered with Java Injection. The Resin @Name binding is the ejb-name. Stateful beans can use the <Stateful> tag for custom configuration, or rely on the standard EJB discovery mechanism. Each injection or bean lookup will return a new stateful bean reference, modified by the bean's scope (see below.) Each EJB 3.0 @Local interface is registered separately in the WebBeans registry.

    EntityManager and EntityManagerFactory objects from JPA are automatically registered with WebBeans. The default Resin @Name value is the persistence-unit name.

    <env-entry> tags register their values with Java Inject. The default @Name value is the env-entry-name. The registered type is the env-entry-type.

    <jms-connection-factory> automatically registers the configured factory with WebBeans. Connection factories can also be configured with <bean> or <resource>, depending on the JMS provider. The registered type is the class of the connection factory, usually javax.jms.ConnectionFactory

    <jms-topic> automatically registers the configured topic with WebBeans. The default @Named value is the topic name. Topic can also be configured with <bean> or <resource>, depending on the JMS provider. The registered type is javax.jms.Topic

    <jms-queue> automatically registers the configured queue with WebBeans. The default @Named value is the queue name. Queue can also be configured with <bean> or <resource>, depending on the JMS provider. The registered type is javax.jms.Queue

    <remote-client> registers remoting clients with WebBeans. The <remote-client> tag will configure the protocol used and the expected proxy class. The registered type is the API class of the remote service.

    Example: resin-web.xml for remote-client
    <web-app xmlns="http://caucho.com/ns/resin">
    
      <remote-client class="example.HelloService">
        <url>hessian:http://localhost:8080/hello/</url>
      </remote-client>
    
    </web-app>
    
    Example: Injecting for remote-client
    public class MyServlet extends GenericServlet {
      @Current example.HelloService _hello;
      ...
    }
    

    Application components

    The primary value of Resin's dependency injection system is as a type-safe component and service organization registry. Module and component-oriented software has been a goal of software developers for decades, but in practice developing components and services is a difficult task, in large part because the configuration and assembly of the components has been just as complicated as the code itself. There are no silver bullets in software, but the WebBeans registry does significatly reduce the housekeeping code and XML which gets in the way of good design.

    Annotation-based Component Discovery

    At startup, Resin will scan jars and class directories for a META-INF/beans.xml file. The presence of that file tells Resin to start scanning all the classes in the jar or directory Resin will register each class with the Java Injection registry. The META-INF/beans.xml can be trivial, since its primary purpose is speeding up startup time by letting Resin scan only the jars which contain components. So, applications will generally want to minimize the number of classes in beans.xml jars to make startup fast.

    Example: META-INF/beans.xml
    <Beans xmlns="urn:java:ee">
    </Beans>
    

    The component itself can be any Java class. Since Resin manages the component, it can use @Current, @BindingType annotations and Resin's @Name to inject any other component or resource. Resin will take care of any circular dependencies automatically.

    Example: Movie.java
    import javax.annotation.PostConstruct;
    
    public class Movie {
      private String _title;
      private String _director;
    
      public String getTitle() { return _title; }
      public void setTitle(String title) { _title = _title; }
    
      public String getDirector() { return _director; }
      public void setDirector(String director) { _director = director; }
    
      @PostConstruct
      public void init()
      {
        ...
      }
    }
    

    The @PostConstruct annotation tells Resin to call the init() method once all the injection and configuration is complete.

    Any other component or Resin-managed class like servlets can now use @Current Movie to inject the movie resource.

    Example: MyServlet.java
    import javax.inject.In;
    
    public class MyServlet extends GenericServlet {
      @Current Movie _movie;
    
      ...
    }
    

    Most application components will use the Java Injection class scanning mechanism. Except for the META-INF/beans.xml marker file, no additional housekeeping code or XML is required. As described below, applications can reduce the configuration by one more step with the @New annotation replacing @Current. The target class of the @New annotation is automatically registered with Java Injection even if the META-INF/beans.xml is missing. In other words, any plain Java class can become a part of the Java Injection system without overhead.

    Scopes: @ApplicationScoped, @Dependent, @RequestScoped

    The scope of the component determines when Resin will create a new component and when it will reuse an old one. Singletons will always return the same object, while dependent components will always return a new object instance. Long-lived services will typically be singletons, while scratch-space modules will be dependent components.

    Components default to @Dependent scope. Since many components will be used as pieces of other components, @Dependent is the least-surprising value as a default.

    You can specify a component's scope with an annotation or in the <my:MyBean> tag. The predefined scope values are: @Dependent, @RequestScoped, @ConversationScoped, @SessionScoped, and @ApplicationScoped.

    • @Dependent creates a new instance each time.
    • @RequestScoped creates a new instance for each servlet request, reusing the instance for the same request.
    • @ConversationScoped creates a new instance for each JSF conversation, i.e. for each JSF view page.
    • @SessionScoped creates a new instance for each HTTP session, reusing the instance for the same session.
    • @ApplicationScoped uses a single instance for the application. For web applications, this will be the same lifecycle as <web-app> For virtual hosts, this will be the same lifecycle as <host>.

    An example scoped resource might be a Calculator object which is used only for a single instance. It might fill the arguments while processing a form and then calculate the result. The @RequestScoped makes sure scripts receive the same instance each time it's called.

    Example: @RequestScoped Calculator
    package example;
    
    import javax.context.RequestScoped;
    
    @RequestScoped
    public class Calculator {
      private int _a;
      private int _b;
    
      public void setA(int a) { _a = a; }
      public void setB(int b) { _b = b; }
    
      public int getSum() { return _a + _b; }
    }
    

    You could also register the same calculator using XML:

    Example: META-INF/beans.xml Calculator
    <Beans xmlns="urn:java:ee" xmlns:example="urn:java:example">
    
      <example:Calculator>
        <RequestScoped/>
      </example:Calculator>
    
    </Beans>
    

    @New bean discovery

    The @New annotation automatically registers the target class with the Java Injection registry and tells Resin to create a new instance of the bean, even if the bean has an application scope definition. Since @New replaces @Current, it can be used anywhere @Current can be used.

    Example: MyServlet.java
    import javax.inject.New;
    
    public class MyServlet extends GenericServlet {
      @New Movie _movie;
    
      ...
    }
    

    The Movie is identical to the movie class defined above, but doesn't need the META-INF/web-beans.xml marker file. In many cases, the @New annotation can replace the Java new operator. If your application starts using @New consistently, it can add injection capabilities to a growing share of your code, letting you simplify and refactor incrementally.

    Example: Movie.java
    package example;
    
    public class Movie {
      private String _title;
    
      public String getTitle() { return _title; }
      public void setTitle(String title) { _title = title; }
    
      @PostConstruct
      public void init() { ... }
    }
    

    Lifecycle: @PostConstruct and @PreDestroy

    If your service needs to initialize itself after being configured, it can annotation an initialization method with @PostConstruct. After Resin creates, injects, and configures your component, it will call any @PostConstruct methods. Long-lived services or services that need to register themselves with other services will typically need to use the @PostConstruct annotation.

    At the end of a component's lifetime, you might need to close some resources, e.g. closing a socket or delisting from a timer service. Resin will call any component method marked with @PreDestroy before it destroys the method.

    For example, a TimerService may want to schedule a event every 2 seconds. The @PostConstruct method will start the timer and the @PreDestroy method will stop the timer.

    Example: Timer Service
    import javax.annotation.PostConstruct;
    import javax.inject.Current;
    import java.util.concurrent.ScheduledExecutorService;
    import com.caucho.config.Service;
    
    @Service
    public class TimerService {
      @Current ScheduledExecutorService _timer;
    
      @PostConstruct
      public void init()
      {
        _timerFuture = _timer.scheduleAtFixedRate(this, 0, 2, TimeUnit.SECONDS);
      }
    
      ...
    
      @PreDestroy
      public void close()
      {
        _timerFuture.cancel(false);
      }
    }
    

    XML configuration

    You can register your components and services with Resin using the resin.xml or resin-web.xml files as well as the META-INF/beans.xml. Since the Java Injection registry is integrated with Resin, your services be treated as first-class components along with the Resin resources. Although most components will not need XML, there are a few advantages for the small number of services which do use 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.

    bean 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.annotation.Name annotations for EL naming
    <BindingType>any @javax.annotation.BindingType annotations for injection
    my:myFieldoptional configuration, using bean-style assignment
    <SessionScoped>specifies scope of the instances: request, conversation, session, application, or singleton

    Bean 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 {
      private String _greeting = "default";
    
      public void setGreeting(String greeting) { _greeting = greeting; }
      public String getGreeting() { return _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>
    

    Resin's configuration uses 5 basic bean patterns, extending the JavaBeans conventions. It can configure literal values like string and integers as well as configuring other beans. Any component bean configured by Resin has full access to @BindingType injection as well as the standard @PostConstruct annotations. Sub-beans are not automatically registered with Java Inection, i.e. they act like the servlet configuration.

    (Currently the patterns are name-based like JavaBeans, since Resin was designed before annotations. We may add configuration annotations in the future.

    Example: Bean configuration patterns
      public void setFoo(String data);
    
      public void setFoo(Movie data);
    
      public void addFoo(Movie data);
    
      public Movie createFoo();
    
      public void setText(String data);
    
    1. setFoo(String) configures a standard JavaBeans-style literal.
    2. setFoo(Movie) creates a new instance of Movie and recursively configures it.
    3. addFoo(Movie) also creates a new instance of Movie and recursively configures it. addFoo is an easy way of configuring lists.
    4. Movie createFoo() lets the bean create the Movie instance. Many beans can use createFoo with inner classes to handle complex configuration.
    5. setText is called with the text contents of the XML. Value-style beans will use this. (somewhat rare).

    As mentioned above, Resin uses these 5 patterns to handle all of the JavaEE configuration files. In particular, the createFoo pattern returning inner classes is very handy for some complicated configuration cases, and for cases where a sub-tag needs information about the parent.

    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 classes uses an inner Movie class to illustrate the use of the create pattern.

    Example: Theater.java
    public class Theater {
      String _name;
    
      ArrayList<Movie> _movies = new ArrayList<Movie>();
    
      public void setName(String name) { _name = name; }
    
      public Movie createMovie()
      {
        return new Movie(this);
      }
    
      public void addMovie(Movie movie)
      {
        _movies.add(movie);
      }
    
      public static class Movie {
        private Theater _theater;
        private String _title;
    
        Movie(Theater theater)
        {
          _theater = theater;
        }
    
        public void setTitle(String title) { _title = title; }
      }
    }
    

    Base configuration: string conversions

    Java Injection provides a number of built-in string conversion types as well as supporting JavaBeans PropertyEditor and custom converters.

    Built-in String Converters
    TYPEDESCRIPTION
    boolean, BooleanJava boolean
    byte, ByteJava byte
    short, ShortJava short
    int, IntegerJava integer
    long, LongJava long
    float, FloatJava float
    double, DoubleJava double
    char, CharacterJava char
    String[]String array separated by commas
    ClassJava classes
    PathResin VFS Paths
    Filejava.io.File
    URLjava.net.URL
    Patternjava.util.regex.Pattern
    Localejava.util.Locale
    Datejava.util.Date
    Propertiesjava.util.Properties
    RawStringcom.caucho.config.type.RawString

    enumerations

    Enumerations are automatically converted from their string representation.

    String constructor

    Resin-IoC will automatically convert a string to an object if the object has a single String argument constructor.

    Example: MyBean with constructor
    public class MyBean {
      public MyBean(String value)
      {
        ...
      }
    }
    

    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

    Compound types

    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-IoC 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>
    

    References and EL Expressions

    Resin-IoC configuration files can use EL expressions to get references to resources, beans, system properties, and calculate generatal expressions based on those values. Since all Resin's resources are added to the WebBeans 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, since Resin-IoC initializes beans lazily to handle circular references.

    Example: circular references in resin-web.xml
    <web-app xmlns="http://caucho.com/ns/resin">
    
      <bean name="a" class="qa.FooBean">
        <init bar="#{b}"/>
      </bean>
    
      <bean name="b" class="qa.BarBean">
        <init foo="#{a}"/>
      </bean>
    
    </web-app>
    

    Because Resin's EL implementation allows method expressions, you can use beans as factories in the EL expressions.

    Scripting: PHP, JSF and JSP

    If your application is using a scripting language like PHP for the presentation layer, the WebBeans registry provides a simple interface to use your components and services. Although Java Injection injection is typed, each simple bean can bean registered under its name for scripting applications. The name must be globally unique, of course, unlike the typed injection binding.

    By default, beans do not have a name, so you'll need to specify it by an annotation or the configuration file. You can change the name by adding a @Named annotation or <Named> XML configuration.

    Example: Movie.java
    pakcage example;
    
    import javax.annotation;
    import javax.context;
    
    @RequestScoped
    @Named
    public class Movie {
      ...
    }
    

    Quercus/PHP

    In Quercus/PHP, the java_bean(name) method returns the component with the given name. For singletons, Resin will return the unique bean. For other beans, Resin will create the bean if necessary and store it in the configured scope.

    Example: accessing the movie from PHP
    <?php
    
    $movie = java_bean("movie");
    
    echo "title: " . $movie->title . "\n";
    
    ?>
    

    JSP/JSF EL

    Resin automatically provides the Java Injection variables to EL expressions for both JSP and JSF.

    Example: accessing the movie from JSP
    <c:out value="${movie.title}"/>
    

    The JSF also uses the expression language, but uses the deferred syntax, since JSF needs to build a component tree first.

    Example: accessing the movie from JSF
    <f:view>
      <h:outputText value="#{movie.title}"/>
    </f:view>
    

    @BindingType: custom injection binding

    Applications will typically create custom @BindingType annotations to clearly specify their expected beans. In many cases, @Current will be appropriate for unique beans, and Resin @com.caucho.config.Named is used for Resin's resources like <database>. Some bindings might be more logical, for example an @XA annotation might mark the transactional DataSource, while @ReadOnly might mark a read-only DataSource. Drivers might use Scheme("mysql") to allow for URL-based configuration, like the "jdbc:mysql://localhost:3306/test" of JDBC.

    Example: ReadOnly and XA databases
    import com.foo.webbeans.ReadOnly;
    import com.foo.webbeans.XA;
    
    public class MyServlet extends GenericServlet {
      @ReadOnly DataSource _readDatabase;
      @XA DataSource _xaDatabase;
    
      ...
    }
    

    You can create a custom binding annotation using the @BindingType annotation. When Resin introspects the injection point and the components, it will look for any annotation with the @BindingType meta-annotation.

    The annotation can also have annotation parameters. If they exist, Resin will make sure only matching components will be injected.

    The custom binding annotation can be used anywhere predefined binding annotations can, including fields, methods, constructor, producers, or event observers.

    Example: ReadOnly.java
    package com.foo.webbeans;
    
    import javax.inject.BindingType;
    
    @BindingType
    @Target({TYPE, METHOD, FIELD, PARAMETER})
    @Retention(RUNTIME)
    public @interface ReadOnly {
    }
    

    @Produces methods

    Some components are more easily produced using a factory method rather than getting instantiated directly. In those cases, your application can mark a factory component's method with the @Produces annotation. Resin will register the results of the method with WebBeans.

    Example: @Produces
    import javax.inject.Produces;
    import javax.context.ApplicationScoped;
    
    @ApplicationScoped
    public class MyFactory {
      @Produces public List<Movie> currentMovies()
      {
        ...
      }
    

    The produces method can be marked with @ScopeType, @DeploymentType or @BindingType annotations just like a class-based component can.

    Aspects: Method Interception

    Some functions like security, logging and transaction handing need to be used for each method invidually, but require a common implementation pattern. The WebBeans AOP uses a single method as a interceptor for each method invocation.

    Your method will use an @InterceptorType annotation letting Resin know where it should apply the interceptor:

    Example: secure method
    import com.foo.webbeans.Secure;
    
    public class MyBean {
      @Secure
      public void doSomethingSafely() { ... }
    }
    

    The implementation class will use the javax.interceptor.* API to implement the interceptor.

    Example: security implementation
    import javax.interceptor.*;
    
    @Secure @Interceptor
    public class MySecureInterceptor {
      @AroundInvoke
      public Object checkSecurity(InvocationContext inv) throws Exception
      {
        if (! myContextIsSecure())
          throw new MySecurityException("permissiong denied");
    
        return inv.proceed();
      }
    }
    

    The interceptors must be enabled in the META-INF/beans.xml file. This protects your code from any surprising interceptors.

    Example: META-INF/beans.xml
    <Beans xmlns="urn:java:ee" xmlns:foo="urn:java:com.foo">
    
      <Interceptors>
      
        <foo:MySecureInterceptor/>
        
      </Interceptors>
      
    </Beans>
    

    Event Handling

    Your components can also handle events thrown through the WebBeans API. Any method with an @Observes parameter will receive events with the proper type. The event can be any Java class.

    Example: event handler
    import javax.context.ApplicationScoped;
    import javax.event.Observes;
    
    @ApplicationScoped
    public class MyHandler {
      public void myHandlerMethod(@Observes Movie movie)
      {
        ...
      }
    }
    

    Your application can throw events through the WebBeans Manager API, which is available through injection:

    Example: raising events
    import javax.inject.manager.Manager;
    
    public void MyServlet extends GenericServlet {
      @Current Manager _webbeans;
    
      public void service(ServletRequest req, ServletResponse res)
      {
        _webbeans.fireEvent(new Movie("A Bridge Too Far"));
      }
    }
    

    For the above example, Resin will look for all components which have an @Observes method receiving a Movie and deliver the event to that component.

    Aspect Annotations

    @AroundInvoke

    @AroundInvoke marks an interception method on the bean or an interceptor class. The interceptor is invoked while processing a business method.

    javax.interceptor.AroundInvoke
    @Target(METHOD)
    @Retention(RUNTIME)
    public @interface AroundInvoke {
    }
    
    Example: @AroundInvoke method
    import javax.interceptor.*;
    
    public class MyBean {
      @AroundInvoke
      protected Object log(InvocationContext cxt)
        throws Exception
      {
        System.out.println("Before: " + cxt.getMethod());
    
        Object value = cxt.proceed();
    
        System.out.println("After: " + cxt.getMethod());
    
        return value;
      }
    
      public String hello()
      {
        return "hello, world";
      }
    }
    

    @DenyAll

    @DenyAll annotation marks a method as forbidden to all users.

    javax.annotation.security.DenyAll
    @Target({METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DenyAll {
    }
    

    @Interceptor

    @Interceptor marks a class as an interceptor using WebBeans-style interception. The class will normally also have an @AroundInvoke method as well as any InterceptorBindingType annotations.

    javax.interceptor.Interceptor
    @Target({TYPE})
    @Retention(RUNTIME)
    public @interface Interceptor {
    }
    

    @InterceptorBindingType

    @InterceptorBindingType is a Java Injection meta-annotation for creating interceptor binding types. Applications will use @InterceptorBindingType to create application-specific interceptors. The Java Injection binding of interception decouples the interception declaration from the interceptor classes.

    javax.interceptor.InterceptorBindingType
    @Target({TYPE})
    @Retention(RUNTIME)
    public @interface InterceptorBindingType {
    }
    

    @Interceptors

    @Interceptors marks an method or class as being intercepted by the named classes. The interceptor classes will implement an @AroundInvoke method to process the InvocationContext.

    @Interceptors properties
    VALUEMEANINGDEFAULT
    valueLists the interceptor classes to apply to the method.
    javax.interceptor.Interceptors
    @Target({TYPE,METHOD})
    @Retention(RUNTIME)
    public @interface Interceptors {
      public Class []value();
    }
    
    Example: @Interceptor method
    import javax.interceptor.*;
    
    public class MyBean {
      @Interceptors(MyInterceptor.class)
      public String hello()
      {
        return "hello, world";
      }
    }
    
    public class MyInterceptor {
      @AroundInvoke
      protected Object log(InvocationContext cxt)
        throws Exception
      {
        System.out.println("Before: " + cxt.getMethod());
    
        Object value = cxt.proceed();
    
        System.out.println("After: " + cxt.getMethod());
    
        return value;
      }
    }
    

    InvocationContext

    The InvocationContext API is used by invocation methods to examine the calling context, and possibly set parameters. A no-op interceptor would just call the proceed() method.

    InvocationContext methods
    METHODDESCRIPTION
    getContextDataReturns a map containing any context information
    getMethodReturns the called API method
    getParametersReturns the Java parameters for the call
    getTargetReturns the target object, i.e. the Java object that will receive the call after all the interceptors complete.
    proceedCall the next interceptor in the chain, or call the final object at the end of the chain.
    setParametersSets the Java parameters for the call
    javax.interceptor.InvocationContext
    public interface InvocationContext {
      public Object proceed() throws Exception;
    
      public Map<String, Object> getContextData();
      public Method getMethod();
      public Object[] getParameters() throws IllegalStateException;
      public void setParameters(Object[] parameters) throws IllegalStateException;
      public Object getTarget();
    }
    

    @PermitAll

    @PermitAll annotation marks a method as allowed for all users.

    javax.annotation.security.PermitAll
    @Target({METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface PermitAll {
    }
    

    @RolesAllowed

    @RolesAllowed lists all the roles (i.e. permissions) allowed to access the method. If the user in the security context does not match the role, an exception will be thrown.

    RolesAllowed properties
    VALUEMEANINGDEFAULT
    valueLists the roles (permissions) that are allowed.
    javax.annotation.security.RolesAllowed
    @Target({TYPE,METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface RolesAllowed {
      String []value();
    }
    

    @RunAs

    @RunAs changes the security context user to a defined role. Security tests within the context of the @RunAs will match the specified role.

    RunAs properties
    VALUEMEANINGDEFAULT
    valueThe role name to run as.
    javax.annotation.security.RunAs
    @Target({TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface RunAs {
      String value();
    }
    

    @TransactionAttribute

    Defines the transaction boundary for business methods. The default value is REQUIRED. If @TransactionAttribute annotates the class, it defines the default value.

    All Resin-managed beans can use @TransactionAttribute: @Stateful, @Stateless, @MessageDriven and plain Java beans.

    TransactionAttributeType
    VALUEMEANING
    REQUIREDStart a new transaction if necessary
    SUPPORTSDon't start a new transaction, but use one if it exists
    MANDATORYRequire the caller to have started a transaction
    NEVERForbid the caller to have started a transaction
    REQUIRESNEWAlways start a new transaction, suspending the old one
    NOTSUPPORTEDSuspend any active transaction
    • SUPPORTS is typically used for read-only methods
    • REQUIRED is typically used for updating (read/write) methods
    javax.ejb.TransactionAttribute
    @Target({TYPE,METHOD})
    @Retention(RUNTIME)
    public @interface TransactionAttribute {
      TransactionAttributeType value() default REQUIRED;
    }
    

    Dependency Injection Annotations

    @BindingType

    @BindingType is a meta-annotation for creating custom injection binding types. Applications can create their own injection annotations like @Named to provide application-specific binding. For example, a database might have a @XA and a @NonXA connector implemented.

    javax.inject.BindingType
    @Target({TYPE})
    @Retention(RUNTIME)
    public @interface BindingType {
    }
    
    Example: custom @XA binding type
    package demo;
    
    @BindingType
    @Target({TYPE, METHOD, FIELD, PARAMETER})
    @Retention(RUNTIME)
    public @interface XA {
    }
    
    Example: using the custom @XA binding type
    package demo;
    
    import javax.sql.*;
    
    public class MyBean {
      @XA DataSource _xa;
      @NonXA DataSource _nonXa;
    
      ...
    }
    

    @EJB

    Configures EJB values for a field or method.

    @EJB is essentially a @Resource where it's known that the result is an EJB interface.

    PROPERTYDESCRIPTIONDEFAULT
    businessInterfaceThe EJB interface to lookupThe field type
    nameThe EJB name of the resourceThe field name
    jndiNameThe jndi name of the resourceThe EJB name
    javax.ejb.EJB
    @Target({TYPE, METHOD, FIELD, PARAMETER})
    @Retention(RUNTIME)
    public @interface EJB {
      String name() default "";
      String businessInterface() default "";
      String jndiName() default "";
    }
    

    In the following exaple, Resin will call setFoo method with the bean in "java:comp/env/ejb/foo" before the session is started.

    Example: @EJB method injection
    @EJB
    void setFoo(example.Test test)
    {
      _test = test;
    }
    

    @Current

    Marks a field, method, or parameter for injection. When used with a constructor, it marks the given constructor as the constructor to use when creating new instances.

    javax.inject.Current
    @Target({CONSTRUCTOR, METHOD, FIELD, PARAMETER, TYPE})
    @Retention(RUNTIME)
    public @interface Current {
    }
    

    @Named

    @Named is used to define an EL name for the bean used for JSP, JSF and PHP named objects. type.

    @Named parameters
    PROPERTYDESCRIPTIONDEFAULT
    valueThe name binding for the object to injectrequired
    javax.annotation.Named
    @BindingType
    @Target({METHOD, FIELD, PARAMETER, TYPE})
    @Retention(RUNTIME)
    public @interface Named {
      String value();
    }
    

    @New

    Marks a field, method, or parameter for injection with a new instance of the object. If the type of the @New has not yet been registered with the WebBeans directory, it will be registered automatically..

    javax.inject.New
    @Target({METHOD, FIELD, PARAMETER, TYPE})
    @Retention(RUNTIME)
    public @interface New {
    }
    

    @NonBinding

    @NonBinding is a meta-annotation used for creating @BindingType annotations. It excludes an annotation property from the binding algorithm. Normally, the injection binding must matches all the propeties in the object's annotations with the properties in the injection property. The @NonBinding annotation skips the check for the annotated property.

    javax.annotation.NonBinding
    @Target({FIELD, METHOD})
    @Retention(RUNTIME)
    public @interface NonBinding {
    }
    
    Example: @Demo with @NonBinding
    package demo;
    
    import javax.inject.BindingType;
    
    @BindingType
    @Target({TYPE, METHOD, FIELD, PARAMETER})
    @Retention(RUNTIME)
    public @interface Demo {
      @NonBinding String description() default "";
    }
    

    @Resource

    @Resource provides JNDI-based resource injection. @Resource can also be used at the Class level to declare a dependency in cases where the session bean loads the JNDI value by itself.

    In general, it's better to use the Java Injection annotations: @Current, Resin's @Name or custom @BindingType annotations, since they use the type-safe WebBeans registry instead of JNDI. @Resource is supported for backwards compatibility.

    PROPERTYDESCRIPTIONDEFAULT
    authenticationTypeWhat kind of authentication is expected for the resource: APPLICATION or CONTAINERCONTAINER
    descriptionAn optional description of the resource
    nameThe jndi-name of the resourcejava:comp/env/class-name#field-name
    typeThe class of the expected resourceThe field type
    shareableTrue if the bean follows JCA shareability requirements.true
    mappedNameThe produce-specific name of the resourceThe field name

    Framework Integration

    Frameworks like Struts2, Wicket, and Mule can delegate object creation to Resin-IoC. By configuration Resin-IoC to create the framework objects, your application's components can directly inject Resin resources and application components configured with Resin.

    Integration information for the frameworks is maintained on the Caucho wiki site. Currently supported frameworks include:

    Implementing new object factories for other frameworks is straightforward.

    ObjectFactory pattern

    Frameworks like Struts2 provide an ObjectFactory pattern. In this case, the framework gives a Class object and asks the factory to create a new instance. The ObjectFactory is the most powerful pattern, since objects can use @Observes, @InterceptionType, @TransactionAttribute and even @Stateless, as well as the usual dependency injection.

    Example: Struts2 integration
    package com.caucho.xwork2;
    
    import com.caucho.config.inject.*;
    import com.opensymphony.xwork2.ObjectFactory;
    import java.util.*;
    import javax.inject.*;
    
    public class ResinObjectFactory extends ObjectFactory
    {
      private final InjectManager _webBeans = InjectManager.create();
      
      @Override
      public Object buildBean(Class clazz, Map extraContext)
        throws Exception
      {
        return _webBeans.getObject(clazz);
      }
    }
    

    Injection pattern

    Some frameworks, like Wicket, prefer to instantiate the object, but can call Resin-IoC for a dependency-injection step. With this kind of framework integration, the created object only gets dependency-injection; it does not get any aspects or interception.

    Example: Wicket injection
    package com.caucho.wicket;
    
    import com.caucho.config.inject.*;
    
    import org.apache.wicket.Component;
    import org.apache.wicket.application.*;
    
    public class ResinComponentInjector implements IComponentInstantiationListener
    {
      private InjectManager _webBeans = InjectManager.create();
      
      public void onInstantiation(Component component)
      {
        _webBeans.injectObject(component);
      }
    }
    

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