Spring Boot
JNDI
Embedded Tomcat
Java
Spring Framework

How to create JNDI context in Spring Boot with Embedded Tomcat Container

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Spring Boot with embedded Tomcat, JNDI is not preconfigured the same way it often is in a full external application server. If you want to look up a resource such as a DataSource through JNDI, you usually need to register that resource programmatically inside the embedded Tomcat context.

The normal pattern is to customize Tomcat, enable naming, add the resource, and then point Spring at the JNDI name. This is useful when you want app-server-style resource lookup while still packaging the application as a self-contained Boot app.

Customize the Embedded Tomcat Context

A common approach is to create a TomcatServletWebServerFactory bean and register a resource on the Tomcat context:

java
1import org.apache.catalina.Context;
2import org.apache.tomcat.util.descriptor.web.ContextResource;
3import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
4import org.springframework.context.annotation.Bean;
5import org.springframework.context.annotation.Configuration;
6
7@Configuration
8public class TomcatJndiConfig {
9
10    @Bean
11    public TomcatServletWebServerFactory tomcatFactory() {
12        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
13        factory.addContextCustomizers(this::customizeContext);
14        return factory;
15    }
16
17    private void customizeContext(Context context) {
18        ContextResource resource = new ContextResource();
19        resource.setName("jdbc/MyAppDb");
20        resource.setType(javax.sql.DataSource.class.getName());
21        resource.setProperty("driverClassName", "org.postgresql.Driver");
22        resource.setProperty("url", "jdbc:postgresql://localhost:5432/appdb");
23        resource.setProperty("username", "appuser");
24        resource.setProperty("password", "secret");
25        resource.setProperty("maxTotal", "20");
26
27        context.getNamingResources().addResource(resource);
28    }
29}

The important part is that the resource becomes known to the embedded container before Spring tries to look it up.

Look Up the Resource from Spring

Once the resource exists, Spring can obtain it through JNDI:

java
1import org.springframework.context.annotation.Bean;
2import org.springframework.context.annotation.Configuration;
3import org.springframework.jndi.JndiObjectFactoryBean;
4
5import javax.sql.DataSource;
6
7@Configuration
8public class DataSourceConfig {
9
10    @Bean
11    public DataSource dataSource() throws Exception {
12        JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
13        bean.setJndiName("java:comp/env/jdbc/MyAppDb");
14        bean.setProxyInterface(DataSource.class);
15        bean.afterPropertiesSet();
16        return (DataSource) bean.getObject();
17    }
18}

This tells Spring to use the container-managed resource instead of constructing a data source directly from standard Boot properties.

Alternative Property-Based Configuration

In many cases, the simplest Spring side is just setting the JNDI property:

properties
spring.datasource.jndi-name=java:comp/env/jdbc/MyAppDb

If the embedded Tomcat resource is already registered correctly, Boot can wire the DataSource from that property without an explicit JndiObjectFactoryBean.

Know When JNDI Is Worth the Complexity

JNDI is useful when you want deployment-time indirection or compatibility with Java EE style resource management. But in ordinary Spring Boot applications, plain spring.datasource.* configuration is often simpler and easier to maintain.

That means JNDI should be a deliberate choice, not a default habit. If you do not need container-style naming indirection, normal Spring configuration is usually the better fit.

Test the Lookup Early

A small startup check can save time when wiring this for the first time. If the application fails early with a clear JNDI lookup error, that is much easier to debug than discovering the misconfiguration only after database code executes deeper in the stack.

It also helps confirm that embedded Tomcat customization ran at all, which is often the real source of confusion.

Common Pitfalls

  • Expecting embedded Tomcat to expose the same JNDI resources as an external server without extra configuration.
  • Registering a resource under one name and trying to look it up under another.
  • Mixing JNDI configuration with direct spring.datasource.* settings and creating confusing behavior.
  • Forgetting that the embedded container must be customized before the lookup happens.
  • Using JNDI when standard Boot configuration would have been simpler.

Summary

  • In Spring Boot with embedded Tomcat, JNDI resources usually need to be registered programmatically.
  • Customize the Tomcat context and add the resource there.
  • Point Spring at the JNDI name through code or spring.datasource.jndi-name.
  • Use JNDI when you actually need container-style indirection.
  • Prefer plain Boot configuration when JNDI adds complexity without a clear benefit.

Course illustration
Course illustration

All Rights Reserved.