uima-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Alex Chaphiv <achap...@gmail.com>
Subject Re: Dependency Injection support?
Date Mon, 21 Mar 2011 17:39:46 GMT
Hey,

Ideally I wanted to be able to construct a workflow without having to deal with
external resources, and pass everything I need into the constructor.

I.E.

	public class SomeAnnotator extends JCasAnnotator_ImplBase {
	  private Type someType;
	  private Foo foo;
	  private Bar bar;

	  SomeAnnotator(Type someType, Foo foo, Bar bar) {
		// set everything
	  }
	 
	  public void process(JCas jcas) {
		// loop over annotations of "someType" and perform something with foo & bar
	  }
	}

Since UIMA requires a default constructor, I've been getting away with using a
wrapper that deals with all the initialization logic and then forwards all calls
to a delegate.
This is not ideal, but it allows me to test annotator logic in isolation of
initialization logic.  
Note: this uses uimaFIT.

	public class SomeAnnotatorWrapper extends
org.uimafit.component.JCasAnnotator_ImplBase {
	  public static final String SOME_TYPE_NAME = "someType";
	  public static final String FOO_KEY = "foo";
	  public static final String BAR_KEY = "bar";

	  @ConfigurationParameter(name = SOME_TYPE_NAME, mandatory = true)
	  private String someTypeName;  

	  @ExternalResource(key = FOO_KEY, api = ExternalResourceLocator.class,
mandatory = true)
	  private Foo foo;

	  @ExternalResource(key = BAR_KEY, api = ExternalResourceLocator.class,
mandatory = true) 
	  private Bar bar;
	  
	  private SomeAnnotator delegate;
	  
	  private initDelegate(TypeSystem ts) {
		Type someType = ts.getType(someTypeName);
		delegate = new SomeAnnotator(someType, foo, bar);
	  }

	  public void process(JCas jcas) {
		if (delegate == null) initDelegate(jcas.getTypeSystem());
		delegate.process(jcas);
	  }
	}

The problem is that this still requires 2 separate implementations of
ExternalResourceLocators for Foo and Bar, and they can't share dependencies
without some type of global state.

	public class FooResource implements ExternalResourceLocator {
	  public Foo getResource() {
	    Baz baz = ???; // Have to make a new baz here
	    return new Foo(baz, ...);
	  }
	  
	  // rest of Resource methods not shown
	}

	public class BarResource implements ExternalResourceLocator {
	  public Bar getResource() {
	    Baz baz = ???; // Here as well since can't share
	    return new Bar(baz, ...);
	  }
	  
	  // rest of Resource methods not shown
	}


What I would like is for SomeAnnotatorWrapper to remain the same (although maybe
with an extra @Inject with each @ExternalResource) and then have some dependency
injection framework
deal with how to construct Foo & Bar.

That last line was kind of vague, because I don't know myself.  This is what I
was wondering about.
I suppose one solution would have the respective Injector for Guice/Spring
passed in as another @ExternalResource and then a subclass could take that and
inject the other field(s).

However, this may be too uimaFIT specific, which was why I was hoping for a
solution in UIMA core.





Mime
View raw message