The Annotations
There are three annotations that drive Coinjema:
- @CoinjemaObject - Annotate your class with
this and Coinjema will introduce the ContextOriented
interface to your class. The annotation has one optional attribute:
- type - Specify a substitute name in place of the class name for Coinjema to use in finding the appropriate groovy script. ie instead of MyClass.setLogger.groovy you could use the "type" field of the annotation for class MyClass to change it to My.setLogger.groovy
- @CoinjemaDependency - Annotate the
dependency injection methods on your class with this. The method must
take one parameter that represents the dependency. The annotation
has four optional attributes:
- order - set to CoinjemaDependency.ORDER.LAST to force Coinjema to call this dependency injection method last. This lets your class do initialization routines. This is not recommended as a replacement for a life-cycle-managing IoC container - it is provided as a convenience, and for when your needs are very simple.
- method - Specify a string in place of the method name for Coinjema to use in finding the appropriate groovy script. Defaults to the name of the method. Ie, instead of the above My.setLogger.groovy, you can change it to My.logger.groovy.
- type - Specify a string in place of the class name of the injected object for Coinjema to use in finding the appropriate groovy script. Defaults to the simple class name of the injected object's type. For shared object dependencies. Instead of LDAPServer.groovy you could change it to ldap.groovy
- hasDefault - indicates whether the dependent method or class has a default value for the dependency. If true, Coinjema will not report an error if it fails to find an associated script or dependency object. Instead the method will be skipped. By default, hasDefault is false.
- alias - Create an alias to a very simple filename that holds the dependency. The alias plus extension will be the full filename for this dependency. ie, instead of the above My.logger.groovy, you could specify it to be mylogger.groovy. Be aware that an alias cannot refer to a shared dependency. If two classes use the same alias, they will get two different instantiations of the dependency.
- @CoinjemaDynamic - Annotate a getter method that returns a dependency.
Coinjema will intercept the call and retrieve the right dependency from the current context. The
current context is retrieved from the call stack - the deepest context found in the stack. This means that
even if the dynamic dependency method is found in a class shared by multiple contexts, if the
shared class is called from an object in context x/y/z, and the shared class was defined by context x, then
the dynamic dependency will retrieved from context x/y/z. A class does not have to be annotated
with @CoinjemaObject to use this annotation. One of type, method,
or alias must be specified for this annotation.
There are 3 attributes:- method - Just like for @CoinjemaDependency, method tells Coinjema what name to use in replace of the method name when finding the right config file. Dynamic script names are determined by the same rules as for the injected dependencies. (ie, "class_name.method.***")
- type - Specify a name of a shared dependency script to look for (ie "type.***").
- alias - A shortened name for a non-shared dependency config script file.
- @CoinjemaContextTrack - This annotation indicates to Coinjema that the object or method should be intercepted to allow Coinjema to update the current context for the current thread. Previously, Coinjema tracked all calls into CoinjemaObject objects, which was wasteful and slow. This annotation allows developers to pinpoint for Coinjema where meaningful context shifts will occur. The primary benefit of this annotation is to speed up dynamic dependency retrieval. There are no options with this annotation. Simply annotate your class and Coinjema will intercept all public- and package-level methods and remember the current context for that thread or annotate specific methods for Coinjema to track.
Context Tracking essentially works because you can create your Coinjema
Objects with a specific CoinjemaContext by optionally providing constructors in
your class in which the last parameter is a CoinjemaContext object. Ie:
This allows users of your class to create the class in a new context. If the class
or a method within the class is being tracked, then that context will "take over" until the thread flow
leaves the class or method. All objects created within that flow will be created in
the context of the tracked class - without needing to pass the CoinjemaContext into
their constructors.
public MyObject(..,CoinjemaContext) { ... }
CoinjemaContext takes a string in its constructor that names a context. Contexts are organized hierarchically, and you can specify sub contexts in your string with a "/". Ie, "topContext/subContext/subsubContext".