From e571ebe84e3098a2818f26621bfcd3c4b1098570 Mon Sep 17 00:00:00 2001 From: Jason Schindler Date: Thu, 3 Dec 2020 17:32:56 -0600 Subject: [PATCH 1/7] Adds more entity types to CI (#199) --- .github/workflows/samples.yml | 2 + test-integration/samples/jdl-default-app.jdl | 189 +++++++++++++++++++ test-integration/scripts/99-cleanup.sh | 5 +- 3 files changed, 193 insertions(+), 3 deletions(-) create mode 100644 test-integration/samples/jdl-default-app.jdl diff --git a/.github/workflows/samples.yml b/.github/workflows/samples.yml index d134323f..6c4e0db6 100644 --- a/.github/workflows/samples.yml +++ b/.github/workflows/samples.yml @@ -46,6 +46,7 @@ jobs: - gradle-oauth-angular - mvn-ms-consul-jwt - gradle-ms-eureka-oauth + - jdl-default-app include: - app-type: gradle-jwt-react - app-type: mvn-jwt-angular @@ -55,6 +56,7 @@ jobs: - app-type: gradle-oauth-angular - app-type: mvn-ms-consul-jwt - app-type: gradle-ms-eureka-oauth + - app-type: jdl-default-app steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 diff --git a/test-integration/samples/jdl-default-app.jdl b/test-integration/samples/jdl-default-app.jdl new file mode 100644 index 00000000..a30c4a4e --- /dev/null +++ b/test-integration/samples/jdl-default-app.jdl @@ -0,0 +1,189 @@ +// Inspired by: https://github.com/jhipster/generator-jhipster/blob/main/test-integration/samples/jdl-default/app.jdl + +application { + config { + applicationType monolith + baseName jhipsterSampleApplication + blueprints [generator-jhipster-micronaut] + packageName tech.jhipster.sample + authenticationType jwt + prodDatabaseType postgresql + buildTool maven + searchEngine false + testFrameworks [] + clientFramework angularX + enableTranslation true + nativeLanguage en + languages [ en, fr ] + } + entities * +} + +entity Bank { + bankNumber Integer +} +entity BankAccount { + name String required + bankNumber Integer + agencyNumber Long + lastOperationDuration Float + meanOperationDuration Double + balance BigDecimal required + openingDay LocalDate + lastOperationDate Instant + active Boolean + accountType BankAccountType + attachment AnyBlob + description TextBlob +} +entity TheLabel { + labelName String required minlength(3) +} +entity Operation { + date Instant required + description String + amount BigDecimal required +} + +enum BankAccountType { + CHECKING (checking_account), + SAVINGS (savings_account), + LOAN (loan_account) +} + +entity Department { + name String required, + description TextBlob, + advertisement Blob, + logo ImageBlob +} + +/** + * JobHistory comment. + */ +entity JobHistory { + startDate ZonedDateTime, + endDate ZonedDateTime, + language Language +} + +enum Language { + FRENCH, ENGLISH, SPANISH +} + +enum JobType { + BOSS, SLAVE +} + +entity Job { + title String minlength(5) maxlength(25), + type JobType, + minSalary Long, + maxSalary Long +} + +/** + * The Employee entity. + * Second line in javadoc. + */ +entity Employee { + /** + * The firstname attribute. + */ + firstName String, + lastName String, + email String, + phoneNumber String, + hireDate ZonedDateTime, + salary Long, + commissionPct Long +} + +entity Location { + streetAddress String, + postalCode String, + city String, + stateProvince String +} + +entity Task { + title String, + description String +} + +entity GoldenBadge { + name String +} + +entity SilverBadge { + name String +} + +entity Identifier { + name String required unique +} + +entity Country { + name String +} + +entity Region { + name String +} + +relationship OneToOne { + Department{location} to Location, + Employee{user(login)} to User with jpaDerivedIdentifier +} + +relationship OneToMany { + BankAccount{operation} to Operation{bankAccount(name)} +} +relationship ManyToOne { + BankAccount{user(login)} to User +} +relationship ManyToMany { + Operation{theLabel(labelName)} to TheLabel{operation} +} + +relationship OneToMany { + /** + * A relationship + */ + Department{employee} to + /** + * Another side of the same relationship, + */ + Employee{department}, + Employee{job} to Job{emp(lastName)}, + Location{country} to Country, + Country{area(name)} to Region +} + +relationship ManyToOne { + Employee{manager(lastName)} to Employee, + Employee{sibag(name) required} to SilverBadge, + Employee{gobag(name) required} to GoldenBadge, + SilverBadge{iden(name) required} to Identifier, + GoldenBadge{iden(name) required} to Identifier +} + +relationship ManyToMany { + JobHistory{department} to Department{history}, + JobHistory{job} to Job{history}, + JobHistory{emp(firstName)} to Employee{history}, + Job{chore(title)} to Task{linkedJob(title)}, + Bank{account} to BankAccount{bank} +} + +dto BankAccount, Employee, Department, Location, Country, Region, SilverBadge, GoldenBadge, Identifier with mapstruct + +angularSuffix BankAccount with mySuffix +// filter BankAccount, Employee +clientRootFolder BankAccount, TheLabel, Operation with test-root + +paginate TheLabel, Job with pagination +paginate Operation, JobHistory, Employee with infinite-scroll + +service TheLabel, Employee, Department, Region with serviceClass +service BankAccount, Location, Country with serviceImpl diff --git a/test-integration/scripts/99-cleanup.sh b/test-integration/scripts/99-cleanup.sh index dd14c9a8..c36faf00 100755 --- a/test-integration/scripts/99-cleanup.sh +++ b/test-integration/scripts/99-cleanup.sh @@ -4,8 +4,6 @@ set -ex mv backup.eslintrc.json .eslintrc.json -rm -rf ./sample-output/ - SCRIPT_FOLDER=`dirname "$0"` UTIL_FOLDER="$SCRIPT_FOLDER/util" @@ -20,5 +18,6 @@ else echo "Protractor is not being used in this sample" fi -cd ../../ +cd .. +rm -rf ./sample-output/ From aab88e453416787cf144a0ae6d13b7b186397084 Mon Sep 17 00:00:00 2001 From: Jason Schindler Date: Thu, 3 Dec 2020 18:10:27 -0600 Subject: [PATCH 2/7] Replaces old ApiModel and ApiModelProperty Swagger annotations with v3 Schema (#199) --- .../src/main/java/package/domain/Entity.java.ejs | 12 +++++------- .../main/java/package/service/dto/EntityDTO.java.ejs | 12 +++++------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/generators/entity-server/templates/src/main/java/package/domain/Entity.java.ejs b/generators/entity-server/templates/src/main/java/package/domain/Entity.java.ejs index 25ecb6f5..8b8156f0 100644 --- a/generators/entity-server/templates/src/main/java/package/domain/Entity.java.ejs +++ b/generators/entity-server/templates/src/main/java/package/domain/Entity.java.ejs @@ -53,10 +53,8 @@ _%> import com.fasterxml.jackson.annotation.JsonIgnore; <%_ } if (importJsonIgnoreProperties === true) { _%> import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -<%_ } if (!hasDto && typeof javadoc != 'undefined') { _%> -import io.swagger.annotations.ApiModel; -<%_ } if (!hasDto && importApiModelProperty === true) { _%> -import io.swagger.annotations.ApiModelProperty; +<%_ } if (!hasDto && (typeof javadoc != 'undefined' || importApiModelProperty)) { _%> +import io.swagger.v3.oas.annotations.media.Schema; <%_ } if (enableHibernateCache) { _%> import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @@ -128,7 +126,7 @@ import static <%= packageName %>.config.Constants.ID_DELIMITER; <%_ } else { _%> <%- formatAsClassJavadoc(javadoc) %> <%_ if (!hasDto) { _%> -@ApiModel(description = "<%- formatAsApiDescription(javadoc) %>") +@Schema(description = "<%- formatAsApiDescription(javadoc) %>") <%_ } _%> <%_ } _%> <%_ if (databaseType === 'sql') { _%> @@ -199,7 +197,7 @@ public class <%= asEntity(entityClass) %> implements Serializable { <%- include('../common/field_validators') -%> <%_ } _%> <%_ if (!hasDto && typeof fields[idx].javadoc != 'undefined') { _%> - @ApiModelProperty(value = "<%- formatAsApiDescription(fields[idx].javadoc) %>"<% if (required) { %>, required = true<% } %>) + @Schema(description = "<%- formatAsApiDescription(fields[idx].javadoc) %>"<% if (required) { %>, required = true<% } %>) <%_ } _%> <%_ if (databaseType === 'sql') { if (fields[idx].fieldIsEnum) { _%> @@ -265,7 +263,7 @@ public class <%= asEntity(entityClass) %> implements Serializable { if (typeof relationships[idx].javadoc != 'undefined') { _%> <%- formatAsFieldJavadoc(relationships[idx].javadoc) %> <%_ if (!hasDto) { _%> - @ApiModelProperty(value = "<%- formatAsApiDescription(relationships[idx].javadoc) %>") + @Schema(description = "<%- formatAsApiDescription(relationships[idx].javadoc) %>") <%_ } _%> <%_ } if (relationshipType === 'one-to-many') { diff --git a/generators/entity-server/templates/src/main/java/package/service/dto/EntityDTO.java.ejs b/generators/entity-server/templates/src/main/java/package/service/dto/EntityDTO.java.ejs index 1a4a4a8a..d207aa36 100644 --- a/generators/entity-server/templates/src/main/java/package/service/dto/EntityDTO.java.ejs +++ b/generators/entity-server/templates/src/main/java/package/service/dto/EntityDTO.java.ejs @@ -22,10 +22,8 @@ import io.micronaut.core.annotation.Introspected; <%_ let { importApiModelProperty, importJsonIgnore, importJsonIgnoreProperties, importSet, uniqueEnums } = _processJavaEntityImports(fields, relationships); _%> -<%_ if (typeof javadoc != 'undefined') { _%> -import io.swagger.annotations.ApiModel; -<%_ } if (importApiModelProperty === true) { _%> -import io.swagger.annotations.ApiModelProperty; +<%_ if (typeof javadoc != 'undefined' || importApiModelProperty) { _%> +import io.swagger.v3.oas.annotations.media.Schema; <%_ } _%> <%_ if (fieldsContainInstant) { _%> import java.time.Instant; @@ -68,7 +66,7 @@ import <%= packageName %>.domain.enumeration.<%= element %>; * A DTO for the {@link <%= packageName %>.domain.<%= asEntity(entityClass) %>} entity. */ <%_ if (typeof javadoc !== 'undefined') { _%> -@ApiModel(description = "<%- formatAsApiDescription(javadoc) %>") +@Schema(description = "<%- formatAsApiDescription(javadoc) %>") <%_ } _%> @Introspected public class <%= asDto(entityClass) %> implements Serializable { @@ -99,7 +97,7 @@ public class <%= asDto(entityClass) %> implements Serializable { <%- include('../../common/field_validators') -%> <%_ } _%> <%_ if (typeof fields[idx].javadoc != 'undefined') { _%> - @ApiModelProperty(value = "<%- formatAsApiDescription(fields[idx].javadoc) %>"<% if (required) { %>, required = true<% } %>) + @Schema(description = "<%- formatAsApiDescription(fields[idx].javadoc) %>"<% if (required) { %>, required = true<% } %>) <%_ } _%> <%_ if (fieldType === 'byte[]' && databaseType === 'sql') { _%> @Lob @@ -125,7 +123,7 @@ public class <%= asDto(entityClass) %> implements Serializable { const ownerSide = relationships[idx].ownerSide; if (typeof relationships[idx].javadoc != 'undefined') { _%> <%- formatAsFieldJavadoc(relationships[idx].javadoc) %> - @ApiModelProperty(value = "<%- formatAsApiDescription(relationships[idx].javadoc) %>") + @Schema(description = "<%- formatAsApiDescription(relationships[idx].javadoc) %>") <%_ } if (relationshipType === 'many-to-many' && ownerSide === true) { _%> From 2c573e37faae3d64609fabd920ea56e1671328d0 Mon Sep 17 00:00:00 2001 From: Jason Schindler Date: Fri, 4 Dec 2020 10:54:55 -0600 Subject: [PATCH 3/7] Fixes enum issues identified adding more entity examples (#199) --- .../java/package/web/rest/EntityResourceIT.java.ejs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/generators/entity-server/templates/src/test/java/package/web/rest/EntityResourceIT.java.ejs b/generators/entity-server/templates/src/test/java/package/web/rest/EntityResourceIT.java.ejs index 4e298799..969a80fa 100644 --- a/generators/entity-server/templates/src/test/java/package/web/rest/EntityResourceIT.java.ejs +++ b/generators/entity-server/templates/src/test/java/package/web/rest/EntityResourceIT.java.ejs @@ -173,10 +173,10 @@ public class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { let enumValue1; let enumValue2; if (isEnum) { - const values = fields[idx].fieldValues.replace(/\s/g, '').split(','); - enumValue1 = values[0]; - if (values.length > 1) { - enumValue2 = values[1]; + const enumValues = getEnumValuesWithCustomValues(fields[idx].fieldValues); + enumValue1 = enumValues[0]; + if (enumValues.length > 1) { + enumValue2 = enumValues[1]; } else { enumValue2 = enumValue1; } @@ -308,8 +308,8 @@ public class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { private static final String <%= updatedValueName %>_CONTENT_TYPE = "image/png"; <%_ } else if (isEnum) { _%> - private static final <%= fieldType %> <%= defaultValueName %> = <%= fieldType %>.<%= enumValue1 %>; - private static final <%= fieldType %> <%= updatedValueName %> = <%= fieldType %>.<%= enumValue2 %>; + private static final <%= fieldType %> <%= defaultValueName %> = <%= fieldType %>.<%= enumValue1.name %>; + private static final <%= fieldType %> <%= updatedValueName %> = <%= fieldType %>.<%= enumValue2.name %>; <%_ } } _%> <%_ if (usesDto) { _%> From 38298ce3c13276d763c06203bf8a6eeb1552dc37 Mon Sep 17 00:00:00 2001 From: Jason Schindler Date: Sat, 19 Dec 2020 00:24:53 -0600 Subject: [PATCH 4/7] Updates UserResourceIT to have the same create/delete API as other EntityResourceIT tests --- .../web/rest/EntityResourceIT.java.ejs | 2 +- .../package/web/rest/UserResourceIT.java.ejs | 36 +++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/generators/entity-server/templates/src/test/java/package/web/rest/EntityResourceIT.java.ejs b/generators/entity-server/templates/src/test/java/package/web/rest/EntityResourceIT.java.ejs index 969a80fa..eb7d8e6c 100644 --- a/generators/entity-server/templates/src/test/java/package/web/rest/EntityResourceIT.java.ejs +++ b/generators/entity-server/templates/src/test/java/package/web/rest/EntityResourceIT.java.ejs @@ -394,7 +394,7 @@ public class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { // Add required entity <%_ if (alreadyGeneratedEntities.indexOf(otherEntityName) == -1) { _%> <%_ if (otherEntityName === 'user') { // TODO or other entity has no unique fields _%> - <%= asEntity(otherEntityNameCapitalized) %> <%= otherEntityName %> = <%= otherEntityNameCapitalized %>ResourceIT.createEntity(transactionManager); + <%= asEntity(otherEntityNameCapitalized) %> <%= otherEntityName %> = <%= otherEntityNameCapitalized %>ResourceIT.createEntity(transactionManager, em); <%_ if (databaseType === 'sql' && !reactive) { _%> transactionManager.executeWrite(status -> { em.persist(<%= otherEntityName %>); diff --git a/generators/server/templates/src/test/java/package/web/rest/UserResourceIT.java.ejs b/generators/server/templates/src/test/java/package/web/rest/UserResourceIT.java.ejs index b806f0f5..3c8a7493 100644 --- a/generators/server/templates/src/test/java/package/web/rest/UserResourceIT.java.ejs +++ b/generators/server/templates/src/test/java/package/web/rest/UserResourceIT.java.ejs @@ -29,6 +29,10 @@ import io.micronaut.http.client.RxHttpClient; import io.micronaut.http.client.annotation.Client; import io.micronaut.http.client.exceptions.HttpClientResponseException; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +<%_ if (databaseType === 'sql') { _%> +import io.micronaut.transaction.SynchronousTransactionManager; +import io.micronaut.transaction.TransactionOperations; +<%_ } _%> import io.micronaut.test.annotation.MockBean; import org.apache.commons.lang3.RandomStringUtils; import org.junit.jupiter.api.*; @@ -38,6 +42,12 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import javax.inject.Inject; +<%_ if (databaseType === 'sql' && !reactive) { _%> +import javax.persistence.EntityManager; +<%_ } _%> +<%_ if (databaseType === 'sql') { _%> +import java.sql.Connection; +<%_ } _%> import java.time.Instant; import java.util.*; @@ -86,6 +96,14 @@ public class UserResourceIT { @Inject AuthorityRepository authorityRepository; + <%_ if (databaseType === 'sql') { _%> + + @Inject + private EntityManager em; + + @Inject + SynchronousTransactionManager transactionManager; + <%_ } _%> @Inject private UserMapper userMapper; @@ -100,7 +118,7 @@ public class UserResourceIT { private User user; - public static User createEntity() { + public static User createEntity(<% if (databaseType === 'sql') { %>TransactionOperations transactionManager, EntityManager em<% } %>) { User user = new User(); user.setLogin(DEFAULT_LOGIN + RandomStringUtils.randomAlphabetic(5)); <%_ if (authenticationType !== 'oauth2') { _%> @@ -116,10 +134,22 @@ public class UserResourceIT { user.setLangKey(DEFAULT_LANGKEY); return user; } + <%_ if (databaseType === 'sql' && !reactive) { _%> + + /** + * Delete all User entities. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static void deleteAll(TransactionOperations transactionManager, EntityManager em) { + TestUtil.removeAll(transactionManager, em, User.class); + } + <%_ } _%> @BeforeAll public void initTest() { - user = createEntity(); + user = createEntity(transactionManager, em); user.setLogin(DEFAULT_LOGIN); user.setEmail(DEFAULT_EMAIL); userRepository.saveAndFlush(user); @@ -150,7 +180,7 @@ public class UserResourceIT { private void resetDefaultUser() { - User reInsert = createEntity(); + User reInsert = createEntity(transactionManager, em); reInsert.setLogin(DEFAULT_LOGIN); reInsert.setEmail(DEFAULT_EMAIL); userRepository.deleteById(user.getId()); From 2e0f6e57cd1cea84b45163fd8fe2b15c72bbe6b4 Mon Sep 17 00:00:00 2001 From: Jason Schindler Date: Sat, 19 Dec 2020 00:31:11 -0600 Subject: [PATCH 5/7] Renames BankAccount relationship so that relationship table doesn't collide with entity table --- test-integration/samples/jdl-default-app.jdl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-integration/samples/jdl-default-app.jdl b/test-integration/samples/jdl-default-app.jdl index a30c4a4e..30efabf7 100644 --- a/test-integration/samples/jdl-default-app.jdl +++ b/test-integration/samples/jdl-default-app.jdl @@ -173,7 +173,7 @@ relationship ManyToMany { JobHistory{job} to Job{history}, JobHistory{emp(firstName)} to Employee{history}, Job{chore(title)} to Task{linkedJob(title)}, - Bank{account} to BankAccount{bank} + Bank{bankAccount} to BankAccount{bank} } dto BankAccount, Employee, Department, Location, Country, Region, SilverBadge, GoldenBadge, Identifier with mapstruct From b5339da7439ffa035d80420d147430953b7031d2 Mon Sep 17 00:00:00 2001 From: Jason Schindler Date: Wed, 20 Jan 2021 15:37:49 -0600 Subject: [PATCH 6/7] Print a warning when tests are unable to delete enitites --- .../java/package/web/rest/TestUtil.java.ejs | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/generators/server/templates/src/test/java/package/web/rest/TestUtil.java.ejs b/generators/server/templates/src/test/java/package/web/rest/TestUtil.java.ejs index 19cfd2eb..b546217b 100644 --- a/generators/server/templates/src/test/java/package/web/rest/TestUtil.java.ejs +++ b/generators/server/templates/src/test/java/package/web/rest/TestUtil.java.ejs @@ -6,6 +6,8 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; <%_ if (databaseType === 'sql') { _%> import io.micronaut.transaction.TransactionOperations; <%_ } _%> +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; <%_ if (databaseType === 'sql') { _%> import javax.persistence.EntityManager; @@ -29,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat; public final class TestUtil { private static final ObjectMapper mapper = createObjectMapper(); + private static final Logger log = LoggerFactory.getLogger(TestUtil.class); private static ObjectMapper createObjectMapper() { ObjectMapper mapper = new ObjectMapper(); @@ -109,13 +112,17 @@ public final class TestUtil { * @param */ public static void removeAll(TransactionOperations transactionManager, EntityManager em, Class clss) { - transactionManager.executeWrite(status -> { - CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaDelete query = cb.createCriteriaDelete(clss); - Root root = query.from(clss); - query.where(root.isNotNull()); - return em.createQuery(query).executeUpdate(); - }); + try { + transactionManager.executeWrite(status -> { + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaDelete query = cb.createCriteriaDelete(clss); + Root root = query.from(clss); + query.where(root.isNotNull()); + return em.createQuery(query).executeUpdate(); + }); + } catch (Exception e) { + log.warn("Failed to remove instances", e); + } } <%_ } _%> From ed96961656ede8afda9ee28060e40abd3b199770 Mon Sep 17 00:00:00 2001 From: Jason Schindler Date: Wed, 20 Jan 2021 15:47:50 -0600 Subject: [PATCH 7/7] Temporarily commenting out 'with jpaDerivedIdentifier' --- test-integration/samples/jdl-default-app.jdl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test-integration/samples/jdl-default-app.jdl b/test-integration/samples/jdl-default-app.jdl index 30efabf7..d4d69386 100644 --- a/test-integration/samples/jdl-default-app.jdl +++ b/test-integration/samples/jdl-default-app.jdl @@ -133,7 +133,9 @@ entity Region { relationship OneToOne { Department{location} to Location, - Employee{user(login)} to User with jpaDerivedIdentifier + Employee{user(login)} to User + // Employee{user(login)} to User with jpaDerivedIdentifier + // Please see: https://github.com/jhipster/generator-jhipster-micronaut/issues/219 } relationship OneToMany {