-
1. Re: BeanIO Writer arraylist of objects
cfang Aug 19, 2017 9:11 PM (in response to richardmoore)If we forget about BeanIOItemWriter for a moment, the unusual part of your case is that the item processor may produce multiple items from one single reader item. Any item processor can already filter out reader items (in your case, the reader item key2 will be filtered out and will not have any items out of the item processor). The mismatch is that the item processor API returns one single item, which will be accummulated by JBeret batch runtime. If your item processor returns a List<Record>, JBeret will think the type of items is List<Record>, while you intend it to be Record.
The other option is to keep your intelligence inside item reader, such that the item reader still returns a single item, pass it to the optional item processor (your may not need the item processor any more). The item reader may need to cache the multiple spawned items and return them one at a time. This will fit into the typical chunk processing pattern.
-
2. Re: BeanIO Writer arraylist of objects
richardmoore Aug 21, 2017 7:59 AM (in response to cfang)The problem is that I can't select just what I need off the tables, a part of the business logic is to do some field compares in order to determine which records need to be written for this customer. My plan was to select off all the keys needed, then let the item processor get all the rows involved for the given key, compare and apply the business logic to determine which if any of the records need written then pass a List of records.
I achieved this by creating a new writer from the BeanIOItemWriter and modifying the following method -
@Override
public void writeItems(final List<Object> items) throws Exception {
for (final Object e : items) {
System.out.println(e.getClass().getName() + " -> " + e);
if (e instanceof Collection) {
for (Object o : ((Collection<?>) e)) {
beanWriter.write(o);
}
} else {
beanWriter.write(e);
}
}
}
-
3. Re: BeanIO Writer arraylist of objects
cfang Aug 21, 2017 8:45 AM (in response to richardmoore)Good to know you found the solution for your case. Just adding a note here that in other cases, exploding a collection into individual items may not be the right choice, because a collection may indeed form a single item. For instance, a list of strings forms multiple fields in a CSV row: {"John", "Smith", "M", "30"}.
-
4. Re: BeanIO Writer arraylist of objects
cfang Aug 25, 2017 4:03 AM (in response to cfang)You can also attach a ItemWriteListener to the chunk processing, and inside its beforeWrite(List<Object>) method expand and replace those special container collections.
ItemWriteListener (Java(TM) EE 7 Specification APIs)
This can shield this type of special handling from the item writer class.
-
5. Re: BeanIO Writer arraylist of objects
richardmoore Aug 25, 2017 12:03 PM (in response to richardmoore)I like the ItemWriteListener idea. I set one up and have a question.
- Reads input, which contains 2 records.
- The item processor takes each input records and performs additional business logic to create a List of records to be written. The first input record becomes a List of 4 records, the second becomes a List of 2 records.
- The write listener (below) converts the container/list and the writer writes a total of 6 records, as expected.
- The step listener display the metrics but it only shows a WRITE_COUNT of 2, I was expecting 6.
Is there something I can do to ensure the write count matches the file's record count?
Step listener's afterStep() contains the following -
for (Metric metric : stepContext.getMetrics()) {
log.info("Metric " + metric.getType() + "=" + metric.getValue());
}
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.batch.api.chunk.listener.ItemWriteListener;
public class CollectionTestWriteListener implements ItemWriteListener {
@Override
public void afterWrite(List<Object> arg0) throws Exception {
}
@Override
public void beforeWrite(List<Object> arg0) throws Exception {
List<Object> list = new ArrayList<Object>();
for (Object o : arg0) {
if (o instanceof Collection) {
list.addAll((Collection<?>) o);
} else {
list.add(o);
}
}
arg0.clear();
arg0.addAll(list);
}
@Override
public void onWriteError(List<Object> arg0, Exception arg1) throws Exception {
}
}
-
6. Re: BeanIO Writer arraylist of objects
cfang Aug 25, 2017 8:26 PM (in response to richardmoore)step metrics should correctly reflect the number of items to be written.
do you cache step metrics or the like inside your step listener class?
-
7. Re: BeanIO Writer arraylist of objects
cfang Aug 27, 2017 10:33 PM (in response to cfang)Step metrics WRITE_COUNT does not correctly reflect the number of items to be written
-
8. Re: BeanIO Writer arraylist of objects
richardmoore Aug 28, 2017 10:26 AM (in response to richardmoore)I do cache any metrics but rely on the following -
Step listener's afterStep() contains the following -
for (Metric metric : stepContext.getMetrics()) {
log.info("Metric " + metric.getType() + "=" + metric.getValue());
}
-
9. Re: BeanIO Writer arraylist of objects
cfang Aug 28, 2017 7:04 PM (in response to richardmoore)Your code looks right. The above JIRA issue (JBERET-351) will be fixed soon to address this problem.