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
* ...