{"id":15724277,"url":"https://github.com/cedlemo/spring-boot-gradle-notes","last_synced_at":"2025-03-31T01:14:15.548Z","repository":{"id":144940308,"uuid":"141007134","full_name":"cedlemo/spring-boot-gradle-notes","owner":"cedlemo","description":"Mes notes sur la creation d'une simple application spring boot avec gradle","archived":false,"fork":false,"pushed_at":"2018-07-15T08:32:37.000Z","size":89,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-06T06:24:10.177Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cedlemo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-15T07:25:33.000Z","updated_at":"2018-07-15T08:32:38.000Z","dependencies_parsed_at":"2023-04-04T21:03:06.452Z","dependency_job_id":null,"html_url":"https://github.com/cedlemo/spring-boot-gradle-notes","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedlemo%2Fspring-boot-gradle-notes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedlemo%2Fspring-boot-gradle-notes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedlemo%2Fspring-boot-gradle-notes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedlemo%2Fspring-boot-gradle-notes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cedlemo","download_url":"https://codeload.github.com/cedlemo/spring-boot-gradle-notes/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246399798,"owners_count":20770908,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-03T22:15:59.029Z","updated_at":"2025-03-31T01:14:15.530Z","avatar_url":"https://github.com/cedlemo.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Introduction à spring boot + gradle\n\n## Initialisation\nNotes et traduction de https://spring.io/guides/gs/spring-boot/#scratch\n\n* Initialisation du wrapper gradle:\n\n```\ngradle wrapper --gradle-version 4.8.1\n```\n\n* Creation de l'arborescence du projet:\n\n```\nmkdir -p src/main/java/hello\n```\n\n* src/main/java/hello/HelloControler.java\n\n## Création d'une simple application web.\n\n### Génération d'un contrôleur.\n\n* src/main/java/hello/HelloController.java\n\n```java\npackage hello;\n\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\n@RestController\npublic class HelloController {\n\n    @RequestMapping(\"/\")\n    public String index() {\n        return \"Greetins from Spring Boot!\";\n    }\n}\n```\nL'annotation `@RestController` associée à cette classe fait que cette\ndernière est prête à être utilisé par Spring MVC pour répondre à\ndes requêtes web.\n\n`@RequestMapping` lie l'url `/` à la méthode `index` de la classe. Tout\naccès à cette méthode par un navigateur ou autre, une chaine de caractère\nsimple est retournée. Cela s'explique par le fait que `@RestController`\n 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\n requête web.\n\n### Création d'une classe Application\n\n* src/main/java/hello/Application.java\n\n```java\npackage hello;\n\nimport java.util.Arrays;\n\nimport org.springframework.boot.CommandLineRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.Bean;\n\n@SpringBootApplication\npublic class Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Application.class, args);\n    }\n\n    @Bean\n    public CommandLineRunner commandLineRunner(ApplicationContext ctx) {\n        return args -\u003e {\n            System.out.println(\"Let's inspect the beans provided by Spring Boot:\");\n            String[] beanNames = ctx.getBeanDefinitionNames();\n            Arrays.sort(beanNames);\n            for(String beanName : beanNames) {\n                System.out.println(beanName);\n            }\n        };\n    }\n}\n```\n\nL'annotation `@SpringBootApplication` est un raccourci pour les 3 annotations suivantes:\n* `@Configuration` : definie la classe comme étant la source de definitions de *bean* pour le contexte de l'application.\n* `@EnableAutoConfiguration` : spécifie à Spring Boot d'ajouter des *beans* et des propriétés de configuration.\n* `@EnableWebMvc`: normalement on devrait l'ajouter, mais Spring Boot le\nfait 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`.\n* `@ComponentScan` pousse Spring à chercher d'autres composants, configurations et services dans le package `hello` lui permettant de trouver les contrôleurs.\n\nLa 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.\n\nLa 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.\n\n### Lancement de l'application.\n\n#### Création du gradle.build file\n\n```groovy\nbuildscript {\n    repositories {\n        mavenCentral()\n    }\n    dependencies {\n        classpath(\"org.springframework.boot:spring-boot-gradle-plugin:2.0.3.RELEASE\")\n    }\n}\n\napply plugin: 'java'\napply plugin: 'eclipse'\napply plugin: 'idea'\napply plugin: 'org.springframework.boot'\napply plugin: 'io.spring.dependency-management'\n\nbootJar {\n    baseName = 'gs-spring-boot'\n    version =  '0.1.0'\n}\n\nrepositories {\n    mavenCentral()\n}\n\nsourceCompatibility = 1.8\ntargetCompatibility = 1.8\n\ndependencies {\n    compile(\"org.springframework.boot:spring-boot-starter-web\")\n    testCompile(\"junit:junit\")\n}\n```\n\n* block `buildscript`: ce block controle les dépendances pour le\nle 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\n`dependencies`.\n\n#### Construction et lancement.\n\n```bash\n./gradlew build\njava -jar build/libs/gs-spring-boot-0.1.0.jar\n```\n\nVoici ce que renvoie l'application à partir du momment ou est lancé\nla méthode `commandLineRunner` :\n\n```\nlet's inspect the beans provided by Spring Boot:\napplication\nbasicErrorController\nbeanNameHandlerMapping\nbeanNameViewResolver\ncharacterEncodingFilter\ncommandLineRunner\nconventionErrorViewResolver\ndefaultServletHandlerMapping\ndefaultValidator\ndefaultViewResolver\ndispatcherServlet\ndispatcherServletRegistration\nerror\nerrorAttributes\nerrorPageCustomizer\nerrorPageRegistrarBeanPostProcessor\nfaviconHandlerMapping\nfaviconRequestHandler\nhandlerExceptionResolver\nhelloController\nhiddenHttpMethodFilter\nhttpPutFormContentFilter\nhttpRequestHandlerAdapter\njacksonCodecCustomizer\njacksonObjectMapper\njacksonObjectMapperBuilder\njsonComponentModule\nlocaleCharsetMappingsCustomizer\nmainDispatcherServletPathProvider\nmappingJackson2HttpMessageConverter\nmbeanExporter\nmbeanServer\nmessageConverters\nmethodValidationPostProcessor\nmultipartConfigElement\nmultipartResolver\nmvcContentNegotiationManager\nmvcConversionService\nmvcHandlerMappingIntrospector\nmvcPathMatcher\nmvcResourceUrlProvider\nmvcUriComponentsContributor\nmvcUrlPathHelper\nmvcValidator\nmvcViewResolver\nobjectNamingStrategy\norg.springframework.boot.autoconfigure.AutoConfigurationPackages\norg.springframework.boot.autoconfigure.condition.BeanTypeRegistry\norg.springframework.boot.autoconfigure.context.ConfigurationProperConfiguration\norg.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration\norg.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration\norg.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration\norg.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration\norg.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration\norg.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration\norg.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration$JacksonCodecConfiguration\norg.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration\norg.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory\norg.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration\norg.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration\norg.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration\norg.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration\norg.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$ParameterNamesModuleConfiguration\norg.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration\norg.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration\nrg.springframework.boot.autoconfigure.validation.ValidationAutoCoion\norg.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration\norg.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration\norg.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration$TomcatWebServerFactoryCustomizerConfiguration\norg.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration\norg.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletConfiguration\norg.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration\norg.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration\norg.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration\norg.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration\norg.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat\norg.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration\norg.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration\norg.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter\norg.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter$FaviconConfiguration\norg.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcA[37/817]guration\norg.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration\norg.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration\norg.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration\norg.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration$TomcatWebSocketConfiguration\norg.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata\norg.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor\norg.springframework.context.annotation.internalAutowiredAnnotationProcessor\norg.springframework.context.annotation.internalCommonAnnotationProcessor\norg.springframework.context.annotation.internalConfigurationAnnotationProcessor\norg.springframework.context.annotation.internalRequiredAnnotationProcessor\norg.springframework.context.event.internalEventListenerFactory\norg.springframework.context.event.internalEventListenerProcessor\nparameterNamesModule\npreserveErrorControllerTargetClassPostProcessor\npropertySourcesPlaceholderConfigurer\nrequestContextFilter\nrequestMappingHandlerAdapter\nrequestMappingHandlerMapping\nresourceHandlerMapping\nrestTemplateBuilder\nspring.jackson-org.springframework.boot.autoconfigure.jackson.JacksonProperties\nspring.mvc-org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties\nspring.resources-org.springframework.boot.autoconfigure.web.ResourceProperties\nspring.security-org.springframework.boot.autoconfigure.security.SecurityProperties\nspring.servlet.multipart-org.springframework.boot.autoconfigure.web.servlet.MultipartProperties\nstandardJacksonObjectMapperBuilderCustomizer\nstringHttpMessageConverter\ntomcatServletWebServerFactory\ntomcatServletWebServerFactoryCustomizer\ntomcatWebServerFactoryCustomizer\nviewControllerHandlerMapping\nviewResolver\nwebServerFactoryCustomizerBeanPostProcessor\nwebsocketContainerCustomizer\nwelcomePageHandlerMapping\n```\n\nOn peut voir au début les beans `org.springframework.boot.autoconfigure` ainsi que les beans liés à *Tomcat* et ceux liés aux *webservlets*.\n\nDans un autre terminal, on peut se connecter au service lancé pour voir ce qu'il nous renvoie.\n\n```\n$ curl localhost:8080\nGreetings from Spring Boot!\n```\n\n### Ajout de tests unitaires.\n* ajout d'une instruction de test dans *build.gradle.*:\n\n```groovy\ntestCompile(\"org.springframework.boot:spring-boot-starter-test\")\n```\n\n* Test et simulation (mockage) de requete HTTP.\n\n  *  src/test/java/hello/HelloControllerTest.java\n\n```java\npackage hello;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.http.MediaType;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest\n@AutoConfigureMockMvc\npublic class HelloControllerTest {\n\n    @Autowired\n    private MockMvc mvc;\n\n    @Test\n    public void getHello() throws Exception {\n        mvc.perform(MockMvcRequestBuilders.get(\"/\").accept(MediaType.APPLICATION_JSON))\n                .andExpect(status().isOk())\n                .andExpect(content().string(equalTo(\"Greetings from Spring Boot!\")));\n    }\n}\n```\n\n`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.\nOn notera l'utilisation conjointe des annotations `@AutoConfigureMockMvc` et `@SpringBootTest` qui injecte une instance de `@MockMvc`.\n\nL'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`.\n\nSpring boot va essayer de trouver la classe principale de l'application mais il est tout à fait possible de personnaliser ce comportement.\n\n* Simple test d'integration fullstack:\n\n    * src/test/java/hello/HelloControllerIT.java\n\n```java\npackage hello;\n\nimport static org.hamcrest.Matchers.*;\nimport static org.junit.Assert.*;\n\nimport java.net.URL;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.web.client.TestRestTemplate;\nimport org.springframework.boot.web.server.LocalServerPort;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\npublic class HelloControllerIT {\n\n    @LocalServerPort\n    private int port;\n\n    private URL base;\n\n    @Autowired\n    private TestRestTemplate template;\n\n    @Before\n    public void setUp() throws Exception {\n        this.base = new URL(\"http://localhost:\" + port + \"/\");\n    }\n\n    @Test\n    public void getHello() throws Exception {\n        ResponseEntity\u003cString\u003e response = template.getForEntity(base.toString(),\n                String.class);\n        assertThat(response.getBody(), equalTo(\"Greetings from Spring Boot!\"));\n    }\n```\n\nOn pourra lancer les tests avec:\n\n```\n./gradlew test\n```\n\nLe rapport de test pourra être consulté via le fichier :\nbuild/reports/tests/test/classes/hello.HelloControllerIT.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcedlemo%2Fspring-boot-gradle-notes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcedlemo%2Fspring-boot-gradle-notes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcedlemo%2Fspring-boot-gradle-notes/lists"}