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