Announcement Announcement Module
Collapse
No announcement yet.
All at sea with Spring Batch Integration Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • All at sea with Spring Batch Integration

    Greetings fellow batchonauts

    I am writing software to propagate changes to user accounts across several different external systems. I have used Spring Integration to acquire user data from a source system, resolve user account metadata and create a Message containing all the data required to batch update a specific external system. At that point it's over to Spring Batch.

    The messages that emerge from Integration come from a custom message splitter. The message header is the name of the target external system and the payload is a Collection of beans. The splitter returns this:
    Code:
    Collection<Message<List<UserUpdateBean>>>
    Using this code:
    Code:
    Collection<Message<List<UserUpdateBean>>> messages = new ArrayList<Message<List<UserUpdateBean>>>();
    
    MessageBuilder<List<UserUpdateBean>> messageBuilder = MessageBuilder.withPayload(messagePayload);
    messageBuilder.setHeader(MessageHeaderNames.RECIPIENT.name(), recipientHeaderValue);
    
    Message<List<UserUpdateBean>> message = messageBuilder.build();
    messages.add(message);
    Where the user bean looks like this:
    Code:
    public class UserUpdateBean {
       private String userID;
       private boolean isNewUser;
       private String userName;
       private String screenName;
       private String firstName;
       private String middleName;
       private String lastName;
       private Date birthday;
       private Long employeeNumber;
       private String emailAddress;
       private String jobTitle;
       private String jobClass;
       private String greeting;
    
       ...
    }
    A custom message router sends a Message<List<UserUpdateBean>> to a specific channel based on the header value. The header value contains the name of the target system.. The channel is used only for updates for a specific external system.
    Code:
    <si:header-value-router input-channel="outboundUserUpdateRoutingChannel" header-name="${message.header.name.recipient}">
    	<si:mapping value="${message.header.value.loginmanagement}" channel="outboundLoginManagementUserUpdateChannel" />
    	<si:mapping value="${message.header.value.arvalonline}" channel="outboundArvalOnlineUserUpdateChannel" />
    	<si:mapping value="${message.header.value.card}" channel="outboundCardUserUpdateChannel" />
    	<si:mapping value="${message.header.value.drive}" channel="outboundDriveUserUpdateChannel" />
    </si:header-value-router>
    This is what I am aiming for:
    1. Batch receives a Message<List<UserUpdateBean>>
    2. An ItemReader implementation gets the message payload (List<UserUpdateBean>) and chunk-reads the UserUpdateBeans from the List
    3. An ItemProcessor implementation does some further processing (optional step)
    4. An ItemWriter implementation puts values from each UserUpdateBean in the chunk into a SQL batch update statement and executes it

    This is my (incomplete) Batch configuration:
    Code:
    @Bean
    public JobLaunchingMessageHandler jobLaunchingMessageHandler() {
    	JobLaunchingMessageHandler jobLaunchingMessageHandler = new JobLaunchingMessageHandler(this.jobLauncher);
    	return jobLaunchingMessageHandler;
    }
    Code:
    <bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
    <bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    	<property name="jobRepository" ref="jobRepository" />
    </bean>
    <bean id="jobRegistryBeanPostProcessor" class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
    	<property name="jobRegistry" ref="jobRegistry" />
    </bean>
    <bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
    	<property name="dataSource" ref="ulmDataSource" />
    	<property name="transactionManager" ref="ulmDataSourceTransactionManager" />
    </bean>
    
    <si:service-activator input-channel="outboundLoginManagementUserBatchUpdateChannel" output-channel="loginManagementUserUpdateStatusChannel" ref="jobLaunchingMessageHandler" />
    The problem is that I just cannot see how to link Integration and Batch together using Batch Integration.

    The message arrives in JobLaunchingMessageHandler service activator. Then what? I don't know where the message ends up or how to the message's payload into the ItemReader. The message seems to disappear into a black hole.

    I have scoured Google and read the Batch manual plus other documentation a hundred times but I can't make sense of it. I am completely stuck.
Working...
X