Repository: jhipster/generator-jhipster
Pull request #9402 (2019-03-08 15:39:07)

Set locale to 'en' if not specified by IdP
-   Please make sure the below checklist is followed for Pull Requests.

-   [ ] [Travis tests](https://travis-ci.org/jhipster/generator-jhipster/pull_requests) are green
-   [x] Tests are added where necessary
-   [x] Documentation is added/updated where necessary
-   [x] Coding Rules & Commit Guidelines as per our [CONTRIBUTING.md document](https://github.com/jhipster/generator-jhipster/blob/master/CONTRIBUTING.md) are followed

Fixes https://github.com/jhipster/generator-jhipster/issues/9400.


Patch:
diff --git a/cli/cli.js b/cli/cli.js
index 1a680d4172..40d112398d 100644
--- a/cli/cli.js
+++ b/cli/cli.js
@@ -72,12 +72,6 @@ Object.keys(SUB_GENERATORS).forEach(key => {
                 require(`./${key}`)(program.args, options, env);
                 /* eslint-enable */
             } else {
-                if (key === 'server') {
-                    logger.error('Please run "jhipster --skip-client" instead');
-                }
-                if (key === 'client') {
-                    logger.error('Please run "jhipster --skip-server" instead');
-                }
                 runYoCommand(key, program.args, options, opts);
             }
         })
diff --git a/cli/commands.js b/cli/commands.js
index 98ebcafa5d..b89b22f6b8 100644
--- a/cli/commands.js
+++ b/cli/commands.js
@@ -30,10 +30,6 @@ module.exports = {
     'ci-cd': {
         desc: 'Create pipeline scripts for popular Continuous Integration/Continuous Deployment tools'
     },
-    client: {
-        desc:
-            'DEPRECATED: Create a new JHipster client-side application based on the selected options -  Use jhipster --skip-server instead'
-    },
     cloudfoundry: {
         desc: 'Generate a `deploy/cloudfoundry` folder with a specific manifest.yml to deploy to Cloud Foundry'
     },
@@ -94,9 +90,6 @@ Example:
     openshift: {
         desc: 'Deploy the current application to OpenShift'
     },
-    server: {
-        desc: 'DEPRECATED: Create a new JHipster server-side application - Use jhipster --skip-client instead'
-    },
     'spring-service': {
         alias: 'service',
         argument: ['name'],
diff --git a/cli/utils.js b/cli/utils.js
index 3913a17a33..b282070402 100644
--- a/cli/utils.js
+++ b/cli/utils.js
@@ -185,9 +185,11 @@ const done = () => {
 const createYeomanEnv = () => {
     const env = yeoman.createEnv();
     /* Register yeoman generators */
-    Object.keys(SUB_GENERATORS).forEach(generator => {
-        env.register(require.resolve(`../generators/${generator}`), `${CLI_NAME}:${generator}`);
-    });
+    Object.keys(SUB_GENERATORS)
+        .filter(command => !SUB_GENERATORS[command].cliOnly)
+        .forEach(generator => {
+            env.register(require.resolve(`../generators/${generator}`), `${CLI_NAME}:${generator}`);
+        });
     return env;
 };
 
diff --git a/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity-management-update.component.html.ejs b/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity-management-update.component.html.ejs
index e7e0d0802f..cf58111d6b 100644
--- a/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity-management-update.component.html.ejs
+++ b/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity-management-update.component.html.ejs
@@ -236,8 +236,8 @@ _%>
                 </div>
                 <%_ } else if (relationshipType === 'many-to-many' && relationships[idx].ownerSide === true) { _%>
                 <div class="form-group">
-                    <label jhiTranslate="<%= translationKey %>" for="field_<%= relationshipName %>"><%= relationshipNameHumanized %></label>
-                    <select class="form-control" id="field_<%= relationshipName %>" multiple name="<%= relationshipName %>" formControlName="<%=relationshipName %>">
+                    <label jhiTranslate="<%= translationKey %>" for="field_<%= relationshipFieldNamePlural %>"><%= relationshipNameHumanized %></label>
+                    <select class="form-control" id="field_<%= relationshipFieldNamePlural %>" multiple name="<%= relationshipFieldNamePlural %>" formControlName="<%=relationshipFieldNamePlural %>">
                         <option [ngValue]="getSelected(editForm.get('<%= relationshipFieldNamePlural %>').value, <%=otherEntityName %>Option)" *ngFor="let <%=otherEntityName %>Option of <%=otherEntityNamePlural.toLowerCase() %>; trackBy: track<%=otherEntityNameCapitalized %>ById">{{<%=otherEntityName %>Option.<%=otherEntityField %>}}</option>
                     </select>
                 </div>
diff --git a/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity-management-update.component.ts.ejs b/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity-management-update.component.ts.ejs
index 1b36451c35..4651c234d4 100644
--- a/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity-management-update.component.ts.ejs
+++ b/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity-management-update.component.ts.ejs
@@ -264,48 +264,49 @@ _%>
     }
 
     private createFromForm(): I<%= entityAngularName %> {
-        return new <%= entityAngularName %>(
-            this.editForm.get(['id']).value,
-<%_ for (idx in fields) {
-    const fieldName = fields[idx].fieldName;
-    const fieldType = fields[idx].fieldType;
-    const fieldTypeBlobContent = fields[idx].fieldTypeBlobContent;
-_%>
-    <%_ if (['Instant', 'ZonedDateTime'].includes(fieldType)) { _%>
-    this.editForm.get(['<%= fieldName %>']).value != null ? moment(this.editForm.get(['<%= fieldName %>']).value, DATE_TIME_FORMAT) : undefined,
-    <%_ } else if (['byte[]', 'ByteBuffer'].includes(fieldType) && fieldTypeBlobContent !== 'text') { _%>
-    this.editForm.get(['<%= fieldName %>ContentType']).value,
-    this.editForm.get(['<%= fieldName %>']).value,
-    <%_ } else { _%>
-    this.editForm.get(['<%= fieldName %>']).value,
-    <%_ } _%>
-<%_ } _%>
-<%_ for (idx in relationships) {
-    const relationshipType = relationships[idx].relationshipType;
-    const ownerSide = relationships[idx].ownerSide;
-    const otherEntityName = relationships[idx].otherEntityName;
-    const otherEntityNamePlural = relationships[idx].otherEntityNamePlural;
-    const otherEntityNameCapitalized = relationships[idx].otherEntityNameCapitalized;
-    const relationshipName = relationships[idx].relationshipName;
-    const relationshipNameHumanized = relationships[idx].relationshipNameHumanized;
-    const relationshipFieldName = relationships[idx].relationshipFieldName;
-    const relationshipFieldNamePlural = relationships[idx].relationshipFieldNamePlural;
-    const otherEntityField = relationships[idx].otherEntityField;
-    const otherEntityFieldCapitalized = relationships[idx].otherEntityFieldCapitalized;
-    const relationshipRequired = relationships[idx].relationshipRequired;
-    const translationKey = `${i18nKeyPrefix}.${relationshipName}`; _%>
-    <%_ if (relationshipType === 'many-to-one' || (relationshipType === 'one-to-one' && ownerSide === true)) { _%>
-        <%_ if (dto === 'no') { _%>
-    this.editForm.get(['<%= relationshipName %>']).value,
+        const entity = {
+                       ...new <%= entityAngularName %>(),
+            id: this.editForm.get(['id']).value,
+    <%_ for (idx in fields) {
+        const fieldName = fields[idx].fieldName;
+        const fieldType = fields[idx].fieldType;
+        const fieldTypeBlobContent = fields[idx].fieldTypeBlobContent;
+    _%>
+        <%_ if (['Instant', 'ZonedDateTime'].includes(fieldType)) { _%>
+            <%= fieldName %>: this.editForm.get(['<%= fieldName %>']).value != null ? moment(this.editForm.get(['<%= fieldName %>']).value, DATE_TIME_FORMAT) : undefined,
+        <%_ } else if (['byte[]', 'ByteBuffer'].includes(fieldType) && fieldTypeBlobContent !== 'text') { _%>
+            <%= fieldName %>ContentType: this.editForm.get(['<%= fieldName %>ContentType']).value,
+            <%= fieldName %>: this.editForm.get(['<%= fieldName %>']).value,
         <%_ } else { _%>
-    this.editForm.get(['<%= relationshipName %>Id']).value,
+            <%= fieldName %>: this.editForm.get(['<%= fieldName %>']).value,
         <%_ } _%>
-    <%_ } else if (relationshipType === 'many-to-many' && relationships[idx].ownerSide === true) { _%>
-    this.editForm.get(['<%= relationshipFieldNamePlural %>']).value,
     <%_ } _%>
+    <%_ for (idx in relationships) {
+        const relationshipType = relationships[idx].relationshipType;
+        const ownerSide = relationships[idx].ownerSide;
+        const otherEntityName = relationships[idx].otherEntityName;
+        const otherEntityNamePlural = relationships[idx].otherEntityNamePlural;
+        const otherEntityNameCapitalized = relationships[idx].otherEntityNameCapitalized;
+        const relationshipName = relationships[idx].relationshipName;
+        const relationshipNameHumanized = relationships[idx].relationshipNameHumanized;
+        const relationshipFieldName = relationships[idx].relationshipFieldName;
+        const relationshipFieldNamePlural = relationships[idx].relationshipFieldNamePlural;
+        const otherEntityField = relationships[idx].otherEntityField;
+        const otherEntityFieldCapitalized = relationships[idx].otherEntityFieldCapitalized;
+        const relationshipRequired = relationships[idx].relationshipRequired;
+        const translationKey = `${i18nKeyPrefix}.${relationshipName}`; _%>
+        <%_ if (relationshipType === 'many-to-one' || (relationshipType === 'one-to-one' && ownerSide === true)) { _%>
+            <%_ if (dto === 'no') { _%>
+            <%= relationshipName %>: this.editForm.get(['<%= relationshipName %>']).value,
+            <%_ } else { _%>
+            <%= relationshipName %>Id: this.editForm.get(['<%= relationshipName %>Id']).value,
+            <%_ } _%>
+        <%_ } else if (relationshipType === 'many-to-many' && relationships[idx].ownerSide === true) { _%>
+            <%= relationshipFieldNamePlural %>: this.editForm.get(['<%= relationshipFieldNamePlural %>']).value,
+        <%_ } _%>
 <%_ } _%>
-
-        );
+        }
+        return entity;
     }
 
     protected subscribeToSaveResponse(result: Observable<HttpResponse<I<%= entityAngularName %>>>) {
diff --git a/generators/entity-server/templates/src/main/resources/config/liquibase/data/table.csv.ejs b/generators/entity-server/templates/src/main/resources/config/liquibase/data/table.csv.ejs
index 4ab84aa160..ea17299a44 100644
--- a/generators/entity-server/templates/src/main/resources/config/liquibase/data/table.csv.ejs
+++ b/generators/entity-server/templates/src/main/resources/config/liquibase/data/table.csv.ejs
@@ -123,7 +123,11 @@ for (lineNb = 1; lineNb <= 10; lineNb++) {
     }
     for (idx in relationships) {
         if (relationships[idx].relationshipValidate === true && relationships[idx].relationshipRequired) {
-            line.push(this.faker.random.number({min: 1, max: 10}));
+            if (relationships[idx].otherEntityNameCapitalized === 'User') {
+                line.push(this.faker.random.number({min: 1, max: 2}));
+            } else {
+                line.push(this.faker.random.number({min: 1, max: 10}));
+            }
         }
     }
     table.push(line);
diff --git a/generators/generator-base.js b/generators/generator-base.js
index 8c0995199a..1d4b603083 100644
--- a/generators/generator-base.js
+++ b/generators/generator-base.js
@@ -48,24 +48,6 @@ const SERVER_MAIN_RES_DIR = constants.SERVER_MAIN_RES_DIR;
  * The method signatures in public API should not be changed without a major version change
  */
 module.exports = class extends PrivateBase {
-    /**
-     * Deprecated
-     * Get the JHipster configuration from the .yo-rc.json file.
-     *
-     * @param {string} namespace - namespace of the .yo-rc.json config file. By default: generator-jhipster
-     */
-    getJhipsterAppConfig(namespace = 'generator-jhipster') {
-        this.warning('This method is deprecated. Use getAllJhipsterConfig');
-        const fromPath = '.yo-rc.json';
-        if (shelljs.test('-f', fromPath)) {
-            const fileData = this.fs.readJSON(fromPath);
-            if (fileData && fileData[namespace]) {
-                return fileData[namespace];
-            }
-        }
-        return false;
-    }
-
     /**
      * Add a new menu element, at the root of the menu.
      *
@@ -576,6 +558,29 @@ module.exports = class extends PrivateBase {
         this.needleApi.clientAngular.addVendorSCSSStyle(style, comment);
     }
 
+    /**
+     * Add new scss style to the react application in "app.scss".
+     *
+     * @param {string} style - css to add in the file
+     * @param {string} comment - comment to add before css code
+     *
+     * example:
+     *
+     * style = '.jhipster {\n     color: #baa186;\n}'
+     * comment = 'New JHipster color'
+     *
+     * * ==========================================================================
+     * New JHipster color
+     * ========================================================================== *
+     * .jhipster {
+     *     color: #baa186;
+     * }
+     *
+     */
+    addAppSCSSStyle(style, comment) {
+        this.needleApi.clientReact.addAppSCSSStyle(style, comment);
+    }
+
     /**
      * Copy third-party library resources path.
      *
@@ -1748,17 +1753,6 @@ module.exports = class extends PrivateBase {
         }
     }
 
-    /**
-     * @Deprecated
-     * Add numbering to a question
-     *
-     * @param {String} msg - question text
-     * @param {boolean} cond - increment question
-     */
-    getNumberedQuestion(msg, cond) {
-        return msg;
-    }
-
     /**
      * build a generated application.
      *
diff --git a/generators/import-jdl/USAGE b/generators/import-jdl/USAGE
deleted file mode 100644
index 498da59bc6..0000000000
--- a/generators/import-jdl/USAGE
+++ /dev/null
@@ -1,4 +0,0 @@
-Description:
-    Creates entities from the passed JDL file location
-Example:
-    jhipster import-jdl .\model.jh
diff --git a/generators/import-jdl/index.js b/generators/import-jdl/index.js
deleted file mode 100644
index cba9f273b6..0000000000
--- a/generators/import-jdl/index.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * 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.
- */
-const chalk = require('chalk');
-const BaseGenerator = require('../generator-base');
-
-/**
- * This sub-generatot is deprecated. Import JDL is now handled by JHipster CLI. See "./cli/import-jdl.js"
- */
-module.exports = class extends BaseGenerator {
-    initializing() {
-        if (!this.options['from-cli']) {
-            this.warning('Deprecated: JHipster seems to be invoked using Yeoman command. Please use the JHipster CLI');
-            this.error(`Deprecated: Run ${chalk.red('jhipster import-jdl')} instead of ${chalk.red('yo jhipster:import-jdl')}`);
-        }
-    }
-};
diff --git a/generators/kubernetes-helm/files.js b/generators/kubernetes-helm/files.js
index 945cf64965..8f992c521a 100644
--- a/generators/kubernetes-helm/files.js
+++ b/generators/kubernetes-helm/files.js
@@ -53,8 +53,8 @@ function writeFiles() {
                     (this.app.applicationType === 'gateway' || this.app.applicationType === 'monolith') &&
                     this.kubernetesServiceType === 'Ingress'
                 ) {
-                    if (this.istio !== 'no') {
-                        this.template(`${k8s}/gateway.yml.ejs`, `${appName}/templates/${appName}-gateway.yaml`);
+                    if (this.istio) {
+                        this.template(`${k8s}/istio/gateway.yml.ejs`, `${appName}/templates/${appName}-gateway.yaml`);
                     } else {
                         this.template(`${k8s}/ingress.yml.ejs`, `${appName}/templates/${appName}-ingress.yaml`);
                     }
@@ -62,7 +62,7 @@ function writeFiles() {
                 if (!this.app.serviceDiscoveryType && this.app.authenticationType === 'jwt') {
                     this.template(`${k8s}/secret/jwt-secret.yml.ejs`, `${appName}/templates/jwt-secret.yaml`);
                 }
-                if (this.istioRoute === true) {
+                if (this.istio) {
                     this.template(`${k8s}/istio/destination-rule.yml.ejs`, `${appName}/templates/${appName}-destination-rule.yaml`);
                     this.template(`${k8s}/istio/virtual-service.yml.ejs`, `${appName}/templates/${appName}-virtual-service.yaml`);
                 }
diff --git a/generators/kubernetes-helm/index.js b/generators/kubernetes-helm/index.js
index 6a50eaf772..ba99094fc9 100644
--- a/generators/kubernetes-helm/index.js
+++ b/generators/kubernetes-helm/index.js
@@ -57,7 +57,6 @@ module.exports = class extends BaseDockerGenerator {
                 this.kubernetesServiceType = this.config.get('kubernetesServiceType');
                 this.ingressDomain = this.config.get('ingressDomain');
                 this.istio = this.config.get('istio');
-                this.istioRoute = this.config.get('istioRoute');
                 this.jhipsterVersion = packagejs.version;
                 this.dbRandomPassword = Math.random()
                     .toString(36)
@@ -79,7 +78,6 @@ module.exports = class extends BaseDockerGenerator {
             askForDockerRepositoryName: prompts.askForDockerRepositoryName,
             askForDockerPushCommand: prompts.askForDockerPushCommand,
             askForIstioSupport: prompts.askForIstioSupport,
-            askForIstioRouteFiles: prompts.askForIstioRouteFiles,
             askForKubernetesServiceType: prompts.askForKubernetesServiceType,
             askForIngressDomain: prompts.askForIngressDomain
         };
@@ -118,8 +116,7 @@ module.exports = class extends BaseDockerGenerator {
                     kubernetesServiceType: this.kubernetesServiceType,
                     ingressDomain: this.ingressDomain,
                     monitoring: this.monitoring,
-                    istio: this.istio,
-                    istioRoute: this.istioRoute
+                    istio: this.istio
                 });
             }
         };
diff --git a/generators/kubernetes/files.js b/generators/kubernetes/files.js
index 65d0ad1e27..5a0b324f4d 100644
--- a/generators/kubernetes/files.js
+++ b/generators/kubernetes/files.js
@@ -40,8 +40,8 @@ function writeFiles() {
                     (this.app.applicationType === 'gateway' || this.app.applicationType === 'monolith') &&
                     this.kubernetesServiceType === 'Ingress'
                 ) {
-                    if (this.istio !== 'no') {
-                        this.template('gateway.yml.ejs', `${appName}/${appName}-gateway.yml`);
+                    if (this.istio) {
+                        this.template('istio/gateway.yml.ejs', `${appName}/${appName}-gateway.yml`);
                     } else {
                         this.template('ingress.yml.ejs', `${appName}/${appName}-ingress.yml`);
                     }
@@ -52,7 +52,7 @@ function writeFiles() {
                 if (this.monitoring === 'prometheus') {
                     this.template('monitoring/jhipster-prometheus-sm.yml.ejs', `${appName}/${appName}-prometheus-sm.yml`);
                 }
-                if (this.istioRoute === true) {
+                if (this.istio) {
                     this.template('istio/destination-rule.yml.ejs', `${appName}/${appName}-destination-rule.yml`);
                     this.template('istio/virtual-service.yml.ejs', `${appName}/${appName}-virtual-service.yml`);
                 }
@@ -83,6 +83,9 @@ function writeFiles() {
                 if (this.deploymentApplicationType === 'microservice') {
                     this.template('console/jhipster-zipkin.yml.ejs', 'console/jhipster-zipkin.yml');
                 }
+                if (this.kubernetesServiceType === 'Ingress' && this.istio) {
+                    this.template('istio/gateway/jhipster-console-gateway.yml.ejs', 'console/jhipster-console-gateway.yml');
+                }
             }
         },
 
@@ -92,6 +95,9 @@ function writeFiles() {
                 this.template('monitoring/jhipster-prometheus-cr.yml.ejs', 'monitoring/jhipster-prometheus-cr.yml');
                 this.template('monitoring/jhipster-grafana.yml.ejs', 'monitoring/jhipster-grafana.yml');
                 this.template('monitoring/jhipster-grafana-dashboard.yml.ejs', 'monitoring/jhipster-grafana-dashboard.yml');
+                if (this.kubernetesServiceType === 'Ingress' && this.istio) {
+                    this.template('istio/gateway/jhipster-grafana-gateway.yml.ejs', 'monitoring/jhipster-grafana-gateway.yml');
+                }
             }
         },
 
@@ -108,6 +114,16 @@ function writeFiles() {
 
         writeConfigRunFile() {
             this.template('kubectl-apply.sh.ejs', 'kubectl-apply.sh');
+        },
+
+        writeObservabilityGatewayFiles() {
+            if (!this.istio) return;
+            if (this.kubernetesServiceType === 'Ingress') {
+                this.template('k8s-addons.sh.ejs', 'k8s-addons.sh');
+                this.template('istio/gateway/grafana-gateway.yml.ejs', 'istio/grafana-gateway.yml');
+                this.template('istio/gateway/jaeger-gateway.yml.ejs', 'istio/jaeger-gateway.yml');
+                this.template('istio/gateway/kiali-gateway.yml.ejs', 'istio/kiali-gateway.yml');
+            }
         }
     };
 }
diff --git a/generators/kubernetes/index.js b/generators/kubernetes/index.js
index e90ce9ef7e..0dca3f2342 100644
--- a/generators/kubernetes/index.js
+++ b/generators/kubernetes/index.js
@@ -56,7 +56,6 @@ module.exports = class extends BaseDockerGenerator {
                 this.kubernetesServiceType = this.config.get('kubernetesServiceType');
                 this.ingressDomain = this.config.get('ingressDomain');
                 this.istio = this.config.get('istio');
-                this.istioRoute = this.config.get('istioRoute');
                 this.dbRandomPassword = Math.random()
                     .toString(36)
                     .slice(-8);
@@ -77,7 +76,6 @@ module.exports = class extends BaseDockerGenerator {
             askForDockerRepositoryName: prompts.askForDockerRepositoryName,
             askForDockerPushCommand: prompts.askForDockerPushCommand,
             askForIstioSupport: prompts.askForIstioSupport,
-            askForIstioRouteFiles: prompts.askForIstioRouteFiles,
             askForKubernetesServiceType: prompts.askForKubernetesServiceType,
             askForIngressDomain: prompts.askForIngressDomain
         };
@@ -116,8 +114,7 @@ module.exports = class extends BaseDockerGenerator {
                     kubernetesServiceType: this.kubernetesServiceType,
                     ingressDomain: this.ingressDomain,
                     monitoring: this.monitoring,
-                    istio: this.istio,
-                    istioRoute: this.istioRoute
+                    istio: this.istio
                 });
             }
         };
@@ -151,7 +148,7 @@ module.exports = class extends BaseDockerGenerator {
         }
 
         this.log('\nYou can deploy all your apps by running the following script:');
-        this.log(`  ${chalk.cyan('./kubectl-apply.sh')}`);
+        this.log(`  ${chalk.cyan('bash kubectl-apply.sh')}`);
         if (this.gatewayNb + this.monolithicNb >= 1) {
             const namespaceSuffix = this.kubernetesNamespace === 'default' ? '' : ` -n ${this.kubernetesNamespace}`;
             this.log("\nUse these commands to find your application's IP addresses:");
diff --git a/generators/kubernetes/prompts.js b/generators/kubernetes/prompts.js
index f962d066b8..b1eee06e51 100644
--- a/generators/kubernetes/prompts.js
+++ b/generators/kubernetes/prompts.js
@@ -23,7 +23,6 @@ module.exports = {
     askForKubernetesServiceType,
     askForIngressDomain,
     askForIstioSupport,
-    askForIstioRouteFiles,
     ...dockerPrompts
 };
 
@@ -83,6 +82,7 @@ function askForIngressDomain() {
     if (this.regenerate) return;
     const done = this.async();
     const kubernetesServiceType = this.kubernetesServiceType;
+    this.ingressDomain = this.ingressDomain && this.ingressDomain.startsWith('.') ? this.ingressDomain.substring(1) : this.ingressDomain;
 
     const prompts = [
         {
@@ -92,7 +92,7 @@ function askForIngressDomain() {
             message:
                 'What is the root FQDN for your ingress services (e.g. example.com, sub.domain.co, www.10.10.10.10.xip.io, [namespace.ip]...)?',
             // default to minikube ip
-            default: this.ingressDomain ? this.ingressDomain : `${this.kubernetesNamespace}.192.168.99.100.nip.io`,
+            default: this.ingressDomain ? this.ingressDomain : '192.168.99.100.nip.io',
             validate: input => {
                 if (input.length === 0) {
                     return 'domain name cannot be empty';
@@ -110,7 +110,7 @@ function askForIngressDomain() {
     ];
 
     this.prompt(prompts).then(props => {
-        this.ingressDomain = props.ingressDomain;
+        this.ingressDomain = props.ingressDomain ? '.'.concat(props.ingressDomain) : '';
         done();
     });
 }
@@ -118,7 +118,7 @@ function askForIngressDomain() {
 function askForIstioSupport() {
     if (this.regenerate) return;
     if (this.deploymentApplicationType === 'monolith') {
-        this.istio = 'no';
+        this.istio = false;
         return;
     }
     const done = this.async();
@@ -127,44 +127,7 @@ function askForIstioSupport() {
         {
             type: 'list',
             name: 'istio',
-            message: 'Do you want to configure Istio?',
-            choices: [
-                {
-                    value: 'no',
-                    name: 'Not required'
-                },
-                {
-                    value: 'manualInjection',
-                    name: 'Manual sidecar injection (ensure istioctl in $PATH)'
-                },
-                {
-                    value: 'autoInjection',
-                    name: 'Label tag namespace as automatic injection is already configured'
-                }
-            ],
-            default: this.istio ? this.istio : 'no'
-        }
-    ];
-
-    this.prompt(prompts).then(props => {
-        this.istio = props.istio;
-        done();
-    });
-}
-
-function askForIstioRouteFiles() {
-    if (this.regenerate) return;
-    if (this.istio === 'no') {
-        this.istioRoute = false;
-        return;
-    }
-    const done = this.async();
-
-    const prompts = [
-        {
-            type: 'list',
-            name: 'istioRoute',
-            message: 'Do you want to generate Istio route files?',
+            message: 'Do you want to enable Istio?',
             choices: [
                 {
                     value: false,
@@ -175,12 +138,12 @@ function askForIstioRouteFiles() {
                     name: 'Yes'
                 }
             ],
-            default: this.istioRoute
+            default: this.istio
         }
     ];
 
     this.prompt(prompts).then(props => {
-        this.istioRoute = props.istioRoute;
+        this.istio = props.istio;
         done();
     });
 }
diff --git a/generators/kubernetes/templates/console/jhipster-console.yml.ejs b/generators/kubernetes/templates/console/jhipster-console.yml.ejs
index b51dd21e0b..1db2495078 100644
--- a/generators/kubernetes/templates/console/jhipster-console.yml.ejs
+++ b/generators/kubernetes/templates/console/jhipster-console.yml.ejs
@@ -27,6 +27,10 @@ spec:
     metadata:
       labels:
         app: jhipster-console
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       containers:
       - image: <%= DOCKER_JHIPSTER_CONSOLE %>
@@ -55,7 +59,7 @@ spec:
   selector:
     app: jhipster-console
 ---
-<%_ if (kubernetesServiceType === 'Ingress') { _%>
+<%_ if (kubernetesServiceType === 'Ingress' && !istio) { _%>
 apiVersion: extensions/v1beta1
 kind: Ingress
 metadata:
@@ -63,7 +67,7 @@ metadata:
   namespace: <%= kubernetesNamespace %>
 spec:
   rules:
-  - host: jhipster-console.<%= ingressDomain %>
+  - host: jhipster-console.<%= kubernetesNamespace %><%= ingressDomain %>
     http:
       paths:
       - path: /
diff --git a/generators/kubernetes/templates/console/jhipster-dashboard-console.yml.ejs b/generators/kubernetes/templates/console/jhipster-dashboard-console.yml.ejs
index 8dbeac8f2f..4683e4415a 100644
--- a/generators/kubernetes/templates/console/jhipster-dashboard-console.yml.ejs
+++ b/generators/kubernetes/templates/console/jhipster-dashboard-console.yml.ejs
@@ -30,6 +30,9 @@ spec:
         job: jhipster-import-dashboards
       annotations:
         "helm.sh/hook": post-install
+     <%_ if (istio) { _%>
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       initContainers:
         - name: init-dependent-service-check
diff --git a/generators/kubernetes/templates/console/jhipster-elasticsearch.yml.ejs b/generators/kubernetes/templates/console/jhipster-elasticsearch.yml.ejs
index f4bd72a411..3489bee879 100644
--- a/generators/kubernetes/templates/console/jhipster-elasticsearch.yml.ejs
+++ b/generators/kubernetes/templates/console/jhipster-elasticsearch.yml.ejs
@@ -49,6 +49,10 @@ spec:
       labels:
         component: jhipster-elasticsearch
         role: master
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       initContainers:
       - name: init-sysctl
@@ -195,6 +199,10 @@ spec:
       labels:
         component: jhipster-elasticsearch
         role: data
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       initContainers:
       - name: init-sysctl
@@ -336,6 +344,10 @@ spec:
       labels:
         component: jhipster-elasticsearch
         role: client
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       initContainers:
       - name: init-sysctl
diff --git a/generators/kubernetes/templates/console/jhipster-logstash.yml.ejs b/generators/kubernetes/templates/console/jhipster-logstash.yml.ejs
index 1ddc2e6d98..471a81205f 100644
--- a/generators/kubernetes/templates/console/jhipster-logstash.yml.ejs
+++ b/generators/kubernetes/templates/console/jhipster-logstash.yml.ejs
@@ -45,6 +45,10 @@ spec:
     metadata:
       labels:
         app: jhipster-logstash
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       initContainers:
         - name: init-es-check
diff --git a/generators/kubernetes/templates/console/jhipster-zipkin.yml.ejs b/generators/kubernetes/templates/console/jhipster-zipkin.yml.ejs
index 128d3095ca..fd0b8a2061 100644
--- a/generators/kubernetes/templates/console/jhipster-zipkin.yml.ejs
+++ b/generators/kubernetes/templates/console/jhipster-zipkin.yml.ejs
@@ -27,6 +27,10 @@ spec:
     metadata:
       labels:
         app: jhipster-zipkin
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       containers:
       - name: jhipster-zipkin
diff --git a/generators/kubernetes/templates/db/couchbase.yml.ejs b/generators/kubernetes/templates/db/couchbase.yml.ejs
index 06d7f44b59..d37b49957f 100644
--- a/generators/kubernetes/templates/db/couchbase.yml.ejs
+++ b/generators/kubernetes/templates/db/couchbase.yml.ejs
@@ -41,6 +41,10 @@ spec:
     metadata:
       labels:
         app: <%= app.baseName.toLowerCase() %>-couchbase
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       containers:
       - name: <%= app.baseName.toLowerCase() %>-couchbase
diff --git a/generators/kubernetes/templates/db/elasticsearch.yml.ejs b/generators/kubernetes/templates/db/elasticsearch.yml.ejs
index fba0e53871..4ecc235f0d 100644
--- a/generators/kubernetes/templates/db/elasticsearch.yml.ejs
+++ b/generators/kubernetes/templates/db/elasticsearch.yml.ejs
@@ -27,6 +27,10 @@ spec:
     metadata:
       labels:
         app: <%= app.baseName.toLowerCase() %>-elasticsearch
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       volumes:
       - name: data
diff --git a/generators/kubernetes/templates/db/mariadb.yml.ejs b/generators/kubernetes/templates/db/mariadb.yml.ejs
index 0b4c451ab5..4f2ef289fd 100644
--- a/generators/kubernetes/templates/db/mariadb.yml.ejs
+++ b/generators/kubernetes/templates/db/mariadb.yml.ejs
@@ -38,6 +38,10 @@ spec:
     metadata:
       labels:
         app: <%= app.baseName.toLowerCase() %>-mariadb
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       volumes:
       - name: data
diff --git a/generators/kubernetes/templates/db/mongodb.yml.ejs b/generators/kubernetes/templates/db/mongodb.yml.ejs
index 3dbfeac7de..36c70fc90a 100644
--- a/generators/kubernetes/templates/db/mongodb.yml.ejs
+++ b/generators/kubernetes/templates/db/mongodb.yml.ejs
@@ -180,7 +180,10 @@ spec:
     metadata:
       labels:
         app: <%= app.baseName.toLowerCase() %>-mongodb
+     <%_ if (istio) { _%>
       annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       initContainers:
         - name: config
diff --git a/generators/kubernetes/templates/db/mysql.yml.ejs b/generators/kubernetes/templates/db/mysql.yml.ejs
index 7611740088..bfae88e47b 100644
--- a/generators/kubernetes/templates/db/mysql.yml.ejs
+++ b/generators/kubernetes/templates/db/mysql.yml.ejs
@@ -27,6 +27,10 @@ spec:
     metadata:
       labels:
         app: <%= app.baseName.toLowerCase() %>-mysql
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       volumes:
       - name: data
diff --git a/generators/kubernetes/templates/db/postgresql.yml.ejs b/generators/kubernetes/templates/db/postgresql.yml.ejs
index 4d6eb25d95..00d3496ac5 100644
--- a/generators/kubernetes/templates/db/postgresql.yml.ejs
+++ b/generators/kubernetes/templates/db/postgresql.yml.ejs
@@ -38,6 +38,10 @@ spec:
     metadata:
       labels:
         app: <%= app.baseName.toLowerCase() %>-postgresql
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       volumes:
       - name: data
diff --git a/generators/kubernetes/templates/deployment.yml.ejs b/generators/kubernetes/templates/deployment.yml.ejs
index 507ec9e091..bd409c786c 100644
--- a/generators/kubernetes/templates/deployment.yml.ejs
+++ b/generators/kubernetes/templates/deployment.yml.ejs
@@ -80,7 +80,7 @@ spec:
               key: registry-admin-password
         - name: EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE
           value: http://admin:${jhipster.registry.password}@jhipster-registry.<%= kubernetesNamespace %>.svc.cluster.local:8761/eureka/
-          <%_ if (istio !== 'no') { _%>
+          <%_ if (istio) { _%>
         - name: EUREKA_INSTANCE_PREFER_IP_ADDRESS
           value: "false"
         - name: EUREKA_INSTANCE_HOSTNAME
@@ -92,7 +92,7 @@ spec:
           value: consul.<%= kubernetesNamespace %>.svc.cluster.local
         - name: SPRING_CLOUD_CONSUL_PORT
           value: "8500"
-          <%_ if (istio !== 'no') { _%>
+          <%_ if (istio) { _%>
         - name: SPRING_CLOUD_CONSUL_DISCOVERY_PREFER_IP_ADDRESS
           value: "false"
         - name: SPRING_CLOUD_CONSUL_DISCOVERY_HOSTNAME
diff --git a/generators/kubernetes/templates/ingress.yml.ejs b/generators/kubernetes/templates/ingress.yml.ejs
index 16d9a019ed..89b84f7783 100644
--- a/generators/kubernetes/templates/ingress.yml.ejs
+++ b/generators/kubernetes/templates/ingress.yml.ejs
@@ -23,7 +23,7 @@ metadata:
   namespace: <%= kubernetesNamespace %>
 spec:
   rules:
-  - host: <%= app.baseName.toLowerCase() %>.<%= ingressDomain %>
+  - host: <%= app.baseName.toLowerCase() %>.<%= kubernetesNamespace %><%= ingressDomain %>
     http:
       paths:
       - path: /.*
diff --git a/generators/kubernetes/templates/gateway.yml.ejs b/generators/kubernetes/templates/istio/gateway.yml.ejs
similarity index 80%
rename from generators/kubernetes/templates/gateway.yml.ejs
rename to generators/kubernetes/templates/istio/gateway.yml.ejs
index b650ca4a06..ef4477e728 100644
--- a/generators/kubernetes/templates/gateway.yml.ejs
+++ b/generators/kubernetes/templates/istio/gateway.yml.ejs
@@ -21,6 +21,9 @@ kind: Gateway
 metadata:
   name: <%= app.baseName.toLowerCase() %>-gateway
   namespace: <%= kubernetesNamespace %>
+  labels:
+    gateway: <%= app.baseName.toLowerCase() %>-gateway
+    istio: ingressgateway
 spec:
   selector:
     istio: ingressgateway
@@ -30,28 +33,24 @@ spec:
       name: http
       protocol: HTTP
     hosts:
-    - <%= app.baseName.toLowerCase() %>.<%= ingressDomain %>
+    - <%= app.baseName.toLowerCase() %>.<%= kubernetesNamespace %><%= ingressDomain %>
   - port:
       number: 80
       name: http2
       protocol: HTTP2
     hosts:
-    - <%= app.baseName.toLowerCase() %>.<%= ingressDomain %>
-#  - port:
-#      number: 443
-#      name: https
-#      protocol: HTTPS
-#    hosts:
-#    - <%= app.baseName.toLowerCase() %>.<%= ingressDomain %>
+    - <%= app.baseName.toLowerCase() %>.<%= kubernetesNamespace %><%= ingressDomain %>
 ---
 apiVersion: networking.istio.io/v1alpha3
 kind: VirtualService
 metadata:
   name: <%= app.baseName.toLowerCase() %>-gw-virtualservice
   namespace: <%= kubernetesNamespace %>
+  labels:
+    service: <%= app.baseName.toLowerCase() %>-gw-virtualservice
 spec:
   hosts:
-  - <%= app.baseName.toLowerCase() %>.<%= ingressDomain %>
+  - <%= app.baseName.toLowerCase() %>.<%= kubernetesNamespace %><%= ingressDomain %>
   gateways:
   - <%= app.baseName.toLowerCase() %>-gateway
   http:
diff --git a/generators/kubernetes/templates/istio/gateway/grafana-gateway.yml.ejs b/generators/kubernetes/templates/istio/gateway/grafana-gateway.yml.ejs
new file mode 100644
index 0000000000..a842a8af24
--- /dev/null
+++ b/generators/kubernetes/templates/istio/gateway/grafana-gateway.yml.ejs
@@ -0,0 +1,57 @@
+<%#
+ Copyright 2013-2018 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.
+-%>
+apiVersion: networking.istio.io/v1alpha3
+kind: Gateway
+metadata:
+  name: grafana-observability-gateway
+  namespace: istio-system
+spec:
+  selector:
+    istio: ingressgateway
+  servers:
+  - port:
+      number: 80
+      name: http
+      protocol: HTTP
+    hosts:
+    - grafana.istio-system<%= ingressDomain %>
+  - port:
+      number: 80
+      name: http2
+      protocol: HTTP2
+    hosts:
+    - grafana.istio-system<%= ingressDomain %>
+---
+apiVersion: networking.istio.io/v1alpha3
+kind: VirtualService
+metadata:
+  name: grafana-gw-virtualservice
+  namespace: istio-system
+spec:
+  hosts:
+  - grafana.istio-system<%= ingressDomain %>
+  gateways:
+  - grafana-observability-gateway
+  http:
+  - match:
+    - uri:
+        prefix: /
+    route:
+    - destination:
+        host: grafana
diff --git a/generators/kubernetes/templates/istio/gateway/jaeger-gateway.yml.ejs b/generators/kubernetes/templates/istio/gateway/jaeger-gateway.yml.ejs
new file mode 100644
index 0000000000..658d0ec206
--- /dev/null
+++ b/generators/kubernetes/templates/istio/gateway/jaeger-gateway.yml.ejs
@@ -0,0 +1,57 @@
+<%#
+ Copyright 2013-2018 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.
+-%>
+apiVersion: networking.istio.io/v1alpha3
+kind: Gateway
+metadata:
+  name: jaeger-observability-gateway
+  namespace: istio-system
+spec:
+  selector:
+    istio: ingressgateway
+  servers:
+  - port:
+      number: 80
+      name: http
+      protocol: HTTP
+    hosts:
+    - jaeger.istio-system<%= ingressDomain %>
+  - port:
+      number: 80
+      name: http2
+      protocol: HTTP2
+    hosts:
+    - jaeger.istio-system<%= ingressDomain %>
+---
+apiVersion: networking.istio.io/v1alpha3
+kind: VirtualService
+metadata:
+  name: jaeger-gw-virtualservice
+  namespace: istio-system
+spec:
+  hosts:
+  - jaeger.istio-system<%= ingressDomain %>
+  gateways:
+  - jaeger-observability-gateway
+  http:
+  - match:
+    - uri:
+        prefix: /
+    route:
+    - destination:
+        host: jaeger-query
diff --git a/generators/kubernetes/templates/istio/gateway/jhipster-console-gateway.yml.ejs b/generators/kubernetes/templates/istio/gateway/jhipster-console-gateway.yml.ejs
new file mode 100644
index 0000000000..8259779467
--- /dev/null
+++ b/generators/kubernetes/templates/istio/gateway/jhipster-console-gateway.yml.ejs
@@ -0,0 +1,57 @@
+<%#
+ Copyright 2013-2018 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.
+-%>
+apiVersion: networking.istio.io/v1alpha3
+kind: Gateway
+metadata:
+  name: jhipster-console-gateway
+  namespace: <%= kubernetesNamespace %>
+spec:
+  selector:
+    istio: ingressgateway
+  servers:
+  - port:
+      number: 80
+      name: http
+      protocol: HTTP
+    hosts:
+    - jhipster-console<%= ingressDomain %>
+  - port:
+      number: 80
+      name: http2
+      protocol: HTTP2
+    hosts:
+    - jhipster-console<%= ingressDomain %>
+---
+apiVersion: networking.istio.io/v1alpha3
+kind: VirtualService
+metadata:
+  name: jhipster-console-gw-virtualservice
+  namespace: <%= kubernetesNamespace %>
+spec:
+  hosts:
+  - jhipster-console<%= ingressDomain %>
+  gateways:
+  - jhipster-console-gateway
+  http:
+  - match:
+    - uri:
+        prefix: /
+    route:
+    - destination:
+        host: jhipster-console
diff --git a/generators/kubernetes/templates/istio/gateway/jhipster-grafana-gateway.yml.ejs b/generators/kubernetes/templates/istio/gateway/jhipster-grafana-gateway.yml.ejs
new file mode 100644
index 0000000000..634cbbfe58
--- /dev/null
+++ b/generators/kubernetes/templates/istio/gateway/jhipster-grafana-gateway.yml.ejs
@@ -0,0 +1,57 @@
+<%#
+ Copyright 2013-2018 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.
+-%>
+apiVersion: networking.istio.io/v1alpha3
+kind: Gateway
+metadata:
+  name: jhipster-grafana-gateway
+  namespace: <%= kubernetesNamespace %>
+spec:
+  selector:
+    istio: ingressgateway
+  servers:
+  - port:
+      number: 80
+      name: http
+      protocol: HTTP
+    hosts:
+    - jhipster-grafana<%= ingressDomain %>
+  - port:
+      number: 80
+      name: http2
+      protocol: HTTP2
+    hosts:
+    - jhipster-grafana<%= ingressDomain %>
+---
+apiVersion: networking.istio.io/v1alpha3
+kind: VirtualService
+metadata:
+  name: jhipster-grafana-gw-virtualservice
+  namespace: <%= kubernetesNamespace %>
+spec:
+  hosts:
+  - jhipster-grafana<%= ingressDomain %>
+  gateways:
+  - jhipster-grafana-gateway
+  http:
+  - match:
+    - uri:
+        prefix: /
+    route:
+    - destination:
+        host: grafana
diff --git a/generators/kubernetes/templates/istio/gateway/kiali-gateway.yml.ejs b/generators/kubernetes/templates/istio/gateway/kiali-gateway.yml.ejs
new file mode 100644
index 0000000000..432458f27c
--- /dev/null
+++ b/generators/kubernetes/templates/istio/gateway/kiali-gateway.yml.ejs
@@ -0,0 +1,57 @@
+<%#
+ Copyright 2013-2018 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.
+-%>
+apiVersion: networking.istio.io/v1alpha3
+kind: Gateway
+metadata:
+  name: kiali-observability-gateway
+  namespace: istio-system
+spec:
+  selector:
+    istio: ingressgateway
+  servers:
+  - port:
+      number: 80
+      name: http
+      protocol: HTTP
+    hosts:
+    - kiali.istio-system<%= ingressDomain %>
+  - port:
+      number: 80
+      name: http2
+      protocol: HTTP2
+    hosts:
+    - kiali.istio-system<%= ingressDomain %>
+---
+apiVersion: networking.istio.io/v1alpha3
+kind: VirtualService
+metadata:
+  name: kiali-gw-virtualservice
+  namespace: istio-system
+spec:
+  hosts:
+  - kiali.istio-system<%= ingressDomain %>
+  gateways:
+  - kiali-observability-gateway
+  http:
+  - match:
+    - uri:
+        prefix: /
+    route:
+    - destination:
+        host: kiali
diff --git a/generators/kubernetes/templates/k8s-addons.sh.ejs b/generators/kubernetes/templates/k8s-addons.sh.ejs
new file mode 100755
index 0000000000..f21b4b14ac
--- /dev/null
+++ b/generators/kubernetes/templates/k8s-addons.sh.ejs
@@ -0,0 +1,68 @@
+#!/bin/bash
+<%#
+ Copyright 2013-2018 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.
+-%>
+# Files are ordered in proper order with needed wait for the dependent custom resource definitions to get initialized.
+# kiali - istio service mesh observability
+export GRAFANA_URL="http://grafana.${ISTIO_SYSTEM}<%= ingressDomain %>"
+export JAEGER_URL="http://jaeger.${ISTIO_SYSTEM}<%= ingressDomain %>"
+export IMAGE_NAME="${IMAGE_NAME:-kiali/kiali}"
+export IMAGE_VERSION=
+export VERSION_LABEL=
+export IMAGE_PULL_POLICY_TOKEN="${IMAGE_PULL_POLICY_TOKEN:-imagePullPolicy: Always}"
+export NAMESPACE=istio-system
+export ISTIO_NAMESPACE="${NAMESPACE}"
+export VERBOSE_MODE="${VERBOSE_MODE:-3}"
+export KIALI_USERNAME_BASE64="YWRtaW4K"
+export KIALI_PASSPHRASE_BASE64="YWRtaW4K"
+
+if ! which 'envsubst' > /dev/null 2>&1 ; then
+  echo "ERROR: You do not have 'envsubst' in your PATH. Please install it and retry."
+  echo "If you are on MacOS, you can get this by installing the gettext package"
+  exit 1
+fi
+
+IMAGE_VERSION=$(curl https://api.github.com/repos/kiali/kiali/releases/latest 2> /dev/null | grep  "tag_name" | sed -e 's/.*://' -e 's/ *"//' -e 's/",//')
+VERSION_LABEL=${IMAGE_VERSION}
+
+get_downloader() {
+  if [ ! "$downloader" ] ; then
+    # Use wget command if available, otherwise try curl
+    if which wget > /dev/null ; then
+      downloader="wget -q -O -"
+    fi
+    if [ ! "$downloader" ] ; then
+      if which curl > /dev/null ; then
+        downloader="curl -s"
+      fi
+    fi
+    if [ ! "$downloader" ] ; then
+      echo "ERROR: You must install either curl or wget to allow downloading"
+      exit 1
+    fi
+  fi
+}
+
+for yaml in secret configmap serviceaccount clusterrole clusterrolebinding deployment service ingress
+do
+    get_downloader
+    yaml_url="https://raw.githubusercontent.com/kiali/kiali/${VERSION_LABEL}/deploy/kubernetes/${yaml}.yaml"
+    ${downloader} ${yaml_url} | envsubst | kubectl apply -n ${NAMESPACE} -f -
+done
+
+kubectl apply -f istio/
diff --git a/generators/kubernetes/templates/kubectl-apply.sh.ejs b/generators/kubernetes/templates/kubectl-apply.sh.ejs
index 747ec59403..a25df4e771 100755
--- a/generators/kubernetes/templates/kubectl-apply.sh.ejs
+++ b/generators/kubernetes/templates/kubectl-apply.sh.ejs
@@ -19,12 +19,38 @@
 -%>
 # Files are ordered in proper order with needed wait for the dependent custom resource definitions to get initialized.
 # Usage: bash kubectl-apply.sh
-<%_ if (istio === 'manualInjection') { _%>
-loopDir(){
-  for entry in "$1"/*
-  do
-    kubectl apply -f <(istioctl kube-inject -f ${entry})
-  done
+
+logSummary(){
+    echo ""
+    echo "#####################################################"
+    echo "Please find the below useful endpoints,"
+    <%_ if (monitoring === 'elk') { _%>
+    echo "JHipster Console - http://jhipster-console.<%= kubernetesNamespace %><%= ingressDomain %>"
+    <%_ } _%>
+    <%_ if (monitoring === 'prometheus') { _%>
+    echo "JHipster Grafana - http://jhipster-grafana.<%= kubernetesNamespace %><%= ingressDomain %>"
+    <%_ } _%>
+    <%_ if (kubernetesServiceType === 'Ingress') { _%>
+    <%_ appConfigs.forEach((appConfig) =>  { _%>
+    <%_ if (appConfig.applicationType === 'gateway') {_%>
+    echo "Gateway - http://<%= appConfig.baseName.toLowerCase() %>.<%= kubernetesNamespace %><%= ingressDomain %>"
+    <%_ } _%><%_ if (appConfig.applicationType === 'monolith') {_%>
+    echo "<%= appConfig.baseName %> - http://<%= appConfig.baseName.toLowerCase() %>.<%= kubernetesNamespace %><%= ingressDomain %>"
+    <%_ } _%>
+    <%_ }) _%>
+    <%_ if (istio) { _%>
+    echo "Jaeger - http://jaeger.${ISTIO_SYSTEM}<%= ingressDomain %>"
+    echo "Grafana - http://grafana.${ISTIO_SYSTEM}<%= ingressDomain %>"
+    echo "Kiali - http://kiali.${ISTIO_SYSTEM}<%= ingressDomain %>"
+    <%_ } _%>
+    <%_ } _%>
+    echo "#####################################################"
+}
+
+<%_ if (istio && kubernetesServiceType === 'Ingress') { _%>
+execAddons(){
+    chmod +x k8s-addons.sh
+    bash k8s-addons.sh
 }
 <%_ } _%>
 
@@ -32,16 +58,12 @@ loopDir(){
 kubectl apply -f namespace.yml
 <%_ } _%> <%_ if (serviceDiscoveryType === 'eureka' || serviceDiscoveryType === 'consul') { _%>
 kubectl apply -f registry/
-<%_ } _%> <%_ if (istio === 'autoInjection') { _%>
-kubectl label namespace <%-kubernetesNamespace%> istio-injection=enabled
-<%_ } _%> <%_ if (istio === 'manualInjection') { _%>
-<%_ appConfigs.forEach((appConfig, index) =>  { _%>
-loopDir "<%- appConfig.baseName.toLowerCase() %>"
-<%_ }) _%>
-<%_ } else {_%>
-<%_ appConfigs.forEach((appConfig, index) =>  { _%>
+<%_ } _%> <%_ if (istio) { _%>
+kubectl label namespace <%-kubernetesNamespace%> istio-injection=enabled --overwrite=true
+<%_ } _%> <%_ appConfigs.forEach((appConfig, index) =>  { _%>
 kubectl apply -f <%- appConfig.baseName.toLowerCase() %>/
-<%_ }) _%> <%_ } _%> <%_ if (useKafka === true) { _%>
+<%_ }) _%>
+<%_ if (useKafka === true) { _%>
 kubectl apply -f messagebroker/
 <%_ } _%> <%_ if (monitoring === 'elk') { _%>
 kubectl apply -f console/
@@ -55,3 +77,9 @@ kubectl apply -f monitoring/jhipster-prometheus-cr.yml
 kubectl apply -f monitoring/jhipster-grafana.yml
 kubectl apply -f monitoring/jhipster-grafana-dashboard.yml
 <%_ } _%>
+
+<%_ if (istio && kubernetesServiceType === 'Ingress') { _%>
+export ISTIO_SYSTEM=istio-system
+execAddons
+<%_ } _%>
+logSummary
diff --git a/generators/kubernetes/templates/messagebroker/kafka.yml.ejs b/generators/kubernetes/templates/messagebroker/kafka.yml.ejs
index a46e3f1dc9..5d34ebf56e 100644
--- a/generators/kubernetes/templates/messagebroker/kafka.yml.ejs
+++ b/generators/kubernetes/templates/messagebroker/kafka.yml.ejs
@@ -27,6 +27,10 @@ spec:
     metadata:
       labels:
         app: jhipster-kafka
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       containers:
       - name: kafka
@@ -65,6 +69,10 @@ spec:
     metadata:
       labels:
         app: jhipster-zookeeper
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       containers:
       - name: zookeeper
diff --git a/generators/kubernetes/templates/monitoring/jhipster-grafana-dashboard.yml.ejs b/generators/kubernetes/templates/monitoring/jhipster-grafana-dashboard.yml.ejs
index 79f04094eb..80db0106de 100644
--- a/generators/kubernetes/templates/monitoring/jhipster-grafana-dashboard.yml.ejs
+++ b/generators/kubernetes/templates/monitoring/jhipster-grafana-dashboard.yml.ejs
@@ -2311,6 +2311,10 @@ spec:
     metadata:
       labels:
         job: jhipster-grafana-dashboard
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       initContainers:
         - name: init-dependent-services-check
diff --git a/generators/kubernetes/templates/monitoring/jhipster-grafana.yml.ejs b/generators/kubernetes/templates/monitoring/jhipster-grafana.yml.ejs
index 987b51c1cf..eff5b363c1 100644
--- a/generators/kubernetes/templates/monitoring/jhipster-grafana.yml.ejs
+++ b/generators/kubernetes/templates/monitoring/jhipster-grafana.yml.ejs
@@ -36,6 +36,10 @@ spec:
     metadata:
       labels:
         app: jhipster-grafana
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       containers:
       - name: jhipster-grafana
@@ -92,7 +96,7 @@ spec:
   selector:
     app: jhipster-grafana
 ---
-<%_ if (kubernetesServiceType === 'Ingress') { _%>
+<%_ if (kubernetesServiceType === 'Ingress' && !istio ) { _%>
 apiVersion: extensions/v1beta1
 kind: Ingress
 metadata:
@@ -100,7 +104,7 @@ metadata:
   namespace: <%= kubernetesNamespace %>
 spec:
   rules:
-  - host: jhipster-grafana.<%= ingressDomain %>
+  - host: jhipster-grafana.<%= kubernetesNamespace %><%= ingressDomain %>
     http:
       paths:
       - path: /
diff --git a/generators/kubernetes/templates/monitoring/jhipster-prometheus-crd.yml.ejs b/generators/kubernetes/templates/monitoring/jhipster-prometheus-crd.yml.ejs
index 1a46091a4e..f123e4a78d 100644
--- a/generators/kubernetes/templates/monitoring/jhipster-prometheus-crd.yml.ejs
+++ b/generators/kubernetes/templates/monitoring/jhipster-prometheus-crd.yml.ejs
@@ -102,6 +102,10 @@ spec:
     metadata:
       labels:
         k8s-app: prometheus-operator
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       containers:
       - args:
diff --git a/generators/kubernetes/templates/registry/consul.yml.ejs b/generators/kubernetes/templates/registry/consul.yml.ejs
index c3a816d403..0009f51df5 100644
--- a/generators/kubernetes/templates/registry/consul.yml.ejs
+++ b/generators/kubernetes/templates/registry/consul.yml.ejs
@@ -90,6 +90,10 @@ spec:
       name: consul
       labels:
         app: consul
+     <%_ if (istio) { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       securityContext:
         fsGroup: 1000
diff --git a/generators/kubernetes/templates/registry/jhipster-registry.yml.ejs b/generators/kubernetes/templates/registry/jhipster-registry.yml.ejs
index d3c3f846ea..0313b2b96f 100644
--- a/generators/kubernetes/templates/registry/jhipster-registry.yml.ejs
+++ b/generators/kubernetes/templates/registry/jhipster-registry.yml.ejs
@@ -73,7 +73,7 @@ spec:
       labels:
         app: jhipster-registry
         version: "1.0"
-     <%_ if (istio !== 'no') { _%>
+     <%_ if (istio) { _%>
       annotations:
         sidecar.istio.io/inject: "false"
      <%_ } _%>
@@ -94,7 +94,7 @@ spec:
             secretKeyRef:
               name: registry-secret
               key: registry-admin-password
-        <%_ if (istio !== 'no') { _%>
+        <%_ if (istio) { _%>
         - name: EUREKA_INSTANCE_PREFER_IP_ADDRESS
           value: "false"
         <%_ } _%>
diff --git a/generators/server/templates/build.gradle.ejs b/generators/server/templates/build.gradle.ejs
index 057fdcfbf9..eaab709ddf 100644
--- a/generators/server/templates/build.gradle.ejs
+++ b/generators/server/templates/build.gradle.ejs
@@ -44,7 +44,7 @@ plugins {
     id "com.google.cloud.tools.jib" version "0.9.11"
     id "com.gorylenko.gradle-git-properties" version "2.0.0"
     <%_ if (!skipClient) { _%>
-    id "com.moowork.node" version "1.2.0"
+    id "com.github.node-gradle.node" version "1.3.0"
     <%_ } _%>
     id "net.ltgt.apt-eclipse" version "0.21"
     id "net.ltgt.apt-idea" version "0.21"
diff --git a/generators/server/templates/gradle/profile_dev.gradle.ejs b/generators/server/templates/gradle/profile_dev.gradle.ejs
index acf7915281..44911de2cd 100644
--- a/generators/server/templates/gradle/profile_dev.gradle.ejs
+++ b/generators/server/templates/gradle/profile_dev.gradle.ejs
@@ -45,15 +45,16 @@ bootRun {
 
 <%_ if (!skipClient) { _%>
 task webpackBuildDev(type: <%= _.upperFirst(clientPackageManager) %>Task) {
-    inputs.files(fileTree("<%= CLIENT_MAIN_SRC_DIR %>"))
+    inputs.file("package-lock.json")
+    inputs.dir("<%= CLIENT_MAIN_SRC_DIR %>")
 
     def webpackDevFiles = fileTree("<%= CLIENT_WEBPACK_DIR %>/")
     webpackDevFiles.exclude("webpack.prod.js")
     inputs.files(webpackDevFiles)
 
-    outputs.files(fileTree("<%= CLIENT_DIST_DIR %>"))
+    outputs.dir("<%= CLIENT_DIST_DIR %>")
 
-    dependsOn <%= clientPackageManager %>_install
+    dependsOn <%= clientPackageManager %>Install
 
     args = ["run", "webpack:build"]
 }
diff --git a/generators/server/templates/gradle/profile_prod.gradle.ejs b/generators/server/templates/gradle/profile_prod.gradle.ejs
index 606eacf57d..dea4ceb53b 100644
--- a/generators/server/templates/gradle/profile_prod.gradle.ejs
+++ b/generators/server/templates/gradle/profile_prod.gradle.ejs
@@ -40,11 +40,11 @@ bootRun {
 }
 
 <%_ if (!skipClient) { _%>
-task webpack_test(type: <%= _.upperFirst(clientPackageManager) %>Task, dependsOn: "<%= clientPackageManager %>_install") {
+task webpack_test(type: <%= _.upperFirst(clientPackageManager) %>Task, dependsOn: "<%= clientPackageManager %>Install") {
     args = ["run", "webpack:test"]
 }
 
-task webpack(type: <%= _.upperFirst(clientPackageManager) %>Task, dependsOn: "<%= clientPackageManager %>_install") {
+task webpack(type: <%= _.upperFirst(clientPackageManager) %>Task, dependsOn: "<%= clientPackageManager %>Install") {
     args = ["run", "webpack:prod"]
 }
 <%_ } _%>
diff --git a/generators/server/templates/src/main/java/package/service/UserService.java.ejs b/generators/server/templates/src/main/java/package/service/UserService.java.ejs
index abd81c56e1..cd24b5d42e 100644
--- a/generators/server/templates/src/main/java/package/service/UserService.java.ejs
+++ b/generators/server/templates/src/main/java/package/service/UserService.java.ejs
@@ -847,12 +847,16 @@ public class UserService {
             // Here we can't cater for all the use-cases, see:
             // https://github.com/jhipster/generator-jhipster/issues/7866
             // for the en_US or en_** issue.
-            // Since JHipter only have one "en" language, we will handle it here, for other languages, please handle it accordingly.
+            // Since JHipter only has one "en" language, we will handle it here,
+            // for other languages, please handle it accordingly.
             String locale = (String) details.get("locale");
-            if(locale.startsWith("en_") || locale.startsWith("en-")) {
+            if (locale.startsWith("en_") || locale.startsWith("en-")) {
                 locale = "en";
             }
             user.setLangKey(locale.toLowerCase());
+        } else {
+            // set langKey to default if not specified by IdP
+            user.setLangKey(Constants.DEFAULT_LANGUAGE);
         }
         if (details.get("picture") != null) {
             user.setImageUrl((String) details.get("picture"));


Test patch:
diff --git a/generators/entity-client/templates/angular/src/test/javascript/spec/app/entities/entity-management.service.spec.ts.ejs b/generators/entity-client/templates/angular/src/test/javascript/spec/app/entities/entity-management.service.spec.ts.ejs
index d7ae92acbe..55c3ba6cde 100644
--- a/generators/entity-client/templates/angular/src/test/javascript/spec/app/entities/entity-management.service.spec.ts.ejs
+++ b/generators/entity-client/templates/angular/src/test/javascript/spec/app/entities/entity-management.service.spec.ts.ejs
@@ -91,7 +91,7 @@ describe('Service Tests', () => {
             )
         });
 
-        describe('Service methods', async () => {
+        describe('Service methods', () => {
             it('should find an element', async () => {
                 const returnedFromService = Object.assign({
 <%_ fields.forEach((field) => {
diff --git a/test-integration/samples/jdl-default/app.jdl b/test-integration/samples/jdl-default/app.jdl
index fdc699ccdb..7732c8c03d 100644
--- a/test-integration/samples/jdl-default/app.jdl
+++ b/test-integration/samples/jdl-default/app.jdl
@@ -13,7 +13,7 @@ application {
     nativeLanguage en,
     languages [ en, fr ]
   }
-  entities BankAccount, TheLabel, Operation
+  entities *
 }
 
 entity BankAccount {
@@ -44,6 +44,79 @@ enum BankAccountType {
   SAVINGS,
   LOAN
 }
+
+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 Country {
+  name String
+}
+
+entity Region {
+  name String
+}
+
+relationship OneToOne {
+  Department{location} to Location
+}
+
 relationship OneToMany {
   BankAccount{operation} to Operation{bankAccount(name)}
 }
@@ -53,11 +126,41 @@ relationship ManyToOne {
 relationship ManyToMany {
   Operation{theLabel(labelName)} to TheLabel{operation}
 }
-dto BankAccount  with mapstruct
-service BankAccount with serviceImpl
+
+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(region)} to Region
+}
+
+relationship ManyToOne {
+  Employee{user(login)} to User{employee},
+  Employee{manager(lastName)} to Employee
+}
+
+relationship ManyToMany {
+  JobHistory to Department,
+  JobHistory to Job{history},
+  JobHistory{emp(employee)} to Employee{history},
+  Job{chore(title)} to Task{linkedJob(JobTitle)}
+}
+
+dto BankAccount, Employee, Department, Location, Country, Region with mapstruct
+
 angularSuffix BankAccount with mySuffix
 filter BankAccount
 clientRootFolder BankAccount, TheLabel, Operation with test-root
-paginate TheLabel with pagination
-service TheLabel with serviceClass
-paginate Operation with infinite-scroll
+
+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/kubernetes.helm.spec.js b/test/kubernetes.helm.spec.js
index 7d7b27b87a..04f247c07c 100644
--- a/test/kubernetes.helm.spec.js
+++ b/test/kubernetes.helm.spec.js
@@ -430,7 +430,7 @@ describe('JHipster Kubernetes Helm Sub Generator', () => {
         });
     });
 
-    describe('gateway with istio routing', () => {
+    describe('gateway with istio', () => {
         beforeEach(done => {
             helpers
                 .run(require.resolve('../generators/kubernetes-helm'))
@@ -448,8 +448,7 @@ describe('JHipster Kubernetes Helm Sub Generator', () => {
                     kubernetesServiceType: 'Ingress',
                     ingressDomain: 'example.com',
                     clusteredDbApps: [],
-                    istio: 'manualInjection',
-                    istioRoute: true
+                    istio: true
                 })
                 .on('end', done);
         });
diff --git a/test/kubernetes.spec.js b/test/kubernetes.spec.js
index 11043174ea..69bc989273 100644
--- a/test/kubernetes.spec.js
+++ b/test/kubernetes.spec.js
@@ -399,8 +399,7 @@ describe('JHipster Kubernetes Sub Generator', () => {
                     kubernetesServiceType: 'Ingress',
                     ingressDomain: 'example.com',
                     clusteredDbApps: [],
-                    istio: 'manualInjection',
-                    istioRoute: true
+                    istio: true
                 })
                 .on('end', done);
         });
diff --git a/test/needle-api/needle-client-react.spec.js b/test/needle-api/needle-client-react.spec.js
index f72b10c566..201984ddf2 100644
--- a/test/needle-api/needle-client-react.spec.js
+++ b/test/needle-api/needle-client-react.spec.js
@@ -42,8 +42,8 @@ const mockBlueprintSubGen = class extends ClientGenerator {
         const customPhaseSteps = {
             addAppCssStep() {
                 // please change this to public API when it will be available see https://github.com/jhipster/generator-jhipster/issues/9234
-                this.needleApi.clientReact.addAppSCSSStyle('@import without-comment');
-                this.needleApi.clientReact.addAppSCSSStyle('@import with-comment', 'my comment');
+                this.addAppSCSSStyle('@import without-comment');
+                this.addAppSCSSStyle('@import with-comment', 'my comment');
             },
             addEntityToMenuStep() {
                 this.addEntityToMenu('routerName', false, 'react', false);