diff --git a/generators/gae/index.js b/generators/gae/index.js
index 9b57b63153de..637846066e42 100644
--- a/generators/gae/index.js
+++ b/generators/gae/index.js
@@ -41,7 +41,7 @@ module.exports = class extends BaseGenerator {
const done = this.async();
shelljs.exec('gcloud version', { silent: true }, (code, stdout, err) => {
- if (err) {
+ if (err && code !== 0) {
this.log.error(
"You don't have the Cloud SDK (gcloud) installed. \nDownload it from https://cloud.google.com/sdk/install"
);
@@ -66,7 +66,7 @@ module.exports = class extends BaseGenerator {
this.log(chalk.bold('\nInstalling App Engine Java SDK'));
this.log(`... Running: gcloud components install ${component} --quiet`);
shelljs.exec(`gcloud components install ${component} --quiet`, { silent: true }, (code, stdout, err) => {
- if (err) {
+ if (err && code !== 0) {
this.log.error(err);
done(
`Installation failed. \nPlease try to install the app-engine-java component manually via; gcloud components install ${component}`
@@ -83,6 +83,7 @@ module.exports = class extends BaseGenerator {
const configuration = this.getAllJhipsterConfig(this, true);
this.env.options.appPath = configuration.get('appPath') || constants.CLIENT_MAIN_SRC_DIR;
this.baseName = configuration.get('baseName');
+ this.mainClass = this.getMainClassName();
this.packageName = configuration.get('packageName');
this.packageFolder = configuration.get('packageFolder');
this.cacheProvider = configuration.get('cacheProvider') || configuration.get('hibernateCache') || 'no';
@@ -107,6 +108,10 @@ module.exports = class extends BaseGenerator {
this.gaeMaxInstances = configuration.get('gaeMaxInstances');
this.gaeMinInstances = configuration.get('gaeMinInstances');
this.gaeCloudSQLInstanceNeeded = configuration.get('gaeCloudSQLInstanceNeeded');
+ this.CLIENT_DIST_DIR = this.getResourceBuildDirectoryForBuildTool(this.config.buildTool) + constants.CLIENT_DIST_DIR;
+ this.skipClient = this.config.get('skipClient');
+ this.clientPackageManager = this.config.get('clientPackageManager');
+ this.dasherizedBaseName = _.kebabCase(this.baseName);
}
};
}
@@ -148,15 +153,13 @@ module.exports = class extends BaseGenerator {
message: 'Google Cloud Project ID',
default: this.defaultProjectId(),
validate: input => {
- if (input.length === 0) {
+ if (input.trim().length === 0) {
return 'Project ID cannot empty';
}
try {
shelljs.exec(`gcloud projects describe ${input}`, { silent: true });
- this.gcpProjectIdExists = true;
} catch (ex) {
- this.gcpProjectIdExists = false;
- return `Project ID "${chalk.cyan(input)}" does not exist, please create one first!`;
+ return `Project ID "${chalk.cyan(input.trim())}" does not exist, please create one first!`;
}
return true;
}
@@ -164,7 +167,7 @@ module.exports = class extends BaseGenerator {
];
this.prompt(prompts).then(props => {
- this.gcpProjectId = props.gcpProjectId;
+ this.gcpProjectId = props.gcpProjectId.trim();
done();
});
},
@@ -177,7 +180,7 @@ module.exports = class extends BaseGenerator {
`gcloud app describe --format="value(locationId)" --project="${this.gcpProjectId}"`,
{ silent: true },
(code, stdout, err) => {
- if (err) {
+ if (err && code !== 0) {
const prompts = [
{
type: 'list',
@@ -381,7 +384,7 @@ module.exports = class extends BaseGenerator {
prompts.push({
type: 'input',
name: 'gaeCloudSQLInstanceNeeded',
- message: 'Initialize a new Cloud SQL instance (Y/N) ?',
+ message: 'Use a Cloud SQL instance (Y/N) ?',
default: this.gaeCloudSQLInstanceNeeded ? this.gaeCloudSQLInstanceNeeded : 'Y',
validate: input => {
if (input !== 'Y' && input !== 'N') {
@@ -408,9 +411,8 @@ module.exports = class extends BaseGenerator {
const cloudSqlInstances = [{ value: '', name: 'New Cloud SQL Instance' }];
shelljs.exec(
`gcloud sql instances list --format='value[separator=":"](project,region,name)' --project="${this.gcpProjectId}"`,
- { silent: true },
(code, stdout, err) => {
- if (err) {
+ if (err && code !== 0) {
this.log.error(err);
} else {
_.forEach(stdout.toString().split(os.EOL), instance => {
@@ -508,7 +510,7 @@ module.exports = class extends BaseGenerator {
`gcloud sql databases list -i ${name} --format='value(name)' --project="${this.gcpProjectId}"`,
{ silent: true },
(code, stdout, err) => {
- if (err) {
+ if (err && code !== 0) {
this.log.error(err);
} else {
_.forEach(stdout.toString().split(os.EOL), database => {
@@ -581,7 +583,7 @@ module.exports = class extends BaseGenerator {
`gcloud app create --region="${this.gaeLocation}" --project="${this.gcpProjectId}"`,
{ silent: true },
(code, stdout, err) => {
- if (err) {
+ if (err && code !== 0) {
this.log.error(err);
this.abort = true;
}
@@ -612,15 +614,16 @@ module.exports = class extends BaseGenerator {
this.log(chalk.bold(`\n... Running: ${cmd}`));
shelljs.exec(cmd, { silent: true }, (code, stdout, err) => {
- if (err) {
+ if (err && code !== 0) {
this.abort = true;
this.log.error(err);
}
- this.gcpCloudSqlInstanceName = shelljs.exec(
+ const cloudSQLInstanceName = shelljs.exec(
`gcloud sql instances describe ${name} --format="value(connectionName)" --project="${this.gcpProjectId}"`,
{ silent: true }
);
+ this.gcpCloudSqlInstanceName = cloudSQLInstanceName.trim();
done();
});
@@ -648,7 +651,7 @@ module.exports = class extends BaseGenerator {
const cmd = `gcloud sql users create "${this.gcpCloudSqlUserName}" -i "${name}" --host="%" --password="${this.gcpCloudSqlPassword}" --project="${this.gcpProjectId}"`;
this.log(chalk.bold(`... Running: ${cmd}`));
shelljs.exec(cmd, { silent: true }, (code, stdout, err) => {
- if (err) {
+ if (err && code !== 0) {
this.log.error(err);
}
done();
@@ -670,7 +673,7 @@ module.exports = class extends BaseGenerator {
const cmd = `gcloud sql databases create "${this.gcpCloudSqlDatabaseName}" --charset=utf8 -i "${name}" --project="${this.gcpProjectId}"`;
this.log(chalk.bold(`... Running: ${cmd}`));
shelljs.exec(cmd, { silent: true }, (code, stdout, err) => {
- if (err) {
+ if (err && code !== 0) {
this.log.error(err);
}
done();
@@ -705,9 +708,7 @@ module.exports = class extends BaseGenerator {
this.log(chalk.bold('\nCreating Google App Engine deployment files'));
this.template('app.yaml.ejs', `${constants.MAIN_DIR}/appengine/app.yaml`);
- if (this.gaeCloudSQLInstanceNeeded === 'Y') {
- this.template('application-prod-gae.yml.ejs', `${constants.SERVER_MAIN_RES_DIR}/config/application-prod-gae.yml`);
- }
+ this.template('application-prod-gae.yml.ejs', `${constants.SERVER_MAIN_RES_DIR}/config/application-prod-gae.yml`);
if (this.buildTool === 'gradle') {
this.template('gae.gradle.ejs', 'gradle/gae.gradle');
}
@@ -719,6 +720,9 @@ module.exports = class extends BaseGenerator {
addDependencies() {
if (this.abort) return;
+ if (this.buildTool === 'maven') {
+ this.addMavenDependency('org.springframework.boot.experimental', 'spring-boot-thin-layout', '1.0.23.RELEASE');
+ }
if (this.gaeCloudSQLInstanceNeeded === 'N') return;
if (this.prodDatabaseType === 'mysql' || this.prodDatabaseType === 'mariadb') {
if (this.buildTool === 'maven') {
@@ -739,9 +743,8 @@ module.exports = class extends BaseGenerator {
addGradlePlugin() {
if (this.abort) return;
if (this.buildTool === 'gradle') {
- if (this.gaeCloudSQLInstanceNeeded === 'Y') {
- this.addGradlePlugin('com.google.cloud.tools', 'appengine-gradle-plugin', '2.1.0');
- }
+ this.addGradlePlugin('com.google.cloud.tools', 'appengine-gradle-plugin', '2.2.0');
+ this.addGradlePlugin('org.springframework.boot.experimental', 'spring-boot-thin-gradle-plugin', '1.0.13.RELEASE');
this.applyFromGradleScript('gradle/gae');
}
},
@@ -749,14 +752,15 @@ module.exports = class extends BaseGenerator {
addMavenPlugin() {
if (this.abort) return;
if (this.buildTool === 'maven') {
- if (this.gaeCloudSQLInstanceNeeded === 'Y') {
- this.render('pom-plugin.xml.ejs', rendered => {
- this.addMavenPlugin('com.google.cloud.tools', 'appengine-maven-plugin', '2.1.0', rendered.trim());
- });
- }
+ this.render('pom-plugin.xml.ejs', rendered => {
+ this.addMavenPlugin('com.google.cloud.tools', 'appengine-maven-plugin', '2.2.0', rendered.trim());
+ });
this.render('pom-profile.xml.ejs', rendered => {
this.addMavenProfile('prod-gae', ` ${rendered.trim()}`);
});
+ this.render('pom-gae-build-profile.xml.ejs', rendered => {
+ this.addMavenProfile('gae', ` ${rendered.trim()}`);
+ });
}
}
};
@@ -769,10 +773,16 @@ module.exports = class extends BaseGenerator {
if (this.buildTool === 'maven') {
this.log(chalk.bold('\nRun App Engine DevServer Locally: ./mvnw package appengine:run -DskipTests'));
- this.log(chalk.bold('Deploy to App Engine: ./mvnw package appengine:deploy -DskipTests -Pprod,prod-gae'));
+ this.log(
+ chalk.bold('Deploy to App Engine: ./mvnw clean && ./mvnw package appengine:deploy -DskipTests -Pgae,prod-gae')
+ );
} else if (this.buildTool === 'gradle') {
this.log(chalk.bold('\nRun App Engine DevServer Locally: ./gradlew appengineRun'));
- this.log(chalk.bold('Deploy to App Engine: ./gradlew appengineDeploy -Pprod -Pprod-gae'));
+ this.log(
+ chalk.bold(
+ 'Deploy to App Engine: ./gradlew thinResolve -Pgae -Pprod-gae && ./gradlew appengineDeploy -Pgae -Pprod-gae'
+ )
+ );
}
/*
if (this.gcpSkipBuild || this.gcpDeployType === 'git') {
diff --git a/generators/gae/templates/app.yaml.ejs b/generators/gae/templates/app.yaml.ejs
index f08370907fc5..1da7e840e39d 100644
--- a/generators/gae/templates/app.yaml.ejs
+++ b/generators/gae/templates/app.yaml.ejs
@@ -1,3 +1,21 @@
+<%#
+ Copyright 2013-2019 the original author or authors from the JHipster project.
+
+ This file is part of the JHipster project, see https://www.jhipster.tech/
+ for more information.
+
+ Licensed 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.
+-%>
# ========================================================================
# App Engine Configuration.
# Full reference is available at:
@@ -28,3 +46,4 @@ automatic_scaling:
max_instances: <%= gaeMaxInstances %>
<%_ } _%>
<%_ } _%>
+entrypoint: java -Dthin.root=. -jar <%= dasherizedBaseName %>-0.0.1-SNAPSHOT.jar
diff --git a/generators/gae/templates/application-prod-gae.yml.ejs b/generators/gae/templates/application-prod-gae.yml.ejs
index cf68e4a59dd3..f972ee7179ed 100644
--- a/generators/gae/templates/application-prod-gae.yml.ejs
+++ b/generators/gae/templates/application-prod-gae.yml.ejs
@@ -27,9 +27,11 @@
# Full reference is available at:
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
# ===================================================================
-
+server:
+ port: ${PORT}
+<%_ if (gaeCloudSQLInstanceNeeded === 'Y') { _%>
spring:
-<%_ if (prodDatabaseType === 'mysql' || prodDatabaseType === 'mariadb') { _%>
+ <%_ if (prodDatabaseType === 'mysql' || prodDatabaseType === 'mariadb') { _%>
datasource:
type: com.zaxxer.hikari.HikariDataSource
url: "jdbc:mysql://google/<%=gcpCloudSqlDatabaseName%>?cloudSqlInstance=<%=gcpCloudSqlInstanceName%>&socketFactory=com.google.cloud.sql.mysql.SocketFactory&useSSL=false"
@@ -37,8 +39,8 @@ spring:
password: "<%=gcpCloudSqlPassword%>"
hikari:
maximumPoolSize: 8
-<%_ } _%>
-<%_ if (prodDatabaseType === 'postgresql') { _%>
+ <%_ } _%>
+ <%_ if (prodDatabaseType === 'postgresql') { _%>
datasource:
type: com.zaxxer.hikari.HikariDataSource
url: "jdbc:postgresql://google/<%=gcpCloudSqlDatabaseName%>?cloudSqlInstance=<%=gcpCloudSqlInstanceName%>&socketFactory=com.google.cloud.sql.postgres.SocketFactory"
@@ -46,4 +48,5 @@ spring:
password: "<%=gcpCloudSqlPassword%>"
hikari:
maximumPoolSize: 8
+ <%_ } _%>
<%_ } _%>
diff --git a/generators/gae/templates/gae.gradle.ejs b/generators/gae/templates/gae.gradle.ejs
index 401cab3dc5fe..60b7a61d73ac 100644
--- a/generators/gae/templates/gae.gradle.ejs
+++ b/generators/gae/templates/gae.gradle.ejs
@@ -20,15 +20,11 @@ apply plugin: "com.google.cloud.tools.appengine"
appengine {
deploy {
- project = "<%=gcpProjectId%>"
+ projectId = "<%=gcpProjectId%>"
version = "1"
}
}
-bootWar {
- webXml = file("${project.rootDir}/<%= CLIENT_MAIN_SRC_DIR %>WEB-INF/web.xml")
-}
-
processResources {
if (project.hasProperty("prod-gae")) {
filesMatching("**/application.yml") {
@@ -38,3 +34,10 @@ processResources {
}
}
}
+
+task copyFolders(type: Copy) {
+ into "$buildDir/staged-app/"
+ from "$buildDir/thin/root/"
+}
+
+appengineStage.finalizedBy copyFolders
diff --git a/generators/gae/templates/pom-gae-build-profile.xml.ejs b/generators/gae/templates/pom-gae-build-profile.xml.ejs
new file mode 100644
index 000000000000..1157c7b34e02
--- /dev/null
+++ b/generators/gae/templates/pom-gae-build-profile.xml.ejs
@@ -0,0 +1,61 @@
+<%#
+ Copyright 2013-2019 the original author or authors from the JHipster project.
+
+ This file is part of the JHipster project, see https://www.jhipster.tech/
+ for more information.
+
+ Licensed 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.
+-%>
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.springframework.boot.experimental
+ spring-boot-thin-layout
+ 1.0.23.RELEASE
+
+
+
+
+ org.springframework.boot.experimental
+ spring-boot-thin-maven-plugin
+ 1.0.23.RELEASE
+
+ ${project.build.directory}/appengine-staging
+
+
+
+ resolve
+
+ resolve
+
+ false
+
+
+
+
+ pl.project13.maven
+ git-commit-id-plugin
+
+
+
diff --git a/generators/gae/templates/pom-plugin.xml.ejs b/generators/gae/templates/pom-plugin.xml.ejs
index 3f0c8cabafd5..04194a83be3e 100644
--- a/generators/gae/templates/pom-plugin.xml.ejs
+++ b/generators/gae/templates/pom-plugin.xml.ejs
@@ -1,4 +1,22 @@
+<%#
+ Copyright 2013-2019 the original author or authors from the JHipster project.
+
+ This file is part of the JHipster project, see https://www.jhipster.tech/
+ for more information.
+
+ Licensed 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.
+-%>
- <%=gcpProjectId%>
+ <%=gcpProjectId%>
1
diff --git a/generators/gae/templates/pom-profile.xml.ejs b/generators/gae/templates/pom-profile.xml.ejs
index 3712dda60863..27e277d8b38f 100644
--- a/generators/gae/templates/pom-profile.xml.ejs
+++ b/generators/gae/templates/pom-profile.xml.ejs
@@ -1,3 +1,21 @@
+<%#
+ Copyright 2013-2019 the original author or authors from the JHipster project.
+
+ This file is part of the JHipster project, see https://www.jhipster.tech/
+ for more information.
+
+ Licensed 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.
+-%>
- prod${profile.swagger}${profile.no-liquibase},prod-gae
+ prod${profile.swagger}<%_ if (databaseType === 'sql') { _%>${profile.no-liquibase},prod-gae<%_ } _%>
diff --git a/generators/server/templates/build.gradle.ejs b/generators/server/templates/build.gradle.ejs
index ff011d7957e1..3d752192ca6c 100644
--- a/generators/server/templates/build.gradle.ejs
+++ b/generators/server/templates/build.gradle.ejs
@@ -71,7 +71,7 @@ apply from: "gradle/swagger.gradle"
<%_ } _%>
//jhipster-needle-gradle-apply-from - JHipster will add additional gradle scripts to be applied here
-if (project.hasProperty("prod")) {
+if (project.hasProperty("prod") || project.hasProperty("gae")) {
apply from: "gradle/profile_prod.gradle"
} else {
apply from: "gradle/profile_dev.gradle"
@@ -81,6 +81,19 @@ if (project.hasProperty("war")) {
apply from: "gradle/war.gradle"
}
+if (project.hasProperty("gae")) {
+ apply plugin: 'maven'
+ apply plugin: 'org.springframework.boot.experimental.thin-launcher'
+ apply plugin: 'io.spring.dependency-management'
+
+ dependencyManagement {
+ imports {
+ mavenBom 'io.github.jhipster:jhipster-dependencies:${jhipster_dependencies_version}'
+ }
+ }
+ appengineStage.dependsOn thinResolve
+}
+
<%_ if (serviceDiscoveryType || applicationType === 'gateway' || applicationType === 'microservice' || applicationType === 'uaa') { _%>
if (project.hasProperty("zipkin")) {
apply from: "gradle/zipkin.gradle"
@@ -260,7 +273,9 @@ repositories {
dependencies {
// import JHipster dependencies BOM
- implementation platform("io.github.jhipster:jhipster-dependencies:${jhipster_dependencies_version}" )
+ if (!project.hasProperty("gae")) {
+ implementation platform("io.github.jhipster:jhipster-dependencies:${jhipster_dependencies_version}")
+ }
// Use ", version: jhipster_dependencies_version, changing: true" if you want
// to use a SNAPSHOT release instead of a stable release
@@ -437,8 +452,13 @@ dependencies {
<%_ } _%>
<%_ if (authenticationType === 'jwt') { _%>
implementation "io.jsonwebtoken:jjwt-api"
- runtimeOnly "io.jsonwebtoken:jjwt-impl"
- runtimeOnly "io.jsonwebtoken:jjwt-jackson"
+ if (!project.hasProperty("gae")) {
+ runtimeOnly "io.jsonwebtoken:jjwt-impl"
+ runtimeOnly "io.jsonwebtoken:jjwt-jackson"
+ } else {
+ implementation "io.jsonwebtoken:jjwt-impl"
+ implementation "io.jsonwebtoken:jjwt-jackson"
+ }
<%_ } _%>
<%_ if (authenticationType === 'uaa') { _%>
implementation "org.springframework.security.oauth:spring-security-oauth2"
@@ -536,6 +556,18 @@ dependencies {
//jhipster-needle-gradle-dependency - JHipster will add additional dependencies here
}
+if (project.hasProperty("gae")) {
+ task createPom {
+ def basePath = 'build/resources/main/META-INF/maven'
+ doLast {
+ pom {
+ withXml(dependencyManagement.pomConfigurer)
+ }.writeTo("${basePath}/${project.group}/${project.name}/pom.xml")
+ }
+ }
+ bootJar.dependsOn = [createPom]
+}
+
task cleanResources(type: Delete) {
delete "build/resources"
}