Announcement Announcement Module
Collapse
No announcement yet.
In my example how to handle errors with agregator ? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    No ideas, sorry; like I said the only difference I see is the good test sends a result with 30 DTOs, the bad one has 21.

    Maybe a problem on the client?

    If I were debugging it myself, the next step I'd do is use wireshark (or eclipse's TCP/IP Monitor if the client is on the same host) to examine the TCP packets between the client and server).

    If that shows no data going to the client, I'd then start debugging the message conversion in HttpRequestHandlingMessagingGateway.writeResponse.

    Comment


    • #17
      With eclipse TCP/IP monitor, when it works I have the following informations :

      The request with the content below
      POST /httpRemoting/getAccounts HTTP/1.1
      Host: localhost:8886
      User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
      Accept-Language: fr-fr,fr;q=0.9,de-de;q=0.7,de;q=0.6,en-us;q=0.4,en-gb;q=0.3,en;q=0.1
      Accept-Encoding: gzip, deflate
      DNT: 1
      Connection: keep-alive
      Content-Type: application/json; charset=UTF-8
      Content-Length: 102
      Cookie: LoadBalancer=eqDtNm4UKBsc5ZarA+cVNDCCIyk-; JSESSIONID=17t492r6kjusm
      Pragma: no-cache
      Cache-Control: no-cache

      {"inputString":"ERROR","inputInt":20,"wholeYear":f alse,"byDate":false,"startDate":null,"endDate":nul l}
      The response with the content below

      HTTP/1.1 200 OK
      Set-Cookie: LoadBalancer=eqDtNm4UKBsc5ZarA+cVNDCCIyk-;Path=/
      Content-Type: application/json;charset=UTF-8
      Pragma: no-cache
      Cache-Control: no-cache
      Transfer-Encoding: chunked
      Server: Jetty(6.1.x)

      [{"state":"created","accAmount":-1641119218,"accHolder":"getAccounts on thread id: 17 - executor-1","accNumber":304228,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":-1355771089,"accHolder":"getAccounts on thread id: 17 - executor-1","accNumber":671936,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":1214773831,"accHolder":"getAccounts on thread id: 17 - executor-1","accNumber":100369,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":-1261219646,"accHolder":"getAccounts on thread id: 17 - executor-1","accNumber":296585,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":-1786189229,"accHolder":"getAccounts on thread id: 17 - executor-1","accNumber":75373,"accCurrency":"EUR","confiden tial":"CONFIDENTIAL"},{"state":"created","accAmoun t":-1643335048,"accHolder":"getAccounts on thread id: 17 - executor-1","accNumber":361580,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":349927893,"accHolder":"getAccounts on thread id: 17 - executor-1","accNumber":43807,"accCurrency":"EUR","confiden tial":"CONFIDENTIAL"},{"state":"created","accAmoun t":1377750342,"accHolder":"getAccounts on thread id: 17 - executor-1","accNumber":267444,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":-482126822,"accHolder":"getAccounts on thread id: 17 - executor-1","accNumber":112043,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":-1801492515,"accHolder":"getAccounts on thread id: 17 - executor-1","accNumber":495283,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":2028040078,"accHolder":"getAccountsBis on thread id: 21 - executor-5","accNumber":500451,"accCurrency":"EUR","confide ntial":"TRANSFORMED"},{"state":"created","accAmoun t":1306230895,"accHolder":"getAccountsBis on thread id: 21 - executor-5","accNumber":160424,"accCurrency":"EUR","confide ntial":"TRANSFORMED"},{"state":"created","accAmoun t":1203244186,"accHolder":"getAccountsBis on thread id: 21 - executor-5","accNumber":403355,"accCurrency":"EUR","confide ntial":"TRANSFORMED"},{"state":"created","accAmoun t":-1755597415,"accHolder":"getAccountsBis on thread id: 21 - executor-5","accNumber":552121,"accCurrency":"EUR","confide ntial":"TRANSFORMED"},{"state":"created","accAmoun t":1860364189,"accHolder":"getAccountsBis on thread id: 21 - executor-5","accNumber":733569,"accCurrency":"EUR","confide ntial":"TRANSFORMED"},{"state":"created","accAmoun t":1566743242,"accHolder":"getAccountsBis on thread id: 21 - executor-5","accNumber":167608,"accCurrency":"EUR","confide ntial":"TRANSFORMED"},{"state":"created","accAmoun t":-2032708713,"accHolder":"getAccountsBis on thread id: 21 - executor-5","accNumber":703847,"accCurrency":"EUR","confide ntial":"TRANSFORMED"},{"state":"created","accAmoun t":-610207596,"accHolder":"getAccountsBis on thread id: 21 - executor-5","accNumber":509744,"accCurrency":"EUR","confide ntial":"TRANSFORMED"},{"state":"created","accAmoun t":1061046775,"accHolder":"getAccountsBis on thread id: 21 - executor-5","accNumber":908835,"accCurrency":"EUR","confide ntial":"TRANSFORMED"},{"state":"created","accAmoun t":1410494634,"accHolder":"getAccountsBis on thread id: 21 - executor-5","accNumber":186013,"accCurrency":"EUR","confide ntial":"TRANSFORMED"},{"state":"created","accAmoun t":482517847,"accHolder":"getAccountsWithFailur e on thread id: 19 - executor-3","accNumber":118613,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":-1063717157,"accHolder":"getAccountsWithFailure on thread id: 19 - executor-3","accNumber":802871,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":-1793749373,"accHolder":"getAccountsWithFailure on thread id: 19 - executor-3","accNumber":510550,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":-1054398149,"accHolder":"getAccountsWithFailure on thread id: 19 - executor-3","accNumber":166706,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":-60159480,"accHolder":"getAccountsWithFailure on thread id: 19 - executor-3","accNumber":633542,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":1602619437,"accHolder":"getAccountsWithFailu re on thread id: 19 - executor-3","accNumber":269645,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":-856637213,"accHolder":"getAccountsWithFailure on thread id: 19 - executor-3","accNumber":112254,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":2096172511,"accHolder":"getAccountsWithFailu re on thread id: 19 - executor-3","accNumber":661543,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":536348989,"accHolder":"getAccountsWithFailur e on thread id: 19 - executor-3","accNumber":618092,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"},{"state":"created","accAmou nt":1752608395,"accHolder":"getAccountsWithFailu re on thread id: 19 - executor-3","accNumber":481948,"accCurrency":"EUR","confide ntial":"CONFIDENTIAL"}]

      When it fails I have this, only a request without response :

      POST /httpRemoting/getAccounts HTTP/1.1
      Host: localhost:8886
      User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
      Accept-Language: fr-fr,fr;q=0.9,de-de;q=0.7,de;q=0.6,en-us;q=0.4,en-gb;q=0.3,en;q=0.1
      Accept-Encoding: gzip, deflate
      DNT: 1
      Connection: keep-alive
      Content-Type: application/json; charset=UTF-8
      Content-Length: 102
      Cookie: LoadBalancer=eqDtNm4UKBsc5ZarA+cVNDCCIyk-; JSESSIONID=1guvmj8hi3z7a
      Pragma: no-cache
      Cache-Control: no-cache


      {"inputString":"ERROR","inputInt":20,"wholeYear":f alse,"byDate":false,"startDate":null,"endDate":nul l}
      And when I put a breakpoint at the first line off the HttpRequestHandlingMessagingGateway.writeResponse method, it is not reached when I use my use case with exception ( It works when I comment the exception ).

      Other ideas ?

      Comment


      • #18
        Oh - of course!

        Once the error occurs, the gateway is no longer waiting on the replyChannel for the original message, it's now waiting on the replyChannel from the ErrorMessage; so the 21 DTO reply is sent to a channel nobody is waiting on.

        When you copy the headers from failedMessage, you shouldn't copy the replyChannel from the failedMessage.
        Last edited by Gary Russell; May 3rd, 2013, 10:37 AM.

        Comment


        • #19
          However, this will cause a problem at the aggregator, because now he won't know which channel to use because he has a choice of 2, and will drop them both because he doesn't know how to reconcile the different headers.

          Stand by...
          Last edited by Gary Russell; May 3rd, 2013, 10:19 AM.

          Comment


          • #20
            Well I can get it to work by manipulating the headers and config, but it only works if the failure is the last one to be processed; and I have realized there is a much bigger issue with your design.

            As soon as one of your threads gets an error, the gateway receives that error and sends it to the error-channel; by definition, the gateway no longer is waiting for its reply so, if a second thread throws an exception, that error will be lost and you'll never complete the aggregation.

            I believe you will need to insert an intermediate gateway on each thread so each has its own error handler. I'll mock something up and post it shortly.

            Comment


            • #21
              OK, I posted a solution in this Gist.

              It's not identical to your scenario but, hopefully, you'll understand how to apply it.

              The bottom line is we have to insert a "try/catch" gateway on each thread in order to be able to handle success or failure on one or more of the threads. The result (or error) returned to each gateway is then forwarded on for aggregation, with the final result going to the original inbound gateway.

              Let me know if you have any questions.
              Last edited by Gary Russell; May 3rd, 2013, 12:33 PM.

              Comment


              • #22
                Updated the Gist to improve the test case.

                Comment


                • #23
                  Hello,

                  I can't run the sample :-(

                  With only this junit test that loads the Spring context :

                  Code:
                  @RunWith(SpringJUnit4ClassRunner.class)
                  @ContextConfiguration(locations = { "/sample-context.xml" })
                  public class SampleTest {
                  	
                  
                  //	@Autowired
                  //	MyGateway gateway;
                  	
                  	@Test
                  	public void test() {
                  //		List<String> result = gateway.send("foo");
                  //		assertEquals("[out:foo, out:foo]", result.toString());
                  //		result = gateway.send("fail1");
                  //		assertEquals("[err:fail1, out:fail1]", result.toString());
                  //		result = gateway.send("fail2");
                  //		assertEquals("[out:fail2, err:fail2]", result.toString());
                  //		result = gateway.send("failAll");
                  //		assertEquals("[err:failAll, err:failAll]", result.toString());
                  	}
                  	
                  }
                  And the Spring XML configuration (with the namespaces added):

                  Code:
                  <?xml version="1.0" encoding="UTF-8"?>
                  <beans xmlns="http://www.springframework.org/schema/beans"
                  	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  	xmlns:si="http://www.springframework.org/schema/integration"
                  	xmlns:int="http://www.springframework.org/schema/integration"
                  	xmlns:task="http://www.springframework.org/schema/task"
                  	xmlns:int-http="http://www.springframework.org/schema/integration/http"
                  	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                  		http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
                  		http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http-2.0.xsd
                  		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
                  
                  	<int:gateway id="gateway"
                  		service-interface="foo.Sample$MyGateway"
                  		default-reply-channel="reply"
                  		default-request-channel="input"/>
                   
                  	<int:channel id="reply" />
                  	
                  	<!-- use a pub-sub channel to insert aggregation headers -->
                   
                  	<int:publish-subscribe-channel id="input" apply-sequence="true" task-executor="exec" />
                   
                  	<task:executor id="exec" pool-size="5" />
                   
                  	<!-- First error-handling gateway -->
                  	
                  	<int:service-activator ref="service1gw" input-channel="input" output-channel="agg" />
                   
                  	<int:gateway id="service1gw" default-request-channel="input1" error-channel="ec" />
                   
                  	<!-- Second error-handling gateway -->
                   
                  	<int:service-activator ref="service2gw" input-channel="input" output-channel="agg" />
                   
                  	<int:gateway id="service2gw" default-request-channel="input2" error-channel="ec" />
                   
                  	<!-- Error flow ("catch" block) -->
                  	<int:channel id="ec" />
                  	
                  	<int:transformer input-channel="ec" ref="foo" method="errorHandler" />
                  	
                  	<!-- Resequence so we have deterministic results for tests -->
                  		
                  	<int:resequencer input-channel="agg" output-channel="agg2"/>
                   
                  	<!-- Aggregates returned results from the error handling gateways -->
                   
                  	<int:aggregator input-channel="agg2" ref="foo" method="aggregate" output-channel="reply" />
                   
                  	<int:channel id="input1" />
                   
                  	<int:channel id="input2" />
                   
                  	<int:service-activator id="service1" input-channel="input1"
                  		 ref="foo" method="service" />
                  	
                  	<int:service-activator id="service2" input-channel="input2"
                  		 ref="foo" method="service" />
                   
                  	<!-- bean with methods for services and transformer -->
                   
                  	<bean id="foo" class="foo.Sample"/>
                  </beans>

                  I obtain this error :

                  Code:
                  GRAVE: Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@1a998c7] to prepare test instance [foo.SampleTest@16d4b50]
                  java.lang.IllegalStateException: Failed to load ApplicationContext
                  	at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:308)
                  	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
                  	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
                  	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
                  	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:220)
                  	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:301)
                  	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
                  	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:303)
                  	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
                  	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
                  	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
                  	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
                  	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
                  	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
                  	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
                  	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
                  	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
                  	at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
                  	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
                  	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
                  	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
                  	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
                  	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
                  	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
                  	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
                  Caused by: java.util.ConcurrentModificationException
                  	at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
                  	at java.util.AbstractList$Itr.next(AbstractList.java:343)
                  	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:559)
                  	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
                  	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
                  	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:84)
                  	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
                  	at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:280)
                  	at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:304)
                  	... 24 more
                  My jdk is 1.6.0.23 and Spring 3.0.5.

                  Do you have an idea ? Could you provide the full project ?

                  Thx by advance.

                  Comment


                  • #24
                    I ran it with Spring Integration 3.0.0.M1 and Spring 3.1.3

                    Just tested again with SI 2.2.3.RELEASE.

                    Looks like you are using some ancient 2.0.x release...
                    spring-integration-http-2.0.xsd
                    ... so I tested with 2.0.4 and Spring 3.0.5 and all still worked fine.

                    I don't have a simple project, I simply added these files to an existing Spring Integration Sample project.

                    I just updated the GIST xml file to include the full file.

                    Code:
                    <?xml version="1.0" encoding="UTF-8"?>
                    <beans xmlns="http://www.springframework.org/schema/beans"
                    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    	xmlns:int="http://www.springframework.org/schema/integration"
                    	xmlns:context="http://www.springframework.org/schema/context"
                    	xmlns:task="http://www.springframework.org/schema/task"
                    	xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
                    		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
                    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
                    ...
                    If you still can't figure it out, I can make a stand-alone project.

                    Comment

                    Working...
                    X