Merge branch 'master' into BAEL-20858-move-spring-boot-camel

This commit is contained in:
Loredana Crusoveanu
2020-01-30 21:57:32 +02:00
committed by GitHub
206 changed files with 1645 additions and 884 deletions

View File

@@ -14,10 +14,18 @@
</parent>
<modules>
<module>spring-boot-admin</module>
<module>spring-boot-artifacts</module>
<module>spring-boot-autoconfiguration</module>
<module>spring-boot-camel</module>
<module>spring-boot-custom-starter</module>
<module>spring-boot-data</module>
<!-- <module>spring-boot-gradle</module> --> <!-- Not a maven project -->
<module>spring-boot-keycloak</module>
<module>spring-boot-mvc-birt</module>
<module>spring-boot-performance</module>
<module>spring-boot-properties</module>
<module>spring-boot-springdoc</module>
<module>spring-boot-testing</module>
<module>spring-boot-vue</module>
</modules>

View File

@@ -0,0 +1,27 @@
## Spring Boot Admin
This module contains articles about Spring Boot Admin
## 1. Spring Boot Admin Server
* mvn clean install
* mvn spring-boot:run
* starts on port 8080
* login with admin/admin
* to activate mail notifications uncomment the starter mail dependency
and the mail configuration from application.properties
* add some real credentials if you want the app to send emails
* to activate Hipchat notifications proceed same as for email
## 2. Spring Boot App Client
* mvn clean install
* mvn spring-boot:run
* starts on port 8081
* basic auth client/client
### Relevant Articles:
- [A Guide to Spring Boot Admin](https://www.baeldung.com/spring-boot-admin)
- [Changing the Logging Level at the Runtime for a Spring Boot Application](https://www.baeldung.com/spring-boot-changing-log-level-at-runtime)

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-admin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-admin</name>
<packaging>pom</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
</parent>
<modules>
<module>spring-boot-admin-server</module>
<module>spring-boot-admin-client</module>
</modules>
<properties>
<spring-boot.version>2.1.9.RELEASE</spring-boot.version>
</properties>
</project>

View File

@@ -0,0 +1,24 @@
target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-admin-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-admin-client</name>
<packaging>jar</packaging>
<description>Spring Boot Admin Client</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>spring-boot-admin</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring-boot-admin-starter-client.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<spring-boot-admin-starter-client.version>2.1.6</spring-boot-admin-starter-client.version>
<spring-boot-maven-plugin.version>2.0.4.RELEASE</spring-boot-maven-plugin.version>
</properties>
</project>

View File

@@ -0,0 +1,12 @@
package com.baeldung.springbootadminclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootAdminClientApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAdminClientApplication.class, args);
}
}

View File

@@ -0,0 +1,20 @@
#basic auth creddentials
spring.security.user.name=client
spring.security.user.password=client
#configs to connect to a secured server
spring.boot.admin.client.url=http://localhost:8080
#spring.boot.admin.client.instance.service-base-url=http://localhost:8081
spring.boot.admin.client.username=admin
spring.boot.admin.client.password=admin
#configs to give secured server info
spring.boot.admin.client.instance.metadata.user.name=${spring.security.user.name}
spring.boot.admin.client.instance.metadata.user.password=${spring.security.user.password}
#app config
spring.application.name=spring-boot-admin-client
server.port=8081
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<jmxConfigurator />
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date [%thread] %-5level %logger{25} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>

View File

@@ -0,0 +1,55 @@
package com.baeldung.springbootadminclient;
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.core.env.Environment;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.junit.Assert.assertEquals;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
public class SpringBootAdminClientApplicationIntegrationTest {
@Autowired Environment environment;
@Autowired WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = MockMvcBuilders
.webAppContextSetup(wac)
.build();
}
@Test
public void whenEnvironmentAvailable_ThenAdminServerPropertiesExist() {
assertEquals(environment.getProperty("spring.boot.admin.client.url"), "http://localhost:8080");
assertEquals(environment.getProperty("spring.boot.admin.client.username"), "admin");
assertEquals(environment.getProperty("spring.boot.admin.client.password"), "admin");
}
@Test
public void whenHttpBasicAttempted_ThenSuccess() throws Exception {
mockMvc.perform(get("/actuator/env").with(httpBasic("client", "client")));
}
@Test
public void whenInvalidHttpBasicAttempted_ThenUnauthorized() throws Exception {
mockMvc
.perform(get("/actuator/env").with(httpBasic("client", "invalid")))
.andExpect(unauthenticated());
}
}

View File

@@ -0,0 +1,17 @@
package org.baeldung;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.springbootadminclient.SpringBootAdminClientApplication;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootAdminClientApplication.class)
public class SpringContextTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}

View File

@@ -0,0 +1,24 @@
target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-admin-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-admin-server</name>
<description>Spring Boot Admin Server</description>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>spring-boot-admin</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- dependencies used to enable admin server and UI -->
<!-- https://mvnrepository.com/artifact/de.codecentric/spring-boot-admin-starter-server -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>${spring-boot-admin-server.version}</version>
</dependency>
<!--Add login page and logout feature -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-ui-login</artifactId>
<version>${spring-boot-admin-server-ui-login.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
</dependency>
<!--declare the admin server as a client, for self monitoring -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring-boot-admin-starter-client.version}</version>
</dependency>
<!--mail notifications -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot-maven-plugin.version}</version>
</plugin>
</plugins>
</build>
<properties>
<spring-boot-admin-server.version>2.1.6</spring-boot-admin-server.version>
<spring-boot-admin-starter-client.version>2.1.6</spring-boot-admin-starter-client.version>
<spring-boot-admin-server-ui-login.version>1.5.7</spring-boot-admin-server-ui-login.version>
<spring-boot-maven-plugin.version>2.0.4.RELEASE</spring-boot-maven-plugin.version>
</properties>
</project>

View File

@@ -0,0 +1,14 @@
package com.baeldung.springbootadminserver;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@EnableAdminServer
@SpringBootApplication
public class SpringBootAdminServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAdminServerApplication.class, args);
}
}

View File

@@ -0,0 +1,47 @@
package com.baeldung.springbootadminserver.configs;
import com.hazelcast.config.Config;
import com.hazelcast.config.EvictionPolicy;
import com.hazelcast.config.InMemoryFormat;
import com.hazelcast.config.MapConfig;
import com.hazelcast.config.MergePolicyConfig;
import com.hazelcast.config.TcpIpConfig;
import com.hazelcast.map.merge.PutIfAbsentMapMergePolicy;
import java.util.Collections;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HazelcastConfig {
@Bean
public Config hazelcast() {
MapConfig eventStoreMap = new MapConfig("spring-boot-admin-event-store").setInMemoryFormat(InMemoryFormat.OBJECT)
.setBackupCount(1)
.setEvictionPolicy(EvictionPolicy.NONE)
.setMergePolicyConfig(new MergePolicyConfig(PutIfAbsentMapMergePolicy.class.getName(), 100));
MapConfig sentNotificationsMap = new MapConfig("spring-boot-admin-application-store").setInMemoryFormat(InMemoryFormat.OBJECT)
.setBackupCount(1)
.setEvictionPolicy(EvictionPolicy.LRU)
.setMergePolicyConfig(new MergePolicyConfig(PutIfAbsentMapMergePolicy.class.getName(), 100));
Config config = new Config();
config.addMapConfig(eventStoreMap);
config.addMapConfig(sentNotificationsMap);
config.setProperty("hazelcast.jmx", "true");
config.getNetworkConfig()
.getJoin()
.getMulticastConfig()
.setEnabled(false);
TcpIpConfig tcpIpConfig = config.getNetworkConfig()
.getJoin()
.getTcpIpConfig();
tcpIpConfig.setEnabled(true);
tcpIpConfig.setMembers(Collections.singletonList("127.0.0.1"));
return config;
}
}

View File

@@ -0,0 +1,48 @@
package com.baeldung.springbootadminserver.configs;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;
import de.codecentric.boot.admin.server.notify.CompositeNotifier;
import de.codecentric.boot.admin.server.notify.LoggingNotifier;
import de.codecentric.boot.admin.server.notify.Notifier;
import de.codecentric.boot.admin.server.notify.RemindingNotifier;
import de.codecentric.boot.admin.server.notify.filter.FilteringNotifier;
@Configuration
public class NotifierConfiguration {
private final InstanceRepository repository;
private final ObjectProvider<List<Notifier>> otherNotifiers;
public NotifierConfiguration(InstanceRepository repository, ObjectProvider<List<Notifier>> otherNotifiers) {
this.repository = repository;
this.otherNotifiers = otherNotifiers;
}
@Bean
public FilteringNotifier filteringNotifier() {
CompositeNotifier delegate = new CompositeNotifier(this.otherNotifiers.getIfAvailable(Collections::emptyList));
return new FilteringNotifier(delegate, this.repository);
}
@Bean
public LoggingNotifier notifier() {
return new LoggingNotifier(repository);
}
@Primary
@Bean(initMethod = "start", destroyMethod = "stop")
public RemindingNotifier remindingNotifier() {
RemindingNotifier remindingNotifier = new RemindingNotifier(filteringNotifier(), repository);
remindingNotifier.setReminderPeriod(Duration.ofMinutes(5));
remindingNotifier.setCheckReminderInverval(Duration.ofSeconds(60));
return remindingNotifier;
}
}

View File

@@ -0,0 +1,58 @@
package com.baeldung.springbootadminserver.configs;
import java.util.UUID;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import de.codecentric.boot.admin.server.config.AdminServerProperties;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final AdminServerProperties adminServer;
public WebSecurityConfig(AdminServerProperties adminServer) {
this.adminServer = adminServer;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
successHandler.setDefaultTargetUrl(this.adminServer.getContextPath() + "/");
http.authorizeRequests()
.antMatchers(this.adminServer.getContextPath() + "/assets/**")
.permitAll()
.antMatchers(this.adminServer.getContextPath() + "/login")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage(this.adminServer.getContextPath() + "/login")
.successHandler(successHandler)
.and()
.logout()
.logoutUrl(this.adminServer.getContextPath() + "/logout")
.and()
.httpBasic()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringRequestMatchers(new AntPathRequestMatcher(this.adminServer.getContextPath() + "/instances", HttpMethod.POST.toString()), new AntPathRequestMatcher(this.adminServer.getContextPath() + "/instances/*", HttpMethod.DELETE.toString()),
new AntPathRequestMatcher(this.adminServer.getContextPath() + "/actuator/**"))
.and()
.rememberMe()
.key(UUID.randomUUID()
.toString())
.tokenValiditySeconds(1209600);
}
}

View File

@@ -0,0 +1,31 @@
spring.application.name=spring-boot-admin-server
spring.security.user.name=admin
spring.security.user.password=admin
#configs to connect to self register the admin server as a client
spring.boot.admin.client.url=http://localhost:8080
spring.boot.admin.client.username=${spring.security.user.name}
spring.boot.admin.client.password=${spring.security.user.password}
#configs to give secured server info
spring.boot.admin.client.instance.metadata.user.name=${spring.security.user.name}
spring.boot.admin.client.instance.metadata.user.password=${spring.security.user.password}
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
#mail notifications
spring.mail.host=
spring.mail.username=
spring.mail.password=
spring.mail.port=
spring.mail.properties.mail.smtp.auth=
spring.mail.properties.mail.smtp.starttls.enable=
spring.boot.admin.notify.mail.to=
#hipchat notifications
#spring.boot.admin.notify.hipchat.auth-token=<generated_token>
#spring.boot.admin.notify.hipchat.room-id=<room-id>
#spring.boot.admin.notify.hipchat.url=https://youcompany.hipchat.com/v2/

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<jmxConfigurator />
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date [%thread] %-5level %logger{25} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>

View File

@@ -0,0 +1,24 @@
package com.baeldung.springbootadminserver;
import com.baeldung.springbootadminserver.configs.HazelcastConfig;
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.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertNotEquals;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { HazelcastConfig.class }, webEnvironment = NONE)
public class HazelcastConfigIntegrationTest {
@Autowired private ApplicationContext applicationContext;
@Test
public void whenApplicationContextStarts_HazelcastConfigBeanExists() {
assertNotEquals(applicationContext.getBean("hazelcast"), null);
}
}

View File

@@ -0,0 +1,43 @@
package com.baeldung.springbootadminserver;
import static org.junit.Assert.assertNotEquals;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE;
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.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.springbootadminserver.configs.NotifierConfiguration;
import de.codecentric.boot.admin.server.notify.Notifier;
import de.codecentric.boot.admin.server.notify.RemindingNotifier;
import de.codecentric.boot.admin.server.notify.filter.FilteringNotifier;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { NotifierConfiguration.class, SpringBootAdminServerApplication.class }, webEnvironment = NONE)
public class NotifierConfigurationIntegrationTest {
@Autowired private ApplicationContext applicationContext;
@Test
public void whenApplicationContextStart_ThenNotifierBeanExists() {
Notifier notifier = (Notifier) applicationContext.getBean("notifier");
assertNotEquals(notifier, null);
}
@Test
public void whenApplicationContextStart_ThenFilteringNotifierBeanExists() {
FilteringNotifier filteringNotifier = (FilteringNotifier) applicationContext.getBean("filteringNotifier");
assertNotEquals(filteringNotifier, null);
}
@Test
public void whenApplicationContextStart_ThenRemindingNotifierBeanExists() {
RemindingNotifier remindingNotifier = (RemindingNotifier) applicationContext.getBean("remindingNotifier");
assertNotEquals(remindingNotifier, null);
}
}

View File

@@ -0,0 +1,72 @@
package com.baeldung.springbootadminserver;
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.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class WebSecurityConfigIntegrationTest {
@Autowired WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = MockMvcBuilders
.webAppContextSetup(wac)
.build();
}
@Test
public void whenApplicationStarts_ThenGetLoginPageWithSuccess() throws Exception {
mockMvc
.perform(get("/login.html"))
.andExpect(status().is2xxSuccessful());
}
@Test
public void whenFormLoginAttempted_ThenSuccess() throws Exception {
mockMvc.perform(formLogin("/login")
.user("admin")
.password("admin"));
}
@Test
public void whenFormLoginWithSuccess_ThenApiEndpointsAreAccessible() throws Exception {
mockMvc.perform(formLogin("/login")
.user("admin")
.password("admin"));
mockMvc
.perform(get("/applications/"))
.andExpect(status().is2xxSuccessful());
}
@Test
public void whenHttpBasicAttempted_ThenSuccess() throws Exception {
mockMvc.perform(get("/actuator/env").with(httpBasic("admin", "admin")));
}
@Test
public void whenInvalidHttpBasicAttempted_ThenUnauthorized() throws Exception {
mockMvc
.perform(get("/actuator/env").with(httpBasic("admin", "invalid")))
.andExpect(unauthenticated());
}
}

View File

@@ -0,0 +1,17 @@
package org.baeldung;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.springbootadminserver.SpringBootAdminServerApplication;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootAdminServerApplication.class)
public class SpringContextTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}

View File

@@ -0,0 +1,11 @@
## Spring Boot Artifacts
This module contains articles about configuring the Spring Boot build process.
### Relevant Articles:
- [Spring Boot Dependency Management with a Custom Parent](https://www.baeldung.com/spring-boot-dependency-management-custom-parent)
- [Create a Fat Jar App with Spring Boot](https://www.baeldung.com/deployable-fat-jar-spring-boot)
- [Intro to Spring Boot Starters](https://www.baeldung.com/spring-boot-starters)
- [Introduction to WebJars](https://www.baeldung.com/maven-webjars)
- [A Quick Guide to Maven Wrapper](https://www.baeldung.com/maven-wrapper)
- [Running a Spring Boot App with Maven vs an Executable War/Jar](https://www.baeldung.com/spring-boot-run-maven-vs-executable-jar)

View File

@@ -0,0 +1,194 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-artifacts</artifactId>
<name>spring-boot-artifacts</name>
<packaging>war</packaging>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>${jpa.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.subethamail</groupId>
<artifactId>subethasmtp</artifactId>
<version>${subethasmtp.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>${bootstrap.version}</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>${jquery.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>${springcloud.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<mainClass>com.baeldung.webjar.WebjarsdemoApplication</mainClass>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18</version>
<executions>
<!-- Invokes both the integration-test and the verify goals of the Failsafe
Maven plugin -->
<execution>
<id>integration-tests</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<!-- Skips integration tests if the value of skip.integration.tests
property is true -->
<includes>
<include>**/ExternalPropertyFileLoaderIntegrationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>autoconfiguration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*LiveTest.java</exclude>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>**/*IntTest.java</exclude>
</excludes>
<includes>
<include>**/AutoconfigurationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<!-- The main class to start by executing java -jar -->
<start-class>org.baeldung.boot.Application</start-class>
<jquery.version>3.1.1</jquery.version>
<bootstrap.version>3.3.7-1</bootstrap.version>
<jpa.version>2.2</jpa.version>
<guava.version>18.0</guava.version>
<subethasmtp.version>3.1.7</subethasmtp.version>
<springcloud.version>2.0.2.RELEASE</springcloud.version>
<httpclient.version>4.5.8</httpclient.version>
</properties>
</project>

View File

@@ -0,0 +1,15 @@
package com.baeldung.webjar;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class TestController {
@GetMapping(value = "/")
public String welcome(Model model) {
return "index";
}
}

View File

@@ -0,0 +1,12 @@
package com.baeldung.webjar;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class WebjarsdemoApplication {
public static void main(String[] args) {
SpringApplication.run(WebjarsdemoApplication.class, args);
}
}

View File

@@ -0,0 +1 @@
spring.main.allow-bean-definition-overriding=true

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,19 @@
<html>
<head>
<title>WebJars Demo</title>
<link rel="stylesheet" href="/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css" />
</head>
<body>
<h1>Welcome Home</h1>
<div class="container"><br/>
<div class="alert alert-success">
<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
<strong>Success!</strong> It is working as we expected.
</div>
</div>
<script src="/webjars/jquery/3.1.1/jquery.min.js"></script>
<script src="/webjars/bootstrap/3.3.7-1/js/bootstrap.min.js"></script>
</body>
</html>

View File

@@ -0,0 +1,18 @@
package com.baeldung.webjar;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = WebjarsdemoApplication.class)
@WebAppConfiguration
public class WebjarsdemoApplicationIntegrationTest {
@Test
public void contextLoads() {
}
}

View File

@@ -0,0 +1,5 @@
/target/
.settings/
.classpath
.project

View File

@@ -0,0 +1,12 @@
## Spring Boot Auto Configuration
This module contains articles about Spring Boot Auto Configuration
### The Course
The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles:
- [Create a Custom Auto-Configuration with Spring Boot](https://www.baeldung.com/spring-boot-custom-auto-configuration)
- [Guide to ApplicationContextRunner in Spring Boot](https://www.baeldung.com/spring-boot-context-runner)
- [A Guide to Spring Boot Configuration Metadata](https://www.baeldung.com/spring-boot-configuration-metadata)

View File

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-autoconfiguration</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-autoconfiguration</name>
<packaging>war</packaging>
<description>This is simple boot application demonstrating a custom auto-configuration</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.1.6.RELEASE</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<finalName>spring-boot</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>autoconfiguration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*LiveTest.java</exclude>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>**/*IntTest.java</exclude>
</excludes>
<includes>
<include>**/AutoconfigurationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<jquery.version>3.1.1</jquery.version>
<bootstrap.version>3.3.7-1</bootstrap.version>
<subethasmtp.version>3.1.7</subethasmtp.version>
<tomee-servlet-api.version>8.5.11</tomee-servlet-api.version>
</properties>
</project>

View File

@@ -0,0 +1,118 @@
package com.baeldung.autoconfiguration;
import java.util.Arrays;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionMessage.Style;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.util.ClassUtils;
@Configuration
@ConditionalOnClass(DataSource.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@PropertySource("classpath:mysql.properties")
public class MySQLAutoconfiguration {
@Autowired
private Environment env;
@Bean
@ConditionalOnProperty(name = "usemysql", havingValue = "local")
@ConditionalOnMissingBean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true&&serverTimezone=UTC");
dataSource.setUsername("mysqluser");
dataSource.setPassword("mysqlpass");
return dataSource;
}
@Bean(name = "dataSource")
@ConditionalOnProperty(name = "usemysql", havingValue = "custom")
@ConditionalOnMissingBean
public DataSource dataSource2() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl(env.getProperty("mysql.url"));
dataSource.setUsername(env.getProperty("mysql.user") != null ? env.getProperty("mysql.user") : "");
dataSource.setPassword(env.getProperty("mysql.pass") != null ? env.getProperty("mysql.pass") : "");
return dataSource;
}
@Bean
@ConditionalOnBean(name = "dataSource")
@ConditionalOnMissingBean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("com.baeldung.autoconfiguration.example");
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
if (additionalProperties() != null) {
em.setJpaProperties(additionalProperties());
}
return em;
}
@Bean
@ConditionalOnMissingBean(type = "JpaTransactionManager")
JpaTransactionManager transactionManager(final EntityManagerFactory entityManagerFactory) {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
@ConditionalOnResource(resources = "classpath:mysql.properties")
@Conditional(HibernateCondition.class)
final Properties additionalProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("mysql-hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("mysql-hibernate.dialect"));
hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("mysql-hibernate.show_sql") != null ? env.getProperty("mysql-hibernate.show_sql") : "false");
return hibernateProperties;
}
static class HibernateCondition extends SpringBootCondition {
private static final String[] CLASS_NAMES = { "org.hibernate.ejb.HibernateEntityManager", "org.hibernate.jpa.HibernateEntityManager" };
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage.forCondition("Hibernate");
return Arrays.stream(CLASS_NAMES).filter(className -> ClassUtils.isPresent(className, context.getClassLoader())).map(className -> ConditionOutcome.match(message.found("class").items(Style.NORMAL, className))).findAny()
.orElseGet(() -> ConditionOutcome.noMatch(message.didNotFind("class", "classes").items(Style.NORMAL, Arrays.asList(CLASS_NAMES))));
}
}
}

View File

@@ -0,0 +1,15 @@
package com.baeldung.autoconfiguration.annotationprocessor;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ComponentScan;
import com.baeldung.autoconfiguration.MySQLAutoconfiguration;
@EnableAutoConfiguration(exclude = { MySQLAutoconfiguration.class})
@ComponentScan(basePackageClasses = {DatabaseProperties.class})
public class AnnotationProcessorApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(AnnotationProcessorApplication.class).run();
}
}

View File

@@ -0,0 +1,73 @@
package com.baeldung.autoconfiguration.annotationprocessor;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "database")
public class DatabaseProperties {
public static class Server {
/**
* The IP of the database server
*/
private String ip;
/**
* The Port of the database server.
* The Default value is 443.
* The allowed values are in the range 400-4000.
*/
@Min(400)
@Max(800)
private int port = 443;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
private String username;
private String password;
private Server server;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Server getServer() {
return server;
}
public void setServer(Server server) {
this.server = server;
}
}

View File

@@ -0,0 +1,12 @@
package com.baeldung.autoconfiguration.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AutoconfigurationApplication {
public static void main(String[] args) {
SpringApplication.run(AutoconfigurationApplication.class, args);
}
}

View File

@@ -0,0 +1,27 @@
package com.baeldung.autoconfiguration.example;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class MyUser {
@Id
private String email;
public MyUser() {
}
public MyUser(String email) {
super();
this.email = email;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

View File

@@ -0,0 +1,7 @@
package com.baeldung.autoconfiguration.example;
import org.springframework.data.jpa.repository.JpaRepository;
public interface MyUserRepository extends JpaRepository<MyUser, String> {
}

View File

@@ -0,0 +1,10 @@
package com.baeldung.autoconfiguration.service;
public class CustomService implements SimpleService {
@Override
public String serve() {
return "Custom Service";
}
}

View File

@@ -0,0 +1,10 @@
package com.baeldung.autoconfiguration.service;
public class DefaultService implements SimpleService {
@Override
public String serve() {
return "Default Service";
}
}

View File

@@ -0,0 +1,7 @@
package com.baeldung.autoconfiguration.service;
public interface SimpleService {
public String serve();
}

View File

@@ -0,0 +1 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.baeldung.autoconfiguration.MySQLAutoconfiguration

View File

@@ -0,0 +1,2 @@
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto = update

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,5 @@
usemysql=local
mysql-hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
mysql-hibernate.show_sql=true
mysql-hibernate.hbm2ddl.auto=create-drop

View File

@@ -0,0 +1,19 @@
package com.baeldung;
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 com.baeldung.autoconfiguration.MySQLAutoconfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MySQLAutoconfiguration.class)
@WebAppConfiguration
public class SpringContextLiveTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}

View File

@@ -0,0 +1,27 @@
package com.baeldung.autoconfiguration;
import com.baeldung.autoconfiguration.example.AutoconfigurationApplication;
import com.baeldung.autoconfiguration.example.MyUser;
import com.baeldung.autoconfiguration.example.MyUserRepository;
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.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = AutoconfigurationApplication.class)
@EnableJpaRepositories(basePackages = { "com.baeldung.autoconfiguration.example" })
public class AutoconfigurationLiveTest {
@Autowired
private MyUserRepository userRepository;
@Test
public void whenSaveUser_thenOk() {
MyUser user = new MyUser("user@email.com");
userRepository.save(user);
}
}

View File

@@ -0,0 +1,77 @@
package com.baeldung.autoconfiguration;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class ConditionalOnBeanIntegrationTest {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();
@Test
public void whenDependentBeanIsPresent_thenConditionalBeanCreated() {
this.contextRunner.withUserConfiguration(BasicConfiguration.class, ConditionalOnBeanConfiguration.class)
.run((context) -> {
assertThat(context).hasBean("created");
assertThat(context).getBean("created")
.isEqualTo("This is always created");
assertThat(context).hasBean("createOnBean");
assertThat(context).getBean("createOnBean")
.isEqualTo("This is created when bean (name=created) is present");
});
}
@Test
public void whenDependentBeanIsPresent_thenConditionalMissingBeanIgnored() {
this.contextRunner.withUserConfiguration(BasicConfiguration.class, ConditionalOnMissingBeanConfiguration.class)
.run((context) -> {
assertThat(context).hasBean("created");
assertThat(context).getBean("created")
.isEqualTo("This is always created");
assertThat(context).doesNotHaveBean("createOnMissingBean");
});
}
@Test
public void whenDependentBeanIsNotPresent_thenConditionalMissingBeanCreated() {
this.contextRunner.withUserConfiguration(ConditionalOnMissingBeanConfiguration.class)
.run((context) -> {
assertThat(context).hasBean("createOnMissingBean");
assertThat(context).getBean("createOnMissingBean")
.isEqualTo("This is created when bean (name=created) is missing");
assertThat(context).doesNotHaveBean("created");
});
}
@Configuration
protected static class BasicConfiguration {
@Bean
public String created() {
return "This is always created";
}
}
@Configuration
@ConditionalOnBean(name = "created")
protected static class ConditionalOnBeanConfiguration {
@Bean
public String createOnBean() {
return "This is created when bean (name=created) is present";
}
}
@Configuration
@ConditionalOnMissingBean(name = "created")
protected static class ConditionalOnMissingBeanConfiguration {
@Bean
public String createOnMissingBean() {
return "This is created when bean (name=created) is missing";
}
}
}

View File

@@ -0,0 +1,76 @@
package com.baeldung.autoconfiguration;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class ConditionalOnClassIntegrationTest {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();
@Test
public void whenDependentClassIsPresent_thenBeanCreated() {
this.contextRunner.withUserConfiguration(ConditionalOnClassConfiguration.class)
.run(context -> {
assertThat(context).hasBean("created");
assertThat(context.getBean("created")).isEqualTo("This is created when ConditionalOnClassIntegrationTest is present on the classpath");
});
}
@Test
public void whenDependentClassIsPresent_thenBeanMissing() {
this.contextRunner.withUserConfiguration(ConditionalOnMissingClassConfiguration.class)
.run(context -> {
assertThat(context).doesNotHaveBean("missed");
});
}
@Test
public void whenDependentClassIsNotPresent_thenBeanMissing() {
this.contextRunner.withUserConfiguration(ConditionalOnClassConfiguration.class)
.withClassLoader(new FilteredClassLoader(ConditionalOnClassIntegrationTest.class))
.run((context) -> {
assertThat(context).doesNotHaveBean("created");
assertThat(context).doesNotHaveBean(ConditionalOnClassIntegrationTest.class);
});
}
@Test
public void whenDependentClassIsNotPresent_thenBeanCreated() {
this.contextRunner.withUserConfiguration(ConditionalOnMissingClassConfiguration.class)
.withClassLoader(new FilteredClassLoader(ConditionalOnClassIntegrationTest.class))
.run((context) -> {
assertThat(context).hasBean("missed");
assertThat(context).getBean("missed")
.isEqualTo("This is missed when ConditionalOnClassIntegrationTest is present on the classpath");
assertThat(context).doesNotHaveBean(ConditionalOnClassIntegrationTest.class);
});
}
@Configuration
@ConditionalOnClass(ConditionalOnClassIntegrationTest.class)
protected static class ConditionalOnClassConfiguration {
@Bean
public String created() {
return "This is created when ConditionalOnClassIntegrationTest is present on the classpath";
}
}
@Configuration
@ConditionalOnMissingClass("com.baeldung.autoconfiguration.ConditionalOnClassIntegrationTest")
protected static class ConditionalOnMissingClassConfiguration {
@Bean
public String missed() {
return "This is missed when ConditionalOnClassIntegrationTest is present on the classpath";
}
}
}

View File

@@ -0,0 +1,64 @@
package com.baeldung.autoconfiguration;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.TestPropertySource;
import com.baeldung.autoconfiguration.service.CustomService;
import com.baeldung.autoconfiguration.service.DefaultService;
import com.baeldung.autoconfiguration.service.SimpleService;
public class ConditionalOnPropertyIntegrationTest {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();
@Test
public void whenGivenCustomPropertyValue_thenCustomServiceCreated() {
this.contextRunner.withPropertyValues("com.baeldung.service=custom")
.withUserConfiguration(SimpleServiceConfiguration.class)
.run(context -> {
assertThat(context).hasBean("customService");
SimpleService simpleService = context.getBean(CustomService.class);
assertThat(simpleService.serve()).isEqualTo("Custom Service");
assertThat(context).doesNotHaveBean("defaultService");
});
}
@Test
public void whenGivenDefaultPropertyValue_thenDefaultServiceCreated() {
this.contextRunner.withPropertyValues("com.baeldung.service=default")
.withUserConfiguration(SimpleServiceConfiguration.class)
.run(context -> {
assertThat(context).hasBean("defaultService");
SimpleService simpleService = context.getBean(DefaultService.class);
assertThat(simpleService.serve()).isEqualTo("Default Service");
assertThat(context).doesNotHaveBean("customService");
});
}
@Configuration
@TestPropertySource("classpath:ConditionalOnPropertyTest.properties")
protected static class SimpleServiceConfiguration {
@Bean
@ConditionalOnProperty(name = "com.baeldung.service", havingValue = "default")
@ConditionalOnMissingBean
public DefaultService defaultService() {
return new DefaultService();
}
@Bean
@ConditionalOnProperty(name = "com.baeldung.service", havingValue = "custom")
@ConditionalOnMissingBean
public CustomService customService() {
return new CustomService();
}
}
}

View File

@@ -0,0 +1,19 @@
package com.baeldung.autoconfiguration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.autoconfiguration.example.AutoconfigurationApplication;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AutoconfigurationApplication.class)
@EnableJpaRepositories(basePackages = { "com.baeldung.autoconfiguration.example" })
public class SpringContextLiveTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}

View File

@@ -0,0 +1,31 @@
package com.baeldung.autoconfiguration.annotationprocessor;
import org.junit.Assert;
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.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AnnotationProcessorApplication.class)
@TestPropertySource("classpath:databaseproperties-test.properties")
public class DatabasePropertiesIntegrationTest {
@Autowired
private DatabaseProperties databaseProperties;
@Test
public void whenSimplePropertyQueriedThenReturnsPropertyValue() throws Exception {
Assert.assertEquals("Incorrectly bound Username property", "baeldung", databaseProperties.getUsername());
Assert.assertEquals("Incorrectly bound Password property", "password", databaseProperties.getPassword());
}
@Test
public void whenNestedPropertyQueriedThenReturnsPropertyValue() throws Exception {
Assert.assertEquals("Incorrectly bound Server IP nested property", "127.0.0.1", databaseProperties.getServer().getIp());
Assert.assertEquals("Incorrectly bound Server Port nested property", 3306, databaseProperties.getServer().getPort());
}
}

View File

@@ -0,0 +1,7 @@
#Simple Properties
database.username=baeldung
database.password=password
#Nested Properties
database.server.ip=127.0.0.1
database.server.port=3306

View File

@@ -0,0 +1,16 @@
## Spring Boot Custom Starter
This module contains articles about writing [Spring Boot Starters](https://www.baeldung.com/spring-boot-starters).
### Relevant Articles:
- [Creating a Custom Starter with Spring Boot](https://www.baeldung.com/spring-boot-custom-starter)
- **greeter-library**: The sample library that we're creating the starter for.
- **greeter-spring-boot-autoconfigure**: The project containing the auto-configuration for the library.
- **greeter-spring-boot-starter**: The custom starter for the library.
- **greeter-spring-boot-sample-app**: The sample project that uses the custom starter.
- [Multi-Module Project With Spring Boot](https://www.baeldung.com/spring-boot-multiple-modules)

View File

@@ -0,0 +1,19 @@
# Greeter App
This app takes in the user's name and messages for different times of day as configuration parameters and outptus the greeting messge. For example it will take the name **John** and the message for morning time as **Good Morning** and output the message **Hello John, Good Morning**.
## Usage
Create and populate the class `GreetingConfig`, instantiate a `Greeter` using the `GreetingConfig` and use it get greeting messages:
```java
GreetingConfig greetingConfig = new GreetingConfig();
greetingConfig.put(USER_NAME, "World");
greetingConfig.put(MORNING_MESSAGE, "Good Morning");
greetingConfig.put(AFTERNOON_MESSAGE, "Good Afternoon");
greetingConfig.put(EVENING_MESSAGE, "Good Evening");
greetingConfig.put(NIGHT_MESSAGE, "Good Night");
Greeter greeter = new Greeter(greetingConfig);
greeter.greet();
```

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>greeter-library</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>greeter-library</name>
<parent>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>spring-boot-custom-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
</project>

View File

@@ -0,0 +1,35 @@
package com.baeldung.greeter.library;
import static com.baeldung.greeter.library.GreeterConfigParams.*;
import java.time.LocalDateTime;
public class Greeter {
private GreetingConfig greetingConfig;
public Greeter(GreetingConfig greetingConfig) {
this.greetingConfig = greetingConfig;
}
public String greet(LocalDateTime localDateTime) {
String name = greetingConfig.getProperty(USER_NAME);
int hourOfDay = localDateTime.getHour();
if (hourOfDay >= 5 && hourOfDay < 12) {
return String.format("Hello %s, %s", name, greetingConfig.get(MORNING_MESSAGE));
} else if (hourOfDay >= 12 && hourOfDay < 17) {
return String.format("Hello %s, %s", name, greetingConfig.get(AFTERNOON_MESSAGE));
} else if (hourOfDay >= 17 && hourOfDay < 20) {
return String.format("Hello %s, %s", name, greetingConfig.get(EVENING_MESSAGE));
} else {
return String.format("Hello %s, %s", name, greetingConfig.get(NIGHT_MESSAGE));
}
}
public String greet() {
return greet(LocalDateTime.now());
}
}

View File

@@ -0,0 +1,11 @@
package com.baeldung.greeter.library;
public class GreeterConfigParams {
public static final String USER_NAME = "user.name";
public static final String MORNING_MESSAGE = "morning.message";
public static final String AFTERNOON_MESSAGE = "afternoon.message";
public static final String EVENING_MESSAGE = "evening.message";
public static final String NIGHT_MESSAGE = "night.message";
}

View File

@@ -0,0 +1,9 @@
package com.baeldung.greeter.library;
import java.util.Properties;
public class GreetingConfig extends Properties{
private static final long serialVersionUID = 5662570853707247891L;
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,58 @@
package com.baeldung.greeter;
import static com.baeldung.greeter.library.GreeterConfigParams.*;
import static org.junit.Assert.assertEquals;
import java.time.LocalDateTime;
import com.baeldung.greeter.library.Greeter;
import com.baeldung.greeter.library.GreetingConfig;
import org.junit.BeforeClass;
import org.junit.Test;
public class GreeterIntegrationTest {
private static GreetingConfig greetingConfig;
@BeforeClass
public static void initalizeGreetingConfig() {
greetingConfig = new GreetingConfig();
greetingConfig.put(USER_NAME, "World");
greetingConfig.put(MORNING_MESSAGE, "Good Morning");
greetingConfig.put(AFTERNOON_MESSAGE, "Good Afternoon");
greetingConfig.put(EVENING_MESSAGE, "Good Evening");
greetingConfig.put(NIGHT_MESSAGE, "Good Night");
}
@Test
public void givenMorningTime_ifMorningMessage_thenSuccess() {
String expected = "Hello World, Good Morning";
Greeter greeter = new Greeter(greetingConfig);
String actual = greeter.greet(LocalDateTime.of(2017, 3, 1, 6, 0));
assertEquals(expected, actual);
}
@Test
public void givenAfternoonTime_ifAfternoonMessage_thenSuccess() {
String expected = "Hello World, Good Afternoon";
Greeter greeter = new Greeter(greetingConfig);
String actual = greeter.greet(LocalDateTime.of(2017, 3, 1, 13, 0));
assertEquals(expected, actual);
}
@Test
public void givenEveningTime_ifEveningMessage_thenSuccess() {
String expected = "Hello World, Good Evening";
Greeter greeter = new Greeter(greetingConfig);
String actual = greeter.greet(LocalDateTime.of(2017, 3, 1, 19, 0));
assertEquals(expected, actual);
}
@Test
public void givenNightTime_ifNightMessage_thenSuccess() {
String expected = "Hello World, Good Night";
Greeter greeter = new Greeter(greetingConfig);
String actual = greeter.greet(LocalDateTime.of(2017, 3, 1, 21, 0));
assertEquals(expected, actual);
}
}

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>greeter-spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>greeter-spring-boot-autoconfigure</name>
<parent>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>spring-boot-custom-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${spring-boot.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>greeter-library</artifactId>
<version>${greeter.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>1.5.2.RELEASE</spring-boot.version>
<greeter.version>0.0.1-SNAPSHOT</greeter.version>
</properties>
</project>

View File

@@ -0,0 +1,48 @@
package com.baeldung.greeter.autoconfigure;
import static com.baeldung.greeter.library.GreeterConfigParams.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baeldung.greeter.library.Greeter;
import com.baeldung.greeter.library.GreetingConfig;
@Configuration
@ConditionalOnClass(Greeter.class)
@EnableConfigurationProperties(GreeterProperties.class)
public class GreeterAutoConfiguration {
@Autowired
private GreeterProperties greeterProperties;
@Bean
@ConditionalOnMissingBean
public GreetingConfig greeterConfig() {
String userName = greeterProperties.getUserName() == null ? System.getProperty("user.name") : greeterProperties.getUserName();
String morningMessage = greeterProperties.getMorningMessage() == null ? "Good Morning" : greeterProperties.getMorningMessage();
String afternoonMessage = greeterProperties.getAfternoonMessage() == null ? "Good Afternoon" : greeterProperties.getAfternoonMessage();
String eveningMessage = greeterProperties.getEveningMessage() == null ? "Good Evening" : greeterProperties.getEveningMessage();
String nightMessage = greeterProperties.getNightMessage() == null ? "Good Night" : greeterProperties.getNightMessage();
GreetingConfig greetingConfig = new GreetingConfig();
greetingConfig.put(USER_NAME, userName);
greetingConfig.put(MORNING_MESSAGE, morningMessage);
greetingConfig.put(AFTERNOON_MESSAGE, afternoonMessage);
greetingConfig.put(EVENING_MESSAGE, eveningMessage);
greetingConfig.put(NIGHT_MESSAGE, nightMessage);
return greetingConfig;
}
@Bean
@ConditionalOnMissingBean
public Greeter greeter(GreetingConfig greetingConfig) {
return new Greeter(greetingConfig);
}
}

View File

@@ -0,0 +1,54 @@
package com.baeldung.greeter.autoconfigure;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "baeldung.greeter")
public class GreeterProperties {
private String userName;
private String morningMessage;
private String afternoonMessage;
private String eveningMessage;
private String nightMessage;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getMorningMessage() {
return morningMessage;
}
public void setMorningMessage(String morningMessage) {
this.morningMessage = morningMessage;
}
public String getAfternoonMessage() {
return afternoonMessage;
}
public void setAfternoonMessage(String afternoonMessage) {
this.afternoonMessage = afternoonMessage;
}
public String getEveningMessage() {
return eveningMessage;
}
public void setEveningMessage(String eveningMessage) {
this.eveningMessage = eveningMessage;
}
public String getNightMessage() {
return nightMessage;
}
public void setNightMessage(String nightMessage) {
this.nightMessage = nightMessage;
}
}

View File

@@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.baeldung.greeter.autoconfigure.GreeterAutoConfiguration

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,17 @@
package org.baeldung;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baeldung.greeter.autoconfigure.GreeterAutoConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = GreeterAutoConfiguration.class)
public class SpringContextTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>greeter-spring-boot-sample-app</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>greeter-spring-boot-sample-app</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../../parent-boot-1</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>greeter-spring-boot-starter</artifactId>
<version>${greeter-starter.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<properties>
<greeter-starter.version>0.0.1-SNAPSHOT</greeter-starter.version>
</properties>
</project>

View File

@@ -0,0 +1,25 @@
package com.baeldung.greeter.sample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.baeldung.greeter.library.Greeter;
@SpringBootApplication
public class GreeterSampleApplication implements CommandLineRunner {
@Autowired
private Greeter greeter;
public static void main(String[] args) {
SpringApplication.run(GreeterSampleApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
String message = greeter.greet();
System.out.println(message);
}
}

View File

@@ -0,0 +1,2 @@
baeldung.greeter.userName=Baeldung
baeldung.greeter.afternoonMessage=Woha\ Afternoon

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,50 @@
package com.baeldung.greeter.sample;
import static org.junit.Assert.assertEquals;
import java.time.LocalDateTime;
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.test.context.junit4.SpringJUnit4ClassRunner;
import com.baeldung.greeter.library.Greeter;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = GreeterSampleApplication.class)
public class GreeterSampleApplicationIntegrationTest {
@Autowired
private Greeter greeter;
@Test
public void givenMorningTime_ifMorningMessage_thenSuccess() {
String expected = "Hello Baeldung, Good Morning";
String actual = greeter.greet(LocalDateTime.of(2017, 3, 1, 6, 0));
assertEquals(expected, actual);
}
@Test
public void givenAfternoonTime_ifAfternoonMessage_thenSuccess() {
String expected = "Hello Baeldung, Woha Afternoon";
String actual = greeter.greet(LocalDateTime.of(2017, 3, 1, 13, 0));
assertEquals(expected, actual);
}
@Test
public void givenEveningTime_ifEveningMessage_thenSuccess() {
String expected = "Hello Baeldung, Good Evening";
String actual = greeter.greet(LocalDateTime.of(2017, 3, 1, 19, 0));
assertEquals(expected, actual);
}
@Test
public void givenNightTime_ifNightMessage_thenSuccess() {
String expected = "Hello Baeldung, Good Night";
String actual = greeter.greet(LocalDateTime.of(2017, 3, 1, 21, 0));
assertEquals(expected, actual);
}
}

View File

@@ -0,0 +1,17 @@
package org.baeldung;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.greeter.sample.GreeterSampleApplication;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = GreeterSampleApplication.class)
public class SpringContextTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>greeter-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>greeter-spring-boot-starter</name>
<parent>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>spring-boot-custom-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>greeter-spring-boot-autoconfigure</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>greeter-library</artifactId>
<version>${greeter.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<greeter.version>0.0.1-SNAPSHOT</greeter.version>
<spring-boot.version>1.5.2.RELEASE</spring-boot.version>
</properties>
</project>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>greeter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>greeter</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../../parent-boot-1</relativePath>
</parent>
</project>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-custom-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-custom-starter</name>
<packaging>pom</packaging>
<parent>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>spring-boot-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modules>
<module>greeter-library</module>
<module>greeter-spring-boot-autoconfigure</module>
<module>greeter-spring-boot-starter</module>
<module>greeter-spring-boot-sample-app</module>
</modules>
</project>

View File

@@ -0,0 +1,2 @@
.gradle/
build/

View File

@@ -0,0 +1,8 @@
## Spring Boot Gradle
This module contains articles about Gradle in Spring Boot projects.
### Relevant Articles:
- [Spring Boot: Configuring a Main Class](https://www.baeldung.com/spring-boot-main-class)
- [Thin JARs with Spring Boot](https://www.baeldung.com/spring-boot-thin-jar)

View File

@@ -0,0 +1,67 @@
buildscript {
ext {
springBootPlugin = 'org.springframework.boot:spring-boot-gradle-plugin'
springBootVersion = '2.0.2.RELEASE'
thinPlugin = 'org.springframework.boot.experimental:spring-boot-thin-gradle-plugin'
thinVersion = '1.0.11.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("${springBootPlugin}:${springBootVersion}")
classpath("${thinPlugin}:${thinVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
//add tasks thinJar and thinResolve for thin JAR deployments
apply plugin: 'org.springframework.boot.experimental.thin-launcher'
group = 'org.baeldung'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
springBoot {
mainClassName = 'org.baeldung.DemoApplication'
}
bootJar {
// This is overridden by the mainClassName in springBoot{} and added here for reference purposes.
mainClassName = 'org.baeldung.DemoApplication'
// This block serves the same purpose as the above thus commented out. Added here for reference purposes
// manifest {
// attributes 'Start-Class': 'org.baeldung.DemoApplication'
// }
}
//Enable this to generate and use a pom.xml file
apply plugin: 'maven'
//If you want to customize the generated pom.xml you can edit this task and add it as a dependency to the bootJar task
task createPom {
def basePath = 'build/resources/main/META-INF/maven'
doLast {
pom {
withXml(dependencyManagement.pomConfigurer)
}.writeTo("${basePath}/${project.group}/${project.name}/pom.xml")
}
}
//Uncomment the following to use your custom generated pom.xml
bootJar.dependsOn = [createPom]
//Enable this to generate and use a thin.properties file
//bootJar.dependsOn = [thinProperties]

View File

@@ -0,0 +1,6 @@
#Fri Jun 01 20:39:48 CEST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-all.zip

172
spring-boot-modules/spring-boot-gradle/gradlew vendored Executable file
View File

@@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save ( ) {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

View File

@@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1 @@
rootProject.name = 'demo'

View File

@@ -0,0 +1,12 @@
package org.baeldung;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,16 @@
package org.baeldung;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Test
public void contextLoads() {
}
}

View File

@@ -0,0 +1,24 @@
target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/

View File

@@ -0,0 +1 @@
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip

View File

@@ -0,0 +1,6 @@
## Spring Boot Keycloak
This module contains articles about Keycloak in Spring Boot projects.
## Relevant articles:
- [A Quick Guide to Using Keycloak with Spring Boot](https://www.baeldung.com/spring-boot-keycloak)

225
spring-boot-modules/spring-boot-keycloak/mvnw vendored Executable file
View File

@@ -0,0 +1,225 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Migwn, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
# TODO classpath?
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
echo $MAVEN_PROJECTBASEDIR
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

View File

@@ -0,0 +1,143 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%

View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung.keycloak</groupId>
<artifactId>spring-boot-keycloak</artifactId>
<version>0.0.1</version>
<name>spring-boot-keycloak</name>
<packaging>jar</packaging>
<description>This is a simple application demonstrating integration between Keycloak and Spring Boot.</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-1</relativePath>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak.bom</groupId>
<artifactId>keycloak-adapter-bom</artifactId>
<version>${keycloak-adapter-bom.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<properties>
<keycloak-adapter-bom.version>3.3.0.Final</keycloak-adapter-bom.version>
</properties>
</project>

View File

@@ -0,0 +1,49 @@
package com.baeldung.keycloak;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
private String serviceRendered;
private String address;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getServiceRendered() {
return serviceRendered;
}
public void setServiceRendered(String serviceRendered) {
this.serviceRendered = serviceRendered;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}

View File

@@ -0,0 +1,7 @@
package com.baeldung.keycloak;
import org.springframework.data.repository.CrudRepository;
public interface CustomerDAO extends CrudRepository<Customer, Long> {
}

View File

@@ -0,0 +1,52 @@
package com.baeldung.keycloak;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
// Submits the KeycloakAuthenticationProvider to the AuthenticationManager
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
// Specifies the session authentication strategy
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/customers*")
.hasRole("user")
.anyRequest()
.permitAll();
}
}

View File

@@ -0,0 +1,14 @@
package com.baeldung.keycloak;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBoot {
public static void main(String[] args) {
SpringApplication.run(SpringBoot.class, args);
}
}

Some files were not shown because too many files have changed in this diff Show More