mybatis/mybatis-3 · error · UnsupportedOperationException

'" + this.getClass() + "' must override the default method '

Error message

'" + this.getClass() + "' must override the default method 'getGenericSetterType()'.

What it means

ObjectWrapper.getGenericSetterType(String) is a Java 8 default method that only exists to be overridden; the default body throws UnsupportedOperationException telling which class failed to override it. It resolves the full generic Type of a writable property (needed for precise TypeHandler selection with generics, e.g. List<String>). BeanWrapper and MapWrapper override it; wrappers like CollectionWrapper do not, so calling it on those throws.

Source

Thrown at src/main/java/org/apache/ibatis/reflection/wrapper/ObjectWrapper.java:46

 */
public interface ObjectWrapper {

  Object get(PropertyTokenizer prop);

  void set(PropertyTokenizer prop, Object value);

  String findProperty(String name, boolean useCamelCaseMapping);

  String[] getGetterNames();

  String[] getSetterNames();

  Class<?> getSetterType(String name);

  Class<?> getGetterType(String name);

  default Entry<Type, Class<?>> getGenericSetterType(String name) {
    throw new UnsupportedOperationException(
        "'" + this.getClass() + "' must override the default method 'getGenericSetterType()'.");
  }

  default Entry<Type, Class<?>> getGenericGetterType(String name) {
    throw new UnsupportedOperationException(
        "'" + this.getClass() + "' must override the default method 'getGenericGetterType()'.");
  }

  boolean hasSetter(String name);

  boolean hasGetter(String name);

  MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory);

  boolean isCollection();

  void add(Object element);

View on GitHub (pinned to 008069adb1)

Solutions

  1. Override getGenericSetterType(String name) in your custom ObjectWrapper implementation (delegate to a Reflector/MetaClass lookup)
  2. Use BeanWrapper/MapWrapper which already override it, instead of CollectionWrapper, when generic type resolution is needed
  3. Avoid calling the generic variant on wrappers that cannot know setter types (collections)

Example fix

// before
class MyWrapper implements ObjectWrapper { /* no getGenericSetterType */ }

// after
@Override
public Entry<Type, Class<?>> getGenericSetterType(String name) {
  return Map.Entry.entry(metaClass.getSetterType(name), metaClass.getSetterType(name));
}
Defensive patterns

Strategy: validation

Validate before calling

ObjectWrapper w = metaObject.getObjectWrapper();
// only call on wrappers known to implement the generic API
if (w instanceof org.apache.ibatis.reflection.wrapper.BeanWrapper
    || w instanceof org.apache.ibatis.reflection.wrapper.MapWrapper) {
  var t = w.getGenericSetterType(name);
}

Prevention

When it happens

Trigger: Calling metaObject.getObjectWrapper().getGenericSetterType(name) on a wrapper that did not override it (e.g. CollectionWrapper); MyBatis internals resolving generic setter types (DefaultParameterHandler parameter setting with generic properties) against a custom ObjectWrapper implementation missing the override.

Common situations: Writing a custom ObjectWrapper (custom wrapper factory setups) without implementing the newer default methods added in recent MyBatis 3.5.x releases; upgrading MyBatis where generic type resolution started calling this method.

Related errors


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/9c9c070d114a9e7f. Report an issue: GitHub.