diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 486ee1cfe3b..753acc6ded0 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -134,6 +134,7 @@ jobs: - oauth2app - mysqlapp - mariadbapp + - mssqlapp - flywayapp - undertowapp - eurekaapp diff --git a/src/main/java/tech/jhipster/lite/generator/project/domain/DatabaseType.java b/src/main/java/tech/jhipster/lite/generator/project/domain/DatabaseType.java index fbf50470b75..4a9b0921109 100644 --- a/src/main/java/tech/jhipster/lite/generator/project/domain/DatabaseType.java +++ b/src/main/java/tech/jhipster/lite/generator/project/domain/DatabaseType.java @@ -5,7 +5,7 @@ public enum DatabaseType { MYSQL("mysql"), MARIADB("mariadb"), ORACLE("oracle"), - MSSQL("mssql"), + MSSQL("mssqlserver"), MONGODB("mongodb"), CASSANDRA("cassandra"), COUCHBASE("couchbase"), diff --git a/src/main/java/tech/jhipster/lite/generator/project/domain/GeneratorAction.java b/src/main/java/tech/jhipster/lite/generator/project/domain/GeneratorAction.java index ce1ea359572..ad7c4019024 100644 --- a/src/main/java/tech/jhipster/lite/generator/project/domain/GeneratorAction.java +++ b/src/main/java/tech/jhipster/lite/generator/project/domain/GeneratorAction.java @@ -76,6 +76,8 @@ private GeneratorAction() {} public static final String MYSQL = "mysql"; + public static final String MSSQL = "mssql"; + public static final String FLYWAY = "flyway"; public static final String FLYWAY_USER_AND_AUTHORITY_CHANGELOGS = "flyway-user-and-authority-changelogs"; diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/application/MssqlApplicationService.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/application/MssqlApplicationService.java new file mode 100644 index 00000000000..a7146d3d622 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/application/MssqlApplicationService.java @@ -0,0 +1,19 @@ +package tech.jhipster.lite.generator.server.springboot.database.mssql.application; + +import org.springframework.stereotype.Service; +import tech.jhipster.lite.generator.project.domain.Project; +import tech.jhipster.lite.generator.server.springboot.database.mssql.domain.MssqlService; + +@Service +public class MssqlApplicationService { + + private final MssqlService mssqlService; + + public MssqlApplicationService(MssqlService mssqlService) { + this.mssqlService = mssqlService; + } + + public void init(Project project) { + mssqlService.init(project); + } +} diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/Mssql.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/Mssql.java new file mode 100644 index 00000000000..81ca2d0cb92 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/Mssql.java @@ -0,0 +1,47 @@ +package tech.jhipster.lite.generator.server.springboot.database.mssql.domain; + +import java.util.Map; +import java.util.TreeMap; +import tech.jhipster.lite.generator.buildtool.generic.domain.Dependency; + +public class Mssql { + + public static final String MSSQL_DOCKER_IMAGE_NAME = "mcr.microsoft.com/mssql/server"; + public static final String LICENSE_TEST_CONTAINER_FILE = "container-license-acceptance.txt"; + + private Mssql() {} + + public static String getDockerImageName() { + return MSSQL_DOCKER_IMAGE_NAME; + } + + public static Dependency driver() { + return Dependency.builder().groupId("com.microsoft.sqlserver").artifactId("mssql-jdbc").build(); + } + + public static Map springProperties(String baseName) { + TreeMap result = new TreeMap<>(); + result.put("spring.datasource.url", "jdbc:sqlserver://localhost:1433;database=" + baseName + ";trustServerCertificate=true"); + result.put("spring.datasource.driver-class-name", "com.microsoft.sqlserver.jdbc.SQLServerDriver"); + result.put("spring.datasource.username", "SA"); + result.put("spring.datasource.password", "yourStrong(!)Password"); + + result.put("spring.jpa.hibernate.ddl-auto", "update"); + result.put("spring.jpa.properties.hibernate.format_sql", true); + result.put("spring.jpa.properties.hibernate.dialect", "org.hibernate.dialect.SQLServer2012Dialect"); + return result; + } + + public static Map springPropertiesForTest(String baseName) { + TreeMap result = new TreeMap<>(); + result.put("spring.datasource.driver-class-name", "org.testcontainers.jdbc.ContainerDatabaseDriver"); + result.put( + "spring.datasource.url", + "jdbc:tc:sqlserver:latest://;database=" + baseName + ";trustServerCertificate=true?TC_TMPFS=/testtmpfs:rw" + ); + result.put("spring.datasource.username", "SA"); + result.put("spring.datasource.password", "yourStrong(!)Password"); + result.put("spring.datasource.hikari.maximum-pool-size", 2); + return result; + } +} diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/MssqlDomainService.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/MssqlDomainService.java new file mode 100644 index 00000000000..b471777e313 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/MssqlDomainService.java @@ -0,0 +1,124 @@ +package tech.jhipster.lite.generator.server.springboot.database.mssql.domain; + +import static tech.jhipster.lite.generator.project.domain.Constants.*; +import static tech.jhipster.lite.generator.project.domain.DefaultConfig.*; + +import tech.jhipster.lite.error.domain.Assert; +import tech.jhipster.lite.error.domain.GeneratorException; +import tech.jhipster.lite.generator.buildtool.generic.domain.BuildToolService; +import tech.jhipster.lite.generator.docker.domain.DockerService; +import tech.jhipster.lite.generator.project.domain.DatabaseType; +import tech.jhipster.lite.generator.project.domain.Project; +import tech.jhipster.lite.generator.project.domain.ProjectFile; +import tech.jhipster.lite.generator.project.domain.ProjectRepository; +import tech.jhipster.lite.generator.server.springboot.common.domain.Level; +import tech.jhipster.lite.generator.server.springboot.common.domain.SpringBootCommonService; +import tech.jhipster.lite.generator.server.springboot.database.sqlcommon.domain.SQLCommonService; + +public class MssqlDomainService implements MssqlService { + + public static final String SOURCE = "server/sql"; + + private final BuildToolService buildToolService; + private final SpringBootCommonService springBootCommonService; + private final SQLCommonService sqlCommonService; + private final DockerService dockerService; + private final ProjectRepository projectRepository; + + public MssqlDomainService( + BuildToolService buildToolService, + SpringBootCommonService springBootCommonService, + SQLCommonService sqlCommonService, + DockerService dockerService, + ProjectRepository projectRepository + ) { + this.buildToolService = buildToolService; + this.springBootCommonService = springBootCommonService; + this.sqlCommonService = sqlCommonService; + this.dockerService = dockerService; + this.projectRepository = projectRepository; + } + + @Override + public void init(Project project) { + Assert.notNull("project", project); + + addSpringData(project); + addDriver(project); + addDockerCompose(project); + addJavaFiles(project); + addHikari(project); + addProperties(project); + addHibernateCore(project); + addTestcontainers(project); + addLoggerInConfiguration(project); + } + + private void addSpringData(Project project) { + sqlCommonService.addSpringDataJpa(project); + } + + private void addDriver(Project project) { + buildToolService.addDependency(project, Mssql.driver()); + } + + private void addDockerCompose(Project project) { + project.addDefaultConfig(BASE_NAME); + + dockerService + .getImageNameWithVersion(Mssql.getDockerImageName()) + .ifPresentOrElse( + imageName -> project.addConfig("dockerImageName", imageName), + () -> { + throw new GeneratorException("Version not found for docker image: " + Mssql.getDockerImageName()); + } + ); + sqlCommonService.addDockerComposeTemplate(project, DatabaseType.MSSQL.id()); + } + + private void addHikari(Project project) { + sqlCommonService.addHikari(project); + } + + private void addJavaFiles(Project project) { + sqlCommonService.addJavaFiles(project, DatabaseType.MSSQL.id()); + } + + private void addProperties(Project project) { + springBootCommonService.addPropertiesComment(project, "Database Configuration"); + + Mssql + .springProperties(project.getBaseName().orElse("jhipster")) + .forEach((k, v) -> springBootCommonService.addProperties(project, k, v)); + springBootCommonService.addPropertiesNewLine(project); + } + + private void addTestcontainers(Project project) { + this.sqlCommonService.addTestcontainers( + project, + DatabaseType.MSSQL.id(), + Mssql.springPropertiesForTest(project.getBaseName().orElse("jhipster")) + ); + this.projectRepository.add( + ProjectFile.forProject(project).withSource(SOURCE, Mssql.LICENSE_TEST_CONTAINER_FILE).withDestinationFolder(TEST_RESOURCES) + ); + } + + private void addHibernateCore(Project project) { + sqlCommonService.addHibernateCore(project); + } + + private void addLoggerInConfiguration(Project project) { + sqlCommonService.addLoggers(project); + addLogger(project, "org.reflections", Level.WARN); + addLogger(project, Mssql.driver().getGroupId(), Level.WARN); + + springBootCommonService.addLoggerTest(project, "com.github.dockerjava", Level.WARN); + springBootCommonService.addLoggerTest(project, "org.testcontainers", Level.WARN); + } + + private void addLogger(Project project, String packageName, Level level) { + springBootCommonService.addLogger(project, packageName, level); + springBootCommonService.addLoggerTest(project, packageName, level); + } +} diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/MssqlService.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/MssqlService.java new file mode 100644 index 00000000000..f5ab19a5a02 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/MssqlService.java @@ -0,0 +1,7 @@ +package tech.jhipster.lite.generator.server.springboot.database.mssql.domain; + +import tech.jhipster.lite.generator.project.domain.Project; + +public interface MssqlService { + void init(Project project); +} diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/infrastructure/config/MssqlBeanConfiguration.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/infrastructure/config/MssqlBeanConfiguration.java new file mode 100644 index 00000000000..5ea396556cf --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/infrastructure/config/MssqlBeanConfiguration.java @@ -0,0 +1,40 @@ +package tech.jhipster.lite.generator.server.springboot.database.mssql.infrastructure.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import tech.jhipster.lite.generator.buildtool.generic.domain.BuildToolService; +import tech.jhipster.lite.generator.docker.domain.DockerService; +import tech.jhipster.lite.generator.project.domain.ProjectRepository; +import tech.jhipster.lite.generator.server.springboot.common.domain.SpringBootCommonService; +import tech.jhipster.lite.generator.server.springboot.database.mssql.domain.MssqlDomainService; +import tech.jhipster.lite.generator.server.springboot.database.mssql.domain.MssqlService; +import tech.jhipster.lite.generator.server.springboot.database.sqlcommon.domain.SQLCommonService; + +@Configuration +public class MssqlBeanConfiguration { + + private final BuildToolService buildToolService; + private final SpringBootCommonService springBootCommonService; + private final SQLCommonService sqlCommonService; + private final DockerService dockerService; + private final ProjectRepository projectRepository; + + public MssqlBeanConfiguration( + BuildToolService buildToolService, + SpringBootCommonService springBootCommonService, + SQLCommonService sqlCommonService, + DockerService dockerService, + ProjectRepository projectRepository + ) { + this.buildToolService = buildToolService; + this.springBootCommonService = springBootCommonService; + this.sqlCommonService = sqlCommonService; + this.dockerService = dockerService; + this.projectRepository = projectRepository; + } + + @Bean + public MssqlService mssqlService() { + return new MssqlDomainService(buildToolService, springBootCommonService, sqlCommonService, dockerService, projectRepository); + } +} diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/infrastructure/primary/rest/MssqlResource.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/infrastructure/primary/rest/MssqlResource.java new file mode 100644 index 00000000000..90df6803c6b --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/mssql/infrastructure/primary/rest/MssqlResource.java @@ -0,0 +1,35 @@ +package tech.jhipster.lite.generator.server.springboot.database.mssql.infrastructure.primary.rest; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import tech.jhipster.lite.generator.project.domain.GeneratorAction; +import tech.jhipster.lite.generator.project.domain.Project; +import tech.jhipster.lite.generator.project.infrastructure.primary.dto.ProjectDTO; +import tech.jhipster.lite.generator.server.springboot.database.mssql.application.MssqlApplicationService; +import tech.jhipster.lite.technical.infrastructure.primary.annotation.GeneratorStep; + +@RestController +@RequestMapping("/api/servers/spring-boot/databases/mssql") +@Tag(name = "Spring Boot - Database") +class MssqlResource { + + private final MssqlApplicationService mongodbApplicationService; + + public MssqlResource(MssqlApplicationService mongodbApplicationService) { + this.mongodbApplicationService = mongodbApplicationService; + } + + @Operation(summary = "Add MSSQL drivers and dependencies, with testcontainers") + @ApiResponse(responseCode = "500", description = "An error occurred while adding MSSQL") + @PostMapping + @GeneratorStep(id = GeneratorAction.MSSQL) + public void init(@RequestBody ProjectDTO projectDTO) { + Project project = ProjectDTO.toProject(projectDTO); + mongodbApplicationService.init(project); + } +} diff --git a/src/main/resources/generator/dependencies/Dockerfile b/src/main/resources/generator/dependencies/Dockerfile index e17011c0961..7ce217ebcdb 100644 --- a/src/main/resources/generator/dependencies/Dockerfile +++ b/src/main/resources/generator/dependencies/Dockerfile @@ -6,6 +6,7 @@ FROM jboss/keycloak:16.1.1 FROM mariadb:10.8.3 FROM mongo:5.0.8 FROM mysql:8.0.29 +FROM mcr.microsoft.com/mssql/server:2019-CU15-ubuntu-20.04 FROM postgres:14.3 FROM confluentinc/cp-zookeeper:7.1.1 FROM confluentinc/cp-kafka:7.1.1 diff --git a/src/main/resources/generator/server/springboot/database/mssqlserver/DatabaseConfiguration.java.mustache b/src/main/resources/generator/server/springboot/database/mssqlserver/DatabaseConfiguration.java.mustache new file mode 100644 index 00000000000..0ad358c0ffc --- /dev/null +++ b/src/main/resources/generator/server/springboot/database/mssqlserver/DatabaseConfiguration.java.mustache @@ -0,0 +1,10 @@ +package {{packageName}}.technical.infrastructure.secondary.mssqlserver; + +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableJpaRepositories({ "{{packageName}}" }) +@EnableTransactionManagement +public class DatabaseConfiguration {} diff --git a/src/main/resources/generator/server/springboot/database/mssqlserver/mssqlserver.yml.mustache b/src/main/resources/generator/server/springboot/database/mssqlserver/mssqlserver.yml.mustache new file mode 100644 index 00000000000..dd3445489da --- /dev/null +++ b/src/main/resources/generator/server/springboot/database/mssqlserver/mssqlserver.yml.mustache @@ -0,0 +1,18 @@ +# This configuration is intended for development purpose, it's **your** responsibility to harden it for production +version: '2' +services: + msmssql-mssql: + image: {{dockerImageName}} + # volumes: + # - ~/volumes/jhipster/{{baseName}}/mssql/:/var/lib/mssql/ + environment: + - ACCEPT_EULA=Y + - SA_PASSWORD=yourStrong(!)Password + - MSSQL_DATABASE={{baseName}} + - MSSQL_PID=Express + - MSSQL_SLEEP=60 + # If you want to expose these ports outside your dev PC, + # remove the "127.0.0.1:" prefix + ports: + - 127.0.0.1:1433:1433 + command: /bin/bash -c '/opt/mssql/bin/sqlservr & echo "wait $$MSSQL_SLEEP sec for DB to start "; sleep $$MSSQL_SLEEP; /opt/mssql-tools/bin/sqlcmd -U sa -P $$SA_PASSWORD -d tempdb -q "EXIT(CREATE DATABASE $$MSSQL_DATABASE)"; wait;' diff --git a/src/main/resources/generator/server/sql/container-license-acceptance.txt b/src/main/resources/generator/server/sql/container-license-acceptance.txt new file mode 100644 index 00000000000..e97c27c2a9b --- /dev/null +++ b/src/main/resources/generator/server/sql/container-license-acceptance.txt @@ -0,0 +1 @@ +mcr.microsoft.com/mssql/server:latest diff --git a/src/test/java/tech/jhipster/lite/generator/docker/application/DockerApplicationServiceIT.java b/src/test/java/tech/jhipster/lite/generator/docker/application/DockerApplicationServiceIT.java index 236f12e4aa7..aa660d97cc6 100644 --- a/src/test/java/tech/jhipster/lite/generator/docker/application/DockerApplicationServiceIT.java +++ b/src/test/java/tech/jhipster/lite/generator/docker/application/DockerApplicationServiceIT.java @@ -1,6 +1,6 @@ package tech.jhipster.lite.generator.docker.application; -import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.*; import java.util.Optional; import org.junit.jupiter.api.Test; @@ -19,7 +19,7 @@ void shouldGetImageNameWithVersion() { Optional imageNameWithVersion = dockerApplicationService.getImageNameWithVersion("mysql"); // Then - assertThat(imageNameWithVersion).contains("mysql:8.0.28"); + assertThat(imageNameWithVersion.get()).contains("mysql:"); } @Test @@ -28,6 +28,6 @@ void shouldGetImageVersion() { Optional imageVersion = dockerApplicationService.getImageVersion("mysql"); // Then - assertThat(imageVersion).contains("8.0.28"); + assertThat(imageVersion).contains("8.0.29"); } } diff --git a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mongodb/MongodbAssert.java b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mongodb/MongodbAssert.java index 5dc885a47cf..28b6040f131 100644 --- a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mongodb/MongodbAssert.java +++ b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mongodb/MongodbAssert.java @@ -1,16 +1,9 @@ package tech.jhipster.lite.generator.server.springboot.database.mongodb; -import static tech.jhipster.lite.TestUtils.assertFileContent; -import static tech.jhipster.lite.TestUtils.assertFileExist; -import static tech.jhipster.lite.common.domain.FileUtils.getPath; -import static tech.jhipster.lite.generator.project.domain.Constants.MAIN_JAVA; -import static tech.jhipster.lite.generator.project.domain.Constants.MAIN_RESOURCES; -import static tech.jhipster.lite.generator.project.domain.Constants.POM_XML; -import static tech.jhipster.lite.generator.project.domain.Constants.TEST_JAVA; -import static tech.jhipster.lite.generator.project.domain.Constants.TEST_RESOURCES; -import static tech.jhipster.lite.generator.server.springboot.core.domain.SpringBoot.APPLICATION_PROPERTIES; -import static tech.jhipster.lite.generator.server.springboot.core.domain.SpringBoot.LOGGING_CONFIGURATION; -import static tech.jhipster.lite.generator.server.springboot.core.domain.SpringBoot.LOGGING_TEST_CONFIGURATION; +import static tech.jhipster.lite.TestUtils.*; +import static tech.jhipster.lite.common.domain.FileUtils.*; +import static tech.jhipster.lite.generator.project.domain.Constants.*; +import static tech.jhipster.lite.generator.server.springboot.core.domain.SpringBoot.*; import java.util.List; import tech.jhipster.lite.common.domain.FileUtils; @@ -57,7 +50,7 @@ public static void assertDependencies(Project project) { public static void assertDockerMongodb(Project project) { assertFileExist(project, "src/main/docker/mongodb.yml"); - assertFileContent(project, "src/main/docker/mongodb.yml", "mongo:5.0.6"); + assertFileContent(project, "src/main/docker/mongodb.yml", "mongo:"); assertFileContent(project, "src/main/docker/mongodb.yml", "- 127.0.0.1:27017:27017"); } diff --git a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/application/MssqlApplicationServiceIT.java b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/application/MssqlApplicationServiceIT.java new file mode 100644 index 00000000000..3375e280e70 --- /dev/null +++ b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/application/MssqlApplicationServiceIT.java @@ -0,0 +1,123 @@ +package tech.jhipster.lite.generator.server.springboot.database.mssql.application; + +import static tech.jhipster.lite.TestUtils.*; +import static tech.jhipster.lite.common.domain.FileUtils.*; +import static tech.jhipster.lite.generator.project.domain.Constants.*; +import static tech.jhipster.lite.generator.server.springboot.core.domain.SpringBoot.*; + +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import tech.jhipster.lite.IntegrationTest; +import tech.jhipster.lite.generator.buildtool.maven.application.MavenApplicationService; +import tech.jhipster.lite.generator.init.application.InitApplicationService; +import tech.jhipster.lite.generator.project.domain.Project; +import tech.jhipster.lite.generator.server.springboot.core.application.SpringBootApplicationService; +import tech.jhipster.lite.generator.server.springboot.database.mssql.domain.Mssql; + +@IntegrationTest +class MssqlApplicationServiceIT { + + @Autowired + MssqlApplicationService mssqlApplicationService; + + @Autowired + InitApplicationService initApplicationService; + + @Autowired + MavenApplicationService mavenApplicationService; + + @Autowired + SpringBootApplicationService springBootApplicationService; + + @Test + void shouldInit() { + Project project = tmpProject(); + initApplicationService.init(project); + mavenApplicationService.addPomXml(project); + springBootApplicationService.init(project); + + mssqlApplicationService.init(project); + + assertFileContent(project, POM_XML, springBootStarterDataJpa()); + assertFileContent(project, POM_XML, mssqlDriver()); + assertFileContent(project, POM_XML, hibernateCore()); + assertFileContent(project, POM_XML, hikari()); + + assertFileExist(project, "src/main/docker/mssqlserver.yml"); + assertFileContent(project, "src/main/docker/mssqlserver.yml", "MSSQL_DATABASE=jhipster"); + + String mariadbPath = getPath("com/mycompany/myapp/technical/infrastructure/secondary/mssqlserver"); + assertFileExist(project, getPath(MAIN_JAVA, mariadbPath, "DatabaseConfiguration.java")); + + assertFileContent( + project, + getPath(MAIN_RESOURCES, "config", APPLICATION_PROPERTIES), + "spring.datasource.url=jdbc:sqlserver://localhost:1433;database=jhipster" + ); + assertTestContainersWasAdded(project); + assertLoggerInConfig(project); + } + + private void assertTestContainersWasAdded(Project project) { + assertFileContent(project, POM_XML, ""); + assertFileContent(project, POM_XML, ""); + assertFileContent(project, POM_XML, testcontainers()); + assertFileContent( + project, + getPath(TEST_RESOURCES, "config/application.properties"), + "spring.datasource.password=yourStrong(!)Password" + ); + assertFileContent(project, getPath(TEST_RESOURCES, "config/application.properties"), "spring.datasource.username=SA"); + assertFileContent( + project, + getPath(TEST_RESOURCES, "config/application.properties"), + "spring.datasource.url=jdbc:tc:sqlserver:latest://;database=jhipster;trustServerCertificate=true?TC_TMPFS=/testtmpfs:rw" + ); + assertFileExist(project, "src/test/resources/container-license-acceptance.txt"); + } + + private void assertLoggerInConfig(Project project) { + assertFileContent( + project, + getPath(MAIN_RESOURCES, LOGGING_CONFIGURATION), + List.of( + "", + "", + "" + ) + ); + } + + private List springBootStarterDataJpa() { + return List.of( + "", + "org.springframework.boot", + "spring-boot-starter-data-jpa", + "" + ); + } + + private List mssqlDriver() { + return List.of("", "com.microsoft.sqlserver", "mssql-jdbc", ""); + } + + private List hibernateCore() { + return List.of("", "org.hibernate", "hibernate-core", ""); + } + + private List hikari() { + return List.of("", "com.zaxxer", "HikariCP", ""); + } + + private List testcontainers() { + return List.of( + "", + "org.testcontainers", + "mssqlserver", + "${testcontainers.version}", + "test", + "" + ); + } +} diff --git a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/MssqlDomainServiceUnitTest.java b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/MssqlDomainServiceUnitTest.java new file mode 100644 index 00000000000..10afa9e37e3 --- /dev/null +++ b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/MssqlDomainServiceUnitTest.java @@ -0,0 +1,85 @@ +package tech.jhipster.lite.generator.server.springboot.database.mssql.domain; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; +import static tech.jhipster.lite.TestUtils.*; + +import java.util.Optional; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import tech.jhipster.lite.UnitTest; +import tech.jhipster.lite.error.domain.GeneratorException; +import tech.jhipster.lite.error.domain.MissingMandatoryValueException; +import tech.jhipster.lite.generator.buildtool.generic.domain.BuildToolService; +import tech.jhipster.lite.generator.buildtool.generic.domain.Dependency; +import tech.jhipster.lite.generator.docker.domain.DockerService; +import tech.jhipster.lite.generator.project.domain.Project; +import tech.jhipster.lite.generator.project.domain.ProjectFile; +import tech.jhipster.lite.generator.project.domain.ProjectRepository; +import tech.jhipster.lite.generator.server.springboot.common.domain.Level; +import tech.jhipster.lite.generator.server.springboot.common.domain.SpringBootCommonService; +import tech.jhipster.lite.generator.server.springboot.database.sqlcommon.domain.SQLCommonService; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class MssqlDomainServiceUnitTest { + + @Mock + BuildToolService buildToolService; + + @Mock + SpringBootCommonService springBootCommonService; + + @Mock + SQLCommonService sqlCommonService; + + @Mock + ProjectRepository projectRepository; + + @Mock + DockerService dockerService; + + @InjectMocks + MssqlDomainService mssqlDomainService; + + @Test + void shouldNotInitWithoutProject() { + assertThatThrownBy(() -> mssqlDomainService.init(null)) + .isExactlyInstanceOf(MissingMandatoryValueException.class) + .hasMessageContaining("project"); + } + + @Test + void shouldInit() { + Project project = tmpProjectWithPomXml(); + + when(dockerService.getImageNameWithVersion("mcr.microsoft.com/mssql/server")).thenReturn(Optional.of("mssql:0.0.0")); + + mssqlDomainService.init(project); + + verify(buildToolService).addDependency(any(Project.class), any(Dependency.class)); + + verify(springBootCommonService, times(4)).addLoggerTest(any(Project.class), anyString(), any(Level.class)); + + verify(sqlCommonService).addTestcontainers(any(Project.class), anyString(), anyMap()); + verify(sqlCommonService).addSpringDataJpa(project); + verify(sqlCommonService).addHibernateCore(project); + verify(sqlCommonService).addDockerComposeTemplate(project, "mssqlserver"); + verify(sqlCommonService).addJavaFiles(project, "mssqlserver"); + verify(projectRepository).add(any(ProjectFile.class)); + verify(springBootCommonService, times(7)).addProperties(eq(project), any(), any()); + verify(springBootCommonService, times(2)).addLogger(eq(project), any(), any()); + verify(sqlCommonService).addLoggers(project); + } + + @Test + void shouldThrowExceptionWhenImageVersionNotFound() { + Project project = tmpProject(); + + assertThatThrownBy(() -> mssqlDomainService.init(project)).isInstanceOf(GeneratorException.class).hasMessageContaining("mssql"); + } +} diff --git a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/MssqlTest.java b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/MssqlTest.java new file mode 100644 index 00000000000..81c5e876389 --- /dev/null +++ b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/domain/MssqlTest.java @@ -0,0 +1,45 @@ +package tech.jhipster.lite.generator.server.springboot.database.mssql.domain; + +import static org.assertj.core.api.Assertions.*; + +import java.util.Map; +import org.junit.jupiter.api.Test; +import tech.jhipster.lite.UnitTest; + +@UnitTest +class MssqlTest { + + @Test + void shouldGetDockerImageName() { + assertThat(Mssql.getDockerImageName()).isEqualTo("mcr.microsoft.com/mssql/server"); + } + + @Test + void shouldGetSpringProperties() { + Map springProperties = Mssql.springProperties("baseName"); + + assertThat(springProperties) + .containsEntry("spring.datasource.url", "jdbc:sqlserver://localhost:1433;database=baseName;trustServerCertificate=true") + .containsEntry("spring.datasource.driver-class-name", "com.microsoft.sqlserver.jdbc.SQLServerDriver") + .containsEntry("spring.datasource.username", "SA") + .containsEntry("spring.datasource.password", "yourStrong(!)Password") + .containsEntry("spring.jpa.hibernate.ddl-auto", "update") + .containsEntry("spring.jpa.properties.hibernate.dialect", "org.hibernate.dialect.SQLServer2012Dialect") + .containsEntry("spring.jpa.properties.hibernate.format_sql", true); + } + + @Test + void shouldGetSpringPropertiesForTest() { + Map springProperties = Mssql.springPropertiesForTest("baseName"); + + assertThat(springProperties) + .containsEntry("spring.datasource.driver-class-name", "org.testcontainers.jdbc.ContainerDatabaseDriver") + .containsEntry( + "spring.datasource.url", + "jdbc:tc:sqlserver:latest://;database=baseName;trustServerCertificate=true?TC_TMPFS=/testtmpfs:rw" + ) + .containsEntry("spring.datasource.username", "SA") + .containsEntry("spring.datasource.password", "yourStrong(!)Password") + .containsEntry("spring.datasource.hikari.maximum-pool-size", 2); + } +} diff --git a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/infrastructure/config/MssqlBeanConfigurationIT.java b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/infrastructure/config/MssqlBeanConfigurationIT.java new file mode 100644 index 00000000000..4b0984e35bf --- /dev/null +++ b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/infrastructure/config/MssqlBeanConfigurationIT.java @@ -0,0 +1,21 @@ +package tech.jhipster.lite.generator.server.springboot.database.mssql.infrastructure.config; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import tech.jhipster.lite.IntegrationTest; +import tech.jhipster.lite.generator.server.springboot.database.mssql.domain.MssqlDomainService; + +@IntegrationTest +class MssqlBeanConfigurationIT { + + @Autowired + ApplicationContext applicationContext; + + @Test + void shouldGetBean() { + assertThat(applicationContext.getBean("mssqlService")).isNotNull().isInstanceOf(MssqlDomainService.class); + } +} diff --git a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/infrastructure/primary/rest/MssqlResourceIT.java b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/infrastructure/primary/rest/MssqlResourceIT.java new file mode 100644 index 00000000000..bc0c3433d39 --- /dev/null +++ b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mssql/infrastructure/primary/rest/MssqlResourceIT.java @@ -0,0 +1,57 @@ +package tech.jhipster.lite.generator.server.springboot.database.mssql.infrastructure.primary.rest; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import static tech.jhipster.lite.TestUtils.*; +import static tech.jhipster.lite.common.domain.FileUtils.*; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import tech.jhipster.lite.IntegrationTest; +import tech.jhipster.lite.TestUtils; +import tech.jhipster.lite.generator.buildtool.maven.application.MavenApplicationService; +import tech.jhipster.lite.generator.init.application.InitApplicationService; +import tech.jhipster.lite.generator.project.domain.Project; +import tech.jhipster.lite.generator.project.infrastructure.primary.dto.ProjectDTO; +import tech.jhipster.lite.generator.server.springboot.core.application.SpringBootApplicationService; + +@IntegrationTest +@AutoConfigureMockMvc +class MssqlResourceIT { + + @Autowired + InitApplicationService initApplicationService; + + @Autowired + MavenApplicationService mavenApplicationService; + + @Autowired + SpringBootApplicationService springBootApplicationService; + + @Autowired + MockMvc mockMvc; + + @Test + void shouldInit() throws Exception { + ProjectDTO projectDTO = TestUtils.readFileToObject("json/chips.json", ProjectDTO.class).folder(tmpDirForTest()); + Project project = ProjectDTO.toProject(projectDTO); + initApplicationService.init(project); + mavenApplicationService.init(project); + springBootApplicationService.init(project); + + mockMvc + .perform( + post("/api/servers/spring-boot/databases/mssql") + .contentType(MediaType.APPLICATION_JSON) + .content(TestUtils.convertObjectToJsonBytes(projectDTO)) + ) + .andExpect(status().isOk()); + + String projectPath = projectDTO.getFolder(); + + assertFileExist(projectPath, "src/main/docker/mssqlserver.yml"); + } +} diff --git a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mysql/application/MySQLApplicationServiceIT.java b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mysql/application/MySQLApplicationServiceIT.java index f10f7300fc8..41f99a66e96 100644 --- a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mysql/application/MySQLApplicationServiceIT.java +++ b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/mysql/application/MySQLApplicationServiceIT.java @@ -1,18 +1,10 @@ package tech.jhipster.lite.generator.server.springboot.database.mysql.application; -import static tech.jhipster.lite.TestUtils.assertFileContent; -import static tech.jhipster.lite.TestUtils.assertFileExist; -import static tech.jhipster.lite.TestUtils.tmpProject; -import static tech.jhipster.lite.common.domain.FileUtils.getPath; -import static tech.jhipster.lite.generator.project.domain.Constants.MAIN_JAVA; -import static tech.jhipster.lite.generator.project.domain.Constants.MAIN_RESOURCES; -import static tech.jhipster.lite.generator.project.domain.Constants.POM_XML; -import static tech.jhipster.lite.generator.project.domain.Constants.TEST_RESOURCES; -import static tech.jhipster.lite.generator.project.domain.DefaultConfig.BASE_NAME; -import static tech.jhipster.lite.generator.project.domain.DefaultConfig.PACKAGE_NAME; -import static tech.jhipster.lite.generator.server.springboot.core.domain.SpringBoot.APPLICATION_PROPERTIES; -import static tech.jhipster.lite.generator.server.springboot.core.domain.SpringBoot.LOGGING_CONFIGURATION; -import static tech.jhipster.lite.generator.server.springboot.core.domain.SpringBoot.LOGGING_TEST_CONFIGURATION; +import static tech.jhipster.lite.TestUtils.*; +import static tech.jhipster.lite.common.domain.FileUtils.*; +import static tech.jhipster.lite.generator.project.domain.Constants.*; +import static tech.jhipster.lite.generator.project.domain.DefaultConfig.*; +import static tech.jhipster.lite.generator.server.springboot.core.domain.SpringBoot.*; import java.util.List; import org.junit.jupiter.api.DisplayName; @@ -75,7 +67,7 @@ private void assertTestContainersWereAdded(Project project) { assertFileContent( project, getPath(TEST_RESOURCES, "config/application.properties"), - List.of("spring.datasource.url=jdbc:tc:mysql:8.0.28:///jhipster", "spring.datasource.username=jhipster") + List.of("spring.datasource.url=jdbc:tc:mysql:", "spring.datasource.username=jhipster") ); } @@ -131,7 +123,7 @@ void shouldAddDockerCompose() { mysqlApplicationService.addDockerCompose(project); assertFileExist(project, "src/main/docker/mysql.yml"); - assertFileContent(project, "src/main/docker/mysql.yml", "mysql:8.0.28"); + assertFileContent(project, "src/main/docker/mysql.yml", "mysql:"); assertFileContent(project, "src/main/docker/mysql.yml", "MYSQL_DATABASE=jhipster"); } diff --git a/src/test/resources/generator/dependencies/Dockerfile b/src/test/resources/generator/dependencies/Dockerfile index 2144e3e986d..da08103188f 100644 --- a/src/test/resources/generator/dependencies/Dockerfile +++ b/src/test/resources/generator/dependencies/Dockerfile @@ -4,8 +4,9 @@ FROM jhipster/consul-config-loader:v0.4.1 FROM jhipster/jhipster-registry:v7.3.0 FROM jboss/keycloak:16.1.1 FROM mariadb:10.8.2 -FROM mongo:5.0.6 -FROM mysql:8.0.28 +FROM mongo:5.0.8 +FROM mysql:8.0.29 +FROM mcr.microsoft.com/mssql/server:2019-CU15-ubuntu-20.04 FROM postgres:14.2 FROM confluentinc/cp-zookeeper:7.0.1 FROM confluentinc/cp-kafka:7.0.1 diff --git a/tests-ci/config/mssqlapp.json b/tests-ci/config/mssqlapp.json new file mode 100644 index 00000000000..e79b931c23e --- /dev/null +++ b/tests-ci/config/mssqlapp.json @@ -0,0 +1,8 @@ +{ + "folder": "/tmp/jhlite/mssqlapp", + "generator-jhipster": { + "projectName": "Mssql Project", + "baseName": "mssqlapp", + "packageName": "tech.jhipster.mssqlapp" + } +} diff --git a/tests-ci/generate.sh b/tests-ci/generate.sh index 58c7dd12b50..49b860a5058 100755 --- a/tests-ci/generate.sh +++ b/tests-ci/generate.sh @@ -148,6 +148,15 @@ elif [[ $application == 'mariadbapp' ]]; then callApi "/api/servers/spring-boot/caches/ehcache/xml-configuration" +elif [[ $application == 'mssqlapp' ]]; then + springboot_mvc + sonar_back + + callApi "/api/servers/spring-boot/api-documentations/springdoc/init" + callApi "/api/servers/spring-boot/features/dummy" + + callApi "/api/servers/spring-boot/databases/mssql" + elif [[ $application == 'flywayapp' ]]; then springboot_mvc sonar_back