Class BeanWrapperRowMapper<T>

java.lang.Object
org.springframework.batch.support.DefaultPropertyEditorRegistrar
org.springframework.batch.extensions.excel.mapping.BeanWrapperRowMapper<T>
Type Parameters:
T - type
All Implemented Interfaces:
RowMapper<T>, org.springframework.beans.factory.Aware, org.springframework.beans.factory.BeanFactoryAware, org.springframework.beans.factory.InitializingBean, org.springframework.beans.PropertyEditorRegistrar

public class BeanWrapperRowMapper<T> extends org.springframework.batch.support.DefaultPropertyEditorRegistrar implements RowMapper<T>, org.springframework.beans.factory.BeanFactoryAware, org.springframework.beans.factory.InitializingBean
RowMapper implementation based on bean property paths. The RowSet to be mapped should have field name meta data corresponding to bean property paths in an instance of the desired type. The instance is created and initialized either by referring to to a prototype object by bean name in the enclosing BeanFactory, or by providing a class to instantiate reflectively.

Nested property paths, including indexed properties in maps and collections, can be referenced by the RowSetnames. They will be converted to nested bean properties inside the prototype. The RowSet and the prototype are thus tightly coupled by the fields that are available and those that can be initialized. If some of the nested properties are optional (e.g. collection members) they need to be removed by a post processor.

To customize the way that RowSet values are converted to the desired type for injecting into the prototype there are several choices. You can inject PropertyEditor instances directly through the customEditors property, or you can override the createBinder(Object) and initBinder(DataBinder) methods, or you can provide a custom RowSet implementation.

Property name matching is "fuzzy" in the sense that it tolerates close matches, as long as the match is unique. For instance:
  • Quantity = quantity (field names can be capitalised)
  • ISIN = isin (acronyms can be lower case bean property names, as per Java Beans recommendations)
  • DuckPate = duckPate (capitalisation including camel casing)
  • ITEM_ID = itemId (capitalisation and replacing word boundary with underscore)
  • ORDER.CUSTOMER_ID = order.customerId (nested paths are recursively checked)
The algorithm used to match a property name is to start with an exact match and then search successively through more distant matches until precisely one match is found. If more than one match is found there will be an error.
Since:
0.1.0
Author:
Marten Deinum
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    Check that precisely one of type or prototype bean name is specified.
    protected org.springframework.validation.DataBinder
    Create a binder for the target object.
    protected void
    initBinder(org.springframework.validation.DataBinder binder)
    Initialize a new binder instance.
    Map the FieldSet to an object retrieved from the enclosing Spring context, or to a new instance of the required type if no prototype is available.
    void
    setBeanFactory(org.springframework.beans.factory.BeanFactory beanFactory)
     
    void
    setDistanceLimit(int distanceLimit)
    The maximum difference that can be tolerated in spelling between input key names and bean property names.
    void
    The bean name (id) for an object that can be populated from the field set that will be passed into mapRow(RowSet).
    void
    setStrict(boolean strict)
    Public setter for the 'strict' property.
    void
    setTargetType(Class<? extends T> type)
    Public setter for the type of bean to create instead of using a prototype bean.

    Methods inherited from class org.springframework.batch.support.DefaultPropertyEditorRegistrar

    registerCustomEditors, setCustomEditors

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • BeanWrapperRowMapper

      public BeanWrapperRowMapper()
  • Method Details

    • setBeanFactory

      public void setBeanFactory(org.springframework.beans.factory.BeanFactory beanFactory)
      Specified by:
      setBeanFactory in interface org.springframework.beans.factory.BeanFactoryAware
    • setDistanceLimit

      public void setDistanceLimit(int distanceLimit)
      The maximum difference that can be tolerated in spelling between input key names and bean property names. Defaults to 5, but could be set lower if the field names match the bean names.
      Parameters:
      distanceLimit - the distance limit to set
    • setPrototypeBeanName

      public void setPrototypeBeanName(String name)
      The bean name (id) for an object that can be populated from the field set that will be passed into mapRow(RowSet). Typically a prototype scoped bean so that a new instance is returned for each field set mapped. Either this property or the type property must be specified, but not both.
      Parameters:
      name - the name of a prototype bean in the enclosing BeanFactory
    • setTargetType

      public void setTargetType(Class<? extends T> type)
      Public setter for the type of bean to create instead of using a prototype bean. An object of this type will be created from its default constructor for every call to mapRow(RowSet).
      Either this property or the prototype bean name must be specified, but not both.
      Parameters:
      type - the type to set
    • afterPropertiesSet

      public void afterPropertiesSet() throws Exception
      Check that precisely one of type or prototype bean name is specified.
      Specified by:
      afterPropertiesSet in interface org.springframework.beans.factory.InitializingBean
      Throws:
      IllegalStateException - if neither is set or both properties are set.
      Exception
      See Also:
      • InitializingBean.afterPropertiesSet()
    • mapRow

      public T mapRow(RowSet rs) throws org.springframework.validation.BindException
      Map the FieldSet to an object retrieved from the enclosing Spring context, or to a new instance of the required type if no prototype is available.
      Specified by:
      mapRow in interface RowMapper<T>
      Parameters:
      rs - the RowSet used for mapping.
      Returns:
      mapped object of type T
      Throws:
      org.springframework.validation.BindException - if there is a type conversion or other error (if the DataBinder from createBinder(Object) has errors after binding).
      org.springframework.beans.NotWritablePropertyException - if the FieldSet contains a field that cannot be mapped to a bean property.
      See Also:
      • FieldSetMapper.mapFieldSet(org.springframework.batch.item.file.transform.FieldSet)
    • createBinder

      protected org.springframework.validation.DataBinder createBinder(Object target)
      Create a binder for the target object. The binder will then be used to bind the properties form a field set into the target object. This implementation creates a new DataBinder and calls out to initBinder(DataBinder) and DefaultPropertyEditorRegistrar.registerCustomEditors(org.springframework.beans.PropertyEditorRegistry).
      Parameters:
      target - the object to bind to.
      Returns:
      a DataBinder that can be used to bind properties to the target.
    • initBinder

      protected void initBinder(org.springframework.validation.DataBinder binder)
      Initialize a new binder instance. This hook allows customization of binder settings such as the direct field access. Called by createBinder(Object).

      Note that registration of custom property editors can be done in DefaultPropertyEditorRegistrar.registerCustomEditors(org.springframework.beans.PropertyEditorRegistry).

      Parameters:
      binder - new binder instance
      See Also:
    • setStrict

      public void setStrict(boolean strict)
      Public setter for the 'strict' property. If true, then mapRow(RowSet) will fail if the RowSet contains fields that cannot be mapped to the bean.
      Parameters:
      strict - fail if non-mappable properties are found