question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Error with interface TypeHandler for enum with interface

See original GitHub issue

Hi, I think I found an issue for a rather specific case. I’m not sure if this issue belongs to this repo, Spring integration, or MyBatis core. I put it here for now, because the demo is using TypeHandler’s component scanning.

When trying to map an enum with an interface using the interface’s TypeHandler Spring bean, there are cases which throws the following exception:

...
Caused by: org.apache.ibatis.type.TypeException: Unable to find a usable constructor for class com.example.demo.mybatis.TheInterfaceTypeHandler
	at org.apache.ibatis.type.TypeHandlerRegistry.getInstance(TypeHandlerRegistry.java:457) ~[mybatis-3.5.5.jar:3.5.5]
	at org.apache.ibatis.type.TypeHandlerRegistry.getJdbcHandlerMapForEnumInterfaces(TypeHandlerRegistry.java:286) ~[mybatis-3.5.5.jar:3.5.5]
	at org.apache.ibatis.type.TypeHandlerRegistry.getJdbcHandlerMap(TypeHandlerRegistry.java:262) ~[mybatis-3.5.5.jar:3.5.5]
	at org.apache.ibatis.type.TypeHandlerRegistry.getTypeHandler(TypeHandlerRegistry.java:237) ~[mybatis-3.5.5.jar:3.5.5]
	...
Caused by: java.lang.NoSuchMethodException: com.example.demo.mybatis.TheInterfaceTypeHandler.<init>()
	at java.lang.Class.getConstructor0(Class.java:3082) ~[na:1.8.0_265]
	at java.lang.Class.getConstructor(Class.java:1825) ~[na:1.8.0_265]

As I understand it, MyBatis is trying to instantiate a new TypeHandler instead of using the one registered as Spring bean, which it failed because the type handler class requires another Spring bean (therefore no no-arg constructor).


Here’s the sample code for demonstrating the case: https://github.com/KniveX/bugreport-springboot-mybatis-200816

  • Java 8 (OpenJDK 1.8.0_265-8u265-b01-0ubuntu2~18.04-b01)
  • Spring Boot (2.3.3.RELEASE)
  • mybatis-spring-boot-starter (2.1.3)

Thank you, and I apologize if my english is not clear.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
kazuki43zoocommented, Aug 18, 2020

I think you don’t need to use the spring bean in this case. I’ve modified as follow, it work fine. WDYT?

package com.example.demo.mybatis;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import com.example.demo.obj.TheInterface;
import com.example.demo.obj.TheRequiredBean;

public class TheInterfaceTypeHandler extends BaseTypeHandler<TheInterface> {

	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, TheInterface parameter, JdbcType jdbcType)
			throws SQLException {
		ps.setString(i, parameter.name());
	}

	@Override
	public TheInterface getNullableResult(ResultSet rs, String columnName) throws SQLException {
		return TheRequiredBean.findByName( rs.getString(columnName) );
	}

	@Override
	public TheInterface getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
		return TheRequiredBean.findByName( rs.getString(columnIndex) );
	}

	@Override
	public TheInterface getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
		return TheRequiredBean.findByName( cs.getString(columnIndex) );
	}

}
package com.example.demo.obj;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.apache.ibatis.io.ResolverUtil;

public class TheRequiredBean {

  private static final Map<String, TheInterface> mapping;

  private TheRequiredBean() {
    // NOP
  }

  static {
    mapping = new ResolverUtil<>().find(new ResolverUtil.IsA(TheInterface.class), "com.example.demo")
        .getClasses().stream()
        .filter(Class::isEnum)
        .map(x -> ((Class<? extends Enum<?>>) x))
        .flatMap(x -> Arrays.stream(x.getEnumConstants()))
        .collect(Collectors.toUnmodifiableMap(Enum::name, x -> (TheInterface) x));
  }

  public static TheInterface findByName(String enumName) {
    return mapping.get(enumName);
  }

}
  • application.properties
mybatis.type-handlers-package=com.example.demo.mybatis
0reactions
KniveXcommented, Aug 18, 2020

Your solution works great! I guess this issue can be safely closed.

Thanks a lot for your help @kazuki43zoo. Cheers

Read more comments on GitHub >

github_iconTop Results From Across the Web

Mybatis how mapping Integer to Enum? - java - Stack Overflow
If your enums implement a common interface like below, you can write a type handler that can map all of them. public interface...
Read more >
How to Fix "class, interface, or enum ... - GeeksforGeeks
In Java, the class interface or enum expected error is a compile-time error. There can be one of the following reasons we get...
Read more >
How to use enum with different values to the enumeration ...
I am currently getting the error as below when trying to unmarshall the value "C" ... The TypeHandler interface wasn't really designed to...
Read more >
MyBatis 3 | Configuration
defaultEnumTypeHandler, Specifies the TypeHandler used by default for Enum. ... To do so, implement the interface org.apache.ibatis.type.
Read more >
Effective Go - The Go Programming Language
Values; Interfaces and other types: Interfaces: Conversions: Interface ... On the other hand, thinking about the problem from a Go perspective could produce ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found