Bienvenue dans le tutoriel sur l’exemple de Spring DataSource JNDI Tomcat. Plus tôt, nous avons vu comment implémenter des opérations de base de données en utilisant l’intégration Spring JDBC. Cependant, la plupart du temps, les applications d’entreprise sont déployées dans un conteneur de servlets tel que Tomcat, JBoss, etc.
Spring DataSource
Nous savons que DataSource avec JNDI est le moyen privilégié pour réaliser un pool de connexions et bénéficier des implémentations de conteneurs. Aujourd’hui, nous verrons comment configurer une application Web Spring pour utiliser des connexions JNDI fournies par Tomcat. Pour mon exemple, je vais utiliser le serveur de base de données MySQL et créer une table simple avec quelques lignes. Nous allons créer un service Web Spring Rest qui renverra la réponse JSON avec la liste de toutes les données dans la table.
Configuration de la base de données
CREATE TABLE `Employee` (
`id` int(11) unsigned NOT NULL,
`name` varchar(20) DEFAULT NULL,
`role` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `Employee` (`id`, `name`, `role`)
VALUES
(1, 'Pankaj', 'CEO'),
(2, 'David', 'Manager');
commit;
Projet Spring DataSource MVC
Créez un projet Spring MVC dans Spring Tool Suite afin que le code squelette de notre application Spring soit prêt. Une fois notre implémentation terminée, la structure de notre projet ressemblera à l’image ci-dessous.
Dépendances Spring JDBC et Jackson
Nous devrons ajouter Spring JDBC, Jackson et le pilote de base de données MySQL en tant que dépendances dans le fichier pom.xml. Mon fichier pom.xml final ressemble à ce qui suit.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev.spring</groupId>
<artifactId>SpringDataSource</artifactId>
<name>SpringDataSource</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.6</java-version>
<org.springframework-version>4.0.2.RELEASE</org.springframework-version>
<org.aspectj-version>1.7.4</org.aspectj-version>
<org.slf4j-version>1.7.5</org.slf4j-version>
<jackson.databind-version>2.2.3</jackson.databind-version>
</properties>
<dependencies>
<!-- Spring JDBC Support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.5</version>
</dependency>
<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.databind-version}</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
Si vous n’êtes pas familier avec Rest dans Spring, veuillez lire Exemple de service Web Restful Spring.
Classe modèle
Notre bean Employee, modélisé d’après la table Employee, ressemble à ce qui suit.
package com.journaldev.spring.jdbc.model;
import java.io.Serializable;
public class Employee implements Serializable{
private static final long serialVersionUID = -7788619177798333712L;
private int id;
private String name;
private String role;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
Classe Contrôleur Spring
Notre classe contrôleur simple ressemble à ce qui suit.
package com.journaldev.spring.jdbc.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.journaldev.spring.jdbc.model.Employee;
/**
* Handles requests for the Employee JDBC Service.
*/
@Controller
public class EmployeeController {
private static final Logger logger = LoggerFactory.getLogger(EmployeeController.class);
@Autowired
@Qualifier("dbDataSource")
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
@RequestMapping(value = "/rest/emps", method = RequestMethod.GET)
public @ResponseBody List getAllEmployees() {
logger.info("Start getAllEmployees.");
List empList = new ArrayList();
// Code JDBC - Début
String query = "select id, name, role from Employee";
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
List
Les points importants concernant la classe Contrôleur sont les suivants :
- La DataSource sera câblée par la configuration de bean Spring avec le nom dbDataSource.
- Nous utilisons JdbcTemplate pour éviter les erreurs courantes telles que les fuites de ressources et supprimer le code JDBC inutile.
- L’URI pour récupérer la liste des employés sera https://{host}:{port}/SpringDataSource/rest/emps
- Nous utilisons @ResponseBody pour envoyer la liste des objets Employé en tant que réponse, Spring se chargera de la convertir en JSON.
Configuration de Bean Spring
Il existe deux façons de faire une recherche JNDI et de la câbler à la DataSource du Contrôleur, mon fichier de configuration de bean Spring contient les deux, mais l’une d’elles est commentée. Vous pouvez basculer entre les deux et la réponse sera la même.
- Utilisation de la balise de l’espace de noms jee pour effectuer la recherche JNDI et la configurer en tant que Bean Spring. Nous devons également inclure l’espace de noms jee et la définition de schéma dans ce cas.
- Création d’un bean de type
org.springframework.jndi.JndiObjectFactoryBean
en passant le nom du contexte JNDI. jndiName est un paramètre requis pour cette configuration.
Mon fichier de configuration de bean Spring ressemble à ce qui suit.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
xmlns:jee="https://www.springframework.org/schema/jee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:beans="https://www.springframework.org/schema/beans"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="https://www.springframework.org/schema/jee https://www.springframework.org/schema/jee/spring-jee.xsd
https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<!-- Configure to plugin JSON as request and response in method handler -->
<beans:bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<beans:property name="messageConverters">
<beans:list>
<beans:ref bean="jsonMessageConverter" />
</beans:list>
</beans:property>
</beans:bean>
<!-- Configure bean to convert JSON to POJO and vice versa -->
<beans:bean id="jsonMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</beans:bean>
<!-- Create DataSource Bean -->
<beans:bean id="dbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<beans:property name="jndiName" value="java:comp/env/jdbc/MyLocalDB"/>
</beans:bean>
<!-- using JEE namespace for lookup -->
<!--
<jee:jndi-lookup id="dbDataSource" jndi-name="jdbc/MyLocalDB"
expected-type="javax.sql.DataSource" />
-->
<context:component-scan base-package="com.journaldev.spring.jdbc.controller" />
</beans:beans>
Configuration JNDI de la source de données Tomcat
Maintenant que nous avons terminé notre projet, la dernière étape consiste à effectuer la configuration JNDI dans le conteneur Tomcat pour créer la ressource JNDI.
<Resource name="jdbc/TestDB"
global="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/TestDB"
username="pankaj"
password="pankaj123"
maxActive="100"
maxIdle="20"
minIdle="5"
maxWait="10000"/>
Ajoutez la configuration ci-dessus dans la section GlobalNamingResources du fichier server.xml.
<ResourceLink name="jdbc/MyLocalDB"
global="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource" />
Nous devons également créer le lien de ressource pour utiliser la configuration JNDI dans notre application, la meilleure façon de l’ajouter dans le fichier context.xml du serveur. Remarquez que le nom de ResourceLink doit correspondre au nom du contexte JNDI que nous utilisons dans notre application. Assurez-vous également que le jar MySQL est présent dans le répertoire lib de tomcat, sinon tomcat ne pourra pas créer le pool de connexions à la base de données MySQL.
Exécution du projet d’exemple Spring DataSource JNDI
Notre projet et la configuration du serveur sont terminés, et nous sommes prêts à le tester. Exportez le projet en tant que fichier WAR et placez-le dans le répertoire de déploiement de Tomcat. La réponse JSON pour l’appel Rest est affichée dans l’image ci-dessous. C’est tout pour l’intégration de Spring avec le contexte JNDI du conteneur de servlets. Téléchargez le projet d’exemple depuis le lien ci-dessous et explorez-le pour en apprendre davantage.
Source:
https://www.digitalocean.com/community/tutorials/spring-datasource-jndi-with-tomcat-example