You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by cw...@apache.org on 2009/01/12 16:35:27 UTC

svn commit: r733791 - in /incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src: main/java/org/apache/uima/adapter/jms/activemq/ main/java/org/apache/uima/adapter/jms/client/ test/java/org/apache/uima/ee/test/ test/resources/deployment/ test/resou...

Author: cwiklik
Date: Mon Jan 12 07:35:17 2009
New Revision: 733791

URL: http://svn.apache.org/viewvc?rev=733791&view=rev
Log:
UIMA-1133 Modified to use one timer to time outgoing requests

Added:
    incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/resources/deployment/Deploy_AggregateAnnotatorWithLongDelayDelegate.xml
    incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/resources/descriptors/analysis_engine/SimpleTestAggregateWithLongDelayDelegate.xml
Modified:
    incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/main/java/org/apache/uima/adapter/jms/activemq/JmsOutputChannel.java
    incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/main/java/org/apache/uima/adapter/jms/client/BaseUIMAAsynchronousEngine_impl.java
    incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/java/org/apache/uima/ee/test/TestUimaASExtended.java

Modified: incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/main/java/org/apache/uima/adapter/jms/activemq/JmsOutputChannel.java
URL: http://svn.apache.org/viewvc/incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/main/java/org/apache/uima/adapter/jms/activemq/JmsOutputChannel.java?rev=733791&r1=733790&r2=733791&view=diff
==============================================================================
--- incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/main/java/org/apache/uima/adapter/jms/activemq/JmsOutputChannel.java (original)
+++ incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/main/java/org/apache/uima/adapter/jms/activemq/JmsOutputChannel.java Mon Jan 12 07:35:17 2009
@@ -50,6 +50,7 @@
 import org.apache.uima.aae.controller.Endpoint;
 import org.apache.uima.aae.controller.PrimitiveAnalysisEngineController;
 import org.apache.uima.aae.controller.LocalCache.CasStateEntry;
+import org.apache.uima.aae.delegate.Delegate;
 import org.apache.uima.aae.error.AsynchAEException;
 import org.apache.uima.aae.error.ErrorContext;
 import org.apache.uima.aae.error.ServiceShutdownException;
@@ -481,7 +482,8 @@
 	 */
 	public void sendRequest(int aCommand, Endpoint anEndpoint)
 	{
-		try
+	  Delegate delegate = null;
+	  try
 		{
 			JmsEndpointConnection_impl endpointConnection = 
 				getEndpointConnection(anEndpoint);
@@ -507,14 +509,6 @@
 			{
 				startTimer = true;
 			}
-			
-			
-			if ( endpointConnection.send(tm, 0, startTimer) != true )
-			{
-				throw new ServiceNotFoundException();
-			}
-			
-			
 			if ( aCommand == AsynchAEMessage.CollectionProcessComplete )
 			{
 		    if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINE)) {
@@ -545,6 +539,10 @@
 							serviceInfo.setReplyQueueName(replyQueueName);
 							serviceInfo.setServiceKey(delegateKey);
 						}
+						delegate = lookupDelegate(delegateKey);
+						if ( delegate.getGetMetaTimeout() > 0 ) {
+	            delegate.startGetMetaRequestTimer();
+						}
 					}
 				}
 				else if ( !anEndpoint.isRemote())
@@ -564,12 +562,17 @@
 	                    new Object[] { endpointConnection.getEndpoint(), endpointConnection.getServerUri() });
 		    }
 			}
+      if ( endpointConnection.send(tm, 0, startTimer) != true )
+      {
+        throw new ServiceNotFoundException();
+      }
+      
 		}
 		catch ( Exception e)
 		{
-			if ( anEndpoint != null && aCommand == AsynchAEMessage.GetMeta )
+      if ( delegate != null && aCommand == AsynchAEMessage.GetMeta )
 			{
-				anEndpoint.cancelTimer();
+			  delegate.cancelDelegateTimer();
 			}
 			// Handle the error
 			ErrorContext errorContext = new ErrorContext();
@@ -1322,7 +1325,15 @@
     //  command line.
     if ( timeout > 0 && addTimeToLive )
 		{
-			aMessage.setJMSExpiration(timeout);
+      Delegate delegate = lookupDelegate(anEndpoint.getDelegateKey());
+			long ttl = timeout;
+			// How many CASes are in the list of CASes pending reply for this delegate
+			int currentOutstandingCasListSize = delegate.getCasPendingReplyListSize();
+			if ( currentOutstandingCasListSize > 0 ) {
+			  // increase the time-to-live
+			  ttl *= currentOutstandingCasListSize;
+			}
+      aMessage.setJMSExpiration(ttl);
 		}
 		if ( getAnalysisEngineController() instanceof AggregateAnalysisEngineController )
 		{
@@ -1534,7 +1545,9 @@
 			tm.setIntProperty(AsynchAEMessage.Payload, AsynchAEMessage.XMIPayload); 
 			//	Add Cas Reference Id to the outgoing JMS Header
 			tm.setStringProperty(AsynchAEMessage.CasReference, aCasReferenceId);
-			//	Add common properties to the JMS Header
+
+			CacheEntry entry = this.getCacheEntry(aCasReferenceId);
+		//	Add common properties to the JMS Header
 			if ( isRequest == true )
 			{
 				populateHeaderWithRequestContext(tm, anEndpoint, AsynchAEMessage.Process); 
@@ -1542,7 +1555,6 @@
 			else
 			{
 				populateHeaderWithResponseContext(tm, anEndpoint, AsynchAEMessage.Process);
-				CacheEntry entry = this.getCacheEntry(aCasReferenceId);
 				tm.setBooleanProperty(AsynchAEMessage.SentDeltaCas, entry.sentDeltaCas());
 			}
 			//	The following is true when the analytic is a CAS Multiplier
@@ -1566,12 +1578,11 @@
 				}
 				if ( UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINE) )
 				{
-					CacheEntry cacheEntry = getCacheEntry(aCasReferenceId);
-					if ( cacheEntry != null )
+					if ( entry != null )
 					{
 						UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, CLASS_NAME.getName(),
 			                    "sendCasToRemoteEndpoint", JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_send_cas_to_collocated_service_detail__FINE",
-			                    new Object[] {getAnalysisEngineController().getComponentName(),"Remote", anEndpoint.getEndpoint(), aCasReferenceId, anInputCasReferenceId, cacheEntry.getInputCasReferenceId() });
+			                    new Object[] {getAnalysisEngineController().getComponentName(),"Remote", anEndpoint.getEndpoint(), aCasReferenceId, anInputCasReferenceId, entry.getInputCasReferenceId() });
 					}
 				}
 			}
@@ -1603,11 +1614,20 @@
 			// ----------------------------------------------------
 			//	Send Request Messsage to the Endpoint
 			// ----------------------------------------------------
-			endpointConnection.send(tm, msgSize, startConnectionTimer);
-			if ( !isRequest )
-			{
-				addIdleTime(tm);
-			}
+      //  Add the CAS to the delegate's list of CASes pending reply. Do the add before
+      //  the send to eliminate a race condition where the reply is received (on different
+      //  thread) *before* the CAS is added to the list.
+      if ( isRequest ) {
+        // Add CAS to the list of CASes pending reply
+        addCasToOutstandingList(entry, isRequest, anEndpoint.getDelegateKey());
+      } else {
+        addIdleTime(tm);
+      }
+      if ( endpointConnection.send(tm, msgSize, startConnectionTimer) == false ) {
+        System.out.println("Send Failed");
+        removeCasFromOutstandingList(entry, isRequest, anEndpoint.getDelegateKey());
+      }
+        
 		}
 		catch( JMSException e)
 		{
@@ -1655,6 +1675,7 @@
       tm.setIntProperty(AsynchAEMessage.Payload, AsynchAEMessage.BinaryPayload); 
       //  Add Cas Reference Id to the outgoing JMS Header
       tm.setStringProperty(AsynchAEMessage.CasReference, aCasReferenceId);
+      CacheEntry entry = this.getCacheEntry(aCasReferenceId);
       //  Add common properties to the JMS Header
       if ( isRequest == true )
       {
@@ -1663,7 +1684,6 @@
       else
       {
         populateHeaderWithResponseContext(tm, anEndpoint, AsynchAEMessage.Process);
-        CacheEntry entry = this.getCacheEntry(aCasReferenceId);
         tm.setBooleanProperty(AsynchAEMessage.SentDeltaCas, entry.sentDeltaCas());
       }
       //  The following is true when the analytic is a CAS Multiplier
@@ -1686,12 +1706,12 @@
         }
         if ( UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINE) )
         {
-          CacheEntry cacheEntry = getCacheEntry(aCasReferenceId);
-          if ( cacheEntry != null )
+//          CacheEntry cacheEntry = getCacheEntry(aCasReferenceId);
+          if ( entry != null )
           {
             UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, CLASS_NAME.getName(),
                           "sendCasToRemoteEndpoint", JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_send_cas_to_collocated_service_detail__FINE",
-                          new Object[] {getAnalysisEngineController().getComponentName(),"Remote", anEndpoint.getEndpoint(), aCasReferenceId, anInputCasReferenceId, cacheEntry.getInputCasReferenceId() });
+                          new Object[] {getAnalysisEngineController().getComponentName(),"Remote", anEndpoint.getEndpoint(), aCasReferenceId, anInputCasReferenceId, entry.getInputCasReferenceId() });
           }
         }
       }
@@ -1723,11 +1743,19 @@
       // ----------------------------------------------------
       //  Send Request Messsage to the Endpoint
       // ----------------------------------------------------
-      endpointConnection.send(tm, msgSize, startConnectionTimer);
-      if ( !isRequest )
-      {
+      //  Add the CAS to the delegate's list of CASes pending reply. Do the add before
+      //  the send to eliminate a race condition where the reply is received (on different
+      //  thread) *before* the CAS is added to the list.
+      if ( isRequest ) {
+        // Add CAS to the list of CASes pending reply
+        addCasToOutstandingList(entry, isRequest, anEndpoint.getDelegateKey());
+      } else {
         addIdleTime(tm);
       }
+      if ( endpointConnection.send(tm, msgSize, startConnectionTimer) == false ) {
+        System.out.println("Send Failed");
+        removeCasFromOutstandingList(entry, isRequest, anEndpoint.getDelegateKey());
+      }
     }
     catch( JMSException e)
     {
@@ -1854,16 +1882,19 @@
 			// ----------------------------------------------------
 			//	Send Request Messsage to the Endpoint
 			// ----------------------------------------------------
-			endpointConnection.send(tm, msgSize, startConnectionTimer);
-
-//			if ( getAnalysisEngineController().isTopLevelComponent() )
-//			{
-//				getAnalysisEngineController().getInProcessCache().dumpContents(getAnalysisEngineController().getComponentName());
-//			}
-			if ( !isRequest )
-			{
-				addIdleTime(tm);
+      //  Add the CAS to the delegate's list of CASes pending reply. Do the add before
+      //  the send to eliminate a race condition where the reply is received (on different
+      //  thread) *before* the CAS is added to the list.
+			if ( isRequest ) {
+	      // Add CAS to the list of CASes pending reply
+	      addCasToOutstandingList(entry, isRequest, anEndpoint.getDelegateKey());
+			} else {
+        addIdleTime(tm);
 			}
+      if ( endpointConnection.send(tm, msgSize, startConnectionTimer) == false ) {
+        System.out.println("Send Failed");
+        removeCasFromOutstandingList(entry, isRequest, anEndpoint.getDelegateKey());
+      }
 		}
 		catch( JMSException e)
 		{
@@ -1987,12 +2018,21 @@
       // ----------------------------------------------------
       //  Send Request Messsage to the Endpoint
       // ----------------------------------------------------
-      endpointConnection.send(tm, msgSize, startConnectionTimer);
-
-      if ( !isRequest )
-      {
+      //  Add the CAS to the delegate's list of CASes pending reply. Do the add before
+      //  the send to eliminate a race condition where the reply is received (on different
+      //  thread) *before* the CAS is added to the list.
+      if ( isRequest ) {
+        // Add CAS to the list of CASes pending reply
+        addCasToOutstandingList(entry, isRequest, anEndpoint.getDelegateKey());
+      } else {
         addIdleTime(tm);
       }
+      //  Send the message to the delegate. If the send fails, remove the CAS id
+      //  from the delegate's list of CASes pending reply.
+      if ( endpointConnection.send(tm, msgSize, startConnectionTimer) == false ) {
+        System.out.println("Send Failed");
+        removeCasFromOutstandingList(entry, isRequest, anEndpoint.getDelegateKey());
+      }
     }
     catch( JMSException e)
     {
@@ -2018,7 +2058,26 @@
     }
     
   }
-	
+	private Delegate lookupDelegate( String aDelegateKey ) {
+    if ( getAnalysisEngineController() instanceof AggregateAnalysisEngineController ) {
+      Delegate delegate = 
+        ((AggregateAnalysisEngineController)getAnalysisEngineController()).lookupDelegate(aDelegateKey);
+      return delegate;             
+    }
+    return null;
+	}
+  private void addCasToOutstandingList(CacheEntry entry, boolean isRequest, String aDelegateKey) {
+    Delegate delegate = null;
+    if ( isRequest && (delegate = lookupDelegate(aDelegateKey)) != null) {
+      delegate.addCasToOutstandingList(entry.getCasReferenceId());             
+    }
+  }
+  private void removeCasFromOutstandingList(CacheEntry entry, boolean isRequest, String aDelegateKey) {
+    Delegate delegate = null;
+    if ( isRequest && (delegate = lookupDelegate(aDelegateKey)) != null) {
+      delegate.removeCasFromOutstandingList(entry.getCasReferenceId());             
+    }
+  }
 	
 	
 	private String getTopParentCasReferenceId( String casReferenceId ) throws Exception

Modified: incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/main/java/org/apache/uima/adapter/jms/client/BaseUIMAAsynchronousEngine_impl.java
URL: http://svn.apache.org/viewvc/incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/main/java/org/apache/uima/adapter/jms/client/BaseUIMAAsynchronousEngine_impl.java?rev=733791&r1=733790&r2=733791&view=diff
==============================================================================
--- incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/main/java/org/apache/uima/adapter/jms/client/BaseUIMAAsynchronousEngine_impl.java (original)
+++ incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/main/java/org/apache/uima/adapter/jms/client/BaseUIMAAsynchronousEngine_impl.java Mon Jan 12 07:35:17 2009
@@ -49,6 +49,7 @@
 import org.apache.uima.aae.controller.ControllerCallbackListener;
 import org.apache.uima.aae.controller.ControllerLifecycle;
 import org.apache.uima.aae.controller.Endpoint;
+import org.apache.uima.aae.delegate.Delegate;
 import org.apache.uima.aae.error.UimaASMetaRequestTimeout;
 import org.apache.uima.aae.jmx.JmxManager;
 import org.apache.uima.aae.message.AsynchAEMessage;
@@ -465,6 +466,8 @@
     if ( UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.CONFIG) ) {
       UIMAFramework.getLogger(CLASS_NAME).logrb(Level.CONFIG, CLASS_NAME.getName(), "initialize", JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_init_uimaee_client__CONFIG", new Object[] { brokerURI, 0, casPoolSize, processTimeout, metadataTimeout, cpcTimeout });
     }
+    super.serviceDelegate = new ClientServiceDelegate(endpoint,applicationName,this);
+    super.serviceDelegate.setCasProcessTimeout(processTimeout);
 		try
 		{
 			jmxManager = new JmxManager("org.apache.uima");

Modified: incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/java/org/apache/uima/ee/test/TestUimaASExtended.java
URL: http://svn.apache.org/viewvc/incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/java/org/apache/uima/ee/test/TestUimaASExtended.java?rev=733791&r1=733790&r2=733791&view=diff
==============================================================================
--- incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/java/org/apache/uima/ee/test/TestUimaASExtended.java (original)
+++ incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/java/org/apache/uima/ee/test/TestUimaASExtended.java Mon Jan 12 07:35:17 2009
@@ -507,6 +507,28 @@
     runTest(appCtx, eeUimaEngine, null, null, 1, PROCESS_LATCH);
   }
 
+  /**
+   * Tests Timeout logic
+   * @throws Exception
+   */
+  public void testRemoteDelegateTimeout() throws Exception
+  {
+    System.out.println("-------------- testRemoteDelegateTimeout -------------");
+    System.out.println("The Aggregate sends 2 CASes to the NoOp Annotator which");
+    System.out.println("delays each CAS for 6000ms. The timeout is set to 4000ms");
+    System.out.println("Two CAS retries are expected");
+    BaseUIMAAsynchronousEngine_impl eeUimaEngine = new BaseUIMAAsynchronousEngine_impl();
+    deployService(eeUimaEngine, relativePath+"/Deploy_NoOpAnnotatorWithLongDelay.xml");
+    deployService(eeUimaEngine, relativePath+"/Deploy_AggregateAnnotatorWithLongDelayDelegate.xml");
+    Map<String, Object> appCtx = buildContext( String.valueOf(broker.getMasterConnectorURI()), "TopLevelTaeQueue" );
+    //  The Remote NoOp delays each CAS for 6000ms. The Aggregate sends two CASes so adjust
+    //  client timeout to be just over 12000ms.
+    appCtx.put(UimaAsynchronousEngine.Timeout, 13000 );
+    addExceptionToignore(org.apache.uima.aae.error.UimaEEServiceException.class);
+    addExceptionToignore(org.apache.uima.aae.error.UimaASProcessCasTimeout.class);
+    
+    runTest(appCtx, eeUimaEngine, null, null, 1, PROCESS_LATCH);
+  }
   public void testDeployAggregateWithCollocatedAggregateService() throws Exception
 	{
     System.out.println("-------------- testDeployAggregateWithCollocatedAggregateService -------------");

Added: incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/resources/deployment/Deploy_AggregateAnnotatorWithLongDelayDelegate.xml
URL: http://svn.apache.org/viewvc/incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/resources/deployment/Deploy_AggregateAnnotatorWithLongDelayDelegate.xml?rev=733791&view=auto
==============================================================================
--- incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/resources/deployment/Deploy_AggregateAnnotatorWithLongDelayDelegate.xml (added)
+++ incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/resources/deployment/Deploy_AggregateAnnotatorWithLongDelayDelegate.xml Mon Jan 12 07:35:17 2009
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   ***************************************************************
+   * Licensed to the Apache Software Foundation (ASF) under one
+   * or more contributor license agreements.  See the NOTICE file
+   * distributed with this work for additional information
+   * regarding copyright ownership.  The ASF licenses this file
+   * to you under the Apache License, Version 2.0 (the
+   * "License"); you may not use this file except in compliance
+   * with the License.  You may obtain a copy of the License at
+         *
+   *   http://www.apache.org/licenses/LICENSE-2.0
+   * 
+   * Unless required by applicable law or agreed to in writing,
+   * software distributed under the License is distributed on an
+   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   * KIND, either express or implied.  See the License for the
+   * specific language governing permissions and limitations
+   * under the License.
+   ***************************************************************
+   -->
+<analysisEngineDeploymentDescription xmlns="http://uima.apache.org/resourceSpecifier">
+  
+  <name>Top Level TAE</name>
+  <description></description>
+  
+  <deployment protocol="jms" provider="activemq">
+    <casPool numberOfCASes="5"/>
+    <service>
+      <inputQueue endpoint="TopLevelTaeQueue" brokerURL="tcp://localhost:8118" prefetch="1"/>
+      <topDescriptor>
+        <import location="../descriptors/analysis_engine/SimpleTestAggregateWithLongDelayDelegate.xml"/>
+      </topDescriptor>
+      <analysisEngine>
+        <delegates>
+        
+          <analysisEngine key="TestMultiplier">
+	        <casMultiplier poolSize="5"/> 
+          </analysisEngine>
+        
+          <remoteAnalysisEngine key="NoOp">
+	                  <inputQueue endpoint="NoOpAnnotatorQueueLongDelay" brokerURL="tcp://localhost:8118"/> 
+	                  <serializer method="xmi"/>
+                      <asyncAggregateErrorConfiguration>
+						  <getMetadataErrors maxRetries="0" timeout="0" errorAction="terminate"/>
+						  <processCasErrors maxRetries="1" timeout="4000" continueOnRetryFailure="false" thresholdCount="0" thresholdWindow="0" thresholdAction="terminate"/>
+						  <collectionProcessCompleteErrors timeout="0" additionalErrorAction="terminate"/>
+                      </asyncAggregateErrorConfiguration>
+          </remoteAnalysisEngine>
+
+        </delegates>
+      </analysisEngine>
+    </service>
+  </deployment>
+  
+</analysisEngineDeploymentDescription>
\ No newline at end of file

Added: incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/resources/descriptors/analysis_engine/SimpleTestAggregateWithLongDelayDelegate.xml
URL: http://svn.apache.org/viewvc/incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/resources/descriptors/analysis_engine/SimpleTestAggregateWithLongDelayDelegate.xml?rev=733791&view=auto
==============================================================================
--- incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/resources/descriptors/analysis_engine/SimpleTestAggregateWithLongDelayDelegate.xml (added)
+++ incubator/uima/sandbox/trunk/uima-as/uimaj-as-activemq/src/test/resources/descriptors/analysis_engine/SimpleTestAggregateWithLongDelayDelegate.xml Mon Jan 12 07:35:17 2009
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+	<!--
+	 ***************************************************************
+	 * Licensed to the Apache Software Foundation (ASF) under one
+	 * or more contributor license agreements.  See the NOTICE file
+	 * distributed with this work for additional information
+	 * regarding copyright ownership.  The ASF licenses this file
+	 * to you under the Apache License, Version 2.0 (the
+	 * "License"); you may not use this file except in compliance
+	 * with the License.  You may obtain a copy of the License at
+         *
+	 *   http://www.apache.org/licenses/LICENSE-2.0
+	 * 
+	 * Unless required by applicable law or agreed to in writing,
+	 * software distributed under the License is distributed on an
+	 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+	 * KIND, either express or implied.  See the License for the
+	 * specific language governing permissions and limitations
+	 * under the License.
+	 ***************************************************************
+   -->
+   
+<analysisEngineDescription xmlns="http://uima.apache.org/resourceSpecifier">
+  <frameworkImplementation>org.apache.uima.java</frameworkImplementation>
+  <primitive>false</primitive>
+  <delegateAnalysisEngineSpecifiers>
+    
+    <delegateAnalysisEngine key="TestMultiplier">
+      <import location="../multiplier/SimpleCasGenerator.xml"/>
+    </delegateAnalysisEngine>
+    
+      <delegateAnalysisEngine key="NoOp">
+		  <import location="NoOpAnnotatorWithLongDelay.xml"/>
+      </delegateAnalysisEngine>
+  
+  </delegateAnalysisEngineSpecifiers>
+  <analysisEngineMetaData>
+    <name>Test Aggregate TAE</name>
+    <description>Detects Nothing</description>
+    <configurationParameters>
+      <configurationParameter>
+        <name>NumberToGenerate</name>
+        <description>Approximate number of CASes to create.</description>
+        <type>Integer</type>
+        <multiValued>false</multiValued>
+        <mandatory>true</mandatory>
+        <overrides>
+          <parameter>TestMultiplier/NumberToGenerate</parameter>
+        </overrides>
+      </configurationParameter>
+    </configurationParameters>
+
+    <configurationParameterSettings>
+      <nameValuePair>
+        <name>NumberToGenerate</name>
+        <value>
+          <integer>2</integer>
+        </value>
+      </nameValuePair>
+    </configurationParameterSettings>
+    <flowConstraints>
+      <fixedFlow>
+      
+        <node>TestMultiplier</node>
+        <node>NoOp</node> 
+      </fixedFlow>
+    </flowConstraints>
+    <capabilities>
+      <capability>
+        <inputs/>
+        <outputs>
+        </outputs>
+        <languagesSupported>
+          <language>en</language>
+        </languagesSupported>
+      </capability>
+    </capabilities>
+	<operationalProperties>
+		<modifiesCas>true</modifiesCas>
+		<multipleDeploymentAllowed>true</multipleDeploymentAllowed>
+		<outputsNewCASes>false</outputsNewCASes>
+	</operationalProperties>
+  </analysisEngineMetaData>
+</analysisEngineDescription>