An open API service indexing awesome lists of open source software.

https://github.com/cedlemo/spring-boot-gradle-notes

Mes notes sur la creation d'une simple application spring boot avec gradle
https://github.com/cedlemo/spring-boot-gradle-notes

Last synced: about 1 year ago
JSON representation

Mes notes sur la creation d'une simple application spring boot avec gradle

Awesome Lists containing this project

README

          

# Introduction à spring boot + gradle

## Initialisation
Notes et traduction de https://spring.io/guides/gs/spring-boot/#scratch

* Initialisation du wrapper gradle:

```
gradle wrapper --gradle-version 4.8.1
```

* Creation de l'arborescence du projet:

```
mkdir -p src/main/java/hello
```

* src/main/java/hello/HelloControler.java

## Création d'une simple application web.

### Génération d'un contrôleur.

* src/main/java/hello/HelloController.java

```java
package hello;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
public class HelloController {

@RequestMapping("/")
public String index() {
return "Greetins from Spring Boot!";
}
}
```
L'annotation `@RestController` associée à cette classe fait que cette
dernière est prête à être utilisé par Spring MVC pour répondre à
des requêtes web.

`@RequestMapping` lie l'url `/` à la méthode `index` de la classe. Tout
accès à cette méthode par un navigateur ou autre, une chaine de caractère
simple est retournée. Cela s'explique par le fait que `@RestController`
combine les annoations `@Controller` et `@ResponseBody` ce qui fait que des données sont retournées plutôt que des vues en réponse à une
requête web.

### Création d'une classe Application

* src/main/java/hello/Application.java

```java
package hello;

import java.util.Arrays;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for(String beanName : beanNames) {
System.out.println(beanName);
}
};
}
}
```

L'annotation `@SpringBootApplication` est un raccourci pour les 3 annotations suivantes:
* `@Configuration` : definie la classe comme étant la source de definitions de *bean* pour le contexte de l'application.
* `@EnableAutoConfiguration` : spécifie à Spring Boot d'ajouter des *beans* et des propriétés de configuration.
* `@EnableWebMvc`: normalement on devrait l'ajouter, mais Spring Boot le
fait automatiquement quand il détecte **spring-webmvc** dans le classpath (chemin d'accès aux classes et packages). Cela marque l'application comme étant une application web et de ce fait active des comportements clefs tels que l'activation de `DispatcherServlet`.
* `@ComponentScan` pousse Spring à chercher d'autres composants, configurations et services dans le package `hello` lui permettant de trouver les contrôleurs.

La méthode `main()` utilise `SpringApplication.run()` de Spring Boot pour lancer l'application. Il n'y a pas de fichier de configuration **web.xml**. C'est une application 100% en java.

La méthode `commandLineRunner` marquée par l'annotation `@Bean` est exécutée au démarrage. Elle retrouve tous les *beans* créés par notre application ou automatiquement ajoutés par Spring Boot et les affiche.

### Lancement de l'application.

#### Création du gradle.build file

```groovy
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.3.RELEASE")
}
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

bootJar {
baseName = 'gs-spring-boot'
version = '0.1.0'
}

repositories {
mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("junit:junit")
}
```

* block `buildscript`: ce block controle les dépendances pour le
le script de génération en lui-même et mais pas les dépendances de l'application qui sont gérées par les deux blocks `repositories` et
`dependencies`.

#### Construction et lancement.

```bash
./gradlew build
java -jar build/libs/gs-spring-boot-0.1.0.jar
```

Voici ce que renvoie l'application à partir du momment ou est lancé
la méthode `commandLineRunner` :

```
let's inspect the beans provided by Spring Boot:
application
basicErrorController
beanNameHandlerMapping
beanNameViewResolver
characterEncodingFilter
commandLineRunner
conventionErrorViewResolver
defaultServletHandlerMapping
defaultValidator
defaultViewResolver
dispatcherServlet
dispatcherServletRegistration
error
errorAttributes
errorPageCustomizer
errorPageRegistrarBeanPostProcessor
faviconHandlerMapping
faviconRequestHandler
handlerExceptionResolver
helloController
hiddenHttpMethodFilter
httpPutFormContentFilter
httpRequestHandlerAdapter
jacksonCodecCustomizer
jacksonObjectMapper
jacksonObjectMapperBuilder
jsonComponentModule
localeCharsetMappingsCustomizer
mainDispatcherServletPathProvider
mappingJackson2HttpMessageConverter
mbeanExporter
mbeanServer
messageConverters
methodValidationPostProcessor
multipartConfigElement
multipartResolver
mvcContentNegotiationManager
mvcConversionService
mvcHandlerMappingIntrospector
mvcPathMatcher
mvcResourceUrlProvider
mvcUriComponentsContributor
mvcUrlPathHelper
mvcValidator
mvcViewResolver
objectNamingStrategy
org.springframework.boot.autoconfigure.AutoConfigurationPackages
org.springframework.boot.autoconfigure.condition.BeanTypeRegistry
org.springframework.boot.autoconfigure.context.ConfigurationProperConfiguration
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration
org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration
org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration$JacksonCodecConfiguration
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$ParameterNamesModuleConfiguration
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration
rg.springframework.boot.autoconfigure.validation.ValidationAutoCoion
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration$TomcatWebServerFactoryCustomizerConfiguration
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletConfiguration
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter$FaviconConfiguration
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcA[37/817]guration
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration$TomcatWebSocketConfiguration
org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.event.internalEventListenerFactory
org.springframework.context.event.internalEventListenerProcessor
parameterNamesModule
preserveErrorControllerTargetClassPostProcessor
propertySourcesPlaceholderConfigurer
requestContextFilter
requestMappingHandlerAdapter
requestMappingHandlerMapping
resourceHandlerMapping
restTemplateBuilder
spring.jackson-org.springframework.boot.autoconfigure.jackson.JacksonProperties
spring.mvc-org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties
spring.resources-org.springframework.boot.autoconfigure.web.ResourceProperties
spring.security-org.springframework.boot.autoconfigure.security.SecurityProperties
spring.servlet.multipart-org.springframework.boot.autoconfigure.web.servlet.MultipartProperties
standardJacksonObjectMapperBuilderCustomizer
stringHttpMessageConverter
tomcatServletWebServerFactory
tomcatServletWebServerFactoryCustomizer
tomcatWebServerFactoryCustomizer
viewControllerHandlerMapping
viewResolver
webServerFactoryCustomizerBeanPostProcessor
websocketContainerCustomizer
welcomePageHandlerMapping
```

On peut voir au début les beans `org.springframework.boot.autoconfigure` ainsi que les beans liés à *Tomcat* et ceux liés aux *webservlets*.

Dans un autre terminal, on peut se connecter au service lancé pour voir ce qu'il nous renvoie.

```
$ curl localhost:8080
Greetings from Spring Boot!
```

### Ajout de tests unitaires.
* ajout d'une instruction de test dans *build.gradle.*:

```groovy
testCompile("org.springframework.boot:spring-boot-starter-test")
```

* Test et simulation (mockage) de requete HTTP.

* src/test/java/hello/HelloControllerTest.java

```java
package hello;

import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {

@Autowired
private MockMvc mvc;

@Test
public void getHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("Greetings from Spring Boot!")));
}
}
```

`MockMvc` est fourni par Spring Test et permet, grâce à des classes très pratiques, d'envoyer des requêtes HTTP dans `DispatcherServlet` et de tester le résultat.
On notera l'utilisation conjointe des annotations `@AutoConfigureMockMvc` et `@SpringBootTest` qui injecte une instance de `@MockMvc`.

L'utilisation de `@SpringBootTest` dit à Spring que l'on veut que soit créé le contexte de l'application dans son intégralité. En effet on aurait put demander seulement le contexte de la couche web avec l'annotation `@WebMvcTest`.

Spring boot va essayer de trouver la classe principale de l'application mais il est tout à fait possible de personnaliser ce comportement.

* Simple test d'integration fullstack:

* src/test/java/hello/HelloControllerIT.java

```java
package hello;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

import java.net.URL;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerIT {

@LocalServerPort
private int port;

private URL base;

@Autowired
private TestRestTemplate template;

@Before
public void setUp() throws Exception {
this.base = new URL("http://localhost:" + port + "/");
}

@Test
public void getHello() throws Exception {
ResponseEntity response = template.getForEntity(base.toString(),
String.class);
assertThat(response.getBody(), equalTo("Greetings from Spring Boot!"));
}
```

On pourra lancer les tests avec:

```
./gradlew test
```

Le rapport de test pourra être consulté via le fichier :
build/reports/tests/test/classes/hello.HelloControllerIT.html