Skip to content

Commit 7e9ea88

Browse files
committed
Add mapping adapter to ItemWriter
Signed-off-by: Stefano Cordio <[email protected]>
1 parent 639d64f commit 7e9ea88

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemWriter.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
1716
package org.springframework.batch.item;
1817

18+
import java.util.function.Function;
19+
1920
import org.springframework.lang.NonNull;
2021

2122
/**
@@ -37,6 +38,7 @@
3738
* @author Lucas Ward
3839
* @author Taeik Lim
3940
* @author Mahmoud Ben Hassine
41+
* @author Stefano Cordio
4042
*/
4143
@FunctionalInterface
4244
public interface ItemWriter<T> {
@@ -50,4 +52,27 @@ public interface ItemWriter<T> {
5052
*/
5153
void write(@NonNull Chunk<? extends T> chunk) throws Exception;
5254

55+
/**
56+
* Adapts an {@code ItemWriter} accepting items of type {@link U} to one accepting
57+
* items of type {@link T} by applying a mapping function to each item before writing.
58+
* <p>
59+
* The {@code mapping()} item writers are most useful when used in combination with a
60+
* {@link org.springframework.batch.item.support.CompositeItemWriter}, where the
61+
* mapping function in front of the downstream writer can be a getter of the input
62+
* item or a more complex transformation logic.
63+
* <p>
64+
* This adapter mimics the behavior of
65+
* {@link java.util.stream.Collectors#mapping(Function, java.util.stream.Collector)}.
66+
* @param <T> the type of the input items
67+
* @param <U> type of items accepted by downstream item writer
68+
* @param mapper a function to be applied to the input items
69+
* @param downstream an item writer which will accept mapped items
70+
* @return an item writer which applies the mapping function to the input items and
71+
* provides the mapped results to the downstream item writer
72+
* @since 6.0
73+
*/
74+
static <T, U> ItemWriter<T> mapping(Function<? super T, ? extends U> mapper, ItemWriter<? super U> downstream) {
75+
return chunk -> downstream.write(new Chunk<>(chunk.getItems().stream().map(mapper).toList()));
76+
}
77+
5378
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.springframework.batch.item;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.springframework.batch.item.support.CompositeItemWriter;
5+
import org.springframework.batch.item.support.ListItemWriter;
6+
7+
import java.util.List;
8+
9+
import static org.assertj.core.api.Assertions.assertThat;
10+
import static org.springframework.batch.item.ItemWriter.mapping;
11+
12+
class ItemWriterIntegrationTests {
13+
14+
@Test
15+
void testMappingWithCompositeItemWriter() throws Exception {
16+
ListItemWriter<String> nameItemWriter = new ListItemWriter<>();
17+
ListItemWriter<Integer> ageItemWriter = new ListItemWriter<>();
18+
19+
ItemWriter<Person> writer = new CompositeItemWriter<>(List.of( //
20+
mapping(Person::name, nameItemWriter), //
21+
mapping(Person::age, ageItemWriter)));
22+
23+
writer.write(Chunk.of(new Person("Foo", 42), new Person("Bar", 24)));
24+
writer.write(Chunk.of(new Person("Baz", 21), new Person("Qux", 12)));
25+
26+
assertThat(nameItemWriter.getWrittenItems()).containsExactly("Foo", "Bar", "Baz", "Qux");
27+
assertThat(ageItemWriter.getWrittenItems()).containsExactly(42, 24, 21, 12);
28+
}
29+
30+
private record Person(String name, int age) {
31+
}
32+
33+
}

0 commit comments

Comments
 (0)