diff --git a/README.md b/README.md index 8236cc930..dde641c6c 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,27 @@ Spring Music ============ -This is a sample application for using database services on [Cloud Foundry](http://cloudfoundry.org) with the [Spring Framework](http://spring.io) and [Spring Boot](http://projects.spring.io/spring-boot/). +This is a sample application for using database services on [Cloud Foundry](https://www.cloudfoundry.org) with the [Spring Framework](https://spring.io) and [Spring Boot](https://spring.io/projects/spring-boot). This application has been built to store the same domain objects in one of a variety of different persistence technologies - relational, document, and key-value stores. This is not meant to represent a realistic use case for these technologies, since you would typically choose the one most applicable to the type of data you need to store, but it is useful for testing and experimenting with different types of services on Cloud Foundry. -The application use Spring Java configuration and [bean profiles](http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html) to configure the application and the connection objects needed to use the persistence stores. It also uses the [Java CFEnv](https://github.com/pivotal-cf/java-cfenv/) library to inspect the environment when running on Cloud Foundry. See the [Cloud Foundry documentation](http://docs.cloudfoundry.org/buildpacks/java/spring-service-bindings.html) for details on configuring a Spring application for Cloud Foundry. +The application uses Spring Java configuration and [bean profiles](https://docs.spring.io/spring-boot/reference/features/profiles.html) to configure the application and the connection objects needed to use the persistence stores. It also uses the [Java CFEnv](https://github.com/pivotal-cf/java-cfenv/) library to inspect the environment when running on Cloud Foundry. + +## Tech stack + +| Component | Version | +|-----------|---------| +| Java | 25 | +| Spring Boot | 4.0.3 | +| Gradle | 9.3.1 | +| Java CFEnv | 4.0.0 | ## Building -This project requires Java version 17 or later to compile. +This project requires Java 25 or later to compile. > [!NOTE] -> If you need to use an earlier Java version, check out the [`spring-boot-2` branch](https://github.com/cloudfoundry-samples/spring-music/tree/spring-boot-2), which can be built with Java 8 and later. +> If you need to use an earlier Java version, check out the [`spring-boot-2` branch](https://github.com/cloudfoundry-samples/spring-music/tree/spring-boot-2), which can be built with Java 8 and later. To build a runnable Spring Boot jar file, run the following command: @@ -37,7 +46,7 @@ where `` is one of the following values: * `mongodb` * `redis` -If no profile is provided, an in-memory relational database will be used. If any other profile is provided, the appropriate database server must be started separately. Spring Boot will auto-configure a connection to the database using it's auto-configuration defaults. The connection parameters can be configured by setting the appropriate [Spring Boot properties](http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html). +If no profile is provided, an in-memory H2 relational database will be used. If any other profile is provided, the appropriate database server must be started separately. Spring Boot will auto-configure a connection to the database using its auto-configuration defaults. The connection parameters can be configured by setting the appropriate [Spring Boot properties](https://docs.spring.io/spring-boot/appendix/application-properties/index.html). If more than one of these profiles is provided, the application will throw an exception and fail to start. @@ -49,7 +58,7 @@ If no bound services are found containing any of these values in the name, an in If more than one service containing any of these values is bound to the application, the application will throw an exception and fail to start. -After installing the 'cf' [command-line interface for Cloud Foundry](http://docs.cloudfoundry.org/cf-cli/), targeting a Cloud Foundry instance, and logging in, the application can be built and pushed using these commands: +After installing the `cf` [command-line interface for Cloud Foundry](https://docs.cloudfoundry.org/cf-cli/), targeting a Cloud Foundry instance, and logging in, the application can be built and pushed using these commands: ~~~ $ cf push @@ -59,7 +68,7 @@ The application will be pushed using settings in the provided `manifest.yml` fil ### Creating and binding services -Using the provided manifest, the application will be created without an external database (in the `in-memory` profile). You can create and bind database services to the application using the information below. +Using the provided manifest, the application will be created without an external database (using the in-memory H2 profile). You can create and bind database services to the application using the information below. #### System-managed services @@ -107,26 +116,32 @@ $ cf restart Database drivers for MySQL, Postgres, Microsoft SQL Server, MongoDB, and Redis are included in the project. -To connect to an Oracle database, you will need to download the appropriate driver (e.g. from http://www.oracle.com/technetwork/database/features/jdbc/index-091264.html). Then make a `libs` directory in the `spring-music` project, and move the driver, `ojdbc7.jar` or `ojdbc8.jar`, into the `libs` directory. -In `build.gradle`, uncomment the line `compile files('libs/ojdbc8.jar')` or `compile files('libs/ojdbc7.jar')` and run `./gradle assemble`. +To connect to an Oracle database, you will need to download the appropriate driver from the [Oracle JDBC Downloads page](https://www.oracle.com/database/technologies/appdev/jdbc-downloads.html). Then make a `libs` directory in the `spring-music` project, and move the driver (`ojdbc8.jar` or `ojdbc7.jar`) into the `libs` directory. +In `build.gradle`, uncomment the appropriate line: + +~~~ +implementation files('libs/ojdbc8.jar') +// or +implementation files('libs/ojdbc7.jar') +~~~ +Then run `./gradlew assemble`. ## Alternate Java versions -By default, the application will be built and deployed using Java 17 compatibility. -If you want to use a more recent version of Java, you will need to update two things. +By default, the application is built and deployed using Java 25. To use a different version, update two places. -In `build.gradle`, change the `targetCompatibility` Java version from `JavaVersion.VERSION_17` to a different value from `JavaVersion`: +In `build.gradle`, change the `targetCompatibility` version: ~~~ java { ... - targetCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_25 } ~~~ -In `manifest.yml`, change the Java buildpack JRE version from `version: 17.+` to a different value: +In `manifest.yml`, change the Java buildpack JRE version: ~~~ - JBP_CONFIG_OPEN_JDK_JRE: '{ jre: { version: 17.+ } }' + JBP_CONFIG_OPEN_JDK_JRE: '{ jre: { version: 25.+ } }' ~~~ diff --git a/build.gradle b/build.gradle index 92e1bf8a5..3495ef917 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,5 @@ plugins { - id 'org.springframework.boot' version '3.1.5' - id 'io.spring.dependency-management' version '1.1.3' + id 'org.springframework.boot' version '4.0.3' id 'java' id 'eclipse-wtp' id 'idea' @@ -9,7 +8,7 @@ plugins { group = 'org.cloudfoundry.samples.music' java { - sourceCompatibility = '17' + sourceCompatibility = '25' } repositories { @@ -17,7 +16,7 @@ repositories { } ext { - javaCfEnvVersion = '3.1.2' + javaCfEnvVersion = '4.0.0' } dependencies { @@ -43,27 +42,26 @@ dependencies { // runtime "io.lettuce:lettuce-core" // Webjars - implementation "org.webjars:bootstrap:3.1.1" - implementation "org.webjars:angularjs:1.2.16" - implementation "org.webjars:angular-ui:0.4.0-2" - implementation "org.webjars:angular-ui-bootstrap:0.10.0-1" - implementation "org.webjars:jquery:2.1.0-2" + implementation "org.webjars:bootstrap:3.4.1" + implementation "org.webjars:angularjs:1.8.3" + implementation "org.webjars:angular-ui:0.4.0-3" + implementation "org.webjars:angular-ui-bootstrap:0.14.3" + implementation "org.webjars:jquery:3.7.1" // Oracle - uncomment one of the following after placing driver in ./libs // compile files('libs/ojdbc8.jar') // compile files('libs/ojdbc7.jar') // Testing - testImplementation "junit:junit" testImplementation "org.springframework.boot:spring-boot-starter-test" } java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 - if (JavaVersion.current() != project.targetCompatibility) { - logger.warn("The build is using Java ${JavaVersion.current()} to build a Java ${project.targetCompatibility} compatible archive.") + if (JavaVersion.current() != JavaVersion.VERSION_25) { + logger.warn("The build is using Java ${JavaVersion.current()} to build a Java ${JavaVersion.VERSION_25} compatible archive.") logger.warn("See the project README for instructions on changing the target Java version.") } } @@ -72,6 +70,10 @@ jar { enabled = false } +test { + useJUnitPlatform() +} + tasks.named("bootBuildImage") { builder = "paketobuildpacks/builder-jammy-base:latest" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 98debb84d..2f2958b92 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/manifest.yml b/manifest.yml index f0448a029..46fc69fdb 100644 --- a/manifest.yml +++ b/manifest.yml @@ -4,7 +4,9 @@ applications: memory: 1G random-route: true path: build/libs/spring-music-1.0.jar + buildpacks: + - java_buildpack_offline env: JBP_CONFIG_SPRING_AUTO_RECONFIGURATION: '{enabled: false}' SPRING_PROFILES_ACTIVE: http2 - JBP_CONFIG_OPEN_JDK_JRE: '{ jre: { version: 17.+ } }' + JBP_CONFIG_OPEN_JDK_JRE: '{ jre: { version: 25.+ } }' diff --git a/src/main/java/org/cloudfoundry/samples/music/config/SpringApplicationContextInitializer.java b/src/main/java/org/cloudfoundry/samples/music/config/SpringApplicationContextInitializer.java index 308f447ee..9bb5a17ef 100644 --- a/src/main/java/org/cloudfoundry/samples/music/config/SpringApplicationContextInitializer.java +++ b/src/main/java/org/cloudfoundry/samples/music/config/SpringApplicationContextInitializer.java @@ -2,14 +2,14 @@ import io.pivotal.cfenv.core.CfEnv; import io.pivotal.cfenv.core.CfService; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; -import org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration; -import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; -import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.data.mongodb.autoconfigure.DataMongoAutoConfiguration; +import org.springframework.boot.data.mongodb.autoconfigure.DataMongoRepositoriesAutoConfiguration; +import org.springframework.boot.data.redis.autoconfigure.DataRedisAutoConfiguration; +import org.springframework.boot.data.redis.autoconfigure.DataRedisRepositoriesAutoConfiguration; +import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration; +import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.ConfigurableEnvironment; @@ -20,8 +20,6 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -30,17 +28,16 @@ public class SpringApplicationContextInitializer implements ApplicationContextInitializer { - private static final Log logger = LogFactory.getLog(SpringApplicationContextInitializer.class); + private static final Logger logger = LoggerFactory.getLogger(SpringApplicationContextInitializer.class); - private static final Map> profileNameToServiceTags = new HashMap<>(); - static { - profileNameToServiceTags.put("mongodb", Collections.singletonList("mongodb")); - profileNameToServiceTags.put("postgres", Collections.singletonList("postgres")); - profileNameToServiceTags.put("mysql", Collections.singletonList("mysql")); - profileNameToServiceTags.put("redis", Collections.singletonList("redis")); - profileNameToServiceTags.put("oracle", Collections.singletonList("oracle")); - profileNameToServiceTags.put("sqlserver", Collections.singletonList("sqlserver")); - } + private static final Map> profileNameToServiceTags = Map.of( + "mongodb", List.of("mongodb"), + "postgres", List.of("postgres"), + "mysql", List.of("mysql"), + "redis", List.of("redis"), + "oracle", List.of("oracle"), + "sqlserver", List.of("sqlserver") + ); @Override public void initialize(ConfigurableApplicationContext applicationContext) { @@ -115,7 +112,7 @@ private void excludeAutoConfiguration(ConfigurableEnvironment environment) { excludeRedisAutoConfiguration(exclude); } - Map properties = Collections.singletonMap("spring.autoconfigure.exclude", + Map properties = Map.of("spring.autoconfigure.exclude", StringUtils.collectionToCommaDelimitedString(exclude)); PropertySource propertySource = new MapPropertySource("springMusicAutoConfig", properties); @@ -130,15 +127,15 @@ private void excludeDataSourceAutoConfiguration(List exclude) { private void excludeMongoAutoConfiguration(List exclude) { exclude.addAll(Arrays.asList( MongoAutoConfiguration.class.getName(), - MongoDataAutoConfiguration.class.getName(), - MongoRepositoriesAutoConfiguration.class.getName() + DataMongoAutoConfiguration.class.getName(), + DataMongoRepositoriesAutoConfiguration.class.getName() )); } private void excludeRedisAutoConfiguration(List exclude) { exclude.addAll(Arrays.asList( - RedisAutoConfiguration.class.getName(), - RedisRepositoriesAutoConfiguration.class.getName() + DataRedisAutoConfiguration.class.getName(), + DataRedisRepositoriesAutoConfiguration.class.getName() )); } } diff --git a/src/main/java/org/cloudfoundry/samples/music/config/data/RedisConfig.java b/src/main/java/org/cloudfoundry/samples/music/config/data/RedisConfig.java index 96aae56a1..522fd13cb 100644 --- a/src/main/java/org/cloudfoundry/samples/music/config/data/RedisConfig.java +++ b/src/main/java/org/cloudfoundry/samples/music/config/data/RedisConfig.java @@ -1,13 +1,15 @@ package org.cloudfoundry.samples.music.config.data; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.json.JsonMapper; import org.cloudfoundry.samples.music.domain.Album; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration @@ -21,7 +23,7 @@ public RedisTemplate redisTemplate(RedisConnectionFactory redisCo template.setConnectionFactory(redisConnectionFactory); RedisSerializer stringSerializer = new StringRedisSerializer(); - RedisSerializer albumSerializer = new Jackson2JsonRedisSerializer<>(Album.class); + RedisSerializer albumSerializer = albumSerializer(); template.setKeySerializer(stringSerializer); template.setValueSerializer(albumSerializer); @@ -31,4 +33,28 @@ public RedisTemplate redisTemplate(RedisConnectionFactory redisCo return template; } + private RedisSerializer albumSerializer() { + ObjectMapper mapper = JsonMapper.builder().build(); + return new RedisSerializer() { + @Override + public byte[] serialize(Album album) throws SerializationException { + try { + return mapper.writeValueAsBytes(album); + } catch (Exception e) { + throw new SerializationException("Could not serialize Album", e); + } + } + + @Override + public Album deserialize(byte[] bytes) throws SerializationException { + if (bytes == null) return null; + try { + return mapper.readValue(bytes, Album.class); + } catch (Exception e) { + throw new SerializationException("Could not deserialize Album", e); + } + } + }; + } + } diff --git a/src/main/java/org/cloudfoundry/samples/music/domain/Album.java b/src/main/java/org/cloudfoundry/samples/music/domain/Album.java index 3b396bbea..5253bd310 100644 --- a/src/main/java/org/cloudfoundry/samples/music/domain/Album.java +++ b/src/main/java/org/cloudfoundry/samples/music/domain/Album.java @@ -1,18 +1,16 @@ package org.cloudfoundry.samples.music.domain; -import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.UuidGenerator; import jakarta.persistence.Column; import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; @Entity public class Album { @Id @Column(length=40) - @GeneratedValue(generator="randomId") - @GenericGenerator(name="randomId", strategy="org.cloudfoundry.samples.music.domain.RandomIdGenerator") + @UuidGenerator private String id; private String title; diff --git a/src/main/java/org/cloudfoundry/samples/music/repositories/AlbumRepositoryPopulator.java b/src/main/java/org/cloudfoundry/samples/music/repositories/AlbumRepositoryPopulator.java index 658c6f6ca..07ffec28b 100644 --- a/src/main/java/org/cloudfoundry/samples/music/repositories/AlbumRepositoryPopulator.java +++ b/src/main/java/org/cloudfoundry/samples/music/repositories/AlbumRepositoryPopulator.java @@ -1,7 +1,7 @@ package org.cloudfoundry.samples.music.repositories; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.json.JsonMapper; import org.cloudfoundry.samples.music.domain.Album; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.boot.context.event.ApplicationReadyEvent; @@ -9,18 +9,15 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.data.repository.CrudRepository; -import org.springframework.data.repository.init.Jackson2ResourceReader; -import java.util.Collection; +import java.util.List; public class AlbumRepositoryPopulator implements ApplicationListener { - private final Jackson2ResourceReader resourceReader; + private final ObjectMapper objectMapper; private final Resource sourceData; public AlbumRepositoryPopulator() { - ObjectMapper mapper = new ObjectMapper(); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - resourceReader = new Jackson2ResourceReader(mapper); + objectMapper = JsonMapper.builder().build(); sourceData = new ClassPathResource("albums.json"); } @@ -36,22 +33,15 @@ public void onApplicationEvent(ApplicationReadyEvent event) { @SuppressWarnings("unchecked") private void populate(CrudRepository repository) { - Object entity = getEntityFromResource(sourceData); - - if (entity instanceof Collection) { - for (Album album : (Collection) entity) { + try { + List albums = objectMapper.readValue( + sourceData.getInputStream(), + objectMapper.getTypeFactory().constructCollectionType(List.class, Album.class)); + for (Album album : albums) { if (album != null) { repository.save(album); } } - } else { - repository.save(entity); - } - } - - private Object getEntityFromResource(Resource resource) { - try { - return resourceReader.readFrom(resource, this.getClass().getClassLoader()); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/src/main/java/org/cloudfoundry/samples/music/repositories/redis/RedisAlbumRepository.java b/src/main/java/org/cloudfoundry/samples/music/repositories/redis/RedisAlbumRepository.java index 1a3dbfb89..a8cbe749b 100644 --- a/src/main/java/org/cloudfoundry/samples/music/repositories/redis/RedisAlbumRepository.java +++ b/src/main/java/org/cloudfoundry/samples/music/repositories/redis/RedisAlbumRepository.java @@ -13,6 +13,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.stream.StreamSupport; @Repository @Profile("redis") @@ -67,7 +68,8 @@ public Iterable findAll() { @Override public Iterable findAllById(Iterable ids) { - return hashOps.multiGet(ALBUMS_KEY, convertIterableToList(ids)); + return hashOps.multiGet(ALBUMS_KEY, + StreamSupport.stream(ids.spliterator(), false).toList()); } @Override @@ -107,11 +109,5 @@ public void deleteAllById(Iterable ids) { } } - private List convertIterableToList(Iterable iterable) { - List list = new ArrayList<>(); - for (T object : iterable) { - list.add(object); - } - return list; - } + } diff --git a/src/main/java/org/cloudfoundry/samples/music/web/AlbumController.java b/src/main/java/org/cloudfoundry/samples/music/web/AlbumController.java index 7f98276b9..cb473fee1 100644 --- a/src/main/java/org/cloudfoundry/samples/music/web/AlbumController.java +++ b/src/main/java/org/cloudfoundry/samples/music/web/AlbumController.java @@ -20,30 +20,30 @@ public AlbumController(CrudRepository repository) { this.repository = repository; } - @RequestMapping(method = RequestMethod.GET) + @GetMapping public Iterable albums() { return repository.findAll(); } - @RequestMapping(method = RequestMethod.PUT) + @PutMapping public Album add(@RequestBody @Valid Album album) { logger.info("Adding album " + album.getId()); return repository.save(album); } - @RequestMapping(method = RequestMethod.POST) + @PostMapping public Album update(@RequestBody @Valid Album album) { logger.info("Updating album " + album.getId()); return repository.save(album); } - @RequestMapping(value = "/{id}", method = RequestMethod.GET) + @GetMapping("/{id}") public Album getById(@PathVariable String id) { logger.info("Getting album " + id); return repository.findById(id).orElse(null); } - @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) + @DeleteMapping("/{id}") public void deleteById(@PathVariable String id) { logger.info("Deleting album " + id); repository.deleteById(id); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index b1fe20272..c0a583e98 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -28,13 +28,13 @@ spring: on-profile: mysql datasource: url: "jdbc:mysql://localhost/music" - driver-class-name: com.mysql.jdbc.Driver + driver-class-name: com.mysql.cj.jdbc.Driver username: password: jpa: properties: hibernate: - dialect: org.hibernate.dialect.MySQL55Dialect + dialect: org.hibernate.dialect.MySQLDialect --- spring: @@ -49,4 +49,4 @@ spring: jpa: properties: hibernate: - dialect: org.hibernate.dialect.ProgressDialect + dialect: org.hibernate.dialect.PostgreSQLDialect diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html index a990301b8..eac9ebecd 100644 --- a/src/main/resources/static/index.html +++ b/src/main/resources/static/index.html @@ -7,7 +7,7 @@ Spring Music - + @@ -27,16 +27,16 @@ - + - - - + + + - - + + - + diff --git a/src/test/java/org/cloudfoundry/samples/music/ApplicationTests.java b/src/test/java/org/cloudfoundry/samples/music/ApplicationTests.java index 54fc5c179..603cdb3b7 100644 --- a/src/test/java/org/cloudfoundry/samples/music/ApplicationTests.java +++ b/src/test/java/org/cloudfoundry/samples/music/ApplicationTests.java @@ -1,17 +1,13 @@ package org.cloudfoundry.samples.music; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest() -public class ApplicationTests { +@SpringBootTest +class ApplicationTests { @Test - public void contextLoads() { + void contextLoads() { } -} \ No newline at end of file +}