1. Overview
In this article, we’ll create a Spring application using Hibernate/JPA with a JNDI datasource.
If you want to rediscover the basics of Spring and Hibernate, check out this article.
2. Declaring the Datasource
2.1. System
Since we’re using a JNDI datasource, we won’t define it in our application, we’ll define it in our application container.
In this example, we’re going to use 8.5.4 version of Tomcat and the 9.5.4 version of the PostgreSQL database.
You should be able to replicate the same steps using any other Java application container and a database of your choice (as long as you have proper JDBC jars for it!).
2.2. Declaring the Datasource on the Application Container
We’ll declare our datasource in <tomcat_home>/conf/server.xml file inside the <GlobalNamingResources> element.
Assuming that the database server is running on the same machine as the application container, and that the intended database is named postgres, and that the username is baeldung with password pass1234, a resource would look like this:
<Resource name="jdbc/BaeldungDatabase" auth="Container" type="javax.sql.DataSource" driverClassName="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/postgres" username="baeldung" password="pass1234" maxActive="20" maxIdle="10" maxWait="-1"/>
Take note that we’ve named our resource jdbc/BaeldungDatabase. This will be the name to be used when referencing this datasource.
We’ve also had to specify its type and database driver’s class name. For it to work, you must also place the corresponding jar in <tomcat_home>/lib/ (in this case, PostgreSQL’s JDBC jar).
Remaining configuration parameters are:
- auth=”Container” – means that the container will be signing on to the resource manager on behalf of the application
- maxActive, maxIdle, and maxWait – are pool connection’s configuration parameters
We must also define a ResourceLink inside the <Context> element in <tomcat_home>/conf/context.xml, which would look like:
<ResourceLink name="jdbc/BaeldungDatabase" global="jdbc/BaeldungDatabase" type="javax.sql.DataSource"/>
Note that we are using the name we defined in our Resource in server.xml.
3. Using the Resource
3.1. Setting the Application
We’re going to define a simple Spring + JPA + Hibernate application using pure Java config now.
We’ll start by defining the Spring context’s configuration (keep in mind that we are focusing on JNDI here and assuming that you already know the basics of Spring’s configuration):
@Configuration @EnableTransactionManagement @PropertySource({ "classpath:persistence-jndi.properties" }) @ComponentScan({ "org.baeldung.persistence" }) @EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao") public class PersistenceJNDIConfig { @Autowired private Environment env; @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); // rest of entity manager configuration return em; } @Bean public DataSource dataSource() throws NamingException { return (DataSource) new JndiTemplate().lookup(env.getProperty("jdbc.url")); } @Bean public PlatformTransactionManager transactionManager(EntityManagerFactory emf) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(emf); return transactionManager; } // rest of persistence configuration }
Note that we have a full example of configuration in the Spring 4 and JPA with Hibernate article.
In order to create our dataSource bean, we need to look for the JNDI resource we defined at our application container. We’ll store this in persistence-jndi.properties key (among other properties):
jdbc.url=java:comp/env/jdbc/BaeldungDatabase
Note that in the jdbc.url property we’re defining a root name to look for: java:comp/env/ (this are defaults and correspond to component and environment) and then the same name we used in server.xml: jdbc/BaeldungDatabase.
3.2. JPA Configuration – Model, DAO and Service
We’re going to use a simple model with the @Entity annotation with a generated id and a name:
@Entity public class Foo { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "ID") private long id; @Column(name = "NAME") private String name; // default getters and setters }
Let’s define a simple repository:
@Repository public class FooDao { @PersistenceContext private EntityManager entityManager; public List<Foo> findAll() { return entityManager .createQuery("from " + Foo.class.getName()).getResultList(); } }
And lastly, let’s create a simple service:
@Service @Transactional public class FooService { @Autowired private FooDao dao; public List<Foo> findAll() { return dao.findAll(); } }
With this, you have everything you need in order to use your JNDI datasource in your Spring application.
4. Conclusion
In this article, we’ve created an example Spring application with a JPA + Hibernate setup working with a JNDI datasource.
Note that the most important parts are the definition of the resource in the application container and the lookup for the JNDI resource on the configuration.
And, as always, the full project can be found on GitHub.