{"record":{"id":"559c9734a8335926","repo":"mybatis/mybatis-3","slug":"classname-is-not-a-wrapper","errorCode":null,"errorMessage":"${className} is not a wrapper.","messagePattern":"(.+?) is not a wrapper\\.","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"warning","filePath":"src/main/java/org/apache/ibatis/datasource/pooled/PooledDataSource.java","lineNumber":631,"sourceCode":"  public static Connection unwrapConnection(Connection conn) {\n    if (Proxy.isProxyClass(conn.getClass())) {\n      InvocationHandler handler = Proxy.getInvocationHandler(conn);\n      if (handler instanceof PooledConnection) {\n        return ((PooledConnection) handler).getRealConnection();\n      }\n    }\n    return conn;\n  }\n\n  @Override\n  protected void finalize() throws Throwable {\n    forceCloseAll();\n    super.finalize();\n  }\n\n  @Override\n  public <T> T unwrap(Class<T> iface) throws SQLException {\n    throw new SQLException(getClass().getName() + \" is not a wrapper.\");\n  }\n\n  @Override\n  public boolean isWrapperFor(Class<?> iface) {\n    return false;\n  }\n\n  @Override\n  public Logger getParentLogger() {\n    return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);\n  }\n\n}\n","sourceCodeStart":613,"sourceCodeEnd":645,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/datasource/pooled/PooledDataSource.java#L613-L645","documentation":"UnpooledDataSource and PooledDataSource implement the java.sql.Wrapper interface but do not wrap anything, so unwrap(Class) always throws SQLException '<ClassName> is not a wrapper.' and isWrapperFor returns false. Wrapper.unwrap is meant to let callers extract a vendor-specific implementation from a proxy; these DataSource implementations are plain, so there is nothing to unwrap.","triggerScenarios":"Calling pooledDataSource.unwrap(SomeClass.class) on the MyBatis DataSource itself; generic framework code (monitoring, metrics, de-correlators) that probes DataSources via unwrap(); attempting unwrap(Connection.class) or a driver class against the DataSource rather than against a Connection obtained from it.","commonSituations":"Integration libraries that try to detect HikariCP/Tomcat/uwm-specific datasources by unwrapping them; migration from a wrapping pool (HikariCP) to MyBatis PooledDataSource where code unwrapped HikariDataSource; trying to access driver-level APIs through the DataSource.","solutions":["Guard with isWrapperFor(iface) before calling unwrap() — it returns false for these classes","To get vendor/driver-specific objects, unwrap the java.sql.Connection obtained from getConnection(), not the DataSource","If you need a pool with unwrap support (JMX metrics, etc.), use an external pool (HikariCP, DBCP) and plug it into MyBatis via a custom DataSourceFactory or env-provided DataSource"],"exampleFix":"// before\nHikariDataSource h = dataSource.unwrap(HikariDataSource.class); // SQLException\n\n// after\nif (dataSource.isWrapperFor(HikariDataSource.class)) {\n  HikariDataSource h = dataSource.unwrap(HikariDataSource.class);\n} else {\n  // MyBatis POOLED/UNPOOLED DataSource: nothing to unwrap\n}","handlingStrategy":"type-guard","validationCode":"if (dataSource.isWrapperFor(HikariDataSource.class)) { // false for MyBatis pools\n  HikariDataSource h = dataSource.unwrap(HikariDataSource.class);\n}","typeGuard":"static boolean isUnwrappable(javax.sql.DataSource ds, Class<?> iface) {\n  return ds != null && ds.isWrapperFor(iface); // MyBatis Pooled/Unpooled return false\n}","tryCatchPattern":"try {\n  return dataSource.unwrap(iface);\n} catch (SQLException e) {\n  if (e.getMessage().endsWith(\"is not a wrapper.\")) return null; // not a proxy\n  throw e;\n}","preventionTips":["Always pair unwrap() with an isWrapperFor() check","Unwrap Connections, not DataSources, for driver-level access","Prefer instanceof checks on the concrete DataSource class you expect"],"tags":["mybatis","jdbc-wrapper","datasource","api-misuse"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}