Accéder au contenu principal

Articles

Les transactions en JPA avec Springs

Comme bien souvent avec le framework spring, une annotation permet de lui confier une tâche. Dans cet article, nous détaillerons quelques points qu'il faut faire attention afin d'obtenir les résultats escompté. Transaction Les transactions sont disponibles dans la majorité des bases de données. Mais qu'est-ce qu'une transaction. C'est une opération avec un début et une fin. Elle est définie par 4 propriétés qui sont désignés par l'acronyme ACID. Atomicité Tous les opérations qui composent la transaction sont soit réussite soit en échec. C'est tout ou rien. Cohérence La transaction doit emmener le système valide dans un état valide Isolation La transaction doit s'exécuter comme si seul elle était seul à fonctionner. Durabilité Les modifications apportés lors d'une transaction doivent être conservés. Spring permet de respecté ces propriétés avec sa gestion des transactions. Nous utiliserons spring boot avec Hibernate comme implémentation de JPA. Dans l...

Lenovo mini5i et Linux

J'ai récemment fait l'acquisiton d'un Lenovo mini 5i au lieu d'un ordinateur portable qui ont de plus en plus de composant soudé. Un petit intel Core i3-10100, qui est au final autrement plus puissant que le i5-5300U de mon T450S Tous les composants sont accessible: ssd, disque dur, carte wifi, mémoire vive. J'ai mis 32 gig de ram. Le ssd a été remplacé par un WD_BLACK  SN850 compatible pcie 4. Tous les composants de la machines sont bien supportés par linux. Suse tumbleweed y a été installé sans aucune anomalie. La machine possède plusieurs ports USB 3.2. Au niveau graphique, il y a un port display port et hdmi 1.4b. Au démarrage, il y a quelques erreur dans les logs CPI BIOS Error (bug): Failure creating named object [\_SB.PCI0.XHC.RHUB.GPLD], AE_ALREADY_EXISTS (20210331/dswload2-326)  ACPI Error: AE_ALREADY_EXISTS, During name lookup/catalog (20210331/psobject-220) ACPI: Skipping parse of AML opcode: Method (0x0014) ACPI BIOS Error (bug): Failure creating named ...

Architecture hexagonale

Introduction Dans une application conventionnel, il ne sera pas rare d'avoir une couche de contrôleur,  de service et de dao. Pour chacune de nos entités, une classe existera sous chacune de ces couches. Il est possible de se retrouver rapidement avec des centaines de classes. Ce type d'architecture utilise un modèle d'objet anémique, c'est-à-dire qu'il ne contient pas de logique métier. Il n'est pas rare de voir un appel à la couche de persistance directement de la première couche. Les entités, les domains object n'ont pas de règle métier. Elle est alors mise dans les classes de service, utilitaire. Ces classes chargent des entités, modifient leurs états et persistent le tout. Les services commencent à utiliser d'autres services et il n'est pas rare de se retrouver avec des classes de plusieurs milliers de lignes. Pour une petite application, de type CRUD, ça peut être plus rapide à développer, mais imaginer maintenant une application avec 200K, 300...

Comment mapper des objets avec MapStruct

Il n'est pas rare dans une application de devoir copier les valeurs d'un type d'objet à un autre. Par exemple les objets de la couche métier à ceux de la présentation. Une multitude de librairie existe en Java pour effectuer cette opération. Dans cet article nous utiliserons un des plus rapides soit MapStruct. Une comparaison est disponible à cette url . Mappage avec les mêmes noms de champs public class Person{     private String name;     private String lastname;     private int age; } public class PersonDto{     private String name;     private String lastname; } Il suffit de créer une interface @Mapper public interface PersonMapper {     PersonDto personToPersonDTO(Person entity);     Person epersonDTOtoPerson(PersonDto dto); } MapStruct générera une classe d'implémentation. Ne surtout pas hésiter à la regarder pour voir le code généré pour éviter des surprises. Mappag...

Générer un rapport grâce à Thymeleaf et Open HTML to PDF

Une multitude de produit existe pour générer des rapports dans différents formats. Jaspert Report, iText. Certain sont plus bas niveau tel que PDFbox. Le moteur de template Thymeleaf permet de générer des pages web. Ensuite il est possible d'utiliser une librarie tierce tel que Open Html To pdf pour générer un pdf. C'est la manière la plus simple et rapide que j'ai trouvé pour générer un pdf. Spring boot sera utilisé, par défaut lorsqu'il est utilisé avec Thymeleaf, une configuration est généré afin de pouvoir généré des pages web. Une autre configuration doit être créé pour être indépendant de celle-ci. @Component public class PdfGeneratorUtil<T> {     @Autowired     private TemplateEngine templateEngine;     public byte[] process(String templateName, String templateExtension, List<T> listT, String contextVariableName) throws Exception {         Context ctx = new Context(); ...

Chargement d'un fragment Thymeleaf en Ajax

Même si le moteur de template Thymeleaf est exécuté du côté serveur, il est possible de charger un fragment à la suite d'un évènement. En utilisant cette façon de procéder, on peut se rapproche de l'expérience utilisation d'une applicate dite SPA. Chargement dynamique d'un fragment L'application ressemble à ceci. En cliquant sur Obtenir un fragment ajax, un appel sera fait sur le serveur et un fragment sera retourné. Il faut avoir une section dans notre template pour insérer le fragment. Dans notre page, nous avons une section avec l'id main <div id="main" class="container-fluid"> </div>   Le fragment sera inséré à cet endroit après un appel sur le serveur.  var XHR = new XMLHttpRequest();  XHR.open('get', '/ajaxfragment');  XHR.send();  XHR.addEventListener('readystatechange', function() {      if (XHR.readyState === XMLHttpRequest.DONE && XHR.status === 200) {          documen...

Les formulaires avec thymeleaf

Dans un précédent tutoriel, le moteur de thymeleaf a été présenté rapidement. Nous allons ici présenté comment utiliser un formulaire avec ce moteur de template. Nous verrons deux façon d'appréhender les formulaires. La sauvegarde est complètement différentes. Le formulaire est utilisé pour la sauvegarde d'un utilisateur. Le modèle est public class User {     private String firstname;     private String lastname;     private boolean enabled;         private String userTypeId;     ... } public class UserType {     private Long id;     private String type;     ... } Le code pour afficher le formulaire est @GetMapping(value = {"/userform"})     public String getUserForm(Model model) {         List<UserType> userTypes = new ArrayList<>();       ...