You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beehive.apache.org by be...@incubator.apache.org on 2004/11/05 01:38:04 UTC

[Apache Beehive Wiki] New: Controls/AnnotationBasedFeatures

   Date: 2004-11-04T16:38:04
   Editor: KenTam <ke...@apache.org>
   Wiki: Apache Beehive Wiki
   Page: Controls/AnnotationBasedFeatures
   URL: http://wiki.apache.org/beehive/Controls/AnnotationBasedFeatures

   no comment

New Page:

= Implementing Annotation-based Controls Programming Model Features =

Many interesting controls programming model features are annotation-based; the values of annotations on control interfaces and extensions drive significant runtime behaviour differences.  Examples of such features include async control operations via message buffering and many security features (run-as, role authorization enforcement, etc).

This proposal describes an general mechanism for implementing such annotation-based features.

== Summary ==

Implementors are required to:
 * Define the annotations that control the desired feature.  Those annotations are meta-annotated with the @ControlAnnotation, which indicates to the infrastructure that this is a controls-related annotation, and specifies a JavaBeans contextual service interface that identifies implementations of the feature.
 * Provide at least one implementation of their contextual services, possibly specific to a particular container.  These implementations extend the InterceptorContext interface, which defines the contract that the controls runtime has with these feature implementations.
 * Register (via addService()) their contextual service implementations in the appropriate control container.  The base container (ControlContainerContext) may register some implementations of some of these features already; downstream container providers (for WLS, Tomcat, Geronimo, etc), may override and/or provide additional services.

The controls infrastructure does the following:
 * The controls compilation process analyzes controls and code-gens implicit references to any contextual services required to support the features those controls use.  It also code-gens initialization for those implicit references.
 * The controls runtime invokes (via the InterceptorContext interface and the implicit references defined in 1) the contextual services at the appropriate times.  For example, when a method has annotations backed by a contextual service implementation, that implementation is called during the control operation's pre and post invoke stages.

== Details ==

Let's consider @MessageBuffer as an example, and walk through the code involved.

The interface that context service implementations must conform to:

{{{
public interface InterceptorContext
{
    // Exact signature TBD
    public preInvoke( Method m, Object [] args, ControlBeanContext cbc, ControlBean bean );
    public postInvoke( Method m, Object [] args, ControlBeanContext cbc, ControlBean bean );
}
}}}

The MessageBuffer contextual service interface

{{{
public interface MessageBufferContext extends InterceptorContext
{
}
}}}

A particular implementation of the MessageBuffer contextual service.

{{{
public class MessageBufferImpl implements MessageBufferContext
{
    private static MessageBufferProvider
    {
        //.. boilerplate
    }

    public preInvoke( Method m, Object [] args, ControlBeanContext cbc, ControlBean bean )
    {
        // Thread-local check for whether we are being invoked on initial call (in which case
        // we enqueue) or on the post-dequeue call (in which case we do nothing)
        if ( isBufferedCall() )
            return;

        ControlHandle handle = cbc.getControlHandle();

        // include security/auth info?  Call should execute in the right security context on dequeue
        QueueMessage msg = new QueueMessage( handle, m.getName(), args );

        Queue q = getAsyncQueue(); // implemented via JMS, simple in memory queuing system.. ?
        q.enqueue( msg );
    }
}

//
// TODO: a listener on the async queue which will use the control handle
// to dispatch back into the control.  Sets a thread local so the interceptor won't enqueue again.
//
}}}

The meta-annotation used to identify annotations that have controls contextual services, and to
provide the mapping to that service.

{{{
@Target(ElementType.ANNOTATION_TYPE)
public @interface ControlAnnotation
{
    Class<? extends InterceptorContext> contextService();
}
}}}

The MessageBuffer annotation.

{{{
@ControlAnnotation( MessageBufferContext.class )
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MessageBuffer
{
    public boolean value() default true;
}
}}}

A client (.jcx in this case) that uses @MessageBuffer.

{{{
@ControlExtension
public interface MyWebService extends ServiceControl
{
    @MessageBuffer
    public String myWebOperation( int a );
}
}}}

Additional content generated into the ControlBean:

{{{
public class MyWebServiceBean
{
    //... section for generated references to implicit contextual services
    
    private InterceptorContext[] _implicitContexts;

    // ...
}
}}}

Additional content generated into the control impl initializer:

{{{
public class ServiceControlImplInitializer
{
    //...

    public initImplicitServices( ControlBean bean )
    {
        ControlBeanContext cbc = bean.getControlBeanContext();
        // ... reflection setAccessible boilerplate
        bean._implicitContexts[0] = ControlBeanContext.getService(MessageBufferContext.class);
        if ( bean._implicitContexts[0] == null )
            throw RequiredRuntimeServiceNotAvailableException( "MessageBufferContext service not provided by container" ); // could configure to catch & ignore, or fail
        //
        // bean._implicitContexts[1] = ControlBeanContext.getService(SecurityContext.class);
        // ...
        // ...
    }
}
}}}

Base top-level container service registration:

{{{
public class ControlContainerContext extends ControlBeanContext
{
    //...

    public initialize()
    {
        super.initialize();

        // Registers a generic, low QoS impl?  Or not at all..
        addService( MessageBufferContext.class, MessageBufferContextProvider.getProvider() );
    }
}
}}}

Downstream controls container service registration/override:

{{{
public class TomcatControlContainerContext extends ControlContainerContext
{
    public initialize()
    {
        super.initialize();

        // If an existing provider has been registered by a base class, this overrides it
        addService( MessageBufferContext.class, MessageBufferContextImpl.getProvider() );
    }
}
}}}

Runtime invocation of interceptors:

{{{
public class ControlBean
{
    //...
    
    protected void preInvoke( Method m, Object [] args )
    {
        //...

        for ( InterceptorContext c : _implicitContexts )
            c.preInvoke( m, args, getControlBeanContext(), this );

        //..
    }
}
}}}

== Open Issues ==

 * Interceptor contract for events & event handlers?
 * Interaction between different interceptors (@Security & @MessageBuffer, which gets processed first?)
 * Signature of InterceptorContext methods not deeply thought out
 * ...