
Des services Web Spring Boot Rest en utilisant Swagger et Orika
Commencer avec Swagger
Lors de la création d’une REST API, une bonne documentation est essentielle
De plus, chaque modification de l’API doit être décrite simultanément dans la documentation de référence.
Qu’est-ce que Swagger ?
Swagger est une spécification permettant de documenter la REST API en tant que développeur d’applications et d’écrire des services Web en utilisant votre Framework préféré.
Swagger analyse le code et expose la documentation sur une URL.
Tout client peut utiliser cette URL (sous forme de documents XML ou JSON) et apprendre à utiliser les services Web REST.
Le client sait maintenant quelles méthodes HTTP appeler sur quelle URL, quels documents d’entrée à envoyer, quel code d’état à attendre, etc..
Swagger est une spécification et prend en charge un large éventail de Framework.
Comment installer Swagger ?
Pour utiliser Swagger dans une application Web Spring, vous devez ajouter les dépendances aux bibliothèques Springfox et Swagger dans le fichier pom.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<!-- Swagger2 dependency --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.5.0</version> <scope>compile</scope> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.5.0</version> <scope>compile</scope> </dependency> |
Configurer Swagger 2 dans le projet
Pour activer la prise en charge de la spécification Swagger 2.0, utilisez l’annotation @EnableSwagger
Pour documenter le service, on utilise un dossier. Ceci est modifié pour être plus en ligne avec le fait que l’expression du contenu de la documentation est indépendante du format de rendu de la documentation .
src/main/java/com/intellitech/springlabs/SwaggerConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
package com.intellitech.springlabs; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.google.common.base.Predicate; import static com.google.common.base.Predicates.or; import static springfox.documentation.builders.PathSelectors.regex; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @EnableSwagger2 @Configuration public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .useDefaultResponseMessages(false) .select() .apis(RequestHandlerSelectors.any()) .apis(RequestHandlerSelectors.basePackage("com.intellitech.springlabs.controller")) .paths(paths()).build() .apiInfo(apiInfo()); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("SPRING LABS") .description("Created by IntelliTech") .version("1.0") .termsOfServiceUrl("http://intellitech.pro/") .build(); } @SuppressWarnings("unchecked") private Predicate paths() { return or( regex("/users.*"), regex("/role.*"), regex("/login.*")); } } |
Dans tous les contrôleurs, on deoit utiliser des annotations Swagger pour documenter l’API.
src/main/java/com/intellitech/springlabs/controller/UserController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
package com.intellitech.springlabs.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.intellitech.springlabs.model.User; import com.intellitech.springlabs.service.UserService; import com.intellitech.springlabs.util.CustomError; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; @RestController @RequestMapping("/users") public class UserController { @Autowired private UserService userService; @ApiOperation(value="Get user by id") @RequestMapping(value="/{userId}",method=RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE) @ApiResponses(value = { @ApiResponse(code = 200, message = "Success", response = User.class), @ApiResponse(code = 403, message = Constants.FORBIDDEN), @ApiResponse(code = 422, message = Constants.USER_NOT_FOUND), @ApiResponse(code = 417, message = Constants.EXCEPTION_FAILED) }) public ResponseEntity<?> getUserById(@PathVariable("userId") Long userId){ try { User user = userService.findById(userId); return new ResponseEntity<User>(user, HttpStatus.OK); } catch (ObjectNotFoundException onfe) { onfe.printStackTrace(); CustomError error = new CustomError("User with id = " + userId + " is not found"); return new ResponseEntity<CustomError>(error, HttpStatus.UNPROCESSABLE_ENTITY); } catch (Exception e) { e.printStackTrace(); CustomError error = new CustomError("An error has occurred"); return new ResponseEntity<CustomError>(error, HttpStatus.EXPECTATION_FAILED); } } |
CustomError est une classe utilisée pour renvoyer un message d’erreur dans la réponse.
src/main/java/com/intellitech /springlabs/util/CustomError.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.intellitech.springlabs.util; public class CustomError { private String errorMessage; public CustomError(String errorMessage) { this.errorMessage = errorMessage; } public String getErrorMessage() { return errorMessage; } } |
Comment débuter avec Orika
Le développement de logiciels d’entreprise nécessite souvent la création d’API pour chaque composant d’application.
Lors de la phase de l’implémentation, il s’agit de mapper des modèles d’API sur différentes couches de composants (par exemple, mapper un modèle de persistance sur un modèle de domaine en DTO).
Une telle cartographie est souvent sujette au code standard, consommant du temps et des efforts de développement.
La bonne solution est qu’il existe plusieurs alternatives pour le mappage d’objet à objet avec Orika.
Bien que ce projet soit assez récent (depuis 2012), il possède une base de code très stable, offre toutes les fonctionnalités pertinentes, et est très facile à comprendre.
Comment installer Orika
1 2 3 4 5 |
<dependency> <groupId>ma.glasnost.orika</groupId> <artifactId>orika-core</artifactId> <version>1.4.2</version> </dependency> |
Configurez Orika avec le framework Spring
Définir la source et la cible des beans
Source bean
src/main/java/com/intellitech/springlabs/model/User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
package com.intellitech.springlabs.model; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table; @Entity @Table(name = "user", schema = "public") public class User implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Long id; @Column(name = "first_name", length = 75) private String firstName; @Column(name = "last_name", length = 80) private String lastName; @Column(name = "username", length = 65) private String username; @Column(name = "password", length = 64) private String password; @Column(name = "email", unique = true, length = 115) private String email; @OneToOne(fetch = FetchType.EAGER) @JoinColumn(name = "role_id") private Role role; public User() { } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Role getRole() { return role; } public void setRole(Role role) { this.role = role; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } |
src/main/java/com/intellitech/springlabs/model/Device.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
package com.intellitech.springlabs.model; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table; import com.intellitech.springlabs.enumeration.Status; @Entity @Table(name = "device", schema = "public") public class Device implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Long id; @Column(name = "name", length = 65) private String name; @Column(name = "unique_id", length = 30) private String uniqueId; @Enumerated(EnumType.STRING) @Column(name = "status") private Status status; @Column(name = "phone_number", length = 65) private String phoneNumber; @OneToOne(fetch = FetchType.EAGER) @JoinColumn(name = "user_id") private User user; public Device() { } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUniqueId() { return uniqueId; } public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } public Status getStatus() { return status; } public void setStatus(Status status) { this.status = status; } public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } } |
src/main/java/com/intellitech/springlabs/model/Role.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
package com.intellitech.springlabs.model; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "role", schema = "public") public class Role implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Integer id; @Column(name = "role_name", length = 65) private String roleName; public Role() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } } |
Cible Bean
src/main/java/com/intellitech/springlabs/model/dto/UserDto.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
package com.intellitech.springlabs.model.dto; import java.io.Serializable; public class UserDto implements Serializable{ private static final long serialVersionUID = 1L; private Long id; private String firstName; private String lastName; private String username; private String password; private String email; private RoleDto roleDto; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public RoleDto getRoleDto() { return roleDto; } public void setRoleDto(RoleDto roleDto) { this.roleDto = roleDto; } } |
src/main/java/com/intellitech/springlabs/model/dto/DeviceDto.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
package com.intellitech.springlabs.model.dto; import java.io.Serializable; import com.intellitech.springlabs.enumeration.Status; public class DeviceDto implements Serializable { private static final long serialVersionUID = 1L; private Long id; private String name; private String uniqueId; private Status status; private String phoneNumber; private UserDto userDto; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUniqueId() { return uniqueId; } public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } public Status getStatus() { return status; } public void setStatus(Status status) { this.status = status; } public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } public UserDto getUserDto() { return userDto; } public void setUserDto(UserDto userDto) { this.userDto = userDto; } } |
src/main/java/com/intellitech/springlabs/model/dto/RoleDto.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.intellitech.springlabs.model.dto; import java.io.Serializable; public class RoleDto implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String roleName; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } } |
La pierre angulaire de base du mapping Framework Orika est la classe MapperFactory.
C’est la classe que vous utiliserez pour configurer les mappages et obtenir le MapperFacade qui effectue le travail de mappage proprement dit
src/main/java/com/intellitech/springlabs/model.mapper/UserMapper.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package com.intellitech.springlabs.model.mapper; import org.springframework.stereotype.Component; import com.intellitech.springlabs.model.User; import com.intellitech.springlabs.model.dto.UserDto; import ma.glasnost.orika.MapperFactory; import ma.glasnost.orika.impl.ConfigurableMapper; @Component public class UserMapper extends ConfigurableMapper{ protected void configure(MapperFactory factory) { factory.classMap(User.class, UserDto.class) .field("id", "id") .field("firstName", "firstName") .field("lastName", "lastName") .field("username", "username") .field("firstName", "firstName") .field("password", "password") .field("email", "email") .field("role", "roleDto") .byDefault() .register(); } } |
src/main/java/com/intellitech/springlabs/model.mapper/RoleMapper.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.intellitech.springlabs.model.mapper; import org.springframework.stereotype.Component; import com.intellitech.springlabs.model.Role; import com.intellitech.springlabs.model.dto.RoleDto; import ma.glasnost.orika.MapperFactory; import ma.glasnost.orika.impl.ConfigurableMapper; @Component public class RoleMapper extends ConfigurableMapper{ protected void configure(MapperFactory factory) { factory.classMap(Role.class, RoleDto.class) .field("id", "id") .field("roleName", "roleName") .byDefault() .register(); } } |
src/main/java/com/intellitech/springlabs/model.mapper/DeviceMapper.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package com.intellitech.springlabs.model.mapper; import org.springframework.stereotype.Component; import com.intellitech.springlabs.model.Device; import com.intellitech.springlabs.model.dto.DeviceDto; import ma.glasnost.orika.MapperFactory; import ma.glasnost.orika.impl.ConfigurableMapper; @Component public class DeviceMapper extends ConfigurableMapper{ protected void configure(MapperFactory factory) { factory.classMap(Device.class, DeviceDto.class) .field("id", "id") .field("name", "name") .field("uniqueId", "uniqueId") .field("status", "status") .field("phoneNumber", "phoneNumber") .field("user", "userDto") .field("user.role", "userDto.roleDto") .byDefault() .register(); } } |
src/main/java/com/intellitech/springlabs/repository/DeviceRepository.java
1 2 3 4 5 6 7 8 9 10 |
package com.intellitech.springlabs.repository; import org.springframework.data.jpa.repository.JpaRepository; import com.intellitech.springlabs.model.Device; public interface DeviceRepository extends JpaRepository { Device findByUniqueId(String uniqueId); } |
Couche de service
Créons maintenant les couches UserService, DeviceService et RoleService (interface et implémentation)
Nous allons injecter UserRepository, DeviceRepository et RoleRepository dans l’implémentation de nos services
src/main/java/com/intellitech/springlabs/service/UserService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.intellitech.springlabs.service; import com.intellitech.springlabs.model.dto.UserDto; import javassist.tools.rmi.ObjectNotFoundException; public interface UserService { UserDto findByUsernameOrEmail(String usernameOrEmail); UserDto findById(Long id) throws ObjectNotFoundException; UserDto findByEmail(String email) throws ObjectNotFoundException; UserDto save(UserDto userDto); } |
src/main/java/com/intellitech/springlabs/service/DeviceService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.intellitech.springlabs.service; import com.intellitech.springlabs.model.dto.DeviceDto; import javassist.tools.rmi.ObjectNotFoundException; public interface DeviceService { DeviceDto saveDevice(DeviceDto device); void deleteDevice(DeviceDto device); void deleteDevice(Long deviceId) throws IllegalArgumentException; DeviceDto updateDevice(DeviceDto device); DeviceDto findById(Long deviceId) throws ObjectNotFoundException; DeviceDto findByUniqueId(String uniqueId)throws ObjectNotFoundException; List findByUserId(Long userId) throws ObjectNotFoundException; } |
src/main/java/com/intellitech/springlabs/service/RoleService.java
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.intellitech.springlabs.service; import java.util.List; import com.intellitech.springlabs.model.dto.RoleDto; import javassist.tools.rmi.ObjectNotFoundException; public interface RoleService { List findAll() throws ObjectNotFoundException; } |
src/main/java/com/intellitech/springlabs/service/impl/UserServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
package com.intellitech.springlabs.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.intellitech.springlabs.model.User; import com.intellitech.springlabs.model.dto.UserDto; import com.intellitech.springlabs.model.mapper.UserMapper; import com.intellitech.springlabs.repository.UserRepository; import com.intellitech.springlabs.service.UserService; import javassist.tools.rmi.ObjectNotFoundException; @Service("userService") @Transactional public class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; @Autowired private UserMapper userMapper; @Override @Transactional(readOnly = true) public UserDto findByUsernameOrEmail(String username) { try { User user = userRepository.findByUsernameOrEmail(username); return userMapper.map(user, UserDto.class); } catch (Exception e) { throw e; } } @Override @Transactional(readOnly = true) public UserDto findById(Long id) throws ObjectNotFoundException { User user = userRepository.findOne(id); if (user == null) { throw new ObjectNotFoundException("User not found"); } return userMapper.map(user, UserDto.class); } @Override @Transactional(readOnly = true) public UserDto findByEmail(String email) throws ObjectNotFoundException { User user = userRepository.findByEmail(email); if (user == null) { throw new ObjectNotFoundException("User not found"); } return userMapper.map(user, UserDto.class); } @Override public UserDto save(UserDto userDto) { if (userDto != null) { User user = userMapper.map(userDto, User.class); User userSaved = userRepository.save(user); if (userSaved != null) { return userMapper.map(userSaved, UserDto.class); } } return null; } } |
src/main/java/com/intellitech/springlabs/util/MapperUtil.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package com.intellitech.springlabs.util; import java.util.ArrayList; import java.util.List; import ma.glasnost.orika.MapperFacade; public class MapperUtil { public static List<u> map(final MapperFacade mapper, final List source, final Class<u> destType) { if (mapper == null || source == null) { return null; } List<u> dest = new ArrayList<u>(); dest = mapper.mapAsList(source, destType); return dest; } } </u></u></u></u> |
src/main/java/com/intellitech/springlabs/controller/UserController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
package com.intellitech.springlabs.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.intellitech.springlabs.model.dto.UserDto; import com.intellitech.springlabs.model.request.UpdateUserProfileRequest; import com.intellitech.springlabs.service.UserService; import com.intellitech.springlabs.util.Constants; import com.intellitech.springlabs.util.CurrentSession; import com.intellitech.springlabs.util.CustomError; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; import javassist.tools.rmi.ObjectNotFoundException; @RestController @RequestMapping("/users") public class UserController { @Autowired private UserService userService; @Autowired private CurrentSession currentSession; @ApiOperation(value = "Get current user") @RequestMapping(value = "getCurrentUser", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @ApiResponses(value = { @ApiResponse(code = 200, message = Constants.SUCCESS, response = UserDto.class), @ApiResponse(code = 422, message = Constants.USER_NOT_FOUND), @ApiResponse(code = 417, message = Constants.EXCEPTION_FAILED) }) public ResponseEntity<?> getCurrentUser() { try { UserDto userDto = userService.findById(currentSession.getSpringLabsUser().getUserDto().getId()); return new ResponseEntity<UserDto>(userDto, HttpStatus.OK); } catch (ObjectNotFoundException onfe) { onfe.printStackTrace(); CustomError error = new CustomError("User not found"); return new ResponseEntity<CustomError>(error, HttpStatus.UNPROCESSABLE_ENTITY); } catch (Exception e) { e.printStackTrace(); CustomError error = new CustomError("An error has occurred"); return new ResponseEntity<CustomError>(error, HttpStatus.EXPECTATION_FAILED); } } @ApiOperation(value = "Update user profile") @RequestMapping(value = "updateUserProfile", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @ApiResponses(value = { @ApiResponse(code = 200, message = Constants.SUCCESS, response = UserDto.class), @ApiResponse(code = 422, message = Constants.USER_NOT_FOUND), @ApiResponse(code = 204, message = Constants.USER_PROFILE_NOT_UPDATED), @ApiResponse(code = 417, message = Constants.EXCEPTION_FAILED) }) public ResponseEntity<?> updateUserProfile(@RequestBody UpdateUserProfileRequest request) { try { UserDto userDto = userService.findById(currentSession.getSpringLabsUser().getUserDto().getId()); userDto.setFirstName(request.getFirstName()); userDto.setLastName(request.getLastName()); userDto.setUsername(request.getUsername()); userDto.setEmail(request.getEmail()); UserDto userSaved = userService.save(userDto); if (userSaved != null) { return new ResponseEntity<UserDto>(userDto, HttpStatus.OK); } CustomError error = new CustomError("Cannot update user"); return new ResponseEntity<CustomError>(error, HttpStatus.NO_CONTENT); } catch (ObjectNotFoundException onfe) { onfe.printStackTrace(); CustomError error = new CustomError("User not found"); return new ResponseEntity<CustomError>(error, HttpStatus.UNPROCESSABLE_ENTITY); } catch (Exception e) { e.printStackTrace(); CustomError error = new CustomError("An error has occurred"); return new ResponseEntity<CustomError>(error, HttpStatus.EXPECTATION_FAILED); } } } |
src/main/java/com/intellitech/springlabs/controller/LoginController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
package com.intellitech.springlabs.controller; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.intellitech.springlabs.model.request.AuthenticationRequest; import com.intellitech.springlabs.model.response.UserTransfer; import com.intellitech.springlabs.util.Constants; import com.intellitech.springlabs.util.TokenUtil; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; @RestController @RequestMapping("/login") public class LoginController { @Autowired private AuthenticationManager authenticationManager; @Autowired @Qualifier("customUserDetailsService") private UserDetailsService customUserDetailsService; @RequestMapping(value = "/authenticate", method = { RequestMethod.POST }) @ApiOperation(value = "authenticate") @ApiResponses(value = { @ApiResponse(code = 200, message = Constants.SUCCESS, response = UserTransfer.class), @ApiResponse(code = 403, message = Constants.FORBIDDEN), @ApiResponse(code = 204, message = Constants.NOT_FOUND), @ApiResponse(code = 417, message = Constants.EXCEPTION_FAILED) }) public ResponseEntity<UserTransfer> authenticate(@RequestBody AuthenticationRequest authenticationRequest) { try { String username = authenticationRequest.getUsername(); String password = authenticationRequest.getPassword(); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); Authentication authentication = this.authenticationManager.authenticate(token); SecurityContextHolder.getContext().setAuthentication(authentication); UserDetails userDetails = this.customUserDetailsService.loadUserByUsername(username); List<String> roles = new ArrayList<>(); for (GrantedAuthority authority : userDetails.getAuthorities()) { roles.add(authority.toString()); } return new ResponseEntity<UserTransfer>(new UserTransfer(userDetails.getUsername(), roles, TokenUtil.createToken(userDetails), HttpStatus.OK), HttpStatus.OK); } catch (BadCredentialsException bce) { return new ResponseEntity<UserTransfer>(new UserTransfer(), HttpStatus.NO_CONTENT); } catch (Exception e) { return new ResponseEntity<>(HttpStatus.EXPECTATION_FAILED); } } } |
Exécuter l’application
Vous devez tout d’abord créer une base de données avec le nom springlabs et exécuter le script dans la base de données PostgreSQL
1 2 3 4 |
INSERT INTO public.role (id, role_name) VALUES (1, 'ROLE_ADMIN'); INSERT INTO public.role (id, role_name) VALUES (2, 'ROLE_USER'); INSERT INTO public.user (id, first_name, last_name, email, password, username, role_id) VALUES (1, 'Nizar', 'Ellouze','nizarellouze@gmail.com', '$2a$10$bpNMKeaQXKpJ4JVxOHWvu.tZdmCLT9nKcZreJ/ELfCgmTCyhC7GPy', 'admin', 1); INSERT INTO public.user (id, first_name, last_name, email, password, username, role_id) VALUES (2, 'Omar', 'Kessemtini','kessemtini.omar@gmail.com', '$2a$10$TA.UfUqLa8uDeGkt95FfLeq7T5Y5vpDpzAtvJrHSLzLliY/PARXUq', 'user', 2); |
Ouvrez le terminal et exécutez mvn spring-boot: exécutez et visitez le localhost: 8080 et authentifiez-vous auprès de l’un des deux utilisateurs
USER1: username=user, password=user
USER2: username=admin, password=admin
Source code