{"id":20365010,"url":"https://github.com/h3ar7b3a7/springbootinaction","last_synced_at":"2026-05-17T02:03:48.827Z","repository":{"id":136744862,"uuid":"314789697","full_name":"H3AR7B3A7/SpringBootInAction","owner":"H3AR7B3A7","description":"After exploring servlets and Jsp in a Maven web application and Spring MVC in a custom Maven build with spring mvc dependencies, let us go back to a Spring Boot application, set up with the initializr.","archived":false,"fork":false,"pushed_at":"2020-12-30T19:42:44.000Z","size":493,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-25T18:06:13.215Z","etag":null,"topics":["configuration","security","spring-boot"],"latest_commit_sha":null,"homepage":"","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/H3AR7B3A7.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":"2020-11-21T10:50:45.000Z","updated_at":"2020-12-30T19:42:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"cf6ea312-db36-441d-9d9c-a62e667defc2","html_url":"https://github.com/H3AR7B3A7/SpringBootInAction","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/H3AR7B3A7%2FSpringBootInAction","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/H3AR7B3A7%2FSpringBootInAction/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/H3AR7B3A7%2FSpringBootInAction/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/H3AR7B3A7%2FSpringBootInAction/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/H3AR7B3A7","download_url":"https://codeload.github.com/H3AR7B3A7/SpringBootInAction/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241904719,"owners_count":20040021,"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":["configuration","security","spring-boot"],"created_at":"2024-11-15T00:14:51.649Z","updated_at":"2025-10-28T01:01:48.317Z","avatar_url":"https://github.com/H3AR7B3A7.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spring Boot\n## Preface\nAfter exploring [servlets and Jsp](https://github.com/H3AR7B3A7/ServletsAndJsp) in a Maven web application \nand [Spring MVC](https://github.com/H3AR7B3A7/SpringMVC) in a custom Maven build with spring mvc dependencies, \nlet us go back to a Spring Boot application set up with the initializr.  \nWith a higher appreciation of what SpringBoot and the initializr do in the background for us, \nwe will have a closer look at different aspects of this rather simple application. \n\nIn the [web store](https://github.com/H3AR7B3A7/TjEnterprise-pet-store) we made before we didn't pay attention to all the possibilities because that was not in our interest then. \nThis is a good example of Spring keeping us from having to write a lot of plumbing code and providing adequate defaults. For instance when it comes to security though, Spring doesn't \nreally have any business deciding everything for us.  \nIn [spring courses](https://github.com/H3AR7B3A7/SpringCourses) and 'SpringServletStack' for [XML](https://github.com/H3AR7B3A7/SpringServletStackXml) and \n[JavaConfig](https://github.com/H3AR7B3A7/SpringServletStackCode) we already saw some concepts of configuration and security. We will explore them further in this application.\n\n### Setup\nTo start off we created a project with the initializr including these dependencies:  \n- Web\n- Thymeleaf\n- Jpa  \n- H2 (we include H2, but switch out for MySQL later)\n\n## Configuration\nWhat we need to understand about **Spring conditional configuration:** Most of the Spring default configuration beans only get created when we don't provide any of our own. We can write our own custom conditions\nin Spring by implementing the Condition interface. There are also some standard annotations to choose from like: **@ConditionalOnBean**, **@ConditionalOnMissingBean**, ...  \nCheck out some more examples [here](https://iamninad.com/conditional-bean-creation-in-spring-boot/).\n- **Overriding auto-configuration:** Because of these conditionals we can create our own configuration and Spring will automatically not create the default configuration beans.\n- **Configuration with properties:** We can also modify default behaviour of auto-configuration to some extent with properties. We can do this in different ways with descending precedence in:\n  - Command-line arguments\n  - JNDI attributes from java:comp/env\n  - JVM system properties\n  - Operating system env variables\n  - Randomly generated values dor properties prefixed with random.*  \n  (referenced when setting other properties, such as ${random.long})\n  - An application.properties (or application.yml) file outside the application\n  - An application.properties (or application.yml) packaged inside of the application\n  - Property sources specified by **@PropertySource**\n  - Default properties\n  \nApplication.properties (or application.yml) files can reside in these locations, also with descending precedence:\n- Externally, in a /config subdirectory\n- Externally, in the directory where we run the application\n- Internally, in the 'resources root' in a /config subdirectory\n- Internally, in the 'resources root' (Provided by Spring)\n \nA good rule is to use the generated file provided by Spring unless you want them to be overridden, or when you don't want to publish some sensitive information to GitHub through .gitignore.  \n\n*Although using .yml can save us some work writing out property paths and can hold multiple profiles, I do not recommend using them, so they will not be covered in this document.*\n\n### Externalizing configuration\nTo externalize the configuration of our 'amazon associate id' we add this dependency:\n\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n        \u003cartifactId\u003espring-boot-configuration-processor\u003c/artifactId\u003e\n        \u003coptional\u003etrue\u003c/optional\u003e\n    \u003c/dependency\u003e\n    \nThis way we can keep our configurations in one place and easily change them later when necessary. \nWe set the value in the controller by using the annotation **@ConfigurationProperties(prefix=\"amazon\")** \nand providing a setter:\n\n    public void setAssociateId(String associateId) {this.associateId = associateId;}\n\nNow we can easily see/change the value in application.properties with:\n\n    amazon.associateId=someAssociateID\n    \n### Capturing configuration in a bean\nInstead of annotating the controller and having the setter in there, we could just create a bean for that and then wire in the bean. \nThis way we can isolate the configuration related to Amazon from the controller.\n\n## Configuring with profiles\nWe can specify environments with annotation in our configuration classes with **@Profile(\"production\")**. \nThis way we can choose a profile in applications.properties by specifying the property: \n\n    spring.profiles.active=production\n\n### Profile specific properties files\nWe can have profile specific properties files by using naming them using the pattern:  \n**application-{profile}.properties**  \nFor instance, we can have different logging levels for different environments:  \n\n    logging.level.root=DEBUG / WARN / INFO \n    \nIn IntelliJ we can specify the active profiles under *'Edit configurations...'*.  \nWe can still have a default properties file to hold properties that aren't profile specific when we specified active profiles.\n\n## Configuring SSL/TLS certificate with keystore\nCommand line example:\n\n    keytool -genkeypair -alias spring-https -keyalg RSA -keysize 2048 -keystore spring-https.jks -validity 365\n\nConverting jks to PKCS12 format:\n\n    keytool -importkeystore -srckeystore spring-https.jks -destkeystore spring-https.jks -deststoretype pkcs12\n    \nService will now be served at https://localhost:8443/\nWhile serving locally the browser will complain it is 'not safe', but that's nothing to worry about.\n\n## Logging\nLogback is the standard provided by spring-boot-starter-logging. Other options are 'Log4j' or 'Log4j2'. We could exclude Logback and provide dependencies for them instead, \nbut there is usually no need to do so.  \nFor full control over logging we could add a 'logback.xml'.\n[Documentation](http://logback.qos.ch/documentation.html)\n\n## Custom error handling\nThe default error handler that’s auto-configured by Spring Boot looks for a view\nnamed *'error'*. If it can’t find one, it uses its default whitelabel error view.\n\nThis means we can just add a file *error.html* to easily create a custom error page.\nOn this error page we can refer to the status, url path and the generated error with:  \n\n    ${status}, ${path} and ${error}\n\n## Security\nWe add Spring security by simply adding the following dependency:\n\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n        \u003cartifactId\u003espring-boot-starter-security\u003c/artifactId\u003e\n    \u003c/dependency\u003e\n\nPrior to Spring Security 5.0 the default PasswordEncoder was NoOpPasswordEncoder which required plain text passwords. \nIn Spring Security 5, the default is DelegatingPasswordEncoder, which required Password Storage Format.  \n\nWe can still use the old way by adding a prefix to our password like this:\n\n    insert into Reader (username, password, fullname) values ('test', '{noop}test', 'test');\n\nLater when creating users with a form we will want to use a User Builder with default password encoder.\n\nCheck [here](https://github.com/H3AR7B3A7/SpringCourses/tree/master/security) for a more advanced example of security.\nThere we saw how to generate CSRF-tokens, use password encoders, create custom authorities and more...\n\n## Testing Spring Boot applications\n*I will be documenting testing mainly using JUnit 5 Jupiter. For reference, I will add the JUnit 4 variants of annotations \nbetween square brackets. Be aware they can't always just be switched out, so you might have to check some documentation on their use.*\n\nBecause Spring already provides us with the dependency *spring-boot-starter-test* our project already includes a lot of dependencies for testing purposes:\n- **JUnit:** The de-facto standard for unit testing Java applications\n- **Spring (Boot) Test:** Utilities and integration test support for Spring (Boot) applications\n- **AssertJ:** A fluent assertion library\n- **Hamcrest:** A library of matcher objects (also known as constraints or predicates)\n- **Mockito:** A Java mocking framework\n- **JSONassert:** An assertion library for JSON\n- **JsonPath:** XPath for JSON\n\n### Mock MVC\nTo configure MockMVC we need a WebApplicationContext. We can wire this in and configure MockMVC ourselves like this:\n\n    @Autowired\n    private WebApplicationContext context;\n        \n    private MockMvc mockMvc;\n    \n    @BeforeEach\n    void setMockMvc() {\n        mockMvc = MockMvcBuilders\n                .webAppContextSetup(context)\n                .apply(springSecurity())\n                .build();\n    }\n    \nWe can also accomplish this with an annotation **@AutoConfigureMockMvc**\n\nWhen we configure MockMVC ourselves however, we can choose to only setup the controllers we need:\n- standaloneSetup()\n- webAppContextSetup()\n\n### Testing with security\nBecause we make use of Spring Security we need the following dependency:\n\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.springframework.security\u003c/groupId\u003e\n        \u003cartifactId\u003espring-security-test\u003c/artifactId\u003e\n        \u003cscope\u003etest\u003c/scope\u003e\n    \u003c/dependency\u003e\n\nNow we can simply annotate our test with **@WithUserDetails(value = \"test\")** to authenticate as the user named: *test*.\nThere is also a parameter *userDetailsServiceBeanName* with a default value of \"myUserDetailsService\" hidden in this annotation.  \n\nWe have to use **@WithUserDetails** in our application because we use our custom *'Reader'* class for authentication, \nbut when we use the default User class for authentication **@WithMockUser** is the easy option.\n\n    @Test\n    @WithMockUser(username=\"someName\",\n                  password=\"optional\",\n                  roles=\"READER\")\n    public void someTest() throws Exception {...}\n\n### Integration Test Environment\nWith the **@SpringBootTest** annotation, Spring Boot provides a convenient way to start up an application context to be used in a test.  \n\nWe can use the H2 database we used at the beginning of the project when we are running integration setting the scope to 'test':\n\n    \u003cdependency\u003e\n        \u003cgroupId\u003ecom.h2database\u003c/groupId\u003e\n        \u003cartifactId\u003eh2\u003c/artifactId\u003e\n        \u003cscope\u003etest\u003c/scope\u003e\n    \u003c/dependency\u003e\n\n\nTo enable Spring support for integration testing we annotate the class with **@ExtendWith(SpringExtension.class)**  \n[ **@RunWith(SpringJUnit4ClassRunner.class)** or shortened **@RunWith(SpringRunner.class)** ]  \n\nAs of Spring Boot 2.1, we no longer need to load the SpringExtension because it's included as a meta annotation in the Spring Boot test annotations like **@DataJpaTest**, **@WebMvcTest**, and **@SpringBootTest**.  \n\nI will be diving deeper into testing Spring Boot applications in one of my next projects...","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fh3ar7b3a7%2Fspringbootinaction","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fh3ar7b3a7%2Fspringbootinaction","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fh3ar7b3a7%2Fspringbootinaction/lists"}