Batch and business layer communication
design-patterns, domain-driven-design, spring-batch
Solution
Is there a best practice (maybe a specific design pattern) to use for the interface between the top modules and the business logic layer?
afaik there is no real best practice, which differ to already known best practices,but batches often need to address performance requirements/constraints and even more often produce performance problems, so my best practice is:
- think about the data and the dataflow
- how much data ?
- what is the bottleneck? (processing vs writing, often the writing part)
to give you some inspiration for the interface of writer and business layer
- use the ItemWriterAdapter, which could use a businessLayer.addOrderItem method
- write your own wrapper
- move the business layer into the writer, there is seldom a real need for re-use of batch optimized business layer
i would go with option 2, because in a batch context i would like to use lists and batch SQL
as usual it depends on your specific requirements :-)
ItemWriter wrapper example
public class SimpleItemWriter implements ItemWriter<SimpleItem> {
@Override
public void write(List<? extends SimpleItem> items) throws Exception {
// do something, e.g. delegate to another spring bean
}
}
ItemWriterAdapter configuration example
<bean id="sample-item-writer-adapter" class="org.springframework.batch.item.adapter.ItemWriterAdapter">
<property name="targetObject" ref="businessLayerBean" />
<property name="targetMethod" value="doSomething"
</bean>
<step id="splitFilesStep">
<tasklet>
<chunk
reader="itemReader"
writer="sample-item-writer-adapter"
commit-interval="5">
</chunk>
</tasklet>
</step>
Problem
I'm designing a batch application using Spring batch where I have the following architecture (layers): - A top module where I put all the spring batch code (reading the file, processing and writing). This top module is specific to a certain format of the file. So, I may have in the future an new parallel module that would be able to read/process/write a new format. Independently of the format, each line of a file corresponds to a certain operation to execute. For example, each line may represent the operation "Add line item X to order Y". So, for each line, after finishing to read and process it, I use a custom ItemWriter that calls the required operation of the layer immediately below. - A business logic layer that would implement the different batch operations. Each one of these operations is implemented using the domain layer objects. For example, the "Add line ite; X to order Y" operation would be implemented by retrieving the order using the OrderRepository and then by calling the addLineItem method of the order. - A domain layer where I have all my domain objects. Following the previous example, I have the Order and LineItem entities. My questions are: - Is there a best practice (maybe a specific design pattern) to use for the interface between the top modules and the business logic layer? - Let's assume that each file contains lines for only one order. The naive approach for writing each line would be to call one batch operation per line. In this case, for each line, a call to the OrderRepository is done to retrieve the order and then the order is saved. I'm thinking about another approach where lines are written by chunk (as we do with Spring batch). The argument that the write operation takes has the type List. Following this second approach, I would need to pass to the business operation the data it needs to add the chunk to the concerned order. Which form to use to pass the information between the top module and the business logic layer? Thanks