{"record":{"id":"69ec316e25d69a54","repo":"flowable/flowable-engine","slug":"cannot-unwrap-getclass-getname-as-an-instan","errorCode":null,"errorMessage":"Cannot unwrap ${getClass().getName()} as an instance of ${iface.getName()}","messagePattern":"Cannot unwrap (.+?) as an instance of (.+?)","errorType":"exception","errorClass":"java.sql.SQLException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/cfg/multitenant/TenantAwareDataSource.java","lineNumber":89,"sourceCode":"    }\n\n    @Override\n    public int getLoginTimeout() throws SQLException {\n        return 0; // Default\n    }\n\n    @Override\n    public Logger getParentLogger() throws SQLFeatureNotSupportedException {\n        return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (iface.isInstance(this)) {\n            return (T) this;\n        }\n        throw new SQLException(\"Cannot unwrap \" + getClass().getName() + \" as an instance of \" + iface.getName());\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        return iface.isInstance(this);\n    }\n\n    public Map<Object, DataSource> getDataSources() {\n        return dataSources;\n    }\n\n    public void setDataSources(Map<Object, DataSource> dataSources) {\n        this.dataSources = dataSources;\n    }\n\n    // Unsupported //////////////////////////////////////////////////////////\n\n    @Override","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/cfg/multitenant/TenantAwareDataSource.java#L71-L107","documentation":"TenantAwareDataSource.unwrap() only supports unwrapping to the TenantAwareDataSource class itself; it does not delegate to the underlying per-tenant DataSource. If a caller requests any other interface, it throws SQLException. This is a deliberate (minimal) JDBC Wrapper implementation.","triggerScenarios":"Calling unwrap(SomeInterface.class) on a TenantAwareDataSource where SomeInterface is not the TenantAwareDataSource type — e.g. vendor-specific interfaces like OracleDataSource, pool-specific types, or JDBC 4 Wrapper lookups by connection-pool tooling.","commonSituations":"Framework code (connection pool probes, monitoring, spring DataSource wrappers) probing for vendor extensions; code expecting unwrap to pass through to the underlying tenant DataSource; migrating code that previously used a native DataSource directly.","solutions":["Unwrap via isWrapperFor check only for TenantAwareDataSource.class, or obtain the underlying DataSource directly from the tenant map instead of unwrapping","Extend/wrap TenantAwareDataSource with a delegating unwrap() that forwards to the current tenant's DataSource if you need vendor interfaces","Check the object with isWrapperFor(iface) first and branch your code accordingly","Avoid vendor-specific calls through the tenant-aware layer; use the raw DataSource per tenant for those operations"],"exampleFix":"// before\nOracleDataSource ods = tenantAwareDs.unwrap(OracleDataSource.class);\n// after\nDataSource current = tenantAwareDs.getDataSource(tenantInfoHolder.getCurrentTenantId());\nif (current.isWrapperFor(OracleDataSource.class)) {\n    OracleDataSource ods = current.unwrap(OracleDataSource.class);\n}","handlingStrategy":"type-guard","validationCode":"if (!tenantAwareDs.isWrapperFor(iface)) {\n    throw new SQLException(iface + \" not supported by TenantAwareDataSource\");\n}","typeGuard":"boolean isTenantAwareDs(DataSource ds) {\n    return ds instanceof TenantAwareDataSource;\n}\n// only unwrap TenantAwareDataSource.class from it","tryCatchPattern":"try {\n    T unwrapped = ds.unwrap(iface);\n} catch (SQLException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Cannot unwrap\")) {\n        // fall back to the underlying per-tenant DataSource\n    }\n}","preventionTips":["Never request vendor-specific interfaces from the tenant-aware wrapper; unwrap the underlying DataSource instead","Check isWrapperFor() before calling unwrap()","Remember TenantAwareDataSource only supports unwrapping to itself"],"tags":["jdbc","datasource","unwrap","multi-tenant"],"backgroundTag":"unsupported-operation","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}