Announcement Announcement Module
Collapse
No announcement yet.
Splitter Question: what is happening to the header values I have modified? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Splitter Question: what is happening to the header values I have modified?

    I have a spring integration splitter with the following method signature:

    Code:
    @Splitter
    public List<Message<String[]>> splitCsvIntoSeperateMessages(Message<List<String[]>> message)
    The message payload is an ArrayList of String[]. The splitter reads each row in the List, Creates a new Message setting the payload to the data item in the List, adds a CorrelationId, SequenceNumber and SequenceSize to the header and finally returns an ArrayList of Messages.

    The problem is that when each individual message is sent to the next channel, the CorrelationId, SequenceNumber and SequenceSize are all overwritten with new values. Is that expected behavior or am I missing something?

    Code:
    @Splitter
    public List<Message<String[]>> splitCsvIntoSeperateMessages(Message<List<String[]>> message) {
    
     List<Message<String[]>> returnVal = new ArrayList<Message<String[]>>();
     String headerId = null;
     int sequenceSize = 0;
     int sequenceNumber = 0;
     for(String[] payload : message.getPayload()){
    
      if(payload[0].equals("HEAD")){
       headerId = UUID.randomUUID().toString();
       sequenceSize = Integer.parseInt(payload[payload.length-1]);
       sequenceNumber=0;
      }
      sequenceNumber++;
      Message<String[]> msg = 
       MessageBuilder
            .withPayload(payload)
         .setCorrelationId(headerId)
         .setSequenceSize(sequenceSize)
         .setSequenceNumber(sequenceNumber)
         .build();
    
      returnVal.add(msg);
     }
     return returnVal;
    }

  • #2
    Actually, the internal Splitter implementation does write those headers itself before sending the reply (and since List is an ordered collection, it can determine sequenceNumber/sequenceSize from that).

    Are you using values that would be different from those defaults? If so, can you explain the use-case?

    Thanks,
    Mark

    Comment


    • #3
      That makes sense....the default implementation of a splitter...

      Can you tell me what happens if I use <serivce-activator> vs <spitter>.

      Is it important to annotate the methods with @Splitter or @ServiceActivation?

      John

      Comment


      • #4
        The main difference between Splitter and Service-Activator is that the Splitter will send multiple Messages (one for each "payload" in the list) while a Service-Activator would send the whole list as a single payload.

        Comment


        • #5
          so can you take a look at my configuration file and tell me if I am "over using" service-activator? (this may not be a fair question without explaining my use case)



          Code:
          	<file:inbound-channel-adapter
          		auto-startup="true" auto-create-directory="true" directory="file:c:/temp/vaonce/load/" filename-pattern=".*\.txt"
          		channel="fileInputChannel">
          		<poller default="true">
          			<interval-trigger interval="10000" time-unit="MILLISECONDS" />
          		</poller>
          	</file:inbound-channel-adapter>
          
          	<chain input-channel="fileInputChannel">
          		<transformer ref="transformer" method="enrichHeaderWithFileInfo" />
          		<header-enricher>
          			<error-channel ref="errorChannel"/>
          			<header name="$discardChannel" ref="discardChannel"/>
          		</header-enricher>
          		<router channel-resolver="fileNameResolver">
          			<beans:bean class="org.springframework.integration.router.HeaderValueRouter">
          				<beans:constructor-arg value="$file_name" />
          			</beans:bean>
          		</router>
          	</chain>
          
          	<chain input-channel="enrollmentFile">
          		<service-activator ref="handler" method="loadVaOnceFile"/>
          		<service-activator ref="handler" method="verifyDetailRecordCounts"/>
          		<header-enricher>
          			<reply-channel ref="enrollmentFileSplit"/>
          		</header-enricher>
          		<service-activator ref="splitter" method="splitCsvIntoSeperateMessages"/>
          	</chain>
          
          	<chain input-channel="enrollmentFileSplit">
          		<aggregator/>
          		<transformer ref="transformer" method="transformEnrollmentToJpa" />
          		<splitter ref="splitter" method="splitEnrollmentJpaRecords"  />
          		<service-activator ref="handler" method="saveEnrollment" />
          	</chain>
          
          	<chain input-channel="amendmentFile">
          		<service-activator ref="handler" method="loadVaOnceFile"/>
          		<service-activator ref="handler" method="verifyDetailRecordCounts"/>
          		<header-enricher>
          			<reply-channel ref="enrollmentFileSplit"/>
          		</header-enricher>
          		<service-activator ref="splitter" method="splitCsvIntoSeperateMessages"/>
          	</chain>
          
          	<chain input-channel="amendmentFileSplit">
          		<aggregator/>
          		<transformer ref="transformer" method="transformEnrollmentToJpa" />
          		<splitter ref="splitter" method="splitEnrollmentJpaRecords"  />
          		<service-activator ref="handler" method="saveAmendment" />
          	</chain>

          Comment


          • #6
            Well, the Service Activator's replies are not going to be individual messages right?... would be the full list as a single payload.

            Comment


            • #7
              Actually, I am using the service activator to split and send back the individual messages with the headers I want.

              Let me show you the modified splitCsvIntoSeperateMessages method:


              Code:
              	@ServiceActivator
              	public void splitCsvIntoSeperateMessages(Message<List<String[]>> message) throws IOException {
              
                  	MessageChannel replyChannel =(MessageChannel)message.getHeaders().getReplyChannel();
                  	String headerId = null;
                  	int sequenceSize = 0;
                  	int sequenceNumber = 0;
                  	for(String[] payload : message.getPayload()){
              
                  		if(payload[0].equals("HEAD")){
                  			headerId = UUID.randomUUID().toString();
                  			sequenceSize = Integer.parseInt(payload[payload.length-1])+1;
                  			sequenceNumber=0;
                  		}
                  		sequenceNumber++;
                  		Message<String[]> msg =
                  			MessageBuilder
              		    		.withPayload(payload)
              		    		.copyHeaders(message.getHeaders())
              		    		.setSequenceNumber(sequenceNumber)
              					.setSequenceSize(sequenceSize)
              					.setCorrelationId(headerId)
              		    		.build();
                  		replyChannel.send(msg);
                  	}
              	}

              Comment

              Working...
              X