2

I am trying to process the output of a SQL query in parallel. below given is my code. I have sysout in Aggregator. But I randomly see the sysout in Aggregator is not getting printed. Also, the release method in aggregator is also not printing sysouts. I guess, I am losing the messages some where. Can any one shed some light?

    <int:bridge input-channel="inputChannel" output-channel="dbRequestChannel" />

        <jdbc:outbound-gateway request-channel="dbRequestChannel"
            max-rows-per-poll="0" data-source="dataSource" reply-channel="headerEnricher"
            query="select empname, empno, empdob from employee where empno = 1234" />

        <int:header-enricher input-channel="headerEnricher"
            output-channel="splitterChannel">
            <int:header name="payloadSize" value="3"></int:header>
        </int:header-enricher>

        <int:chain input-channel="splitterChannel" output-channel="splitterOutputChannel">
            <int:splitter />
        </int:chain>


        <int:channel id="splitterOutputChannel">
            <int:dispatcher task-executor="sampleTaskExecutor" />
        </int:channel>

        <bean id="sampleTaskExecutor"
            class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
            <property name="corePoolSize" value="5" />
            <property name="maxPoolSize" value="10" />
            <property name="queueCapacity" value="25" />
        </bean>

        <int:service-activator input-channel="splitterOutputChannel"
            ref="springIntegrationtest" method="testMethod" output-channel="aggregatePayload">
        </int:service-activator>

        <int:aggregator input-channel="aggregatePayload"
            release-strategy-method="release" output-channel="nullChannel"
            send-partial-result-on-expiry="true" ref="springIntegrationtest"
            method="aggregateData" />

    @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring-integration.xml" })
public class SpringIntegrationTest {


    @Autowired
    private MessageChannel inputChannel;

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");



    @Test
    public void testQueue() {
        Message<String> quoteMessage = MessageBuilder
                .withPayload("testPayload").build();
        inputChannel.send(quoteMessage);
    }


    public Map<String, String> testMethod(Message<?> m) {

        System.out.println(sdf.format(new Date()));
        return (Map<String, String>) m.getPayload();
    }

    public boolean release(ArrayList<Map<String, Object>> payload) {
        boolean release = false;
        int size = payload.size();
        if (size == 3) {
            release = true;
        }
        System.out.println(release);
        return release;
    }

    public Message<String> aggregateData(ArrayList<Map<String, Object>> payload) {

        System.out.println("In aggregateData " + payload);
        Message<String> quoteMessage = MessageBuilder
                .withPayload("testPayload").build();
        return quoteMessage;
    }

}

1 Answers1

1

Well, I think your problem is with the combination of states and options.

You have this:

int size = payload.size();
if (size == 3) {
    release = true;
}

so, your aggregator is going to release the group just after a 3 items arrived, meanwhile you may have much more items after splitting.

The release signals aggregator to finish the group and exit. By default it has an option like expireGroupsUponCompletion = false, which means retain group in the store but with the completed state.

If your goal just to emit from aggregator tuples by 3, you should consider to switch the expireGroupsUponCompletion to true. See aggregator manual for more information.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118