{"record":{"id":"57310b6c6875c3f2","repo":"YunaiV/yudao-cloud","slug":"couldn-t-lookup-datasource-from","errorCode":null,"errorMessage":"couldn't lookup datasource from {}: {}","messagePattern":"couldn't lookup datasource from (.+?): (.+?)","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"critical","filePath":"sql/dm/flowable-patch/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java","lineNumber":446,"sourceCode":"    /**\n     * Define a max length for storing String variable types in the database. Mainly used for the Oracle NVARCHAR2 limit of 2000 characters\n     */\n    protected int maxLengthStringVariableType = -1;\n\n    protected void initEngineConfigurations() {\n        addEngineConfiguration(getEngineCfgKey(), getEngineScopeType(), this);\n    }\n\n    // DataSource\n    // ///////////////////////////////////////////////////////////////\n\n    protected void initDataSource() {\n        if (dataSource == null) {\n            if (dataSourceJndiName != null) {\n                try {\n                    dataSource = (DataSource) new InitialContext().lookup(dataSourceJndiName);\n                } catch (Exception e) {\n                    throw new FlowableException(\"couldn't lookup datasource from \" + dataSourceJndiName + \": \" + e.getMessage(), e);\n                }\n\n            } else if (jdbcUrl != null) {\n                if ((jdbcDriver == null) || (jdbcUsername == null)) {\n                    throw new FlowableException(\"DataSource or JDBC properties have to be specified in a process engine configuration\");\n                }\n\n                logger.debug(\"initializing datasource to db: {}\", jdbcUrl);\n\n                if (logger.isInfoEnabled()) {\n                    logger.info(\"Configuring Datasource with following properties (omitted password for security)\");\n                    logger.info(\"datasource driver : {}\", jdbcDriver);\n                    logger.info(\"datasource url : {}\", jdbcUrl);\n                    logger.info(\"datasource user name : {}\", jdbcUsername);\n                }\n\n                PooledDataSource pooledDataSource = new PooledDataSource(this.getClass().getClassLoader(), jdbcDriver, jdbcUrl, jdbcUsername, jdbcPassword);\n","sourceCodeStart":428,"sourceCodeEnd":464,"githubUrl":"https://github.com/YunaiV/yudao-cloud/blob/477be9dd49ab7223a972a6abdff0684d6423dec3/sql/dm/flowable-patch/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java#L428-L464","documentation":"Flowable's AbstractEngineConfiguration.initDataSource() tries InitialContext().lookup(dataSourceJndiName) when no DataSource bean was injected. Any NamingException/ClassCastException/communication failure from the JNDI provider is wrapped in this FlowableException, including the JNDI name in the message.","triggerScenarios":"ProcessEngineConfiguration is built with setDataSourceJndiName(\"java:comp/env/jdbc/ds\") but the app runs outside a container with no JNDI tree, or the name is misspelled, or the bound object is not a javax.sql.DataSource (cast fails), or the app server resource is not deployed/started.","commonSituations":"Moving a Flowable app from a full app server (WildFly/TomEE with JNDI) to Spring Boot embedded Tomcat which has no java:comp/env by default; typos in the JNDI name; resource adapter not yet published during early startup; running unit tests without a JNDI implementation.","solutions":["Verify the exact JNDI name against the server's JNDI tree (e.g. WildFly admin console, Tomcat's ResourceLink + web.xml resource-ref).","On Spring Boot / standalone, skip JNDI and configure jdbcUrl/jdbcDriver/jdbcUsername directly, or inject a DataSource bean via setDataSource().","Ensure the lookup target is really a javax.sql.DataSource and the app has permission to read it.","For embedded Tomcat, register the resource in server.context.xml (or TomcatServletWebServerFactory customization) and the ResourceLink in context.xml."],"exampleFix":"// before\ncfg.setDataSourceJndiName(\"java:comp/env/jdbc/flowable\"); // fails in Spring Boot\n\n// after\ncfg.setJdbcUrl(\"jdbc:dm://localhost:5236\");\ncfg.setJdbcDriver(\"dm.jdbc.driver.DmDriver\");\ncfg.setJdbcUsername(\"SYSDBA\");\ncfg.setJdbcPassword(\"***\");","handlingStrategy":"validation","validationCode":"// Fail fast before engine build with a clear message\nif (cfg.getDataSource() == null && cfg.getDataSourceJndiName() != null) {\n    try {\n        DataSource ds = (DataSource) new InitialContext().lookup(cfg.getDataSourceJndiName());\n        Assert.notNull(ds, \"JNDI name resolved to null\");\n    } catch (Exception e) {\n        throw new IllegalStateException(\"JNDI datasource unavailable: \" + cfg.getDataSourceJndiName(), e);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    processEngine = cfg.buildProcessEngine();\n} catch (FlowableException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"couldn't lookup datasource\")) {\n        // fall back to direct JDBC config or fail with actionable guidance\n        throw new IllegalStateException(\"Configure a valid JNDI name or set jdbc* properties\", e);\n    }\n    throw e;\n}","preventionTips":["In Spring Boot / standalone apps, prefer setDataSource() or jdbc* properties over JNDI","Smoke-test JNDI lookups in a startup health check before the engine builds"],"tags":["flowable","jndi","datasource","configuration","startup"],"backgroundTag":null,"analyzedSha":"477be9dd49ab7223a972a6abdff0684d6423dec3","analyzedAt":"2026-08-14T13:35:31.121Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}