How To Use Coinjema

First of all, read the Coinjema Dependencies Document for how to setup your project to use Coinjema.

For Coinjema to work, it must be initialized with information about where to find context configuration. This means making a call to:

org.coinjema.context.ContextFactory.createRootContext(ContextSource)
A ContextSource defines a location at which configuration information is located - ie a directory. So, a real call might look like:
ContextFactory.createRootContext(new FileContextSource("/home/me/appConfig"));
This is all that's required to initialize Coinjema for basic use. Other contexts can be created in other locations:
ContextFactory.createContext("newContext",new FileContextSource("/home/me/altApp"));
Coinjema will create a hierarchy of contexts using the given directory as the starting point. Any sub-directories will represent sub-contexts.

To write a class that will be handled by Coinjema, use the @CoinjemaObject class-level annotation:

@CoinjemaObject
public class ExampleClass {
   public ExampleClass()
   {
      ..
   }
}
Coinjema will introduce an interface (ContextOriented) and implementation to this class. This interface and implementation lets Coinjema store a small bit of information in each object of your class - information about which context the object is part of.

When the above ExampleClass is instantiated, Coinjema will intercept the constructor call and will look for methods that are annotated with @CoinjemaDependency. These methods are the means by which Coinjema hands your object its dependencies. For instance:

@CoinjemaObject
public class ExampleClass {
   Log log;
	   
   public ExampleClass()
   {
      ..
   }
	   
   @CoinjemaDependency
   public void setLogger(Log l)
   {
       log = l;
   }
}
A @CoinjemaDependency method must take exactly one parameter.

Coinjema will search the current context for a file that matches the setLogger(Log) method. It goes through a series of possibilities that essentially move from more specific to more general. An outline of the steps is:

  1. First, find the already created Log instance for ExampleClass in the current context. Coinjema only runs the configuration scripts once and caches the result for the class.
  2. Look for a file named ExampleClass.setLogger.*** and "evaluate" it to a Java object. *** represents a file extension that Coinjema understands. Out-of-the-box, Coinjema understands .groovy, .groovyClass, .properties, .txt, .jser, .compmap, and .redirect (for groovy script, groovy class, and properties, plain text, serialized java classes, component sets, and redirection files respectively). More can be registered with Coinjema as implementations of the Evaluator interface.

    To summarize, Coinjema will look for files named
    ExampleClass.setLogger.groovy,
    ExampleClass.setLogger.groovyClass
    ExampleClass.setLogger.properties
    etc...

  3. @CoinjemaDependency and@CoinjemaObject have options that can be set to modify the name of the config file that will be searched for.
  4. If none are found, Coinjema looks for a cached object of the type of the injected class (Log, in our case). This would represent a "shared dependency" (Coinjema's version of a singleton).
  5. If no such shared dependency can be found in memory, Coinjema searches again for a file named Log.***.
  6. If still no dependency is found, repeat the entire process for the parent context of the current context. In other words, your configuration contexts inherit their settings from each other.
  7. If no dependency found, Coinjema will throw an runtime exception.