Results 1 to 7 of 7

Thread: how to leverage spring batch's exception handling in RecordMapper implementation

  1. #1
    Join Date
    Dec 2012
    Posts
    17

    Default how to leverage spring batch's exception handling in RecordMapper implementation

    Hello,

    I configured my spring batch ldap chunk processing to skip records when a certain type of exception occurs:
    <batch:chunk reader="multiResourceReader" processor="userProcessor" writer="userWriter" commit-interval="100" skip-limit="1000">
    <batch:skippable-exception-classes>
    <batch:include class="com.test.SyncException"/>
    </batch:skippable-exception-classes>
    </batch:chunk>

    However, other than MappingLdifReader for its read method, the RecordMapper interface does not define Exception throwing for its method mapRecord:

    * Maps an {@link LdapAttributes LdapAttributes} object to the specified type.
    *
    * @param attributes
    * @return object of type T
    */
    T mapRecord(LdapAttributes attributes);

    What is the correct approach to leverage spring batch's exception handling inside the implementation of this method?

    Thanks,
    Elmar

  2. #2
    Join Date
    Sep 2008
    Location
    Chicagoland, IL
    Posts
    349

    Default

    What type of exception handling are you looking for? In order for an exception to be skipped, it doesn't need to be identified in a throws clause...
    Michael Minella
    Spring Batch Lead
    Author - Pro Spring Batch
    http://www.michaelminella.com
    Twitter: @MichaelMinella

  3. #3
    Join Date
    Dec 2012
    Posts
    17

    Default

    Hi,

    I would like to throw com.test.SyncException in mapRecord like I can do in a reader's read method. Later on, I want to log this exception by a skip listener. In a reader's read method this is possible because a throws clause is defined for this method. In maRecord however I have to surround my exception by a try-/catch block because no throws clause is defined and I would expect that the skip listener is not called in that case.

  4. #4
    Join Date
    Sep 2008
    Location
    Chicagoland, IL
    Posts
    349

    Default

    Can you post your entire configuration? Also, is the MappingLdifReader a class you wrote (we don't have anything like that within the framework itself)? If so, can you also include the code for that?

    In general though, if an exception is thrown during a read that is to be skipped, the SkipListener#onSkipInRead method will be called. If an exception is thrown that should be skipped in the processor, the SkipListener#onSkipInProcess method will be called. If an exception is thrown that should be skipped in the write, the SkipListener#onSkipInWrite method will be called. The calling of these methods should be independent of how each of those components are developed.
    Michael Minella
    Spring Batch Lead
    Author - Pro Spring Batch
    http://www.michaelminella.com
    Twitter: @MichaelMinella

  5. #5
    Join Date
    Dec 2012
    Posts
    17

    Default

    Hi,

    I am talking about org.springframework.ldap.ldif.batch.MappingLdifRea der<T>. This class reads entries from an ldif file and has a member interface bean org.springframework.ldap.ldif.batch.RecordMapper<T > which allows you to convert the ldif entry into a Java class by implementing its method T mapRecord(LdapAttributes attributes). However, other than read, write and process methods, this method has no throws clause so that I cannot throw my custom SyncException inside this method.
    Here is my implementation of the RecordMapper interface:
    public class UserRecordMapper implements RecordMapper<User> {
    private static final Object DELETE = "delete";
    private static Logger log = Logger.getLogger(UserRecordMapper.class);

    @Override
    public User mapRecord(LdapAttributes attributes) {
    // I would like to throw a skipped SyncException here instead of the try-/catch block
    try {
    if (attributes == null) {
    return null;
    }

    final User user;

    try {
    user.setAttribute(User.CELL_PHONE, attributes.get("cell_phone").get().toString());
    } catch (NamingException e1) {
    log.error(e1.getMessage());
    } catch (NullPointerException npe) {
    user.setAttribute(User.CELL_PHONE, null);
    }

    return user;
    } catch (SyncException se) {
    log.error(se.getMessage());
    return null;
    }

    }

  6. #6
    Join Date
    Sep 2008
    Location
    Chicagoland, IL
    Posts
    349

    Default

    Ahhh...ok, question: Why is SyncException a checked exception? Make it a RuntimeException and the throws clause is no longer needed (and thus, the exception can be thrown).
    Michael Minella
    Spring Batch Lead
    Author - Pro Spring Batch
    http://www.michaelminella.com
    Twitter: @MichaelMinella

  7. #7
    Join Date
    Dec 2012
    Posts
    17

    Default

    Of course you're right, thanks, I thought this skipping mechanism works only with non runtime exeptions.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •