apereo/cas · warning

Lookup of datasource

Error message

Lookup of datasource [{}] failed due to [{}]. Back to JPA properties.

What it means

JpaBeans.newDataSource first tries to resolve the configured datasource name via JNDI (JndiDataSourceLookup). If the lookup throws DataSourceLookupFailureException - the name is not bound in the container's JNDI tree - it logs this WARN and falls back to building a HikariDataSource from the JPA properties (driver class, URL, user, password). It is a recoverable fallback, not a fatal error; the returned pool just uses local JDBC settings instead of the container-managed datasource.

Solutions

  1. Declare the JNDI datasource in the servlet container (context.xml Resource, server datasource config) so the lookup succeeds
  2. Remove/clear the dataSourceName property so CAS skips the JNDI attempt and builds the Hikari pool directly from JPA properties
  3. Ensure jpaProperties (url, driverClass, user, password) are fully populated since they are used for the fallback
  4. Verify the exact JNDI name string matches the container binding, including java:comp/env prefixing behavior

Example fix

// before
cas.authn.jpa.dataSourceName=jdbc/casDb
// after
cas.authn.jpa.url=jdbc:postgresql://db:5432/cas
cas.authn.jpa.driverClass=org.postgresql.Driver
cas.authn.jpa.user=cam
cas.authn.jpa.password=secret
Defensive patterns

Strategy: fallback

Validate before calling

try { new javax.naming.InitialContext().lookup("java:comp/env/jdbc/casDb"); } catch (NamingException e) { System.out.println("JNDI ds missing - ensure JPA url/driver/user/password are set"); }

Try / catch

try { dataSource = new InitialContext().lookup("java:comp/env/jdbc/casDb"); } catch (NamingException e) { LOGGER.warn("JNDI lookup failed; using Hikari from JPA properties", e); dataSource = buildHikari(jpaProperties); }

Prevention

When it happens

Trigger: Configuring a JPA module (cas.authn.jpa, tickets-jpa, services-jpa, etc.) with a dataSourceName while running outside a servlet container that exposes that JNDI resource; JNDI name typo or missing <Resource>/resource-ref declaration; deploying the CAS WAR standalone (embedded container) where no JNDI datasource is provisioned.

Common situations: Running CAS via embedded Tomcat/Jetty in dev where no JNDI datasource is bound; moving an app from app-server deployment to standalone and forgetting to remove dataSourceName; JNDI binding present only after datasource resource is declared in server config.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/6e861df13a49c18e. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-jpa-util/src/main/java/org/apereo/cas/configuration/support/JpaBeans.java:118

     * <p>
     * If user wants to do lookup as resource, they may include {@code java:/comp/env}
     * in {@code dataSourceName} and put resource reference in web.xml
     * otherwise {@code dataSourceName} is used as JNDI name.
     *
     * @param jpaProperties the jpa properties
     * @return the data source
     */
    public CloseableDataSource newDataSource(final AbstractJpaProperties jpaProperties) {
        val dataSourceName = jpaProperties.getDataSourceName();

        if (StringUtils.isNotBlank(dataSourceName)) {
            try {
                val dsLookup = new JndiDataSourceLookup();
                dsLookup.setResourceRef(false);
                val containerDataSource = dsLookup.getDataSource(dataSourceName);
                return new DefaultCloseableDataSource(containerDataSource);
            } catch (final DataSourceLookupFailureException e) {
                LOGGER.warn("Lookup of datasource [{}] failed due to [{}]. Back to JPA properties.", dataSourceName, e.getMessage());
            }
        }

        val bean = new HikariDataSource();
        FunctionUtils.doIfNotBlank(jpaProperties.getDriverClass(), _ -> bean.setDriverClassName(jpaProperties.getDriverClass()));

        val url = SpringExpressionLanguageValueResolver.getInstance().resolve(jpaProperties.getUrl());
        bean.setJdbcUrl(url);
        bean.setUsername(jpaProperties.getUser());
        bean.setPassword(jpaProperties.getPassword());

        val poolSettings = jpaProperties.getPool();
        FunctionUtils.doUnchecked(_ -> bean.setLoginTimeout((int) Beans.newDuration(poolSettings.getMaxWait()).toSeconds()));
        bean.setMaximumPoolSize(poolSettings.getMaxSize());
        bean.setMinimumIdle(poolSettings.getMinSize());
        bean.setIdleTimeout(Beans.newDuration(jpaProperties.getIdleTimeout()).toMillis());
        bean.setLeakDetectionThreshold(Beans.newDuration(jpaProperties.getLeakThreshold()).toMillis());
        bean.setInitializationFailTimeout(jpaProperties.getFailFastTimeout());

View on GitHub (pinned to e7288fc434)