Repository: jhipster/generator-jhipster
Pull request #6411 (2017-09-26 16:59:02)

Refactor AccountResource, UserResource and EntityResource to use Problem
- Please make sure the below checklist is followed for Pull Requests.

- [x] [Travis tests](https://travis-ci.org/jhipster/generator-jhipster/pull_requests) are green
- [x] Tests are added where necessary
- [ ] 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

Throw `Problem` exceptions that will be treated by the `ExceptionTranslator` instead of returning `ResponseEntity` with an unchecked body
See #6404


jdubois: LGTM - as this is quite big, does anybody has any comment on this, before merging it?
mraible: I'd love to get https://github.com/jhipster/generator-jhipster/pull/6361 in first since this touches AccountResource and UserResource quite a bit too. I think it's close to complete.
jdubois: You are right @mraible - your PR is top priority as it's really a huge work
jdubois: @cbornet so of course we broke your code, but I don't think it's that bad -> WDYT?
cbornet: I'll have a look. Shouldn't be too hard
cbornet: Rebased
jdubois: You still have a conflict :-P
cbornet: Yeah, that happens when pushing muliple related PRs 😄 . Not a big deal.

Patch:
diff --git a/generators/client/files-angular.js b/generators/client/files-angular.js
index 04863011ab..54316c1f51 100644
--- a/generators/client/files-angular.js
+++ b/generators/client/files-angular.js
@@ -384,6 +384,7 @@ const files = {
                 'shared/_shared.module.ts',
                 'shared/_shared-libs.module.ts',
                 'shared/_shared-common.module.ts',
+                'shared/constants/_error.constants.ts',
                 'shared/constants/_pagination.constants.ts',
                 // models
                 'shared/model/_response-wrapper.model.ts',
diff --git a/generators/client/files-angularjs.js b/generators/client/files-angularjs.js
index 305957c007..7f70192a1b 100644
--- a/generators/client/files-angularjs.js
+++ b/generators/client/files-angularjs.js
@@ -308,6 +308,7 @@ const files = {
                 'components/form/_pagination.constants.js',
                 'components/util/_base64.service.js',
                 'components/util/_capitalize.filter.js',
+                'components/util/_error.constants.js',
                 'components/util/_parse-links.service.js',
                 'components/util/_truncate-characters.filter.js',
                 'components/util/_truncate-words.filter.js',
diff --git a/generators/client/templates/angular/src/main/webapp/app/account/password-reset/init/_password-reset-init.component.ts b/generators/client/templates/angular/src/main/webapp/app/account/password-reset/init/_password-reset-init.component.ts
index 1abbbf7b2e..1471fa9c63 100644
--- a/generators/client/templates/angular/src/main/webapp/app/account/password-reset/init/_password-reset-init.component.ts
+++ b/generators/client/templates/angular/src/main/webapp/app/account/password-reset/init/_password-reset-init.component.ts
@@ -19,6 +19,7 @@
 import { Component, OnInit, AfterViewInit, Renderer, ElementRef } from '@angular/core';
 
 import { PasswordResetInitService } from './password-reset-init.service';
+import { EMAIL_NOT_FOUND_TYPE } from '../../../shared';
 
 @Component({
     selector: '<%=jhiPrefix%>-password-reset-init',
@@ -53,7 +54,7 @@ export class PasswordResetInitComponent implements OnInit, AfterViewInit {
             this.success = 'OK';
         }, (response) => {
             this.success = null;
-            if (response.status === 400 && response._body === 'email address not registered') {
+            if (response.status === 400 && response.json().type === EMAIL_NOT_FOUND_TYPE) {
                 this.errorEmailNotExists = 'ERROR';
             } else {
                 this.error = 'ERROR';
diff --git a/generators/client/templates/angular/src/main/webapp/app/account/register/_register.component.ts b/generators/client/templates/angular/src/main/webapp/app/account/register/_register.component.ts
index a0c6708b64..aa239a9a89 100644
--- a/generators/client/templates/angular/src/main/webapp/app/account/register/_register.component.ts
+++ b/generators/client/templates/angular/src/main/webapp/app/account/register/_register.component.ts
@@ -21,7 +21,7 @@ import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
 import { JhiLanguageService } from 'ng-jhipster';
 
 import { Register } from './register.service';
-import { LoginModalService } from '../../shared';
+import { LoginModalService, EMAIL_ALREADY_USED_TYPE, LOGIN_ALREADY_USED_TYPE } from '../../shared';
 
 @Component({
     selector: '<%=jhiPrefix%>-register',
@@ -86,9 +86,9 @@ export class RegisterComponent implements OnInit, AfterViewInit {
 
     private processError(response) {
         this.success = null;
-        if (response.status === 400 && response._body === 'login already in use') {
+        if (response.status === 400 && response.json().type === LOGIN_ALREADY_USED_TYPE) {
             this.errorUserExists = 'ERROR';
-        } else if (response.status === 400 && response._body === 'email address already in use') {
+        } else if (response.status === 400 && response.json().type === EMAIL_ALREADY_USED_TYPE) {
             this.errorEmailExists = 'ERROR';
         } else {
             this.error = 'ERROR';
diff --git a/generators/client/templates/angular/src/main/webapp/app/shared/_index.ts b/generators/client/templates/angular/src/main/webapp/app/shared/_index.ts
index 2c953eca12..7e64e539ec 100644
--- a/generators/client/templates/angular/src/main/webapp/app/shared/_index.ts
+++ b/generators/client/templates/angular/src/main/webapp/app/shared/_index.ts
@@ -16,6 +16,7 @@
  See the License for the specific language governing permissions and
  limitations under the License.
 -%>
+export * from './constants/error.constants';
 export * from './constants/pagination.constants';
 export * from './alert/alert.component';
 export * from './alert/alert-error.component';
diff --git a/generators/client/templates/angular/src/main/webapp/app/shared/constants/_error.constants.ts b/generators/client/templates/angular/src/main/webapp/app/shared/constants/_error.constants.ts
new file mode 100644
index 0000000000..b8de9deec6
--- /dev/null
+++ b/generators/client/templates/angular/src/main/webapp/app/shared/constants/_error.constants.ts
@@ -0,0 +1,22 @@
+<%#
+ Copyright 2013-2017 the original author or authors from the JHipster project.
+
+ This file is part of the JHipster project, see http://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.
+-%>
+export const PROBLEM_BASE_URL = 'http://www.jhipster.tech/problem';
+export const EMAIL_ALREADY_USED_TYPE = PROBLEM_BASE_URL + '/email-already-used';
+export const LOGIN_ALREADY_USED_TYPE = PROBLEM_BASE_URL + '/login-already-used';
+export const EMAIL_NOT_FOUND_TYPE = PROBLEM_BASE_URL + '/email-not-found';
diff --git a/generators/client/templates/angularjs/src/main/webapp/app/account/register/_register.controller.js b/generators/client/templates/angularjs/src/main/webapp/app/account/register/_register.controller.js
index 7de1826606..e6de968043 100644
--- a/generators/client/templates/angularjs/src/main/webapp/app/account/register/_register.controller.js
+++ b/generators/client/templates/angularjs/src/main/webapp/app/account/register/_register.controller.js
@@ -24,9 +24,9 @@
         .controller('RegisterController', RegisterController);
 
 
-    RegisterController.$inject = [<% if (enableTranslation){ %>'$translate',<% } %> '$timeout', 'Auth', 'LoginService'];
+    RegisterController.$inject = [<% if (enableTranslation){ %>'$translate',<% } %> '$timeout', 'Auth', 'LoginService', 'errorConstants'];
 
-    function RegisterController (<% if (enableTranslation){ %>$translate, <% } %>$timeout, Auth, LoginService) {
+    function RegisterController (<% if (enableTranslation){ %>$translate, <% } %>$timeout, Auth, LoginService, errorConstants) {
         var vm = this;
 
         vm.doNotMatch = null;
@@ -53,9 +53,9 @@
                     vm.success = 'OK';
                 }).catch(function (response) {
                     vm.success = null;
-                    if (response.status === 400 && response.data === 'login already in use') {
+                    if (response.status === 400 && angular.fromJson(response.data).type === errorConstants.LOGIN_ALREADY_USED_TYPE) {
                         vm.errorUserExists = 'ERROR';
-                    } else if (response.status === 400 && response.data === 'email address already in use') {
+                    } else if (response.status === 400 && angular.fromJson(response.data).type === errorConstants.EMAIL_ALREADY_USED_TYPE) {
                         vm.errorEmailExists = 'ERROR';
                     } else {
                         vm.error = 'ERROR';
diff --git a/generators/client/templates/angularjs/src/main/webapp/app/account/reset/request/_reset.request.controller.js b/generators/client/templates/angularjs/src/main/webapp/app/account/reset/request/_reset.request.controller.js
index c01848a3e5..3b635a55a9 100644
--- a/generators/client/templates/angularjs/src/main/webapp/app/account/reset/request/_reset.request.controller.js
+++ b/generators/client/templates/angularjs/src/main/webapp/app/account/reset/request/_reset.request.controller.js
@@ -23,9 +23,9 @@
         .module('<%=angularAppName%>')
         .controller('RequestResetController', RequestResetController);
 
-    RequestResetController.$inject = ['$timeout', 'Auth'];
+    RequestResetController.$inject = ['$timeout', 'Auth', 'errorConstants'];
 
-    function RequestResetController ($timeout, Auth) {
+    function RequestResetController ($timeout, Auth, errorConstants) {
         var vm = this;
 
         vm.error = null;
@@ -45,7 +45,7 @@
                 vm.success = 'OK';
             }).catch(function (response) {
                 vm.success = null;
-                if (response.status === 400 && response.data === 'email address not registered') {
+                if (response.status === 400 && angular.fromJson(response.data).type === errorConstants.EMAIL_NOT_FOUND_TYPE) {
                     vm.errorEmailNotExists = 'ERROR';
                 } else {
                     vm.error = 'ERROR';
diff --git a/generators/client/templates/angularjs/src/main/webapp/app/components/util/_error.constants.js b/generators/client/templates/angularjs/src/main/webapp/app/components/util/_error.constants.js
new file mode 100644
index 0000000000..06a986ef73
--- /dev/null
+++ b/generators/client/templates/angularjs/src/main/webapp/app/components/util/_error.constants.js
@@ -0,0 +1,14 @@
+(function() {
+    'use strict';
+
+    angular
+        .module('<%=angularAppName%>')
+        .constant('errorConstants', (function() {
+            var problemBaseUrl = 'http://www.jhipster.tech/problem';
+            return {
+                EMAIL_ALREADY_USED_TYPE: problemBaseUrl + '/email-already-used',
+                LOGIN_ALREADY_USED_TYPE: problemBaseUrl + '/login-already-used',
+                EMAIL_NOT_FOUND_TYPE: problemBaseUrl + '/email-not-found'
+            }
+        })());
+})();
diff --git a/generators/entity/templates/server/src/main/java/package/web/rest/_EntityResource.java b/generators/entity/templates/server/src/main/java/package/web/rest/_EntityResource.java
index d20e6cd4b9..c943f69f74 100644
--- a/generators/entity/templates/server/src/main/java/package/web/rest/_EntityResource.java
+++ b/generators/entity/templates/server/src/main/java/package/web/rest/_EntityResource.java
@@ -26,6 +26,7 @@ import <%=packageName%>.domain.<%= entityClass %>;
 import <%=packageName%>.service.<%= entityClass %>Service;<% } else { %>
 import <%=packageName%>.repository.<%= entityClass %>Repository;<% if (searchEngine === 'elasticsearch') { %>
 import <%=packageName%>.repository.search.<%= entityClass %>SearchRepository;<% }} %>
+import <%=packageName%>.web.rest.errors.BadRequestAlertException;
 import <%=packageName%>.web.rest.util.HeaderUtil;<% if (pagination !== 'no') { %>
 import <%=packageName%>.web.rest.util.PaginationUtil;<% } %>
 <%_ if (dto === 'mapstruct') { _%>
@@ -93,7 +94,7 @@ public class <%= entityClass %>Resource {
     public ResponseEntity<<%= instanceType %>> create<%= entityClass %>(<% if (validation) { %>@Valid <% } %>@RequestBody <%= instanceType %> <%= instanceName %>) throws URISyntaxException {
         log.debug("REST request to save <%= entityClass %> : {}", <%= instanceName %>);
         if (<%= instanceName %>.getId() != null) {
-            return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "idexists", "A new <%= entityInstance %> cannot already have an ID")).body(null);
+            throw new BadRequestAlertException("A new <%= entityInstance %> cannot already have an ID", ENTITY_NAME, "idexists");
         }<%- include('../../common/save_template', {viaService: viaService, returnDirectly: false}); -%>
         return ResponseEntity.created(new URI("/api/<%= entityApiUrl %>/" + result.getId()))
             .headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
diff --git a/generators/server/files.js b/generators/server/files.js
index a961f4fe14..149c0aac48 100644
--- a/generators/server/files.js
+++ b/generators/server/files.js
@@ -425,10 +425,15 @@ function writeFiles() {
 
         writeServerJavaWebErrorFiles() {
             // error handler code - server side
-            this.template(`${SERVER_MAIN_SRC_DIR}package/web/rest/errors/_ErrorConstants.java`, `${javaDir}web/rest/errors/ErrorConstants.java`);
+            this.template(`${SERVER_MAIN_SRC_DIR}package/web/rest/errors/_BadRequestAlertException.java`, `${javaDir}web/rest/errors/BadRequestAlertException.java`);
             this.template(`${SERVER_MAIN_SRC_DIR}package/web/rest/errors/_CustomParameterizedException.java`, `${javaDir}web/rest/errors/CustomParameterizedException.java`);
+            this.template(`${SERVER_MAIN_SRC_DIR}package/web/rest/errors/_EmailAlreadyUsedException.java`, `${javaDir}web/rest/errors/EmailAlreadyUsedException.java`);
+            this.template(`${SERVER_MAIN_SRC_DIR}package/web/rest/errors/_EmailNotFoundException.java`, `${javaDir}web/rest/errors/EmailNotFoundException.java`);
+            this.template(`${SERVER_MAIN_SRC_DIR}package/web/rest/errors/_ErrorConstants.java`, `${javaDir}web/rest/errors/ErrorConstants.java`);
             this.template(`${SERVER_MAIN_SRC_DIR}package/web/rest/errors/_ExceptionTranslator.java`, `${javaDir}web/rest/errors/ExceptionTranslator.java`);
             this.template(`${SERVER_MAIN_SRC_DIR}package/web/rest/errors/_FieldErrorVM.java`, `${javaDir}web/rest/errors/FieldErrorVM.java`);
+            this.template(`${SERVER_MAIN_SRC_DIR}package/web/rest/errors/_InvalidPasswordException.java`, `${javaDir}web/rest/errors/InvalidPasswordException.java`);
+            this.template(`${SERVER_MAIN_SRC_DIR}package/web/rest/errors/_LoginAlreadyUsedException.java`, `${javaDir}web/rest/errors/LoginAlreadyUsedException.java`);
         },
 
         writeServerJavaWebFiles() {
diff --git a/generators/server/templates/src/main/java/package/web/rest/_AccountResource.java b/generators/server/templates/src/main/java/package/web/rest/_AccountResource.java
index 7f1f38e7ae..020e2cc553 100644
--- a/generators/server/templates/src/main/java/package/web/rest/_AccountResource.java
+++ b/generators/server/templates/src/main/java/package/web/rest/_AccountResource.java
@@ -38,22 +38,15 @@ import <%=packageName%>.service.MailService;
 import <%=packageName%>.service.UserService;
 import <%=packageName%>.service.dto.UserDTO;
 <%_ if (authenticationType !== 'oauth2') { _%>
+import <%=packageName%>.web.rest.errors.*;
 import <%=packageName%>.web.rest.vm.KeyAndPasswordVM;
 import <%=packageName%>.web.rest.vm.ManagedUserVM;
-import <%=packageName%>.web.rest.util.HeaderUtil;
 
 import org.apache.commons.lang3.StringUtils;
 <%_ } _%>
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-<%_ if (authenticationType !== 'oauth2') { _%>
-import org.springframework.http.HttpHeaders;
-<%_ } _%>
 import org.springframework.http.HttpStatus;
-<%_ if (authenticationType !== 'oauth2') { _%>
-import org.springframework.http.MediaType;
-<%_ } _%>
-import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 <%_ if (authenticationType === 'oauth2') { _%>
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -99,10 +92,6 @@ public class AccountResource {
 
     private final PersistentTokenRepository persistentTokenRepository;
     <%_ } _%>
-    <%_ if (authenticationType !== 'oauth2') { _%>
-
-    private static final String CHECK_ERROR_MESSAGE = "Incorrect password";
-    <%_ } _%>
 
     public AccountResource(UserRepository userRepository, UserService userService<% if (authenticationType !== 'oauth2') { %>, MailService mailService<% } %><% if (authenticationType === 'session') { %>, PersistentTokenRepository persistentTokenRepository<% } %>) {
 
@@ -133,12 +122,13 @@ public class AccountResource {
     /**
      * GET  /account : get the current user.
      *
-     * @return the ResponseEntity with status 200 (OK) and the current user in body, or status 500 (Internal Server Error) if the user couldn't be returned
+     * @return the current user
+     * @throws RuntimeException 500 (Internal Server Error) if the user couldn't be returned
      */
     @GetMapping("/account")
     @Timed
     @SuppressWarnings("unchecked")
-    public ResponseEntity<UserDTO> getAccount(Principal principal) {
+    public UserDTO getAccount(Principal principal) {
         if (principal != null) {
             if (principal instanceof OAuth2Authentication) {
                 OAuth2Authentication authentication = (OAuth2Authentication) principal;
@@ -240,15 +230,15 @@ public class AccountResource {
                     log.debug("Saving user '{}' in local database...", userDTO.getLogin());
                     userRepository.save(user);
                 }
-                return new ResponseEntity<>(userDTO, HttpStatus.OK);
+                return userDTO;
             } else {
                 // Allow Spring Security Test to be used to mock users in the database
                 return Optional.ofNullable(userService.getUserWithAuthorities())
-                    .map(user -> new ResponseEntity<>(new UserDTO(user), HttpStatus.OK))
-                    .orElse(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
+                    .map(UserDTO::new)
+                    .orElseThrow(RuntimeException::new);
             }
         } else {
-            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+            throw new RuntimeException();
         }
     }
 <%_ } else { _%>
@@ -257,43 +247,33 @@ public class AccountResource {
      * POST  /register : register the user.
      *
      * @param managedUserVM the managed user View Model
-     * @return the ResponseEntity with status 201 (Created) if the user is registered or 400 (Bad Request) if the login or email is already in use
+     * @throws InvalidPasswordException 400 (Bad Request) if the password is incorrect
+     * @throws EmailAlreadyUsedException 400 (Bad Request) if the email is already used
+     * @throws LoginAlreadyUsedException 400 (Bad Request) if the login is already used
      */
-    @PostMapping(path = "/register",
-        produces={MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_PLAIN_VALUE})
+    @PostMapping("/register")
     @Timed
-    public ResponseEntity registerAccount(@Valid @RequestBody ManagedUserVM managedUserVM) {
-
-        HttpHeaders textPlainHeaders = new HttpHeaders();
-        textPlainHeaders.setContentType(MediaType.TEXT_PLAIN);
+    @ResponseStatus(HttpStatus.CREATED)
+    public void registerAccount(@Valid @RequestBody ManagedUserVM managedUserVM) {
         if (!checkPasswordLength(managedUserVM.getPassword())) {
-            return new ResponseEntity<>(CHECK_ERROR_MESSAGE, HttpStatus.BAD_REQUEST);
+            throw new InvalidPasswordException();
         }
-        return userRepository.findOneByLogin(managedUserVM.getLogin().toLowerCase())
-            .map(user -> new ResponseEntity<>("login already in use", textPlainHeaders, HttpStatus.BAD_REQUEST))
-            .orElseGet(() -> userRepository.findOneByEmailIgnoreCase(managedUserVM.getEmail())
-                .map(user -> new ResponseEntity<>("email address already in use", textPlainHeaders, HttpStatus.BAD_REQUEST))
-                .orElseGet(() -> {
-                    User user = userService.registerUser(managedUserVM);
-
-                    mailService.sendActivationEmail(user);
-                    return new ResponseEntity<>(HttpStatus.CREATED);
-                })
-        );
+        userRepository.findOneByLogin(managedUserVM.getLogin().toLowerCase()).ifPresent(u -> {throw new LoginAlreadyUsedException();});
+        userRepository.findOneByEmailIgnoreCase(managedUserVM.getEmail()).ifPresent(u -> {throw new EmailAlreadyUsedException();});
+        User user = userService.registerUser(managedUserVM);
+        mailService.sendActivationEmail(user);
     }
 
     /**
      * GET  /activate : activate the registered user.
      *
      * @param key the activation key
-     * @return the ResponseEntity with status 200 (OK) and the activated user in body, or status 500 (Internal Server Error) if the user couldn't be activated
+     * @throws RuntimeException 500 (Internal Server Error) if the user couldn't be activated
      */
     @GetMapping("/activate")
     @Timed
-    public ResponseEntity<String> activateAccount(@RequestParam(value = "key") String key) {
-        return userService.activateRegistration(key)
-            .map(user -> new ResponseEntity<String>(HttpStatus.OK))
-            .orElse(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
+    public void activateAccount(@RequestParam(value = "key") String key) {
+        userService.activateRegistration(key).orElseThrow(RuntimeException::new);
     }
 
     /**
@@ -312,71 +292,65 @@ public class AccountResource {
     /**
      * GET  /account : get the current user.
      *
-     * @return the ResponseEntity with status 200 (OK) and the current user in body, or status 500 (Internal Server Error) if the user couldn't be returned
+     * @return the current user
+     * @throws RuntimeException 500 (Internal Server Error) if the user couldn't be returned
      */
     @GetMapping("/account")
     @Timed
-    public ResponseEntity<UserDTO> getAccount() {
+    public UserDTO getAccount() {
         return Optional.ofNullable(userService.getUserWithAuthorities())
-            .map(user -> new ResponseEntity<>(new UserDTO(user), HttpStatus.OK))
-            .orElse(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
+            .map(UserDTO::new)
+            .orElseThrow(RuntimeException::new);
     }
 
     /**
      * POST  /account : update the current user information.
      *
      * @param userDTO the current user information
-     * @return the ResponseEntity with status 200 (OK), or status 400 (Bad Request) or 500 (Internal Server Error) if the user couldn't be updated
+     * @throws EmailAlreadyUsedException 400 (Bad Request) if the email is already used
+     * @throws RuntimeException 500 (Internal Server Error) if the user login wasn't found
      */
     @PostMapping("/account")
     @Timed
-    public ResponseEntity saveAccount(@Valid @RequestBody UserDTO userDTO) {
+    public void saveAccount(@Valid @RequestBody UserDTO userDTO) {
         final String userLogin = SecurityUtils.getCurrentUserLogin();
         Optional<User> existingUser = userRepository.findOneByEmailIgnoreCase(userDTO.getEmail());
         if (existingUser.isPresent() && (!existingUser.get().getLogin().equalsIgnoreCase(userLogin))) {
-            return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert("user-management", "emailexists", "Email already in use")).body(null);
+            throw new EmailAlreadyUsedException();
         }
-        return userRepository
-            .findOneByLogin(userLogin)
-            .map(u -> {
-                userService.updateUser(userDTO.getFirstName(), userDTO.getLastName(), userDTO.getEmail(),
+        userRepository.findOneByLogin(userLogin).orElseThrow(RuntimeException::new);
+        userService.updateUser(userDTO.getFirstName(), userDTO.getLastName(), userDTO.getEmail(),
                     userDTO.getLangKey()<% if (databaseType === 'mongodb' || databaseType === 'sql') { %>, userDTO.getImageUrl()<% } %>);
-                return new ResponseEntity(HttpStatus.OK);
-            })
-            .orElseGet(() -> new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
     }
 
     /**
      * POST  /account/change-password : changes the current user's password
      *
      * @param password the new password
-     * @return the ResponseEntity with status 200 (OK), or status 400 (Bad Request) if the new password is not strong enough
+     * @throws InvalidPasswordException 400 (Bad Request) if the new password is incorrect
      */
-    @PostMapping(path = "/account/change-password",
-        produces = MediaType.TEXT_PLAIN_VALUE)
+    @PostMapping(path = "/account/change-password")
     @Timed
-    public ResponseEntity changePassword(@RequestBody String password) {
+    public void changePassword(@RequestBody String password) {
         if (!checkPasswordLength(password)) {
-            return new ResponseEntity<>(CHECK_ERROR_MESSAGE, HttpStatus.BAD_REQUEST);
+            throw new InvalidPasswordException();
         }
         userService.changePassword(password);
-        return new ResponseEntity<>(HttpStatus.OK);
     }<% if (authenticationType === 'session') { %>
 
     /**
      * GET  /account/sessions : get the current open sessions.
      *
-     * @return the ResponseEntity with status 200 (OK) and the current open sessions in body,
-     *  or status 500 (Internal Server Error) if the current open sessions couldn't be retrieved
+     * @return the current open sessions
+     * @throws RuntimeException 500 (Internal Server Error) if the current open sessions couldn't be retrieved
      */
     @GetMapping("/account/sessions")
     @Timed
-    public ResponseEntity<List<PersistentToken>> getCurrentSessions() {
-        return userRepository.findOneByLogin(SecurityUtils.getCurrentUserLogin())
-            .map(user -> new ResponseEntity<>(
-                persistentTokenRepository.findByUser(user),
-                HttpStatus.OK))
-            .orElse(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
+    public List<PersistentToken> getCurrentSessions() {
+        return persistentTokenRepository.findByUser(
+            userRepository.findOneByLogin(SecurityUtils.getCurrentUserLogin())
+                .orElseThrow(RuntimeException::new)
+        );
     }
 
     /**
@@ -410,39 +384,35 @@ public class AccountResource {
      * POST   /account/reset-password/init : Send an email to reset the password of the user
      *
      * @param mail the mail of the user
-     * @return the ResponseEntity with status 200 (OK) if the email was sent, or status 400 (Bad Request) if the email address is not registered
+     * @throws EmailNotFoundException 400 (Bad Request) if the email address is not registered
      */
-    @PostMapping(path = "/account/reset-password/init",
-        produces = MediaType.TEXT_PLAIN_VALUE)
+    @PostMapping(path = "/account/reset-password/init")
     @Timed
-    public ResponseEntity requestPasswordReset(@RequestBody String mail) {
-        return userService.requestPasswordReset(mail)
-            .map(user -> {
-                mailService.sendPasswordResetMail(user);
-                return new ResponseEntity<>("email was sent", HttpStatus.OK);
-            }).orElse(new ResponseEntity<>("email address not registered", HttpStatus.BAD_REQUEST));
+    public void requestPasswordReset(@RequestBody String mail) {
+        mailService.sendPasswordResetMail(
+            userService.requestPasswordReset(mail)
+                .orElseThrow(EmailNotFoundException::new)
+        );
     }
 
     /**
      * POST   /account/reset-password/finish : Finish to reset the password of the user
      *
      * @param keyAndPassword the generated key and the new password
-     * @return the ResponseEntity with status 200 (OK) if the password has been reset,
-     * or status 400 (Bad Request) or 500 (Internal Server Error) if the password could not be reset
+     * @throws InvalidPasswordException 400 (Bad Request) if the password is incorrect
+     * @throws RuntimeException 500 (Internal Server Error) if the password could not be reset
      */
-    @PostMapping(path = "/account/reset-password/finish",
-        produces = MediaType.TEXT_PLAIN_VALUE)
+    @PostMapping(path = "/account/reset-password/finish")
     @Timed
-    public ResponseEntity<String> finishPasswordReset(@RequestBody KeyAndPasswordVM keyAndPassword) {
+    public void finishPasswordReset(@RequestBody KeyAndPasswordVM keyAndPassword) {
         if (!checkPasswordLength(keyAndPassword.getNewPassword())) {
-            return new ResponseEntity<>(CHECK_ERROR_MESSAGE, HttpStatus.BAD_REQUEST);
+            throw new InvalidPasswordException();
         }
-        return userService.completePasswordReset(keyAndPassword.getNewPassword(), keyAndPassword.getKey())
-              .map(user -> new ResponseEntity<String>(HttpStatus.OK))
-              .orElse(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
+        userService.completePasswordReset(keyAndPassword.getNewPassword(), keyAndPassword.getKey())
+            .orElseThrow(RuntimeException::new);
     }
 
-    private boolean checkPasswordLength(String password) {
+    private static boolean checkPasswordLength(String password) {
         return !StringUtils.isEmpty(password) &&
             password.length() >= ManagedUserVM.PASSWORD_MIN_LENGTH &&
             password.length() <= ManagedUserVM.PASSWORD_MAX_LENGTH;
diff --git a/generators/server/templates/src/main/java/package/web/rest/_UserResource.java b/generators/server/templates/src/main/java/package/web/rest/_UserResource.java
index 49add3ba05..127aa529d4 100644
--- a/generators/server/templates/src/main/java/package/web/rest/_UserResource.java
+++ b/generators/server/templates/src/main/java/package/web/rest/_UserResource.java
@@ -29,6 +29,9 @@ import <%=packageName%>.service.MailService;
 import <%=packageName%>.service.UserService;
 import <%=packageName%>.service.dto.UserDTO;
 <%_ if (authenticationType !== 'oauth2') { _%>
+import <%=packageName%>.web.rest.errors.BadRequestAlertException;
+import <%=packageName%>.web.rest.errors.EmailAlreadyUsedException;
+import <%=packageName%>.web.rest.errors.LoginAlreadyUsedException;
 import <%=packageName%>.web.rest.vm.ManagedUserVM;
 import <%=packageName%>.web.rest.util.HeaderUtil;<% } %><% if (databaseType === 'sql' || databaseType === 'mongodb') { %>
 import <%=packageName%>.web.rest.util.PaginationUtil;<% } %>
@@ -120,6 +123,7 @@ public class UserResource {
      * @param managedUserVM the user to create
      * @return the ResponseEntity with status 201 (Created) and with body the new user, or with status 400 (Bad Request) if the login or email is already in use
      * @throws URISyntaxException if the Location URI syntax is incorrect
+     * @throws BadRequestAlertException 400 (Bad Request) if the login or email is already in use
      */
     @PostMapping("/users")
     @Timed
@@ -128,18 +132,12 @@ public class UserResource {
         log.debug("REST request to save User : {}", managedUserVM);
 
         if (managedUserVM.getId() != null) {
-            return ResponseEntity.badRequest()
-                .headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "idexists", "A new user cannot already have an ID"))
-                .body(null);
+            throw new BadRequestAlertException("A new user cannot already have an ID", ENTITY_NAME, "idexists");
         // Lowercase the user login before comparing with database
         } else if (userRepository.findOneByLogin(managedUserVM.getLogin().toLowerCase()).isPresent()) {
-            return ResponseEntity.badRequest()
-                .headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "userexists", "Login already in use"))
-                .body(null);
+            throw new LoginAlreadyUsedException();
         } else if (userRepository.findOneByEmailIgnoreCase(managedUserVM.getEmail()).isPresent()) {
-            return ResponseEntity.badRequest()
-                .headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "emailexists", "Email already in use"))
-                .body(null);
+            throw new EmailAlreadyUsedException();
         } else {
             User newUser = userService.createUser(managedUserVM);
             mailService.sendCreationEmail(newUser);
@@ -153,9 +151,9 @@ public class UserResource {
      * PUT  /users : Updates an existing User.
      *
      * @param managedUserVM the user to update
-     * @return the ResponseEntity with status 200 (OK) and with body the updated user,
-     * or with status 400 (Bad Request) if the login or email is already in use,
-     * or with status 500 (Internal Server Error) if the user couldn't be updated
+     * @return the ResponseEntity with status 200 (OK) and with body the updated user
+     * @throws EmailAlreadyUsedException 400 (Bad Request) if the email is already in use
+     * @throws LoginAlreadyUsedException 400 (Bad Request) if the login is already in use
      */
     @PutMapping("/users")
     @Timed
@@ -164,11 +162,11 @@ public class UserResource {
         log.debug("REST request to update User : {}", managedUserVM);
         Optional<User> existingUser = userRepository.findOneByEmailIgnoreCase(managedUserVM.getEmail());
         if (existingUser.isPresent() && (!existingUser.get().getId().equals(managedUserVM.getId()))) {
-            return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "emailexists", "Email already in use")).body(null);
+            throw new EmailAlreadyUsedException();
         }
         existingUser = userRepository.findOneByLogin(managedUserVM.getLogin().toLowerCase());
         if (existingUser.isPresent() && (!existingUser.get().getId().equals(managedUserVM.getId()))) {
-            return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "userexists", "Login already in use")).body(null);
+            throw new LoginAlreadyUsedException();
         }
         Optional<UserDTO> updatedUser = userService.updateUser(managedUserVM);
 
diff --git a/generators/server/templates/src/main/java/package/web/rest/errors/_BadRequestAlertException.java b/generators/server/templates/src/main/java/package/web/rest/errors/_BadRequestAlertException.java
new file mode 100644
index 0000000000..e509938ee6
--- /dev/null
+++ b/generators/server/templates/src/main/java/package/web/rest/errors/_BadRequestAlertException.java
@@ -0,0 +1,57 @@
+<%#
+ Copyright 2013-2017 the original author or authors from the JHipster project.
+
+ This file is part of the JHipster project, see http://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.
+-%>
+package <%=packageName%>.web.rest.errors;
+
+import org.zalando.problem.AbstractThrowableProblem;
+import org.zalando.problem.Status;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+public class BadRequestAlertException extends AbstractThrowableProblem {
+    private String entityName;
+    private String errorKey;
+
+    public BadRequestAlertException(String defaultMessage, String entityName, String errorKey) {
+        this(ErrorConstants.DEFAULT_TYPE, defaultMessage, entityName, errorKey);
+    }
+
+    public BadRequestAlertException(URI type, String defaultMessage, String entityName, String errorKey) {
+        super(type, defaultMessage, Status.BAD_REQUEST, null, null, null, getAlertParameters(entityName, errorKey));
+        this.entityName = entityName;
+        this.errorKey = errorKey;
+    }
+
+    public String getEntityName() {
+        return entityName;
+    }
+
+    public String getErrorKey() {
+        return errorKey;
+    }
+
+    private static Map<String, Object> getAlertParameters(String entityName, String errorKey) {
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("message", "error." + errorKey);
+        parameters.put("params", entityName);
+        return parameters;
+    }
+
+}
diff --git a/generators/server/templates/src/main/java/package/web/rest/errors/_EmailAlreadyUsedException.java b/generators/server/templates/src/main/java/package/web/rest/errors/_EmailAlreadyUsedException.java
new file mode 100644
index 0000000000..c52d2863c3
--- /dev/null
+++ b/generators/server/templates/src/main/java/package/web/rest/errors/_EmailAlreadyUsedException.java
@@ -0,0 +1,25 @@
+<%#
+ Copyright 2013-2017 the original author or authors from the JHipster project.
+
+ This file is part of the JHipster project, see http://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.
+-%>
+package <%=packageName%>.web.rest.errors;
+
+public class EmailAlreadyUsedException extends BadRequestAlertException {
+    public EmailAlreadyUsedException() {
+        super(ErrorConstants.EMAIL_ALREADY_USED_TYPE, "Email address already in use", "userManagement", "emailexists");
+    }
+}
diff --git a/generators/server/templates/src/main/java/package/web/rest/errors/_EmailNotFoundException.java b/generators/server/templates/src/main/java/package/web/rest/errors/_EmailNotFoundException.java
new file mode 100644
index 0000000000..5d2f22fffd
--- /dev/null
+++ b/generators/server/templates/src/main/java/package/web/rest/errors/_EmailNotFoundException.java
@@ -0,0 +1,28 @@
+<%#
+ Copyright 2013-2017 the original author or authors from the JHipster project.
+
+ This file is part of the JHipster project, see http://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.
+-%>
+package <%=packageName%>.web.rest.errors;
+
+import org.zalando.problem.AbstractThrowableProblem;
+import org.zalando.problem.Status;
+
+public class EmailNotFoundException extends AbstractThrowableProblem {
+    public EmailNotFoundException() {
+        super(ErrorConstants.EMAIL_NOT_FOUND_TYPE, "Email address not registered", Status.BAD_REQUEST);
+    }
+}
diff --git a/generators/server/templates/src/main/java/package/web/rest/errors/_ErrorConstants.java b/generators/server/templates/src/main/java/package/web/rest/errors/_ErrorConstants.java
index bba869cde6..85600e26e6 100644
--- a/generators/server/templates/src/main/java/package/web/rest/errors/_ErrorConstants.java
+++ b/generators/server/templates/src/main/java/package/web/rest/errors/_ErrorConstants.java
@@ -29,6 +29,10 @@ public final class ErrorConstants {
     public static final URI CONSTRAINT_VIOLATION_TYPE = URI.create(PROBLEM_BASE_URL + "/contraint-violation");
     public static final URI PARAMETERIZED_TYPE = URI.create(PROBLEM_BASE_URL + "/parameterized");
     public static final URI UNAUTHORIZED_TYPE = URI.create(PROBLEM_BASE_URL + "/unauthorized");
+    public static final URI INVALID_PASSWORD_TYPE = URI.create(PROBLEM_BASE_URL + "/invalid-password");
+    public static final URI EMAIL_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/email-already-used");
+    public static final URI LOGIN_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/login-already-used");
+    public static final URI EMAIL_NOT_FOUND_TYPE = URI.create(PROBLEM_BASE_URL + "/email-not-found");
 
     private ErrorConstants() {
     }
diff --git a/generators/server/templates/src/main/java/package/web/rest/errors/_ExceptionTranslator.java b/generators/server/templates/src/main/java/package/web/rest/errors/_ExceptionTranslator.java
index 318353bc27..3e6a644617 100644
--- a/generators/server/templates/src/main/java/package/web/rest/errors/_ExceptionTranslator.java
+++ b/generators/server/templates/src/main/java/package/web/rest/errors/_ExceptionTranslator.java
@@ -18,6 +18,8 @@
 -%>
 package <%=packageName%>.web.rest.errors;
 
+import <%=packageName%>.web.rest.util.HeaderUtil;
+
 import org.springframework.core.annotation.AnnotationUtils;
 <%_ if (databaseType !== 'no' && databaseType !== 'cassandra') { _%>
 import org.springframework.dao.ConcurrencyFailureException;
@@ -42,7 +44,6 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.servlet.http.HttpServletRequest;
 import java.util.List;
-import java.util.Optional;
 import java.util.stream.Collectors;
 
 /**
@@ -118,6 +119,11 @@ public class ExceptionTranslator implements ProblemHandling {
             .build();
         return create(ex, problem, request);
     }
+
+    @ExceptionHandler(BadRequestAlertException.class)
+    public ResponseEntity<Problem> handleBadRequestAlertException(BadRequestAlertException ex, NativeWebRequest request) {
+        return create(ex, request, HeaderUtil.createFailureAlert(ex.getEntityName(), ex.getErrorKey(), ex.getMessage()));
+    }
     <%_ if (databaseType !== 'no' && databaseType !== 'cassandra') { _%>
 
     @ExceptionHandler(ConcurrencyFailureException.class)
diff --git a/generators/server/templates/src/main/java/package/web/rest/errors/_InvalidPasswordException.java b/generators/server/templates/src/main/java/package/web/rest/errors/_InvalidPasswordException.java
new file mode 100644
index 0000000000..9defe3f95e
--- /dev/null
+++ b/generators/server/templates/src/main/java/package/web/rest/errors/_InvalidPasswordException.java
@@ -0,0 +1,28 @@
+<%#
+ Copyright 2013-2017 the original author or authors from the JHipster project.
+
+ This file is part of the JHipster project, see http://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.
+-%>
+package <%=packageName%>.web.rest.errors;
+
+import org.zalando.problem.AbstractThrowableProblem;
+import org.zalando.problem.Status;
+
+public class InvalidPasswordException extends AbstractThrowableProblem {
+    public InvalidPasswordException() {
+        super(ErrorConstants.INVALID_PASSWORD_TYPE, "Incorrect password", Status.BAD_REQUEST);
+    }
+}
diff --git a/generators/server/templates/src/main/java/package/web/rest/errors/_LoginAlreadyUsedException.java b/generators/server/templates/src/main/java/package/web/rest/errors/_LoginAlreadyUsedException.java
new file mode 100644
index 0000000000..07ce7864ea
--- /dev/null
+++ b/generators/server/templates/src/main/java/package/web/rest/errors/_LoginAlreadyUsedException.java
@@ -0,0 +1,25 @@
+<%#
+ Copyright 2013-2017 the original author or authors from the JHipster project.
+
+ This file is part of the JHipster project, see http://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.
+-%>
+package <%=packageName%>.web.rest.errors;
+
+public class LoginAlreadyUsedException extends BadRequestAlertException {
+    public LoginAlreadyUsedException() {
+        super(ErrorConstants.LOGIN_ALREADY_USED_TYPE, "Login already in use", "userManagement", "userexists");
+    }
+}


Test patch:
diff --git a/generators/client/templates/angular/src/test/javascript/spec/app/account/password-reset/init/_password-reset-init.component.spec.ts b/generators/client/templates/angular/src/test/javascript/spec/app/account/password-reset/init/_password-reset-init.component.spec.ts
index f28f9e114d..15c1012f0b 100644
--- a/generators/client/templates/angular/src/test/javascript/spec/app/account/password-reset/init/_password-reset-init.component.spec.ts
+++ b/generators/client/templates/angular/src/test/javascript/spec/app/account/password-reset/init/_password-reset-init.component.spec.ts
@@ -22,6 +22,7 @@ import { Observable } from 'rxjs/Rx';
 import { <%=angularXAppName%>TestModule } from '../../../../test.module';
 import { PasswordResetInitComponent } from '../../../../../../../main/webapp/app/account/password-reset/init/password-reset-init.component';
 import { PasswordResetInitService } from '../../../../../../../main/webapp/app/account/password-reset/init/password-reset-init.service';
+import { EMAIL_NOT_FOUND_TYPE } from '../../../../../../../main/webapp/app/shared';
 
 describe('Component Tests', () => {
 
@@ -95,7 +96,9 @@ describe('Component Tests', () => {
             inject([PasswordResetInitService], (service: PasswordResetInitService) => {
                 spyOn(service, 'save').and.returnValue(Observable.throw({
                     status: 400,
-                    _body: 'email address not registered'
+                    json: function() {
+                        return {type : EMAIL_NOT_FOUND_TYPE}
+                    }
                 }));
                 comp.resetAccount.email = 'user@domain.com';
 
diff --git a/generators/client/templates/angular/src/test/javascript/spec/app/account/register/_register.component.spec.ts b/generators/client/templates/angular/src/test/javascript/spec/app/account/register/_register.component.spec.ts
index 68272e8f93..1e0362b5b9 100644
--- a/generators/client/templates/angular/src/test/javascript/spec/app/account/register/_register.component.spec.ts
+++ b/generators/client/templates/angular/src/test/javascript/spec/app/account/register/_register.component.spec.ts
@@ -24,7 +24,7 @@ import { JhiLanguageService } from 'ng-jhipster';
 import { MockLanguageService } from '../../../helpers/mock-language.service';
 <%_ } _%>
 import { <%=angularXAppName%>TestModule } from '../../../test.module';
-import { LoginModalService } from '../../../../../../main/webapp/app/shared';
+import { LoginModalService, EMAIL_ALREADY_USED_TYPE, LOGIN_ALREADY_USED_TYPE } from '../../../../../../main/webapp/app/shared';
 import { Register } from '../../../../../../main/webapp/app/account/register/register.service';
 import { RegisterComponent } from '../../../../../../main/webapp/app/account/register/register.component';
 
@@ -102,7 +102,9 @@ describe('Component Tests', () => {
                 fakeAsync((service: Register) => {
                     spyOn(service, 'save').and.returnValue(Observable.throw({
                         status: 400,
-                        _body: 'login already in use'
+                        json: function() {
+                            return {type : LOGIN_ALREADY_USED_TYPE}
+                        }
                     }));
                     comp.registerAccount.password = comp.confirmPassword = 'password';
 
@@ -121,7 +123,9 @@ describe('Component Tests', () => {
                 fakeAsync((service: Register) => {
                     spyOn(service, 'save').and.returnValue(Observable.throw({
                         status: 400,
-                        _body: 'email address already in use'
+                        json: function() {
+                            return {type : EMAIL_ALREADY_USED_TYPE}
+                        }
                     }));
                     comp.registerAccount.password = comp.confirmPassword = 'password';
 
diff --git a/generators/client/templates/angularjs/src/test/javascript/spec/app/account/register/_register.controller.spec.js b/generators/client/templates/angularjs/src/test/javascript/spec/app/account/register/_register.controller.spec.js
index ca4acf9a3b..9f5c790922 100644
--- a/generators/client/templates/angularjs/src/test/javascript/spec/app/account/register/_register.controller.spec.js
+++ b/generators/client/templates/angularjs/src/test/javascript/spec/app/account/register/_register.controller.spec.js
@@ -25,22 +25,24 @@ describe('Controller Tests', function() {
 
     describe('RegisterController', function() {
 
-        var $scope, $q; // actual implementations
+        var $scope, $q, errorConstants; // actual implementations
         var MockTimeout,<% if(enableTranslation) { %> MockTranslate,<%}%> MockAuth; // mocks
         var createController; // local utility function
 
         beforeEach(inject(function($injector) {
             $q = $injector.get('$q');
             $scope = $injector.get('$rootScope').$new();
+            errorConstants = $injector.get('errorConstants');
             MockTimeout = jasmine.createSpy('MockTimeout');
             MockAuth = jasmine.createSpyObj('MockAuth', ['createAccount']);
             <% if(enableTranslation) { %>MockTranslate = jasmine.createSpyObj('MockTranslate', ['use']);<% } %>
 
             var locals = {
+                'errorConstants': errorConstants,
                 'Auth': MockAuth,<% if(enableTranslation) { %>
                 '$translate': MockTranslate,<% } %>
                 '$timeout': MockTimeout,
-                '$scope': $scope,
+                '$scope': $scope
             };
             createController = function() {
                 $injector.get('$controller')('RegisterController as vm', locals);
@@ -83,7 +85,7 @@ describe('Controller Tests', function() {
             // given
             MockAuth.createAccount.and.returnValue($q.reject({
                 status: 400,
-                data: 'login already in use'
+                data: '{"type": "' + errorConstants.LOGIN_ALREADY_USED_TYPE + '"}'
             }));
             createController();
             $scope.vm.registerAccount.password = $scope.vm.confirmPassword = 'password';
@@ -99,7 +101,7 @@ describe('Controller Tests', function() {
             // given
             MockAuth.createAccount.and.returnValue($q.reject({
                 status: 400,
-                data: 'email address already in use'
+                data: '{"type": "' + errorConstants.EMAIL_ALREADY_USED_TYPE + '"}'
             }));
             createController();
             $scope.vm.registerAccount.password = $scope.vm.confirmPassword = 'password';
diff --git a/generators/client/templates/angularjs/src/test/javascript/spec/app/account/reset/request/_reset.request.controller.spec.js b/generators/client/templates/angularjs/src/test/javascript/spec/app/account/reset/request/_reset.request.controller.spec.js
index 43f895e108..74dd442bd2 100644
--- a/generators/client/templates/angularjs/src/test/javascript/spec/app/account/reset/request/_reset.request.controller.spec.js
+++ b/generators/client/templates/angularjs/src/test/javascript/spec/app/account/reset/request/_reset.request.controller.spec.js
@@ -25,7 +25,7 @@ describe('Controller Tests', function() {
 
     describe('RequestResetController', function() {
 
-        var $rootScope, $scope, $q; // actual implementations
+        var $rootScope, $scope, $q, errorConstants; // actual implementations
         var MockState, MockTimeout, MockAuth; // mocks
         var createController; // local utility function
 
@@ -33,6 +33,7 @@ describe('Controller Tests', function() {
             $q = $injector.get('$q');
             $rootScope = $injector.get('$rootScope');
             $scope = $rootScope.$new();
+            errorConstants = $injector.get('errorConstants');
             MockState = jasmine.createSpy('MockState');
             MockTimeout = jasmine.createSpy('MockTimeout');
             MockAuth = jasmine.createSpyObj('MockAuth', ['resetPasswordInit']);
@@ -40,6 +41,7 @@ describe('Controller Tests', function() {
             var locals = {
                 '$rootScope': $rootScope,
                 '$scope': $scope,
+                'errorConstants': errorConstants,
                 '$state': MockState,
                 '$timeout': MockTimeout,
                 'Auth': MockAuth
@@ -93,7 +95,7 @@ describe('Controller Tests', function() {
             // given
             MockAuth.resetPasswordInit.and.returnValue($q.reject({
                 status: 400,
-                data: 'email address not registered'
+                data: '{"type": "' + errorConstants.EMAIL_NOT_FOUND_TYPE + '"}'
             }));
             createController();
             $scope.vm.resetAccount.email = 'user@domain.com';
diff --git a/generators/server/templates/src/test/java/package/web/rest/_AccountResourceIntTest.java b/generators/server/templates/src/test/java/package/web/rest/_AccountResourceIntTest.java
index 141ed31ecd..4946ccdfda 100644
--- a/generators/server/templates/src/test/java/package/web/rest/_AccountResourceIntTest.java
+++ b/generators/server/templates/src/test/java/package/web/rest/_AccountResourceIntTest.java
@@ -34,6 +34,9 @@ import <%=packageName%>.security.AuthoritiesConstants;
 <%_ if (authenticationType !== 'oauth2') { _%>
 import <%=packageName%>.service.MailService;
 import <%=packageName%>.service.dto.UserDTO;
+<%_ } _%>
+import <%=packageName%>.web.rest.errors.ExceptionTranslator;
+<%_ if (authenticationType !== 'oauth2') { _%>
 import <%=packageName%>.web.rest.vm.KeyAndPasswordVM;
 import <%=packageName%>.web.rest.vm.ManagedUserVM;
 <%_ } _%>
@@ -117,6 +120,9 @@ public class AccountResourceIntTest <% if (databaseType === 'cassandra') { %>ext
     private HttpMessageConverter[] httpMessageConverters;
 <%_ } _%>
 
+    @Autowired
+    private ExceptionTranslator exceptionTranslator;
+
     <% if (authenticationType === 'oauth2') { %>@MockBean<% } else { %>@Mock<% } %>
     private UserService mockUserService;
 <%_ if (authenticationType !== 'oauth2') { _%>
@@ -150,9 +156,12 @@ public class AccountResourceIntTest <% if (databaseType === 'cassandra') { %>ext
         <%_ if (authenticationType !== 'oauth2') { _%>
         this.restMvc = MockMvcBuilders.standaloneSetup(accountResource)
             .setMessageConverters(httpMessageConverters)
+            .setControllerAdvice(exceptionTranslator)
             .build();
         <%_ } _%>
-        this.restUserMockMvc = MockMvcBuilders.standaloneSetup(accountUserMockResource).build();
+        this.restUserMockMvc = MockMvcBuilders.standaloneSetup(accountUserMockResource)
+            .setControllerAdvice(exceptionTranslator)
+            .build();
     }
 
     @Test
diff --git a/test/utils/expected-files.js b/test/utils/expected-files.js
index 29ee874a27..640cff92c8 100644
--- a/test/utils/expected-files.js
+++ b/test/utils/expected-files.js
@@ -253,6 +253,7 @@ const expectedFiles = {
         `${CLIENT_MAIN_SRC_DIR}app/components/util/truncate-characters.filter.js`,
         `${CLIENT_MAIN_SRC_DIR}app/components/util/truncate-words.filter.js`,
         `${CLIENT_MAIN_SRC_DIR}app/components/util/date-util.service.js`,
+        `${CLIENT_MAIN_SRC_DIR}app/components/util/error.constants.js`,
         `${CLIENT_MAIN_SRC_DIR}app/components/util/sort.directive.js`,
         `${CLIENT_MAIN_SRC_DIR}app/components/util/sort-by.directive.js`,
         `${CLIENT_MAIN_SRC_DIR}app/components/util/capitalize.filter.js`,