You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@uima.apache.org by Mario Gazzo <ma...@gmail.com> on 2015/06/19 22:24:45 UTC
Re: Injecting nested resources using UIMA fit
Hi Richard,
Seems something still spooky with my nested resources. This time I added an additional resource, which depends on the same shared resource as another. I now have two different resources dependent on the same external resource but during initialisation I get the error shown below. I can use both resources independently of each other but just not together. I have been able to replicate it by extending the earlier simple example (see further down).
You will notice in the example that I bind every resource to every description specified even though there is no declared dependency. Reason is because our actual application has a small DSL that aggregates the descriptions and then tries to bind resources on all possible descriptions just before execution. However, I just did a naive approach where I bind every resource to every possible description that was added but I didn’t do code that first inspects whether a description has actually declared the dependency before attempting to bind. Yes, its inefficient for a very large amount of resources but we don’t have that. My naive assumption was that the UIMAfit binding process would figure this out way better than I could myself and I just sticked with this since it worked fine until now and it was simple to program. I don’t know whether this actually is the direct cause of the problem or whether my use just triggered a bug. It works if I don’t do these superfluous bindings. If this use case cannot be supported then I would like to know what would alternatively be the simplest way to make these inspections on the descriptors before making a binding attempt?
Thanks a lot for your help.
Cheers
Mario
///////////////////////// EXAMPLE OUTPUT ///////////////////////////////////
Resource A loaded
Resource B loaded
Resource C loaded
Resource C initialized. Now calling resource A
Hello resource A
Exception in thread "main" org.apache.uima.resource.ResourceInitializationException
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.configure(ExternalResourceInitializer.java:128)
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.initialize(ExternalResourceInitializer.java:72)
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.initializeNestedResources(ExternalResourceInitializer.java:199)
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.configure(ExternalResourceInitializer.java:98)
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.configure(ExternalResourceInitializer.java:94)
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.initialize(ExternalResourceInitializer.java:72)
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.initializeNestedResources(ExternalResourceInitializer.java:199)
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.configure(ExternalResourceInitializer.java:98)
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.configure(ExternalResourceInitializer.java:94)
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.configure(ExternalResourceInitializer.java:94)
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.configure(ExternalResourceInitializer.java:94)
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.configure(ExternalResourceInitializer.java:94)
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.configure(ExternalResourceInitializer.java:94)
at org.apache.uima.fit.component.initialize.ExternalResourceInitializer.initialize(ExternalResourceInitializer.java:72)
at org.apache.uima.fit.component.JCasCollectionReader_ImplBase.initialize(JCasCollectionReader_ImplBase.java:55)
at org.apache.uima.collection.CollectionReader_ImplBase.initialize(CollectionReader_ImplBase.java:70)
at org.apache.uima.impl.CollectionReaderFactory_impl.produceResource(CollectionReaderFactory_impl.java:103)
at org.apache.uima.impl.CompositeResourceFactory_impl.produceResource(CompositeResourceFactory_impl.java:62)
at org.apache.uima.UIMAFramework.produceResource(UIMAFramework.java:279)
at org.apache.uima.UIMAFramework.produceResource(UIMAFramework.java:331)
at org.apache.uima.UIMAFramework.produceCollectionReader(UIMAFramework.java:812)
at org.apache.uima.fit.pipeline.SimplePipeline.runPipeline(SimplePipeline.java:134)
at NestedResourceExample.main(NestedResourceExample.java:291)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.IllegalStateException: Mandatory resource [NestedResourceExample$ResourceB-1##Resource-A] is not set on [class NestedResourceExample$ResourceB]
... 28 more
///////////////////////// EXAMPLE CODE ///////////////////////////////////
import org.apache.uima.UIMAException;
import org.apache.uima.analysis_engine.AnalysisEngineDescription;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.analysis_engine.metadata.FixedFlow;
import org.apache.uima.analysis_engine.metadata.FlowConstraints;
import org.apache.uima.cas.AbstractCas;
import org.apache.uima.cas.CAS;
import org.apache.uima.collection.CollectionException;
import org.apache.uima.collection.CollectionReaderDescription;
import org.apache.uima.fit.component.*;
import org.apache.uima.fit.component.JCasFlowController_ImplBase;
import org.apache.uima.fit.component.initialize.ConfigurationParameterInitializer;
import org.apache.uima.fit.descriptor.ConfigurationParameter;
import org.apache.uima.fit.descriptor.ExternalResource;
import org.apache.uima.fit.factory.*;
import org.apache.uima.fit.pipeline.SimplePipeline;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.flow.*;
import org.apache.uima.jcas.JCas;
import org.apache.uima.resource.DataResource;
import org.apache.uima.resource.ExternalResourceDescription;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.resource.SharedResourceObject;
import org.apache.uima.util.Progress;
import org.apache.uima.util.ProgressImpl;
import java.io.IOException;
import java.util.ArrayList;
import static org.apache.uima.fit.factory.ExternalResourceFactory.bindExternalResource;
/**
* Micro example illustrating a problem when initializing nested resources
*/
public class NestedResourceExample {
public static class ResourceA implements SharedResourceObject, ExternalResourceAware {
public static final String RESOURCE_A_KEY = "Resource-A";
@ConfigurationParameter(name= ExternalResourceFactory.PARAM_RESOURCE_NAME)
private String resourceName;
@Override
public String getResourceName() {
return resourceName;
}
@Override
public void afterResourcesInitialized() throws ResourceInitializationException {
System.out.println("Resource A initialized");
}
@Override
public void load(DataResource aData) throws ResourceInitializationException {
ConfigurationParameterInitializer.initialize(this, aData);
System.out.println("Resource A loaded");
}
public void helloA() {
System.out.println("Hello resource A");
}
}
public static class ResourceB implements SharedResourceObject, ExternalResourceAware {
public static final String RESOURCE_B_KEY = "Resource-B";
@ExternalResource(key = ResourceA.RESOURCE_A_KEY)
private ResourceA resourceA;
@ConfigurationParameter(name= ExternalResourceFactory.PARAM_RESOURCE_NAME)
private String resourceName;
@Override
public String getResourceName() {
return resourceName;
}
@Override
public void afterResourcesInitialized() throws ResourceInitializationException {
System.out.println("Resource B initialized. Now calling resource A");
resourceA.helloA();
}
@Override
public void load(DataResource aData) throws ResourceInitializationException {
ConfigurationParameterInitializer.initialize(this, aData);
System.out.println("Resource B loaded");
}
public void helloB() {
System.out.println("Hello resource B");
}
}
public static class ResourceC implements SharedResourceObject, ExternalResourceAware {
public static final String RESOURCE_C_KEY = "Resource-C";
@ExternalResource(key = ResourceA.RESOURCE_A_KEY)
private ResourceA resourceA;
@ConfigurationParameter(name= ExternalResourceFactory.PARAM_RESOURCE_NAME)
private String resourceName;
@Override
public String getResourceName() {
return resourceName;
}
@Override
public void afterResourcesInitialized() throws ResourceInitializationException {
System.out.println("Resource C initialized. Now calling resource A");
resourceA.helloA();
}
@Override
public void load(DataResource aData) throws ResourceInitializationException {
ConfigurationParameterInitializer.initialize(this, aData);
System.out.println("Resource C loaded");
}
public void helloC() {
System.out.println("Hello resource C");
}
}
public static class FlowController extends JCasFlowController_ImplBase {
@ExternalResource(key = ResourceA.RESOURCE_A_KEY)
private ResourceA resourceA;
@ExternalResource(key = ResourceB.RESOURCE_B_KEY)
private ResourceB resourceB;
private ArrayList<Step> pipeline = new ArrayList<>();
@Override
public void initialize(FlowControllerContext context) throws ResourceInitializationException {
super.initialize(context);
FlowConstraints flowConstraints = context.getAggregateMetadata().getFlowConstraints();
String[] sequence = ((FixedFlow) flowConstraints).getFixedFlow();
for( String key : sequence ) {
pipeline.add(new SimpleStep(key));
}
}
@Override
public Flow computeFlow(JCas aJCas) throws AnalysisEngineProcessException {
return new SimpleFlow(aJCas);
}
public class SimpleFlow implements Flow {
private final JCas jCas;
private int step = 0;
public SimpleFlow(JCas jCas) {
this.jCas = jCas;
}
@Override
public Step next() throws AnalysisEngineProcessException {
if(step < pipeline.size()) {
return pipeline.get(step++);
} else {
resourceA.helloA();
resourceB.helloB();
return new FinalStep();
}
}
@Override
public Flow newCasProduced(AbstractCas newCas, String producedBy) throws AnalysisEngineProcessException {
return null;
}
@Override
public boolean continueOnFailure(String failedAeKey, Exception failure) {
return false;
}
@Override
public void aborted() {
System.out.println("Simple flow aborted");
}
}
}
public static class SimpleCollectionReader extends JCasCollectionReader_ImplBase {
@ExternalResource(key = ResourceA.RESOURCE_A_KEY)
private ResourceA resourceA;
@ExternalResource(key = ResourceB.RESOURCE_B_KEY)
private ResourceB resourceB;
private int completed = 0;
@Override
public void getNext(JCas jCas) throws IOException, CollectionException {
try {
JCas view = ViewCreatorAnnotator.createViewSafely(jCas, CAS.NAME_DEFAULT_SOFA);
view.setDocumentText("This is some text "+completed++);
resourceA.helloA();
resourceB.helloB();
} catch (AnalysisEngineProcessException e) {
throw new CollectionException(e);
}
}
@Override
public boolean hasNext() throws IOException, CollectionException {
return completed < 1;
}
@Override
public Progress[] getProgress() {
return new Progress[] { new ProgressImpl(0, 1, Progress.ENTITIES) };
}
}
public static class SimpleAnalyser extends JCasAnnotator_ImplBase {
@ExternalResource(key = ResourceB.RESOURCE_B_KEY)
private ResourceB resourceB;
@Override
public void process(JCas jCas) throws AnalysisEngineProcessException {
JCas view = JCasUtil.getView(jCas, CAS.NAME_DEFAULT_SOFA, true);
System.out.println(view.getDocumentText());
resourceB.helloB();
}
}
public static class AnotherSimpleAnalyser extends JCasAnnotator_ImplBase {
@ExternalResource(key = ResourceC.RESOURCE_C_KEY)
private ResourceC resourceC;
@Override
public void process(JCas jCas) throws AnalysisEngineProcessException {
System.out.println("One more analysis");
resourceC.helloC();
}
}
public static void main(String[] args) throws UIMAException, IOException {
AggregateBuilder builder = new AggregateBuilder();
ExternalResourceDescription resourceA = ExternalResourceFactory.createExternalResourceDescription(ResourceA.class,"http://resource.org/a");
ExternalResourceDescription resourceB = ExternalResourceFactory.createExternalResourceDescription(ResourceB.class,"http://resource.org/b");
ExternalResourceDescription resourceC = ExternalResourceFactory.createExternalResourceDescription(ResourceC.class,"http://resource.org/c");
CollectionReaderDescription reader = CollectionReaderFactory.createReaderDescription(SimpleCollectionReader.class);
FlowControllerDescription flow = FlowControllerFactory.createFlowControllerDescription(FlowController.class);
AnalysisEngineDescription ae1 = AnalysisEngineFactory.createEngineDescription(SimpleAnalyser.class);
AnalysisEngineDescription ae2 = AnalysisEngineFactory.createEngineDescription(AnotherSimpleAnalyser.class);
bindExternalResource(resourceA, ResourceB.RESOURCE_B_KEY, resourceB);
bindExternalResource(resourceC, ResourceC.RESOURCE_C_KEY, resourceC);
bindExternalResource(resourceB, ResourceA.RESOURCE_A_KEY, resourceA);
bindExternalResource(resourceB, ResourceC.RESOURCE_C_KEY, resourceC);
bindExternalResource(resourceC, ResourceA.RESOURCE_A_KEY, resourceA);
bindExternalResource(resourceC, ResourceB.RESOURCE_B_KEY, resourceB);
bindExternalResource(flow, ResourceA.RESOURCE_A_KEY, resourceA);
bindExternalResource(flow, ResourceB.RESOURCE_B_KEY, resourceB);
bindExternalResource(flow, ResourceC.RESOURCE_C_KEY, resourceC);
bindExternalResource(reader, ResourceA.RESOURCE_A_KEY, resourceA);
bindExternalResource(reader, ResourceB.RESOURCE_B_KEY, resourceB);
bindExternalResource(reader, ResourceC.RESOURCE_C_KEY, resourceC);
bindExternalResource(ae1, ResourceA.RESOURCE_A_KEY, resourceA);
bindExternalResource(ae1, ResourceB.RESOURCE_B_KEY, resourceB);
bindExternalResource(ae1, ResourceC.RESOURCE_C_KEY, resourceC);
bindExternalResource(ae2, ResourceA.RESOURCE_A_KEY, resourceA);
bindExternalResource(ae2, ResourceB.RESOURCE_B_KEY, resourceB);
bindExternalResource(ae2, ResourceC.RESOURCE_C_KEY, resourceC);
builder.add(ae1);
builder.add(ae2);
builder.setFlowControllerDescription(flow);
SimplePipeline.runPipeline(reader, builder.createAggregateDescription());
}
}
> On 24 May 2015, at 13:19 , Mario Gazzo <ma...@gmail.com> wrote:
>
> Works nicely now, Richard. Thanks a lot :)
>
> I will run with the 2.2.0 branch from the Git repository in the coming period and I will report back if I stumble upon any issues.
>
> Is there some time horizon for the final release?
>
> Cheers
> Mario
>
>> On 24 May 2015, at 02:26 , Richard Eckart de Castilho <re...@apache.org> wrote:
>>
>> Ok, so for what it's worth - bindExternalResource() should also have worked
>> in the way that you used it and it was a bug that it didn't.
>>
>> So both of these issues are sorted out now:
>>
>> - https://issues.apache.org/jira/browse/UIMA-4425
>> - https://issues.apache.org/jira/browse/UIMA-4426
>>
>> I can now run your code with "bindResourcesFirst" set to true.
>> In fact, resourceA must be bound to resourceB before resourceB
>> is bound to further things.
>>
>> We're not supposed to expose users to unreleased artifacts...
>> but if you know how to get the latest uimaFIT from SVN and hook it
>> up to your code, it wouldn't hurt if you could give the fixes
>> a spin in your environment.
>>
>> -- Richard
>>
>>
>> On 23.05.2015, at 22:52, Richard Eckart de Castilho <re...@apache.org> wrote:
>>
>>> On 23.05.2015, at 22:45, Mario Gazzo <ma...@gmail.com> wrote:
>>>
>>>> Thank you, Richard. The reason I use bindExternalResource is because I have a light DSL layer on top where everything get’s wired together from different aggregate modules. This way the modules don’t need to be that tightly coupled up front but I just do the binding generically right before the execution. The example doesn’t show this.
>>>
>>> ... ok, I'll double check again whether bindExternalResource really cannot be used as you did here ... after fixing the other problem.
>>>
>>> My main local uimaFIT checkout is currently a bit of a mess.
>>>
>>> /me fetching duster and dusting off...
>>>
>>> -- Richard
>>
>
Re: Injecting nested resources using UIMA fit
Posted by Mario Gazzo <ma...@gmail.com>.
Thanks Richard,
No hurry, I have a temporary workaround for it but I probably need to look into this soon. I’ll keep you posted when I dig up some new findings.
Cheers
Mario
> On 24 Jun 2015, at 09:29 , Richard Eckart de Castilho <re...@apache.org> wrote:
>
> Hi Mario,
>
> I'm not sure if the resource injection has a proper two-phase initialization
> (first instantiation, then injection) or if it behaves more like a constructor
> injection (injection during instantiation). I think it is the latter which
> requires that there is no circular injection - but that needs to be checked.
> I may not be able to get my hands into this in the next few days, so if have
> a need and want to dig into it more, feel free.
>
> Cheers,
>
> -- Richard
>
> On 19.06.2015, at 22:24, Mario Gazzo <ma...@gmail.com> wrote:
>
>> Hi Richard,
>>
>> Seems something still spooky with my nested resources. This time I added an additional resource, which depends on the same shared resource as another. I now have two different resources dependent on the same external resource but during initialisation I get the error shown below. I can use both resources independently of each other but just not together. I have been able to replicate it by extending the earlier simple example (see further down).
>>
>> You will notice in the example that I bind every resource to every description specified even though there is no declared dependency. Reason is because our actual application has a small DSL that aggregates the descriptions and then tries to bind resources on all possible descriptions just before execution. However, I just did a naive approach where I bind every resource to every possible description that was added but I didn’t do code that first inspects whether a description has actually declared the dependency before attempting to bind. Yes, its inefficient for a very large amount of resources but we don’t have that. My naive assumption was that the UIMAfit binding process would figure this out way better than I could myself and I just sticked with this since it worked fine until now and it was simple to program. I don’t know whether this actually is the direct cause of the problem or whether my use just triggered a bug. It works if I don’t do these superfluous bindings. If this use case cannot be supported then I would like to know what would alternatively be the simplest way to make these inspections on the descriptors before making a binding attempt?
>>
>> Thanks a lot for your help.
>>
>> Cheers
>> Mario
>
Re: Injecting nested resources using UIMA fit
Posted by Richard Eckart de Castilho <re...@apache.org>.
Hi Mario,
I'm not sure if the resource injection has a proper two-phase initialization
(first instantiation, then injection) or if it behaves more like a constructor
injection (injection during instantiation). I think it is the latter which
requires that there is no circular injection - but that needs to be checked.
I may not be able to get my hands into this in the next few days, so if have
a need and want to dig into it more, feel free.
Cheers,
-- Richard
On 19.06.2015, at 22:24, Mario Gazzo <ma...@gmail.com> wrote:
> Hi Richard,
>
> Seems something still spooky with my nested resources. This time I added an additional resource, which depends on the same shared resource as another. I now have two different resources dependent on the same external resource but during initialisation I get the error shown below. I can use both resources independently of each other but just not together. I have been able to replicate it by extending the earlier simple example (see further down).
>
> You will notice in the example that I bind every resource to every description specified even though there is no declared dependency. Reason is because our actual application has a small DSL that aggregates the descriptions and then tries to bind resources on all possible descriptions just before execution. However, I just did a naive approach where I bind every resource to every possible description that was added but I didn’t do code that first inspects whether a description has actually declared the dependency before attempting to bind. Yes, its inefficient for a very large amount of resources but we don’t have that. My naive assumption was that the UIMAfit binding process would figure this out way better than I could myself and I just sticked with this since it worked fine until now and it was simple to program. I don’t know whether this actually is the direct cause of the problem or whether my use just triggered a bug. It works if I don’t do these superfluous bindings. If this use case cannot be supported then I would like to know what would alternatively be the simplest way to make these inspections on the descriptors before making a binding attempt?
>
> Thanks a lot for your help.
>
> Cheers
> Mario