Pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter, inscrivez-vous gratuitement !

 

  1. #1
    Membre averti
    Avatar de parchemal
    Homme Profil pro
    Ingénieur Développeur Java
    Inscrit en
    août 2009
    Messages
    123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2009
    Messages : 123
    Points : 307
    Points
    307

    Par défaut Apprendre à développer les services REST avec Spring Boot et Spring RestTemplate

    Bonjour chers amis développeurs,

    J'ai rédigé ce tutoriel qui permet d'apprendre à développer les services REST avec Spring Boot et Spring RestTemplate. L'idée dans ce tutoriel consiste à développer les services REST client/serveur dans deux applications distinctes et surtout à montrer qu'avec Spring Boot, le développeur ne passe plus trop du temps de la configuration de son projet, et peut ainsi déployer très facilement son application dans un environnement de développement comme dans un environnement de production.

    Cet espace vous permet de donner votre point de vue et éventuellement une autre façon de répondre au même besoin. Votre participation est très attendue.

    Merci d'avance
    Bertrand Nguimgo



    Retrouvez les meilleurs cours et tutoriels pour apprendre Spring
    Nguimgo Bertrand
    Ingénieur Etudes et Développement JAVA/JEE

    - Guide d'implémentation des services REST avec Spring Boot et Spring RestTemplate
    - Je vous propose de lire le guide d'implémentation du design pattern MVP-GWT
    - N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  2. #2
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : novembre 2003
    Messages : 786
    Points : 1 978
    Points
    1 978

    Par défaut

    Bonjour

    J'ai parcouru ce tuto et je dois dire qu'il est très complet et très bien fait.

    Mais j'ai quand même quelques questions d'enquiquineur ^^

    - UserDTO : pourquoi créer un autre objet plutôt que d'utiliser directement l'objet User? (sachant qu'ils sont identiques, modulo le hashcode/equals)
    Le pattern DTO oblige à sans arrêt passer d'un type d'objet à un autre juste pour obtenir une "pseudo" isolation des couches DAO/Services qui sont quand même liées les unes aux autres.
    Accessoirement, ça se passe bien dans le cas présent parce qu'on ne gère pas de grappe d'objet.

    - L'injection Spring : afin de faciliter les tests unitaires, il pourrait être bon de faire de l'autowire par constructeur plutôt que par propriété
    Avec l'exemple de RoleServiceImpl
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Service(value = "roleService") // c'est optionnel de préciser le value s'il existe une seule implémentation de l'interface
    public class RoleServiceImpl implements RoleService {
        
        private RoleRepository roleRepository;
    
        @Autowired
        public RoleServiceImpl(RoleRepository roleRepository){
            this.roleRepository = roleRepository;
        }
    
        ...
    }
    Ce qui permettrait de créer des tests unitaires sous la forme suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // TU pur : pas d'injection ou de dépendances autres que la classe testée
    public class RoleServiceImplTest {
        
        @Test
        public void should_get_all_roles_when_asking_for_all_roles(){
            // ARRANGE
            RoleRepository roleRepository = Mockito.mock(RoleRepository.class);
            RoleServiceImpl roleService = new  RoleServiceImpl (roleRepository );
            
            Mockito.when(roleRepository.findAll().thenReturn(RoleFixture.getRoles());// classe RoleFixture permettant de créer des rôles à créer
            // ACT
            Collection<Role> result = roleService.getAllRoles();
    
            // ASSERT        
            Assertions.assertThat(result).isNotNull() // Assertions vient de assertJ qui est un excellent framework pour la rédaction de tests unitaires
                    .hasSize(5)
                    ....
        }
    
        ...
    }
    - Pourquoi est-ce que le code "métier" de la sauvegarde de l'utilisateur se trouve dans le contrôleur ?
    Si les services ne servent que de "passe plat" pour les DAO, ils n'ont pas de valeur propre (à part des valeurs purement techniques comme la gestion des transaction et de l'encryptage des mots de passe)

    - Un détail : c'est mieux quand les logger sont `private static final` (il manque le final là)

    - Les requête POST/PUT sont en XML et le retour en JSON, ça fait bizarre non? C'est voulu pour montrer qu'on gère ce qu'on veut comme type de données?

    - Les tests d'intégration avec TestRestTemplate : c'est TOP !

    - Y'a un repo git de dispo avec le code source pour pouvoir faire des propositions d'amélioration?


    Je le répète, c'est du chipotage, et le guide en l'état est très bien.
    Je ne suis pas mort, j'ai du travail !

  3. #3
    Membre averti
    Avatar de parchemal
    Homme Profil pro
    Ingénieur Développeur Java
    Inscrit en
    août 2009
    Messages
    123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2009
    Messages : 123
    Points : 307
    Points
    307

    Par défaut

    Bonjour Monsieur eulbobo,

    Vous avez un regard très pointilleux, et je suis flatté de vous répondre. Merci pour vos remarques.

    Citation Envoyé par eulbobo Voir le message
    - UserDTO : pourquoi créer un autre objet plutôt que d'utiliser directement l'objet User?
    Cette démarche a pour objectif de faire comprendre qu'il est préférable de manipuler un DTO que de manipuler l'objet lui-même, même si dans le cas présent, les deux sont strictement identiques.

    Citation Envoyé par eulbobo Voir le message
    @Service(value = "roleService") // c'est optionnel de préciser le value s'il existe une seule implémentation de l'interface
    Tout à fait, mais de prudence, il faut le préciser pour faciliter la tâche à l'évolution future des différentes implémentations

    Citation Envoyé par eulbobo Voir le message
    - L'injection Spring : afin de faciliter les tests unitaires, il pourrait être bon de faire de l'autowire par constructeur plutôt que par propriété
    Avec l'exemple de RoleServiceImpl
    Très bonne remarque, super!!!!!, avantage donnée aux tests. Avec ça plus besoin d'injecter une instance de la classe à tester. Vous avez parfaitement raison. Merci encore

    Citation Envoyé par eulbobo Voir le message
    - Pourquoi est-ce que le code "métier" de la sauvegarde de l'utilisateur se trouve dans le contrôleur ?
    Ça n'est pas normal. A revoir. Merci pour la remarque

    Citation Envoyé par eulbobo Voir le message
    - Un détail : c'est mieux quand les logger sont `private static final` (il manque le final là)
    Erreur de frappe, vous avez un œil pointu, il faudra mettre à jour

    Citation Envoyé par eulbobo Voir le message
    - Les requête POST/PUT sont en XML et le retour en JSON, ça fait bizarre non? C'est voulu pour montrer qu'on gère ce qu'on veut comme type de données?
    C'est fait express. Car c'est un des avantages de Spring Boot. Il sait se débrouiller tout seul. Et j'ai signalé ce mécanisme quelque part dans le tutoriel

    J'ai tenu à automatiser les tests unitaires et les tests d'intégration comme vous l'avez si bien remarqué.

    Bravo pour toutes vos remarques, je prendrais en compte ces remarques pour une prochaine mise à jour.

    Cordialement
    Bertrand Nguimgo
    Nguimgo Bertrand
    Ingénieur Etudes et Développement JAVA/JEE

    - Guide d'implémentation des services REST avec Spring Boot et Spring RestTemplate
    - Je vous propose de lire le guide d'implémentation du design pattern MVP-GWT
    - N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Membre éclairé
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    mars 2017
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Autre

    Informations professionnelles :
    Activité : Assistant aux utilisateurs

    Informations forums :
    Inscription : mars 2017
    Messages : 55
    Points : 680
    Points
    680

    Par défaut

    Très bon tutoriel, très complet.
    Je vais pinailler aussi : bcrypt est une fonction de hachage, le mot de passe n'est donc pas "encrypté" (chiffré), mais haché.

  5. #5
    Membre averti
    Avatar de parchemal
    Homme Profil pro
    Ingénieur Développeur Java
    Inscrit en
    août 2009
    Messages
    123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2009
    Messages : 123
    Points : 307
    Points
    307

    Par défaut

    Citation Envoyé par John Bournet Voir le message
    Très bon tutoriel, très complet.
    Je vais pinailler aussi : bcrypt est une fonction de hachage, le mot de passe n'est donc pas "encrypté" (chiffré), mais haché.
    Remarque à prendre en compte.

    Merci !

    Bertrand
    Nguimgo Bertrand
    Ingénieur Etudes et Développement JAVA/JEE

    - Guide d'implémentation des services REST avec Spring Boot et Spring RestTemplate
    - Je vous propose de lire le guide d'implémentation du design pattern MVP-GWT
    - N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : novembre 2003
    Messages : 786
    Points : 1 978
    Points
    1 978

    Par défaut

    Bonjour

    Je reviens à nouveau sur deux trucs :

    Citation Envoyé par parchemal Voir le message
    Cette démarche a pour objectif de faire comprendre qu'il est préférable de manipuler un DTO que de manipuler l'objet lui-même, même si dans le cas présent, les deux sont strictement identiques.
    J'ai souvent entendu cet argument du "c'est mieux"
    Je n'ai jamais entendu autre chose de constructif sur le POURQUOI ça serait "mieux" de "copier" les données d'un wrapper à un autre.
    Mais j'ai souvent vu des horreurs avec de la copie en boucle de données d'une grappe d'objets à une autre... Genre une grappe d'objets hibernates qui sont tous copiés un par un dans le DTO qui leur correspond -> duplication totale de code, risque de bug, complexité inutile, etc...

    Et je suis pragmatique, j'ai tendance à ne pas faire de code qui ne m'apporte rien.

    Tout à fait, mais de prudence, il faut le préciser pour faciliter la tâche à l'évolution future des différentes implémentations
    Sur les anciennes versions de Spring, je dis pas, depuis la version 4 je n'ai plus jamais eu le problème.
    Attention de ne pas prévoir des trucs qui ne servent pas au simple principe que peut-être un jour ça sera utile :p
    (cf ci dessus : pas de code qui ne me sert pas même si c'est pour de la configuration)

    C'est fait express. Car c'est un des avantages de Spring Boot. Il sait se débrouiller tout seul. Et j'ai signalé ce mécanisme quelque part dans le tutoriel
    Alors c'est une très bonne initiative ^^
    Je ne suis pas mort, j'ai du travail !

  7. #7
    Membre averti
    Avatar de parchemal
    Homme Profil pro
    Ingénieur Développeur Java
    Inscrit en
    août 2009
    Messages
    123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2009
    Messages : 123
    Points : 307
    Points
    307

    Par défaut

    Bonjour M eulbobo,

    Remarques à prendre en compte.

    Merci pour votre contribution

    Bertrand

    Citation Envoyé par eulbobo Voir le message
    Bonjour

    Je reviens à nouveau sur deux trucs :


    J'ai souvent entendu cet argument du "c'est mieux"
    Je n'ai jamais entendu autre chose de constructif sur le POURQUOI ça serait "mieux" de "copier" les données d'un wrapper à un autre.
    Mais j'ai souvent vu des horreurs avec de la copie en boucle de données d'une grappe d'objets à une autre... Genre une grappe d'objets hibernates qui sont tous copiés un par un dans le DTO qui leur correspond -> duplication totale de code, risque de bug, complexité inutile, etc...

    Et je suis pragmatique, j'ai tendance à ne pas faire de code qui ne m'apporte rien.


    Sur les anciennes versions de Spring, je dis pas, depuis la version 4 je n'ai plus jamais eu le problème.
    Attention de ne pas prévoir des trucs qui ne servent pas au simple principe que peut-être un jour ça sera utile :p
    (cf ci dessus : pas de code qui ne me sert pas même si c'est pour de la configuration)


    Alors c'est une très bonne initiative ^^
    Nguimgo Bertrand
    Ingénieur Etudes et Développement JAVA/JEE

    - Guide d'implémentation des services REST avec Spring Boot et Spring RestTemplate
    - Je vous propose de lire le guide d'implémentation du design pattern MVP-GWT
    - N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Membre éclairé
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    mars 2017
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Autre

    Informations professionnelles :
    Activité : Assistant aux utilisateurs

    Informations forums :
    Inscription : mars 2017
    Messages : 55
    Points : 680
    Points
    680

    Par défaut

    Citation Envoyé par eulbobo Voir le message

    J'ai souvent entendu cet argument du "c'est mieux"
    Je n'ai jamais entendu autre chose de constructif sur le POURQUOI ça serait "mieux" de "copier" les données d'un wrapper à un autre.
    Mais j'ai souvent vu des horreurs avec de la copie en boucle de données d'une grappe d'objets à une autre... Genre une grappe d'objets hibernates qui sont tous copiés un par un dans le DTO qui leur correspond -> duplication totale de code, risque de bug, complexité inutile, etc...
    A l'origine, le pattern DTO a pour philosophie de remonter un maximum d'information depuis un appel distant (forcément coûteux). L'utilisation qui en a été faite au cours du temps est légèrement différente : du mapping d'objet, sans aucune logique supplémentaire, comme c'est le cas dans cet article, un simple "passe plat" en somme. Dans les anciennes versions d'hibernate, cela était nécessaire, dans la mesure où les beans étaient enrichis par le framework artificiellement, pour gérer les états de persistance, et contenaient donc une quantité de données qu'il n'était pas souhaitable de transférer aux autres couches des applications, d'où l'utilisation du pattern DTO. Depuis cette époque, il semble que cette pratique a perduré, même lorsque ça n'a plus été nécessaire, peut être simplement par habitude ou par impression de bonne pratique (ça me rappelle une histoire avec des singes et une échelle).

  9. #9
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : novembre 2003
    Messages : 786
    Points : 1 978
    Points
    1 978

    Par défaut

    J'avoue avoir commencé avec Hibernate 2... Mais déjà à l'époque, les gens qui balançaient ce pattern de tous les bouts ne savaient pas plus "pourquoi" ils le faisaient...
    On appelait ça le pattern VIEW à l'époque, parce qu'on mettait nos données dans des objets "vue" depuis nos beans hibernates... Objets View qui finissaient dans les objets Form de struts...

    Juste ils le faisaient... Et du coup, je le faisais aussi en rageant de toutes les erreurs que ça pouvait générer (c'était en 2006)


    12 ans plus tard, toujours aucune explication du mieux ^^


    Cargo Cult mon amour...
    Je ne suis pas mort, j'ai du travail !

  10. #10
    Membre averti
    Avatar de parchemal
    Homme Profil pro
    Ingénieur Développeur Java
    Inscrit en
    août 2009
    Messages
    123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2009
    Messages : 123
    Points : 307
    Points
    307

    Par défaut

    Citation Envoyé par eulbobo Voir le message
    - Y'a un repo git de dispo avec le code source pour pouvoir faire des propositions d'amélioration?
    Je vais voir comment mettre en place le repo git. As-tu déjà mis en place un repo git, si oui quelques indications ?

    Bertrand
    Nguimgo Bertrand
    Ingénieur Etudes et Développement JAVA/JEE

    - Guide d'implémentation des services REST avec Spring Boot et Spring RestTemplate
    - Je vous propose de lire le guide d'implémentation du design pattern MVP-GWT
    - N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  11. #11
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : novembre 2003
    Messages : 786
    Points : 1 978
    Points
    1 978

    Par défaut

    Citation Envoyé par parchemal Voir le message
    Je vais voir comment mettre en place le repo git. As-tu déjà mis en place un repo git, si oui quelques indications ?

    Bertrand
    Le plus simple :
    - Aller sur github : github.com
    - Se créer un compte
    - Créer un repository public (c'est gratuit tant que c'est public)
    - Suivre les instruction pour pousser du code sur le repo
    - Donner l'URL aux gens

    Hésite pas à demander si tu as besoin d'aide, mais franchement le plus dur est de comprendre la finesse et la puissance de git, pas de créer un repo ou de partager du code :p
    Je ne suis pas mort, j'ai du travail !

  12. #12
    Membre averti
    Avatar de parchemal
    Homme Profil pro
    Ingénieur Développeur Java
    Inscrit en
    août 2009
    Messages
    123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2009
    Messages : 123
    Points : 307
    Points
    307

    Par défaut

    Citation Envoyé par eulbobo Voir le message
    Hésite pas à demander si tu as besoin d'aide, mais franchement le plus dur est de comprendre la finesse et la puissance de git, pas de créer un repo ou de partager du code :p
    Merci pour les indications. C'est juste que je n'ai jamais eu à faire un dépôt sous git public. Sinon, j'utilise Git au quotidien.

    Si je le fais, je mettrais le lien à disposition.

    Merci!
    Nguimgo Bertrand
    Ingénieur Etudes et Développement JAVA/JEE

    - Guide d'implémentation des services REST avec Spring Boot et Spring RestTemplate
    - Je vous propose de lire le guide d'implémentation du design pattern MVP-GWT
    - N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  13. #13
    Membre chevronné Avatar de jeffray03
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juillet 2008
    Messages
    1 331
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : juillet 2008
    Messages : 1 331
    Points : 1 845
    Points
    1 845

    Par défaut

    salut,
    j´ai essayé de creer un projet conformement au tutoriel,
    mais losrque j´appelle cet URI http://localhost:8080/user/users
    j´ai ceci comme erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Caused by: java.lang.IllegalStateException: getOutputStream() has already been called for this response
    Merci.

    Eric

  14. #14
    Membre chevronné Avatar de jeffray03
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juillet 2008
    Messages
    1 331
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : juillet 2008
    Messages : 1 331
    Points : 1 845
    Points
    1 845

    Par défaut

    salut,
    le probleme est reglé,
    c´etait juste une annotation qui a ete oublié sur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    @JsonIgnore
    	public void setRoles(Set<Role> roles) {
    		this.roles = roles;
    	}
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    @JsonIgnore
    	public void setUsers(Set<User> users) {
    		this.users = users;
    	}
    sinon apres tout marches bien.
    Je continue la mise en pratique et je reviens vers vous.

    Eric

  15. #15
    Membre averti
    Avatar de parchemal
    Homme Profil pro
    Ingénieur Développeur Java
    Inscrit en
    août 2009
    Messages
    123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2009
    Messages : 123
    Points : 307
    Points
    307

    Par défaut

    Bonjour jeffray03,

    C'est bien d'avoir trouvé la solution. N'hésitez pas d'aller au bout du tutoriel, il faut éviter surtout de sauter les parties. Je vous encourage de faire aussi les tests unitaires et les tests d'intégration, car j'ai pris le temps pour bien les présenter afin de faciliter leurs mises en pratique.

    Cordialement

    Bertrand Nguimgo
    Nguimgo Bertrand
    Ingénieur Etudes et Développement JAVA/JEE

    - Guide d'implémentation des services REST avec Spring Boot et Spring RestTemplate
    - Je vous propose de lire le guide d'implémentation du design pattern MVP-GWT
    - N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  16. #16
    Membre chevronné Avatar de jeffray03
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juillet 2008
    Messages
    1 331
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : juillet 2008
    Messages : 1 331
    Points : 1 845
    Points
    1 845

    Par défaut

    Salut,

    je ne vois pas ou est ce que tu as definis l´entite (classe) Role.
    Dans les entités User et Role , il n´ya pas d´implementation de la classe Comparable a laquelle tu fais reference dans le controller Usercontroller.

    Dans le Test:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      @Test
        public void testFindByLogin() {
            User userFromDB = userRepository.findByLogin("user2");     
            assertThat("user2", is(userFromDB.getLogin()));//user2 a été créé lors de l'initialisation du fichier data.sql     
        }
    Dans le fichier Data.sql il n´est pas mentioné la création de user2

    Est ce un oublie?

    Merci

    Eric

  17. #17
    Membre averti
    Avatar de parchemal
    Homme Profil pro
    Ingénieur Développeur Java
    Inscrit en
    août 2009
    Messages
    123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2009
    Messages : 123
    Points : 307
    Points
    307

    Par défaut

    Bonjour jeffray03,

    Ça doit être un oublie. Essai de télécharger dans les sources. Sinon, dans tous les cas, je vais compléter dans le tutoriel. merci de la remarque

    Cordialement
    Bertrand

    Citation Envoyé par jeffray03 Voir le message
    Salut,

    je ne vois pas ou est ce que tu as definis l´entite (classe) Role.
    Dans les entités User et Role , il n´ya pas d´implementation de la classe Comparable a laquelle tu fais reference dans le controller Usercontroller.

    Dans le Test:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      @Test
        public void testFindByLogin() {
            User userFromDB = userRepository.findByLogin("user2");     
            assertThat("user2", is(userFromDB.getLogin()));//user2 a été créé lors de l'initialisation du fichier data.sql     
        }
    Dans le fichier Data.sql il n´est pas mentioné la création de user2

    Est ce un oublie?

    Merci

    Eric
    Nguimgo Bertrand
    Ingénieur Etudes et Développement JAVA/JEE

    - Guide d'implémentation des services REST avec Spring Boot et Spring RestTemplate
    - Je vous propose de lire le guide d'implémentation du design pattern MVP-GWT
    - N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  18. #18
    Membre averti
    Avatar de parchemal
    Homme Profil pro
    Ingénieur Développeur Java
    Inscrit en
    août 2009
    Messages
    123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2009
    Messages : 123
    Points : 307
    Points
    307

    Par défaut

    Bonjour,

    Voici la classe demandée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    package com.bnguimgo.springbootrestserver.model;
    import java.io.Serializable;
    
    import javax.persistence.*;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    
    @Entity
    @Table(name = "ROLE")
    @XmlRootElement(name = "role")
    public class Role implements Serializable{
    
    	private static final long serialVersionUID = 2284252532274015507L;
    
    	@Id
    	@GeneratedValue(strategy = GenerationType.IDENTITY)//IDENTITY ==> c'est la base de données qui va générer la clé primaire afin d'éviter les doublons, car cette table contient déjà les données à l'initialisation
    	@Column(name = "ROLE_ID", updatable = false, nullable = false)
    	private int id;
    	
    	@Column(name="ROLE_NAME", updatable = true, nullable = false)
    	private String roleName;
    	
    	public Role(){
    		super();
    	}
    	public Role(String roleName){
    		super();
    		this.roleName = roleName;
    	}
    	public int getId() {
    		return id;
    	}
    	@XmlElement
    	public void setId(int id) {
    		this.id = id;
    	}
    	public String getRoleName() {
    		return roleName;
    	}
    	@XmlElement
    	public void setRoleName(String roleName) {
    		this.roleName = roleName;
    	}
    	@Override
    	public String toString() {
    		return "Role [id=" + id + ", role=" + roleName + "]";
    	}
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + id;
    		result = prime * result + ((roleName == null) ? 0 : roleName.hashCode());
    		return result;
    	}
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		Role other = (Role) obj;
    		if (id != other.id)
    			return false;
    		if (roleName == null) {
    			if (other.roleName != null)
    				return false;
    		} else if (!roleName.equals(other.roleName))
    			return false;
    		return true;
    	}
    	
    	public int compareTo(Role role){
    		return this.roleName.compareTo(role.getRoleName());
    		
    	}
    }
    Citation Envoyé par jeffray03 Voir le message
    Salut,

    je ne vois pas ou est ce que tu as definis l´entite (classe) Role.
    Dans les entités User et Role , il n´ya pas d´implementation de la classe Comparable a laquelle tu fais reference dans le controller Usercontroller.

    Dans le Test:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      @Test
        public void testFindByLogin() {
            User userFromDB = userRepository.findByLogin("user2");     
            assertThat("user2", is(userFromDB.getLogin()));//user2 a été créé lors de l'initialisation du fichier data.sql     
        }
    Dans le fichier Data.sql il n´est pas mentioné la création de user2

    Est ce un oublie?

    Merci

    Eric
    Nguimgo Bertrand
    Ingénieur Etudes et Développement JAVA/JEE

    - Guide d'implémentation des services REST avec Spring Boot et Spring RestTemplate
    - Je vous propose de lire le guide d'implémentation du design pattern MVP-GWT
    - N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  19. #19
    Membre actif

    Homme Profil pro
    Ingénieur
    Inscrit en
    mars 2013
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Industrie

    Informations forums :
    Inscription : mars 2013
    Messages : 34
    Points : 273
    Points
    273

    Par défaut DTO

    bonjour,

    je suis sur la partie * serveur*, je trouve ce tutoriel généreux et très bien réalisé. Merci beaucoup.
    Ce tuto m'a permis de démarrer vraiment rapidement sur cette techno ! (ma toute premiere experience en springboot)

    Evidemment il va me falloir du temps pour digerer car springboot masque la richesse et la complexite de Spring.

    Mais déjà par rapport aux DTOs je me posais quelques questions :
    1/- coté structure, les services REST ne produisent pas des objets UserDTO : c'est un oubli ? (celle classe est comme "débranchée")
    2/- coté technique, j'ai l'impression que Springboot n'utilise pas les annotations javax.xml.bind.* (JAXB) mais plutot celles de com.fasterxml.jackson.* : est ce que je me trompe ? (exemple : @XmlTransient --> @JsonIgnore ) faut il ajouter une dépendance dans le pom.xml pour activer les annotations JAXB ? celles des beans JPA du tuto sont elles utiles (@XmlRootElement @XmlElement) ? on dirait que par défaut Springboot sérialize automatiquement en JSON les entités produites par les services REST via jackson.

    indépendamment de ça j'ai implémenté spring boot 2.0.2.RELEASE (la version courante GA) et voici les adaptations que j'ai effectuées (à tort ou à raison, vous me direz si on doit faire autrement) :
    a)- dans le service User, la méthode findOne(Long) n'est plus disponible alors j'ai remplacé par findById et la signature devient "Optional<User> getUserById(Long id) throws BusinessResourceException;"
    b)- dans le controller correspondant on doit alors gérer l'Optional (voir exemple de code plus bas)
    c)- dans les properties la clé "security.basic.enabled" est invalide, alors j'ai ajouté une classe qui dérive de WebSecurityConfigurerAdapter et surchargé la méthode configure(AuthenticationManagerBuilder auth)


    exemple de code UserController.java (attention a prendre avec precaution car je decouvre java 8 et l'Optional !!) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @PutMapping(value = "/users/{id}")
    	public ResponseEntity<User> updateUser(@PathVariable(value = "id") Long id, @RequestBody User user) {
    
    		Optional<User> userToUpdate = userService.getUserById(id);
    		return userToUpdate
    		.map( x -> {
    			x.setLogin(user.getLogin());
    			x.setPassword(user.getPassword());
    			x.setActive(user.getActive());
    			User userUpdated = userService.saveOrUpdateUser(x);
    			return new ResponseEntity<User>(userUpdated, HttpStatus.OK);})
    		.orElseGet(() -> {
    			logger.debug("L'utilisateur avec l'identifiant " + id + " n'existe pas");
    			return new ResponseEntity<User>(user,HttpStatus.NOT_FOUND);
    		});
    	}
    merci
    bonne journée

  20. #20
    Membre averti
    Avatar de parchemal
    Homme Profil pro
    Ingénieur Développeur Java
    Inscrit en
    août 2009
    Messages
    123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2009
    Messages : 123
    Points : 307
    Points
    307

    Par défaut

    Bonjour,

    1/- coté structure, les services REST ne produisent pas des objets UserDTO : c'est un oubli ? (celle classe est comme "débranchée")
    C'est le développeur qui crée les objets DTOs, ça ne fait pas partie des services REST, et ce n'est même pas obligatoire. Ça te sert juste à manipuler une copie d'objets issues de ta base de données

    2/- ........... celles des beans JPA du tuto sont elles utiles (@XmlRootElement @XmlElement) ? on dirait que par défaut Springboot sérialize automatiquement en JSON ........
    Oui Spring Boot sérialise en JSON par défaut. @XmlRootElement et @XmlElement ne sont pas obligatoires, mais ça te permet de construire tes objets en XML (très facile à utiliser pour les tests), sinon, tu peux aussi utiliser directement JSON

    a)- dans le service User, la méthode findOne(Long) n'est plus disponible
    La méthode est bien disponible et la voici:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    @Override
        public User getUserById(Long id) {
            return userRepository.findOne(id);
        }
    b)- dans le controller correspondant on doit alors gérer l'Optional (voir exemple de code plus bas)
    Oui, si tu as utilisé Optional<User> (Java8), tu dois prendre ça en compte dans le contrôleur. J'avais d'ailleurs essayé ça, et j'ai eu quelques problèmes au niveau des tests. C'est pourquoi j'avais changé. Mais ton choix d'utiliser Optional<User> n'est pas mauvais, il juste aller jusqu'au bout de la logique

    c)- dans les properties la clé "security.basic.enabled" est invalide, alors j'ai ajouté ...
    Non, c'est valide, à moins que ça soit une différence liée à la version de Spring Boot que tu as choisi. Veille bien à ajouter absolument sa dépendance dans le pom.xml comme ci-dessous:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <!-- Spring Security: juste pour chiffrer le mot de passe -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
    N'hésite pas à me faire signe en cas de soucis.
    Pense à faire tous les tests, car c'est un excellent de valide tes développements

    J'espère avoir apporté un peu éclaircissement à tes questions

    Courage !!!!!
    Bertrand Nguimgo
    Nguimgo Bertrand
    Ingénieur Etudes et Développement JAVA/JEE

    - Guide d'implémentation des services REST avec Spring Boot et Spring RestTemplate
    - Je vous propose de lire le guide d'implémentation du design pattern MVP-GWT
    - N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

Discussions similaires

  1. [Web Services] Tutoriel sur le développement des services REST avec Spring 3
    Par regis1512 dans le forum Spring
    Réponses: 0
    Dernier message: 11/02/2015, 12h34
  2. Premier développement de services web avec Spring-WS
    Par Arnaud_03 dans le forum Services Web
    Réponses: 5
    Dernier message: 02/12/2008, 16h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo