I. Introduction▲
Les services Web sont un moyen rapide de distribution de l'information entre les clients et les fournisseurs. Il existe deux grands types de services Web :
- les services Web de type REST (REpresentational State Transfer) qui exposent leurs fonctionnalités en protocole HTTP ou URI ;
- les services Web qui exposent leurs fonctionnalités en protocoles SOAP et WSDL.
Les services Web permettent la communication et l'échange de données entre des systèmes et applications utilisant des différentes technologies.
Le support du protocole REST a été introduit dans le module Spring-MVC à partir de la version 3 de Spring. Les Web services REST utilisent quatre types de méthodes http GET, POST, PUT et DELETE.
Pour mieux appréhender REST, il est vivement conseillé de lire la page suivante : http://www.restapitutorial.com/lessons/restquicktips.html.
I-A. Objectif▲
Tout au long de cet article, j'expliquerai étape par étape, comment implémenter un simple Web service REST avec le framework Spring 4.
Les principales étapes sont :
- créer un projet Maven dans Eclipse ;
- configurer le fichier pom.xml ;
- configurer Spring pour la couche [DAO] ;
- développer les méthodes de la couche [DAO] ;
- configurer Spring pour la couche MVC ;
- exposer les méthodes du Web service ;
- sécuriser les méthodes du Web service (partie 2 du tutoriel).
I-B. Prérequis▲
Il est important d'avoir des notions sur Java/J2EE et sur les principaux modules du framework Spring, à savoir :
- Spring core ;
- Spring MVC ;
- Spring Security ;
- Spring JDBC.
I-C. Versions des logiciels▲
Les versions des principaux logiciels et frameworks utilisés dans cet article sont :
- Eclipse Luna ;
- JDK 8 ;
- Tomcat 8.0 ;
- Maven 3 ;
- Spring 4.1.4 ;
- HSQLDB 2.3.2.
I-D. Création du projet dans Eclipse▲
Pour commencer, nous allons créer une application Web dynamique à partir de Eclipse en utilisant le plugin Maven de Eclipse.
Clic droit dans l'onglet Project Explorer, choisir New puis Other :

La fenêtre suivante s'affiche :
Dans le champ Wizards, saisir Maven, sélectionner Maven Project, puis cliquer sur le bouton Next :
Cocher la case « create a simple… » puis Next :
Saisir les valeurs suivantes :
Groupe Id : fr.idak.tutorial.ws ;
Artifact Id : rest-ws ;
Packaging : war.
Cliquer sur le bouton Finish pour finaliser la création du projet. La structure du projet généré est la suivante :
Un projet Maven standard se compose des dossiers suivants :
- src/main/java : contient les sources Java ;
- src/main/java : contient toutes les sources Java pour les tests unitaires ;
- src/main/resources : contient les fichiers de configuration ;
- target : contient les livrables et les résultats des tests unitaires ;
- pom.xml : contient toute la configuration Maven du projet, à savoir : dépendances, plugins, paramètres…
II. Configuration du fichier Maven pom.xml▲
II-A. Définition des versions des api/framework▲
Les numéros des versions des api/framework utilisées sont définis entre les balises <properties> et </properties> :
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
<properties>
<jdk.version>1.8</jdk.version>
<junit.version>4.12</junit.version>
<hamcrest.version>1.3</hamcrest.version>
<json.path.version>0.8.1</json.path.version>
<mockito.version>1.9.5</mockito.version>
<slf4j.version>1.7.9</slf4j.version>
<hsqldb.version>1.8.0.10</hsqldb.version>
<spring.version>4.1.3.RELEASE</spring.version>
<servlet.api.version>3.1.0</servlet.api.version>
<jackson.version>2.4.4</jackson.version>
</properties>
II-B. Configurer les plugins▲
Les plugins sont définis entre les balises <build> et </build> :
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
<build>
<finalName>rest-ws</finalName>
<plugins>
<!-- Configuration du plugin de compilation -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
<!-- Configuration du plugin de génération du war -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
Le fichier de déploiement web.xml n'est plus obligatoire dans la version 3.0 de la Servlet. L'élément failOnMissingWebXml permet d'indiquer à Maven que le fichier web.xml n'est pas utilisé.
II-C. Dépendances pour les tests unitaires▲
Nous allons utiliser la méthode TDD (Test Driven Development) pour implémenter les méthodes du Web service, pour cela nous avons besoin des API de test suivantes :
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>hamcrest-core</artifactId>
<groupId>org.hamcrest</groupId>
</exclusion>
</exclusions>
</dependency>
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>${json.path.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path-assert</artifactId>
<version>${json.path.version}</version>
<scope>test</scope>
</dependency>
84.
85.
86.
87.
88.
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
91.
92.
93.
94.
95.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
II-D. Dépendances Spring▲
Dans la première partie de cet article, nous allons utiliser deux modules de Spring, à savoir :
123.
124.
125.
126.
127.
128.
129.
130.
131.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
II-E. Autres Dépendances▲
La configuration pour le logeur, la Servlet, la base HSQLDB et Jackson mapper est :
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
<!-- Dépendances du Logeur -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Dépendances de la Servlet Api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.api.version}</version>
</dependency>
<!-- Dépendances HSQLDB -->
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>${hsqldb.version}</version>
</dependency>
<!-- dépendances pour jackson mapper -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
II-F. Mise à jour du projet Maven▲
Clic droit sur le projet puis choisir le sous-menu Maven -> Update Project ; puis OK :
Il reste deux problèmes à corriger, à savoir la version de Java et de la Servlet :

Pour régler ces deux problèmes, il suffirait de modifier le fichier org.eclipse.wst.common.project.facet.core.xml du répertoire .seings, le répertoire de trouve à la racine du projet Eclipse.
2.
3.
4.
5.
6.
7.
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="wst.jsdt.web"/>
<installed facet="java" version="1.8"/>
<installed facet="jst.web" version="3.0"/>
<installed facet="wst.jsdt.web" version="1.0"/>
</faceted-project>
Puis mettre à jour le projet Maven -> Update Project.
III. Configuration de la couche DAO▲
L'architecture du notre Web service évolue comme suit :
III-A. Configuration du contexte Spring▲
La structure du projet pour les prochaines étapes est :
Créer la classe ContextConfig qui nous permettra de configurer le contexte Spring du Web service.
Annoter la classe par @Configurion pour indiquer à Spring que cette classe peut être utilisée par le conteneur Spring IOC comme une source de définition des Beans.
Les Beans de notre repository seront ajoutés au contexte par l'annotation @ComponentScan.
2.
3.
4.
5.
6.
7.
8.
9.
10.
package fr.idak.tutorial.ws.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(value = {"fr.idak.tutorial.ws.repository"})
public class ContextConfig {
}
III-B. Configuration de la source de données▲
Ajouter à la classe ContextConfig la méthode dataSource qui nous permettra d'initialiser la dataSource et de créer une base de données en mémoire. La communication avec la base de données sera assurée par la classe Spring JdbcTemplate définie par la méthode jdbcTemplate.
L'annotation @Bean retourne un objet qui devrait être ajouté au contexte Spring de l'application.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
package fr.idak.tutorial.ws.config;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
@Configuration
@ComponentScan(value = {"fr.idak.tutorial.ws.repository"})
public class ContextConfig {
@Bean
public DataSource dataSource(){
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
builder.addScript("db/schema.sql");
builder.addScript("db/data.sql");
return builder.build();
}
@Bean
public JdbcTemplate jdbcTemplate(){
return new JdbcTemplate(dataSource());
}
}
La méthode dataSource utilise deux fichiers SQL, le premier pour créer le schéma de la base de données et le second pour insérer quelques données de test. Pour simplifier l'exemple, ces fichiers contiendront une seule table nommée BOOK qui sera utilisée tout au long de cet article.
drop table BOOK if exists;
create table BOOK (
BOOK_ID bigint generated by default as identity (start with 1),
TITLE varchar(145),
ISBN varchar(13),
PRICE decimal(10,2),
DT_CREATE date default CURRENT_DATE,
DT_UPDATE date,
primary key (BOOK_ID)
);insert into BOOK (TITLE, ISBN,PRICE, DT_UPDATE)
values ('Spring par la Pratique Spring 2.5 et 3.0', '9782212124217', '34.99 ','2015-01-02');
insert into BOOK (TITLE, ISBN,PRICE)
values ('Programmer en Java : Couvre les nouveautés de Java 8, streams, expressions lambda', '9782212140071', '36.00');
insert into BOOK (TITLE, ISBN,PRICE)
values ('Java Pour les Nuls, Nouvelle édition', '9782754055888','15.99');
insert into BOOK (TITLE, ISBN,PRICE)
values ('Pro Spring MVC: With Web Flow (Professional Apress)', '9781430241553', '51.05');
insert into BOOK (TITLE, ISBN,PRICE)
values ('Spring in Action', '9781617291203', '42.40');
insert into BOOK (TITLE, ISBN,PRICE)
values ('AngularJS - Développez aujourd''hui les applications web de demain', '9782746093348', '54.00');
insert into BOOK (TITLE, ISBN,PRICE)
values ('Pro AngularJS', '9781430264484','35.82');
insert into BOOK (TITLE, ISBN,PRICE)
values ('Node.js, MongoDB, and AngularJS Web Development', '9780321995780', '43.33');
insert into BOOK (TITLE, ISBN,PRICE)
values ('Mastering KnockoutJS', '9781783981007','42.18');
insert into BOOK (TITLE, ISBN,PRICE)
values ('Java Persistence with Hibernate', '9781617290459', '51.28');
insert into BOOK (TITLE, ISBN,PRICE)
values ('Java Persistence et Hibernate', '9782212122596', '81.00');III-C. Développement des couches DAO▲
Créer la classe Java pour le modèle Book, cette classe est une représentation de la table BOOK :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
package fr.idak.tutorial.ws.model;
import java.math.BigDecimal;
import java.util.Date;
public class Book {
private Long bookId;
private String isbn;
private String title;
private BigDecimal price;
private Date dtCreate;
private Date dtUpdate;
// getter et setter ...
}
Créer l'interface BookRepository :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
package fr.idak.tutorial.ws.repository;
import java.util.List;
import fr.idak.tutorial.ws.model.Book;
public interface BookRepository {
/**
* Permet de récupérer tous les enregistrements de la table BOOK
* @return Liste de Book
*/
List<Book> getAll();
/**
* Permet de rechercher un BOOK à partir de son identifiant
* @param id
* @return Book
*/
Book get(Long id);
/**
* Permet d'ajouter un nouvel enregistrement de la table BOOK
* @param book
*/
void create(Book book);
/**
*
* Permet de supprimer un BOOK
* @param book
*/
void delete(Book book);
/**
* Permet de mettre à jour un BOOK
* @param book
*/
void update(Book book);
}
Créer une nouvelle classe BookRepositoryImpl qui implémente l'interface BookRepository. Annoter la classe par @Repository pour indiquer à Spring que la classe doit être ajoutée au contexte comme étant un Bean de type repository.
L'annotation @Resource permet d'injecter une référence du Bean JdbcTemplate.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
package fr.idak.tutorial.ws.repository;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import fr.idak.tutorial.ws.model.Book;
@Repository
public class BookRepositoryImpl implements BookRepository {
@Resource
private JdbcTemplate jt;
@Override
public Book get(Long id) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<Book> getAll() {
// TODO Auto-generated method stub
return null;
}
@Override
public void create(Book article) {
// TODO Auto-generated method stub
}
@Override
public void delete(Book article) {
// TODO Auto-generated method stub
}
@Override
public void update(Book article) {
// TODO Auto-generated method stub
}
}
IV. Tests et implémentation des méthodes de la couche DAO▲
Les méthodes de la classe BookRepository ne sont pas encore implémentées, mais cela ne nous empêchera pas de tester les méthodes du Web service et de continuer à les implémenter en utilisant la technique TDD.
Pour mieux comprendre la méthode TDD, il est vivement conseillé de lire la page suivante : http://fr.wikipedia.org/wiki/Test_Driven_Development.
IV-A. Test de la couche DAO▲
Nous allons créer une nouvelle classe BookRepositoryTest qui nous permettra de tester la configuration Spring et les méthodes du la couche DAO :
- @RunWith : indique à Junit que les tests unitaires seront exécutés par la classe Spring SpringJUnit4ClassRunner ;
- @ContextConfiguration : permet de charger le contexte Spring défini dans la classe ContextConfig.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
package fr.idak.tutorial.ws.repository;
import java.util.List;
import javax.annotation.Resource;
import org.junit.Assert;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.*;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import fr.idak.tutorial.ws.config.ContextConfig;
import fr.idak.tutorial.ws.model.Book;
import fr.idak.tutorial.ws.repository.BookRepository;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={ContextConfig.class})
public class BookRepositoryTest {
@Resource
private BookRepository bookRepository;
@Test
public void getBook(){
Long id = 1L;
Book books = bookRepository.get(id);
Assert.assertNotNull(books);
Assert.assertThat(id, is(books.getBookId()));
}
@Test
public void readAll(){
List<Book> books = bookRepository.getAll();
Assert.assertNotNull(books);
Assert.assertTrue(books.size() > 0);
}
}
L'exécution de ces tests unitaires nous indique qu'ils échouent, il va falloir implémenter les méthodes de la classe BookRepositoryImpl afin que les tests unitaires passent :
IV-B. Implémentation des méthodes de la couche DAO▲
Nous allons utiliser la classe JdbcTemplate et BeanPropertyRowMapper du module Spring-jdbc de Spring pour communiquer avec la base de données.
BeanPropertyRowMapper : permet d'extraire les données de ResultSet sans implémenter un RowMapper. Pour utiliser ce Bean, les noms des attributs du modèle Book et des colonnes de la table BOOK doivent être cohérents, voire identiques (BOOK_ID -> bookId, DT_CREATE -> dtCreate).
L'implémentation des méthodes get(id) et getAll() de la classe BookRepositoryImpl est :
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
@Override
public Book get(Long id) {
String GET_ARTICLE_BY_ID = "select * from book where book_id=?";
return jt.queryForObject(GET_ARTICLE_BY_ID, BeanPropertyRowMapper.newInstance(Book.class), id) ;
}
@Override
public List<Book> getAll() {
String GET_ALL_ARTICLES = "select * from book";
return jt.query(GET_ALL_ARTICLES, BeanPropertyRowMapper.newInstance(Book.class));
}
Désormais, les tests unitaires passent, donc on peut passer à l'étape suivante.
Les autres méthodes de la DAO peuvent être implémentées de la même façon.
V. Configuration de la couche MVC▲
V-A. Configuration de Spring MVC▲
La structure du projet pour les prochaines étapes est la suivante :
Pour configurer la couche Spring MVC, nous avons besoin de créer deux nouvelles classes :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
package fr.idak.tutorial.ws.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@EnableWebMvc
@Configuration
@ComponentScan(basePackages={"fr.idak.tutorial.ws.web"})
public class WebMvcConfig extends WebMvcConfigurerAdapter{
}
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
package fr.idak.tutorial.ws.config;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class WebAppInitializer implements WebApplicationInitializer{
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext =
new AnnotationConfigWebApplicationContext();
//Déclaration de la classe de configuration
//du contexte (dataSource, repositories, spring-security …)
rootContext.register(ContextConfig.class);
servletContext.addListener(new ContextLoaderListener(rootContext));
//Création du distapcher de servlet
AnnotationConfigWebApplicationContext dispatcherServlet =
new AnnotationConfigWebApplicationContext();
dispatcherServlet.register(WebMvcConfig.class);
//Déclaration du distapcher de servlet
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher",
new DispatcherServlet(dispatcherServlet));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
V-B. Développement de la couche Contrôleur▲
Dans cette partie, nous allons exposer une série de méthodes REST standard qui permettent à des applications clientes de réaliser des opérations (CRUD) sur des bouquins. Ces méthodes seront implémentées dans une nouvelle classe BookController.
Désormais avec la version 4 de Spring, il n'y a plus besoin d'effectuer la conversion Objet en JSON et inversement. Le marshaling et le unmarshaling sont effectués grâce à l'annotation @RestController.
@RequestMapping permet d'indiquer le mapping d'URL pour lequel le contrôleur ou la méthode doit répondre :
- value : définit l'URL à traiter ;
- method : définit le type de la requête, GET dans ce cas.
@PathVariable permet de spécifier une valeur en dehors de l'URL (ex. : id) et de l'assigner aux paramètres de la méthode.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
package fr.idak.tutorial.ws.web.controller;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import fr.idak.tutorial.ws.model.Book;
import fr.idak.tutorial.ws.repository.BookRepository;
@RestController
@RequestMapping(value="/api")
public class BookController {
@Resource
private BookRepository bookRepository;
@RequestMapping(value="/book/{id}", method=RequestMethod.GET)
public Book getBook(@PathVariable Long id){
return bookRepository.get(id);
}
@RequestMapping(value="/books", method=RequestMethod.GET)
public List<Book> getBooks(){
return bookRepository.getAll();
}
}
V-C. Tests unitaires des méthodes de contrôleur▲
Nous allons créer une nouvelle classe de test BookControllerTest qui nous permettra de tester les méthodes du Contrôleur BookController.
@WebAppConfiguration : permet d'indiquer au contexte Spring que nous allons utiliser un WebApplicationContext lors d'exécution des tests. Cette annotation est nécessaire pour la configuration du Mock MVC de Spring. La classe MockMvc est initialisée dans la méthode init() à partir de la classe WebApplicationContext avant chaque test.
CheckGetBookByIdUrl() : vérifie le bon fonctionnement l'URL '/api/book/{id}' du Web service.
CheckGetBooksUrl() : vérifie le bon fonctionnement l'URL '/api/books' du Web service.
getBooks() : vérifie le nombre de bouquins par l'URL /api/books du Web service.
D'autres tests unitaires peuvent être ajoutés à la classe pour avoir une bonne couverture de code pour les méthodes du contrôleur. Pour approfondir vos connaissances en tests unitaires de la couche Web, je vous conseille de consulter la page suivante : http://spring.io/guides/tutorials/bookmarks/.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
package fr.idak.tutorial.ws.web.controller;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import fr.idak.tutorial.ws.config.ContextConfig;
import fr.idak.tutorial.ws.config.WebMvcConfig;
import fr.idak.tutorial.ws.repository.BookRepository;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {ContextConfig.class, WebMvcConfig.class})
@WebAppConfiguration
public class BookControllerTest {
@Resource
private WebApplicationContext wac;
@Resource
private BookRepository bookRepositoryMock;
private MockMvc mockMvc;
@Before
public void init() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void checkGetBookByIdUrl() throws Exception{
mockMvc.perform(MockMvcRequestBuilders.get("/api/book/1"))
.andExpect(MockMvcResultMatchers.status().isOk());
}
@Test
public void checkGetBooksUrl() throws Exception{
mockMvc.perform(MockMvcRequestBuilders.get("/api/books"))
.andExpect(MockMvcResultMatchers.status().isOk());
}
@Test
public void getBooks() throws Exception{
mockMvc.perform(MockMvcRequestBuilders.get("/api/books"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(11)));
}
}
VI. Déploiement du Web service▲
VI-A. Installation de Tomcat Sous Eclipse▲
Nous avons besoin d'installer un serveur Tomcat pour pouvoir tester le déploiement et le bon fonctionnement du Web service.
- Télécharger la version 8 de Tomcat à partir du site http://tomcat.apache.org/.
- Dézipper l'archive.
- Créer le serveur Tomcat dans Eclipse (voir http://blog.paumard.org/tutoriaux/eclipse-tomcat/).
- Ajouter le projet Web service au serveur : dans l'onglet Servers, Clic droit, puis Add and Remove…
Dans la fenêtre qui s'affichera, sélectionner le projet, puis cliquer sur le bouton Add pour l'ajouter au serveur puis sur Finish :
- Démarrer le serveur en cliquant sur la petite icône « play ».
- Dans votre navigateur, saisir http://localhost:8080/rest-ws/books.
Si la liste des books s'affiche à l'écran, la configuration du serveur est terminée.
VI-B. Installation d'un client REST pour Chrome▲
VII. Conclusion et remerciements▲
L'objectif initial de ce tutoriel était la sécurité des services Web, j'ai préféré commencer par une présentation d'un simple Web service qui sera le fil conducteur des prochains tutoriels, à savoir :
- sécurité du Web service ;
- utilisation du Web service dans webapp (Spring MVC + KnockoutJS).
Le projet rest-ws peut être importé à partir du l'URL github suivante : https://github.com/idak/idak-projects/tree/master/lambda.
Un grand merci à Mickael BARON et Régis POUILLER pour leur aide ainsi qu'à Claude LELOUP pour la relecture orthographique.


















