IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

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

Spring Boot Java Discussion :

Tutoriel sur le développement full stack d'une application Web avec Angular 7 et Spring Boot 2


Sujet :

Spring Boot Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite

    Homme Profil pro
    Ingénieur R&D en informatique
    Inscrit en
    Août 2011
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur R&D en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2011
    Messages : 313
    Par défaut Tutoriel sur le développement full stack d'une application Web avec Angular 7 et Spring Boot 2
    Bonjour,

    L'article a pour but de présenter la conception, l'architecture et le développement full stack d'une application web en s'appuyant sur les technologies Java, Spring Boot et Angular. Plusieurs concepts sont abordés et expliqués dans l'article par la mise en oeuvre d'un exemple concret d'une application.

    https://gkemayo.developpez.com/tutor...spring-boot-2/

    Qu'en pensez-vous ?

    Retrouvez les meilleurs cours et tutoriels pour apprendre le développement Web avec Spring Boot

  2. #2
    Membre chevronné
    Homme Profil pro
    Ingénieur en génie logiciel
    Inscrit en
    Juin 2012
    Messages
    946
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur en génie logiciel
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Juin 2012
    Messages : 946
    Par défaut
    bravo pour le tutoriel

    en couplant tes entités, tu brises un peu le concept de package by feature architecture
    il aurait été possible de passer par des id, sinon de copier les données et de passer par un événèment pour les mettres à jour, suppression...

  3. #3
    Membre émérite

    Homme Profil pro
    Ingénieur R&D en informatique
    Inscrit en
    Août 2011
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur R&D en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2011
    Messages : 313
    Par défaut
    Citation Envoyé par marc.collin Voir le message
    bravo pour le tutoriel

    en couplant tes entités, tu brises un peu le concept de package by feature architecture
    il aurait été possible de passer par des id, sinon de copier les données et de passer par un événement pour les mettres à jour, suppression...
    Bonjour Marc.collin,

    Tu as parfaitement raison, la contrainte du package by feature vient vraiment des "ressources" qui sont partagées entre domaines. J'étais bien conscient que je n'ai pas fait un aboutissement de cette architecture dans l'article. Le but est dans un premier temps de sensibiliser le lecteur sur cette architecture qui apporte son lot de concepts, d'avantages et d'inconvénients. Si le lecteur s'y intéresse, il ira chercher plus d'infos.

    Les solutions que l'on peut proposer pour adresser ce problème sont multiples, chacune possédant ces avantages et inconvénients. Pour la solution que tu proposes de copier les données et de d'utiliser l'event sourcing pour les mettre à jour, c'est bien, mais ça passe par une duplication de données et la mise en place de l'event sourcing pour mettre à jour chaque domaine. C'est complexe et impossible d'expliquer tout cela dans un seul et même article .

    Je peux même aller plus loin en disant que l'on peut même mettre en place le pattern Capture Data Change couplé à Kafka qui se chargera de mettre à jour la/les tables de chaque domaine. Là encore c'est très complexe et trop de travail rien que pour respecter le principe du package by feature.

    Il vaut mieux s'y investir sur tout ce que nous venons de citer lorsqu'on est vraiment en contexte Microservice ou une vraie architecture domaine driven.

    D'autres son de cloche, disent de sortir exceptionnellement les "ressources" partagées (en veillant à ce que cela ne devienne pas un fourre tout) dans un package "common" afin que les différents domaines se les partagent. Ce n'est pas moins intelligible, après tout c'est une organisation dans un seul et unique projet.

    Cordialement,
    Georges

  4. #4
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    578
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 578
    Par défaut
    Bonjour

    Très bon tutoriel, cependant je rencontre quelques problèmes lors de l'exécution du code source téléchargeable à la fin de l'article.

    Après avoir installé les dépendances avec npm install, j'exécute ng serve --open. Et là je reçois le message d'erreur suivant:

    Proxy config file D:\workspace-spring_tool_suite\library-ui-master\src\proxy.conf.json does not exist.
    Error: Proxy config file D:\workspace-spring_tool_suite\library-ui-master\src\proxy.conf.json does not exist.
    Je ne sais pas si c'est une erreur de votre part, mais il a fallu que je change le chemin menant vers proxy.conf.json dans le fichier angular.json pour régler le problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    "proxyConfig": "proxy.conf.json"
    au lieu de:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    "proxyConfig": "src/proxy.conf.json"
    Ensuite lorsque j'accède à la page book-page, je reçois le message d'erreur suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    An error occurs when retreiving categories data
    Ci-dessous une capture d'écran:

    Nom : error.PNG
Affichages : 14261
Taille : 50,3 Ko

    Voici l'erreur au niveau du log:

    Error occurred while trying to proxy request /library/rest/category/api/allCategories from localhost:4200 to http://localhost:8082 (ECONNREFUSED) (https
    ://nodejs.org/api/errors.html#errors_common_system_errors)
    Merci

  5. #5
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    578
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 578
    Par défaut
    finalement ça marche.

    Je lançais le projet via l'option Spring Boot App, mais j'ai par la suite opté de le lancer via le server tomcat installé, tout en changer le port 8080 en 8082, et ça a marché.

  6. #6
    Membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Février 2016
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Février 2016
    Messages : 7
    Par défaut create-drop inefficace
    Bonjour,

    Le tuto est vraiment bien fait.

    J'ai juste un petit soucis avec la base de données H2. J'ai fait toute la partie back et j'ai voulu tester.
    Au premier démarrage de tomcat, pas de soucis.
    J'ai fais des modifications et depuis impossible de relancer l'application :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Violation d'index unique ou clé primaire: "PUBLIC.PRIMARY_KEY_3 ON PUBLIC.CATEGORY(CODE) VALUES 1"
    Unique index or primary key violation: "PUBLIC.PRIMARY_KEY_3 ON PUBLIC.CATEGORY(CODE) VALUES 1"; SQL statement:
    insert into category values ('INF', 'Informatique') [23505-200]
    Je n'arrive pas à drop les données de la table category :/ j'ai essayé d'ajouté la commande
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    truncate table category;
    dans le fichier sql chargé au début mais cela me retourne une exception ..

    Edit : j'ai augmenté le cache de la log et je vois qu'en fait le soucis provient d'un drop qui ne se fait pas sur mes tables à cause de FK qui ne sont pas supprimées...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Impossible de supprimer "BOOK" car "FK88C0YDLO57PCGP137TNTRGQX1" dépend de lui
    Cannot drop "BOOK" because "FK88C0YDLO57PCGP137TNTRGQX1" depends on it; SQL statement: drop table book if exists [90107-200]

  7. #7
    Membre émérite

    Homme Profil pro
    Ingénieur R&D en informatique
    Inscrit en
    Août 2011
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur R&D en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2011
    Messages : 313
    Par défaut
    Citation Envoyé par DarkChyper Voir le message
    Bonjour,

    Le tuto est vraiment bien fait.

    J'ai juste un petit soucis avec la base de données H2. J'ai fait toute la partie back et j'ai voulu tester.
    Au premier démarrage de tomcat, pas de soucis.
    J'ai fais des modifications et depuis impossible de relancer l'application :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Violation d'index unique ou clé primaire: "PUBLIC.PRIMARY_KEY_3 ON PUBLIC.CATEGORY(CODE) VALUES 1"
    Unique index or primary key violation: "PUBLIC.PRIMARY_KEY_3 ON PUBLIC.CATEGORY(CODE) VALUES 1"; SQL statement:
    insert into category values ('INF', 'Informatique') [23505-200]
    Je n'arrive pas à drop les données de la table category :/ j'ai essayé d'ajouté la commande
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    truncate table category;
    dans le fichier sql chargé au début mais cela me retourne une exception ..

    Edit : j'ai augmenté le cache de la log et je vois qu'en fait le soucis provient d'un drop qui ne se fait pas sur mes tables à cause de FK qui ne sont pas supprimées...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Impossible de supprimer "BOOK" car "FK88C0YDLO57PCGP137TNTRGQX1" dépend de lui
    Cannot drop "BOOK" because "FK88C0YDLO57PCGP137TNTRGQX1" depends on it; SQL statement: drop table book if exists [90107-200]

    Salut DarkChyper,

    Normalement cela ne devrait pas poser de problème si tu arrêtais toute l'application via ton Tomcat en faisant un shutdown en invite de commande dans le dossier bin.
    Puis en redémarrant avec start. Puisque l'appli utilise une base embarquée, tout devrait se réinitialiser au redemarrage.

    Assures toi juste qu'aucun processus lié ne tourne au préalable sur ta machine.

    Cordialement,
    Georges

  8. #8
    Rédacteur
    Avatar de thierryler
    Homme Profil pro
    Inscrit en
    Octobre 2007
    Messages
    4 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 078
    Par défaut
    Bravo et merci pour cet excellent article
    Thierry Leriche-Dessirier
    Consultant Java JEE Web Agile freelance
    Rédacteur pour Developpez
    Professeur de Génie Logiciel à l'ESIEA

    Site : http://www.icauda.com / Linked'in : http://www.linkedin.com/in/thierryler / Twitter : @ThierryLeriche

  9. #9
    Membre émérite

    Homme Profil pro
    Ingénieur R&D en informatique
    Inscrit en
    Août 2011
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur R&D en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2011
    Messages : 313
    Par défaut
    Citation Envoyé par momjunior Voir le message
    finalement ça marche.

    Je lançais le projet via l'option Spring Boot App, mais j'ai par la suite opté de le lancer via le server tomcat installé, tout en changer le port 8080 en 8082, et ça a marché.

  10. #10
    Membre très actif
    Avatar de parchemal
    Homme Profil pro
    Ingénieur Développeur Java
    Inscrit en
    Août 2009
    Messages
    144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

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

    Informations forums :
    Inscription : Août 2009
    Messages : 144
    Par défaut
    Bonjour et Bravo pour ce tutoriel,

    Voici quelques remarques:
    • L'architecture que vous présentez me semble bonne, mais adaptée pour des applications ayant très peu de classes ou de fonctionnalités , qu'en dites-vous ?
    • Par contre faites attention à vos contrôleurs. Car il y a du code métier dans vos contrôleurs puisque vous n'exploitez pas bien les réponses HttpStatus et ResponseEntity


    Voici un exemple de votre contrôleur avec du traitement métier


    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
     
        @PostMapping("/addCustomer")
        public ResponseEntity<CustomerDTO> createNewCustomer(@RequestBody CustomerDTO customerDTORequest) {
            //, UriComponentsBuilder uriComponentBuilder
            Customer existingCustomer = customerService.findCustomerByEmail(customerDTORequest.getEmail());//pas besoin
            if (existingCustomer != null) { //pas besoin
                return new ResponseEntity<CustomerDTO>(HttpStatus.CONFLICT); // pas besoin, ce traitement doit être fait par le service qui gère la sauvegarde, il faut renvoyer directement l'exception depuis le service
            }
            Customer customerRequest = mapCustomerDTOToCustomer(customerDTORequest);
            customerRequest.setCreationDate(LocalDate.now());
            Customer customerResponse = customerService.saveCustomer(customerRequest);
            if (customerResponse != null) {//idem, pas besoin
                CustomerDTO customerDTO = mapCustomerToCustomerDTO(customerResponse);
                return new ResponseEntity<CustomerDTO>(customerDTO, HttpStatus.CREATED);
            }
            return new ResponseEntity<CustomerDTO>(HttpStatus.NOT_MODIFIED);
        }
    Voici un exemple de solution pour le service que je propose (Classe de gestion des exceptions à créer CustomerResourceException):

    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
     
    public Customer saveOrUpdateCustomer(Customer customer) throws CustomerResourceException{
    	try{
    		return customerRepository.save(customer);
    	} catch(DataIntegrityViolationException ex){
    		logger.error("customer non existant", ex);
    		throw new CustomerResourceException("DuplicateValueError", "Un customer existe déjà avec le compte : "+customer.getLogin(), HttpStatus.CONFLICT);
    	} catch (CustomerResourceException e) {
    		logger.error("Utilisateur non existant", e);
    		throw new CustomerResourceException("CustomerNotFound", "Aucun utilisateur avec l'identifiant: "+customer.getId(), HttpStatus.NOT_FOUND);
    	} catch(Exception ex){
    		logger.error("Erreur technique de création ou de mise à jour de l'utilisateur", ex);
    		throw new CustomerResourceException("SaveOrUpdateUserError", "Erreur technique de création ou de mise à jour du customer: "+customer.getLogin(), HttpStatus.INTERNAL_SERVER_ERROR);
    	}
    }
    Et voici ce que devient le contrôleur:

    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
     
        @PostMapping("/addCustomer")
        public ResponseEntity<CustomerDTO> createNewCustomer(@RequestBody CustomerDTO customerDTORequest) {
            //, UriComponentsBuilder uriComponentBuilder
           try{
                Customer customerRequest = mapCustomerDTOToCustomer(customerDTORequest);
                customerRequest.setCreationDate(LocalDate.now());
                Customer customerResponse = customerService.saveCustomer(customerRequest);
                CustomerDTO customerDTO = mapCustomerToCustomerDTO(customerResponse);
                return new ResponseEntity<CustomerDTO>(customerDTO, HttpStatus.CREATED);
           } catch (CustomerResourceException ex) {
             //Traitez vos erreurs ici par un log si nécessaire
            return new ResponseEntity<CustomerDTO>(ex.getHttpStatus()); //Ici tu gères à la fois plusieurs types d'erreurs comme HttpStatus.NOT_MODIFIED, HttpStatus.CONFLICT etc , au lieu de forcer la réponse à HttpStatus.NOT_MODIFIED uniquement
           }  catch (Exception  ex) {
             //Traiter les erreurs techniques ici par un log
           return new ResponseEntity<CustomerDTO>(HttpStatus.INTERNAL_SERVER_ERROR); // un cas typique d'erreur ici serait une erreur liée au mapping, ou autres erreurs non gérées par le service
           }
     
        }
    Voici un exemple du constructeur de ton Exception

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        public CustomerResourceException(String errorCode, String message, HttpStatus httpStatus) {
            super(message);
            this.errorCode = errorCode;
            this.httpStatus = httpStatus;
        }
    Note: Penser aux getter/setter dans l'exception

    Au final, pas besoin d'une requête supplémentaire customerService.findCustomerByEmail(xxx) dans le createNewCustomer car, en cas conflit, le service sait le code d'erreur à retourner

    Bon courage !!!!
    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 émérite

    Homme Profil pro
    Ingénieur R&D en informatique
    Inscrit en
    Août 2011
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur R&D en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2011
    Messages : 313
    Par défaut
    Bonjour parchemal,

    Je te remercie pour tes remarques.

    Citation Envoyé par parchemal Voir le message
    L'architecture que vous présentez me semble bonne, mais adaptée pour des applications ayant très peu de classes ou de fonctionnalités , qu'en dites-vous ?
    Le package by feature est une architecture contraignante qui a ses avantages et ses inconvénients comme j'ai tenté d'en citer quelques uns dans l'article. Je ne peux pas trancher ta question, car elle est philosophique à mon sens. D'aucuns n'y verront aucun souci à tes réserves, d'autres diront autant mieux aller vers les microservices en cas d'un grand nombre de fonctionnalités.

    Citation Envoyé par parchemal Voir le message

    Par contre faites attention à vos contrôleurs. Car il y a du code métier dans vos contrôleurs puisque vous n'exploitez pas bien les réponses HttpStatus et ResponseEntity

    Voici un exemple de votre contrôleur avec du traitement métier


    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
     
        @PostMapping("/addCustomer")
        public ResponseEntity<CustomerDTO> createNewCustomer(@RequestBody CustomerDTO customerDTORequest) {
            //, UriComponentsBuilder uriComponentBuilder
            Customer existingCustomer = customerService.findCustomerByEmail(customerDTORequest.getEmail());//pas besoin
            if (existingCustomer != null) { //pas besoin
                return new ResponseEntity<CustomerDTO>(HttpStatus.CONFLICT); // pas besoin, ce traitement doit être fait par le service qui gère la sauvegarde, il faut renvoyer directement l'exception depuis le service
            }
            Customer customerRequest = mapCustomerDTOToCustomer(customerDTORequest);
            customerRequest.setCreationDate(LocalDate.now());
            Customer customerResponse = customerService.saveCustomer(customerRequest);
            if (customerResponse != null) {//idem, pas besoin
                CustomerDTO customerDTO = mapCustomerToCustomerDTO(customerResponse);
                return new ResponseEntity<CustomerDTO>(customerDTO, HttpStatus.CREATED);
            }
            return new ResponseEntity<CustomerDTO>(HttpStatus.NOT_MODIFIED);
        }
    Voici un exemple de solution pour le service que je propose (Classe de gestion des exceptions à créer CustomerResourceException):

    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
     
    public Customer saveOrUpdateCustomer(Customer customer) throws CustomerResourceException{
    	try{
    		return customerRepository.save(customer);
    	} catch(DataIntegrityViolationException ex){
    		logger.error("customer non existant", ex);
    		throw new CustomerResourceException("DuplicateValueError", "Un customer existe déjà avec le compte : "+customer.getLogin(), HttpStatus.CONFLICT);
    	} catch (CustomerResourceException e) {
    		logger.error("Utilisateur non existant", e);
    		throw new CustomerResourceException("CustomerNotFound", "Aucun utilisateur avec l'identifiant: "+customer.getId(), HttpStatus.NOT_FOUND);
    	} catch(Exception ex){
    		logger.error("Erreur technique de création ou de mise à jour de l'utilisateur", ex);
    		throw new CustomerResourceException("SaveOrUpdateUserError", "Erreur technique de création ou de mise à jour du customer: "+customer.getLogin(), HttpStatus.INTERNAL_SERVER_ERROR);
    	}
    }
    Et voici ce que devient le contrôleur:

    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
     
        @PostMapping("/addCustomer")
        public ResponseEntity<CustomerDTO> createNewCustomer(@RequestBody CustomerDTO customerDTORequest) {
            //, UriComponentsBuilder uriComponentBuilder
           try{
                Customer customerRequest = mapCustomerDTOToCustomer(customerDTORequest);
                customerRequest.setCreationDate(LocalDate.now());
                Customer customerResponse = customerService.saveCustomer(customerRequest);
                CustomerDTO customerDTO = mapCustomerToCustomerDTO(customerResponse);
                return new ResponseEntity<CustomerDTO>(customerDTO, HttpStatus.CREATED);
           } catch (CustomerResourceException ex) {
             //Traitez vos erreurs ici par un log si nécessaire
            return new ResponseEntity<CustomerDTO>(ex.getHttpStatus()); //Ici tu gères à la fois plusieurs types d'erreurs comme HttpStatus.NOT_MODIFIED, HttpStatus.CONFLICT etc , au lieu de forcer la réponse à HttpStatus.NOT_MODIFIED uniquement
           }  catch (Exception  ex) {
             //Traiter les erreurs techniques ici par un log
           return new ResponseEntity<CustomerDTO>(HttpStatus.INTERNAL_SERVER_ERROR); // un cas typique d'erreur ici serait une erreur liée au mapping, ou autres erreurs non gérées par le service
           }
     
        }
    Voici un exemple du constructeur de ton Exception

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        public CustomerResourceException(String errorCode, String message, HttpStatus httpStatus) {
            super(message);
            this.errorCode = errorCode;
            this.httpStatus = httpStatus;
        }
    Note: Penser aux getter/setter dans l'exception

    Au final, pas besoin d'une requête supplémentaire customerService.findCustomerByEmail(xxx) dans le createNewCustomer car, en cas conflit, le service sait le code d'erreur à retourner

    Bon courage !!!!
    Pour ton deuxième point, tu as tout à fait raison, mais je dirai tout d'abord que tout code est perfectible. On pourrait même convoquer d'autres notions de clean code pour améliorer d'avantage. Cela dit, cet article ne porte pas sur le clean code ni sur la gestion optimale des exceptions. L'article se focalise sur l'initiation du lecteur à diverses notions et leurs mises en œuvre et non sur une démonstration du code parfait . La revue de code et son optimisation est très important dans un projet professionnel, mais pas dans un cours à mon avis, sauf si cela fait partir des objectifs explicite du cours.

    Qu'à cela ne tienne, je te remercie encore une fois pour tes remarques pertinentes. Ceux qui réussiront à mettre en place les notions distillées dans mon article et qui veulent aller plus loin doivent s'inspirer de tes remarques.

    Georges

  12. #12
    Membre éprouvé
    Homme Profil pro
    Reconversion
    Inscrit en
    Novembre 2018
    Messages
    503
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Reconversion
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2018
    Messages : 503
    Par défaut Impossible de démarrer le back end avec Tomcat
    Bonjour, et tout d'abord merci beaucoup pour ce tutoriel très bien réalisé au cours duquel j'apprends beaucoup.

    Ayant un profil débutant junior en java/angular, je me suis attelé à ce tutoriel il y a quelques jours. Je rencontre un petit problème que je vais essayer de décrire au mieux :
    En effet, arrivé à la finalisation du back end et au test des web services de l'API Rest, je n'arrive pas à lancer le serveur Tomcat (j'utilise la v.9), j'ai configuré le port en 8082.

    Le problème vient (je suppose) du fait que je n'arrive pas à établir la connexion avec la BDD car je relève un message d'erreur qui jette une DbException avec la mention :
    "Erreur du fichier journal C:/Windows/System32/src/main/resources/database/library-db.trace.db Erreur lors de la création du fichier ""C:/Windows/System32/src""

    D'autre part j'ai une autre exception qui découle de la première du type :
    "org.h2.jdbc.JdbcSQLNonTransientException: Erreur du fichier journal: "C:/Windows/System32/src/main/resources/database/library-db.trace.db"

    Je suppose que j'ai un soucis au niveau de la gestion des ressources de la Database :
    J'ai téléchargé le fichier "library-db.mv.db" dans le dossier database comme indiqué dans l'arborescence du projet, en revanche je n'utilise pas le fichier library-trace.trace.db.
    Je ne sais pas comment me vérifier. Au départ, j'avais tapé tout le code moi-même, et j'ai créé un second projet où j'ai copié-collé les sources sur github et le résultat et le même.

    Vous remerciant

  13. #13
    Membre émérite

    Homme Profil pro
    Ingénieur R&D en informatique
    Inscrit en
    Août 2011
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur R&D en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2011
    Messages : 313
    Par défaut
    Citation Envoyé par olivier252 Voir le message
    Bonjour, et tout d'abord merci beaucoup pour ce tutoriel très bien réalisé au cours duquel j'apprends beaucoup.

    Ayant un profil débutant junior en java/angular, je me suis attelé à ce tutoriel il y a quelques jours. Je rencontre un petit problème que je vais essayer de décrire au mieux :
    En effet, arrivé à la finalisation du back end et au test des web services de l'API Rest, je n'arrive pas à lancer le serveur Tomcat (j'utilise la v.9), j'ai configuré le port en 8082.

    Le problème vient (je suppose) du fait que je n'arrive pas à établir la connexion avec la BDD car je relève un message d'erreur qui jette une DbException avec la mention :
    "Erreur du fichier journal C:/Windows/System32/src/main/resources/database/library-db.trace.db Erreur lors de la création du fichier ""C:/Windows/System32/src""

    D'autre part j'ai une autre exception qui découle de la première du type :
    "org.h2.jdbc.JdbcSQLNonTransientException: Erreur du fichier journal: "C:/Windows/System32/src/main/resources/database/library-db.trace.db"

    Je suppose que j'ai un soucis au niveau de la gestion des ressources de la Database :
    J'ai téléchargé le fichier "library-db.mv.db" dans le dossier database comme indiqué dans l'arborescence du projet, en revanche je n'utilise pas le fichier library-trace.trace.db.
    Je ne sais pas comment me vérifier. Au départ, j'avais tapé tout le code moi-même, et j'ai créé un second projet où j'ai copié-collé les sources sur github et le résultat et le même.

    Vous remerciant

    Bonjour Olivier252,

    Je ne crois pas avoir tout saisi dans vos explications, mais au regard de la stacktrace, le fait d'avoir le chemin C:/Windows/System32/src/main/resources/database/library-db.trace.db montre qu'il y a un problème de configuration. Tu as du faire une manipulation qui force l'application à rechercher ta base de données dans C:/Windows/System32/, ce qui n'est pas du tout cohérent.

    Alors, ce qu'il faut savoir de façon générale, c'est que la base de données utilisée dans cette application exemple est une base de données embarquée. C'est-à-dire, une base régie par une dépendance (en l'occurrence H2) qui fait partir intégrante de ton application. Deux façons de la configurée :
    - soit on la configure pour qu'elle stocke les données en mémoire, c'est-à-dire dans la RAM de ta machine pendant que l'application est en cours d'exécution,
    - soit on la configure pour qu'elle stocke les données dans un fichier de façon plus durable, au délà de l'arrêt de l'appplication. Mais le point important dans ce cas est de savoir que pour une question de portabilité de ton application, il est nécessaire que ce fichier fasse également partir intégrante celle-ci. (Ce cas est celui choisi dans mon article).


    C'est pourquoi tu verras que dans le fichier de configuration application.properties, on a : spring.datasource.url = jdbc:h2:file:./src/main/resources/database/library-db
    Le "." après le ":" est très important. C'est le symbole du répertoire courant qui signale qu'il faut générer la base de données en partant de l'emplacement de l'application.properties jusqu'au répertoire ..../database. Quand tu as fini de faire ceci, c'est la dépendance H2 qui génère ta base de données (library-db.trace.db) pour toi. Cette génération affectera dans les propriétés du fichier résultat son chemin quasi absolu (notamment : /library/src/main/resources/database/library-db.trace.db et non pas C:/Windows/System32/src/main/resources/database/library-db.trace.db).

    Je pense pour ma part qu'il ne faut pas que tu fasses de copier/coller du fichier library-db.trace.db et le déposer n'importe où sur ta machine, comme j'ai cru lire, et espérer que cela fonctionne. Si tu as bien configuré la propriété spring.datasource.url, fait un mvn clean package de ton projet et suit minutieusement l'étape sur le déploiement, ça devrait aller.

    En espérant t'avoir éclairé.

    Cordialement,
    Georges

  14. #14
    Membre éprouvé
    Homme Profil pro
    Reconversion
    Inscrit en
    Novembre 2018
    Messages
    503
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Reconversion
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2018
    Messages : 503
    Par défaut
    Bonjour et merci pour ton aide,

    Le problème vient du fait que je ne suis pas encore à l'aise avec Tomcat. Je pense avoir compris en partie mon erreur car je lançais un serveur Tomcat que j'avais spécialement configuré pour l'appli "library" en allant
    dans Windows->preferences->server...
    J'avais omis le fait que spring boot embarque directement un serveur comme c'est précisé dans le pom.xml et dans tes explications d'ailleurs...
    Du coup en lançant l'appli en "run as->spring boot app" directement je n'ai plus de stack d'erreur en sortie console. En revanche, l'url http://localhost:8082/library/swagger-ui.html#/ (port 8080 pour moi) conduit à une page blanche avec une erreur 404
    Nom : Annotation 2020-05-15 112156.jpg
Affichages : 352
Taille : 19,8 Ko

    Je précise que swagger est bien configuré dans mon pom.xml comme ceci :

    Nom : Annotation 2020-05-15 113355.jpg
Affichages : 350
Taille : 17,5 Ko

    D'autre part le fichier "library-db.trace.db" est bien généré mais il indique qu'il ne peut pas supprimer les tables Book, Customer, et Category à cause des clés étrangères qui unissent ces dernières entre elles (comme DarkShyper qui avait remonté cela).
    Quoi qu'il en soit, merci encore pour ta réponse et ce tuto, j'arrive à faire tourner la partie AngularJs et j'ai compris la liaison d'un backend et d'un frontend dans les grandes lignes pour l'instant. Je vais me remettre au travail sur le backend, je devrais trouver à force de persévérance

  15. #15
    Nouveau candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2020
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2020
    Messages : 2
    Par défaut Probleme Frontend
    Merci pour le travail complet.
    Je te felicite pour le travail qui est bien détaillé et bien expliaué srt pour un débutant.
    Mais, je trouve de mal à le compiler.
    Le Backend marche tres bien, j'ai même réusii à le refaire en suivant tes indications.
    Par contre le front end me signale des erreurs de compilations.
    même en compilant avec: ng serve sur Angular ca marche pas

  16. #16
    Nouveau candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2020
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2020
    Messages : 2
    Par défaut
    Citation Envoyé par Aminou81 Voir le message
    Merci pour le travail complet.
    Je te felicite pour le travail qui est bien détaillé et bien expliaué srt pour un débutant.
    Mais, je trouve de mal à le compiler.
    Le Backend marche tres bien, j'ai même réusii à le refaire en suivant tes indications.
    Par contre le front end me signale des erreurs de compilations.
    même en compilant avec: ng serve sur Angular ca marche pas
    Enfin ca marche. Il fallait que je change dans: proxy.conf.json

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    {
        "/library/*": {
          "target": "http://localhost:8082",
          "secure": false,
          "changeOrigin": "true",
          "logLevel": "debug",
          "pathRewrite": {"^/library" : "http://localhost:80821"}
        }
    }
    Ainsi ca marche et je ne sais par pouquoi;
    Merci une autre fois.

  17. #17
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2012
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2012
    Messages : 92
    Par défaut Error mapping OneToMany or ManyToOne unmapped class
    Bonjour, je reçois cette erreur au niveau de mon mapping


    Error creating bean with name 'ICustomerDao' defined in com.biblio.fr.biblio.repository.ICustomerDao defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot resolve reference to bean 'jpaMappingContext' while setting bean property 'mappingContext'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Use of @OneToMany or @ManyToMany targeting an unmapped class: com.biblio.fr.biblio.entite.Book.loans[com.biblio.fr.biblio.entite.Loan]


    Et pourtant j'ai bien annoté mes classes d'entité.
    Quelq'un a une idée

  18. #18
    Membre émérite

    Homme Profil pro
    Ingénieur R&D en informatique
    Inscrit en
    Août 2011
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur R&D en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2011
    Messages : 313
    Par défaut
    Bonjour lnquaidorsay,

    Je vois que tu reprends la tuto en essayant de construire l'application avec tes packages à toi. C'est très bien, c'est comme cela que l'on apprivoise le truc.
    Cependant pour ton problème, juste deverser la stacktrace ou un bout de stack trace ne suffit pas. Il aurait fallu un petit context aussi.

    Mais vraisemblablement quand je regarde la dernière ligne de ta stack, je mise sur un mauvais mapping au niveau de ton entité Loan (qui est une classe-association !!!). Peut-être as-tu utiliser une autre approche ?

    Cordialement,
    Georges

Discussions similaires

  1. Réponses: 22
    Dernier message: 20/08/2023, 14h41
  2. Réponses: 2
    Dernier message: 05/07/2019, 11h54

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