Protégé : Oh my git

Cette publication est protégée par un mot de passe. Pour la voir, veuillez saisir votre mot de passe ci-dessous :

Publié dans Développement | Saisissez votre mot de passe pour accéder aux commentaires.

WordPress nouveau bloc version simple

La constitution d’un nouveau bloc permet de rapidement produire un contenu répétable pour inclure par exemple une signature automatiquement disponible ou même un short code.

Dans le dossier wp-content\plugins\, en premier lieu, il faut créer un dossier, par exemple block-twitter avec la liste des fichiers suivants :

  • block.asset.php
  • block.js
  • block.json
  • index.php

Le premier fichier block.asset.php est standard avec ce code :

<?php return
    array( 'dependencies' =>
        array(
            'wp-blocks',
            'wp-element',
            'wp-polyfill'
        ),
        'version' => '0.1'
    );

Le second fichier block.js contient le JavaScript pour présenter le contenu du bloc côté front et côté backoffice (côté éditeur). On note dans cette première version que le bloc ne fait que présenter un message côté backoffice légèrement différent de la version frontoffice :

( function ( blocks, element ) {
    var el = element.createElement;

    blocks.registerBlockType( 'block-twitter/basic', {
        edit: function () {
            return el( 'p', {}, 'Signature du Master CTN' );
        },
        save: function () {
            return el( 'p', {}, 'Suivez le Master CTN sur Twitter http://twitter.com/MasterCTN' );
        },
    } );
} )( window.wp.blocks, window.wp.element );

Par la suite, nous mettrons un short code pour déclencher l’appel à un programme :

( function ( blocks, element ) {
    var el = element.createElement;

    blocks.registerBlockType( 'block-twitter/basic', {
        edit: function () {
            return el( 'p', {}, '[twitter_short_code_plugin]' );
        },
        save: function () {
            return el( 'p', {}, '[twitter_short_code_plugin]' );
        },
    } );
} )( window.wp.blocks, window.wp.element );

Le troisième fichier block.json contient la description des informations du bloc notamment son titre, pour le chercher dans la liste des blocs noter la valeur de « name » qui a été utilisée dans le fichier block.js :

{
    "apiVersion": 2,
    "title": "Block Twitter",
    "name": "block-twitter/basic",
    "category": "layout",
    "icon": "universal-access-alt",
    "editorScript": "file:./block.js"
}

Le quatrième fichier est index.php qui permet de fabriquer un plugin dont l’activation dans la liste des plugins de WordPress permettra de lier notre nouveau bloc avec l’éditeur de WordPress :

<?php
/**
 * Plugin Name: Block Twitter
 */

function block_twitter_register_block() {
    register_block_type( __DIR__ );
}
add_action( 'init', 'block_twitter_register_block' );

Pour faire la gestion du short code, ce fichier contiendra ensuite la gestion du code appelé par ce short code, ici juste un simple message :

<?php
/**
 * Plugin Name: Block Twitter
 */


function twitter_short_code_plugin(){
    return "<p>Le compte Twitter</p>";
}

add_shortcode('twitter_short_code_plugin', 'twitter_short_code_plugin');


function block_twitter_register_block() {
    register_block_type( __DIR__ );
}
add_action( 'init', 'block_twitter_register_block' );

Après avoir activé le plugin dans le backoffice de WordPress :

Plugin avant activation pour ajouter le nouveau bloc

Nous pouvons disposer de ce bloc dans la liste des blocs disponibles pour l’utiliser :

Bloc Twitter disponible pour ajouter du contenu

Finalement, avec la solution de gestion du short code on obtient ce rendu dans l’éditeur :

Ajout du short code dans la liste des blocs de la page d’exemple

Et le rendu côté front office remplace le short code par le message prévu entouré en vers juste pour rendre la zone plus visible :

Rendu du short code sur la page d’exemple côté frontoffice

Maintenant, il faut essayer d’ajouter la fonctionnalité de rendu dans l’éditeur du backoffice de WordPress plutôt que d’avoir le short code.

En premier lieu, modifions le fichier block.js qui doit faire un appel au serveur pour afficher le résultat d’un appel « ServerSide » et non plus le message (l’ancien code est en commentaire avec // ):

        edit: function () {
            // return el( 'p', {}, '[twitter_short_code_plugin]' );
            return wp.element.createElement(
                wp.serverSideRender,
                {
                    block: 'block-twitter/editeur'
                }
            );


        },

Dans le fichier index.php il faut que la fonction block_twitter_register_block contiennent l’action à faire suite à cet appel « ServerSide » :

function block_twitter_register_block() {
    register_block_type( __DIR__ );
    register_block_type(
        'block-twitter/editeur',
        [
            'render_callback' => 'block_twitter_render_callback',
        ]
    );
}

On enregistre un appel à la fonction block_twitter_render_callback quand une URL de cette forme sera émise pour afficher le bloc dans l’éditeur http://<serveur web wordpress>/wp-json/wp/v2/block-renderer/block-twitter/editeur?context=edit&post_id=2&_locale=user .

La fonction block_twitter_render_callback est à ajouter dans le fichier index.php pour permettre quand un bloc est affiché d’avoir le rendu au lieu du shortcode :

function block_twitter_render_callback( $atts ) {
 
    return "<p>Compte TWITTER visible Editor</p>";
}
Rendu du bloc dans l’éditeur dans le back office de WordPress

On peut voir qu’au lieu du short code, le HTML prévu dans la fonction block_twitter_render_callback est affiché. Le passage en HTML affiche le short code pour bien rappeler le fonctionnement par défaut de bloc.

Publié dans CTN | Laisser un commentaire

Protégé : Accès serveur calcul CERIS

Cette publication est protégée par un mot de passe. Pour la voir, veuillez saisir votre mot de passe ci-dessous :

Publié dans Développement | Saisissez votre mot de passe pour accéder aux commentaires.

Ajout de Javadoc dans un programme Java

La constitution de la documentation dans un projet Java peut être simplement réalisé directement dans le code source en utilisant un formatage spécifique dans un commentaire.

Le système Javadoc existe depuis la création de Java (https://en.wikipedia.org/wiki/Javadoc) et invite le développeur à produire directement dans son programme la documentation.

En premier lieu, on peut documenter le package si un fichier package-info.java est disponible. Je vous renvoie vers cette documentation qui explique l’utilité de ce fichier: https://www.baeldung.com/java-package-info. Dans le cas d’un petit projet informatique, voici un commentaire explique l’utilisation d’un package:

/**
 * main est le package principal du projet de test d'intégration de Jenkins
 */
package main;

Pour faire la suite, nous allons documenter une classe Main dans le fichier main.java :

/**
 * Classe de test pour l'intégration de Jenkins
 * @author Pierre Jean
 * @version 1.0
 */
public class Main {

Il faut être humble dans la constitution de la documentation. À mon avis, il vaut mieux produire la documentation progressivement en mettant les premiers éléments puis progressivement compléter cette documentation par ajout de détails.

L’étape suivante est l’ajout de la documentation d’une méthode basique.

	/**
	 * Méthode pour afficher le double de ce nombre 
	 * <p>
	 * Cette méthode sert pour tester l'intégration l'affichage d'un nombre. 
	 * Ce nombre est calculé en appelant une méthode d'une classe Calcul
	 * qui retourne le double du nombre.
	 * <p>
	 * Cette méthode permet de réaliser un test unitaire avec Jenkins.
	 *
	 * @param  nombre paramètre du nombre pour réaliser le doublement
	 * @return retourne le nombre affiché 
	 */
	public int afficheDeuxFois(int nombre) {
		System.out.println(Calcul.doublement(nombre));
		return Calcul.doublement(nombre);
	}

J’ai ajouté beaucoup d’explication sur une méthode très basique pour détailler la forme de cette documentation avec un seul paramètre et une valeur de retour.

Nous pouvons maintenant imaginer la génération de la documentation sous la forme de pages HTML via le Menu Project > Generate Javadoc …

Menu Generate Javadoc

Puis dans l’interface suivante, on indique sur quel projet (ou quels projets) on souhaite générer la Javadoc et le dossier de génération de cette documentation.

Projet et dossier de la génération de la documentation

La génération de la documentation va fabriquer différents fichiers HTML dans le dossier doc visible dans Eclipse. On doit donc indiquer si on souhaite réécrire dans le dossier en remplaçant l’ancien contenu.

Mises à jour par remplacement des dossiers

La fabrication du contenu est visible dans Eclipse dans le dossier doc indiqué dans les étapes précédentes. Il suffit ensuite d’ouvrir le fichier index.html via le menu « Open With » > « Web Browser » pour afficher la documentation finale.

Le rendu final de la documentation est alors affiché dans une forme standardisé réalisant les liens entre les différentes pages de la documentation.

Page finale de la documentation

La création de la documentation est simplifiée et standardisée facilement. Chaque langage de programmation dispose de sa propre version de Javadoc.

Publié dans Développement, IMT Mines Alès | Laisser un commentaire

Plugin WordPress simple pour Google Calendar

Suite à plusieurs problèmes avec un plugin de Google Calendar et à la suite de la création d’un plugin très simple pour Twitter. Je me suis posé la question de réaliser le même plugin pour accéder à un calendrier publique des conférences et séminaires EuroMov DHM dont l’URL est publique : https://calendar.google.com/calendar/embed?src=at9mn12tnpc5p25u6k8l9ksd44%40group.calendar.google.com&ctz=Europe%2FParis.

La première chose à obtenir est un code appelé API_KEY via la Console Google. Pour cela je vous renvoie vers ces 2 tutoriels qui m’ont bien aidée à fabriquer cette clef.

Cette clef de la forme « a4db08b757294ba98c08f2df493465a1 » est à conserver et à ne pas diffuser, car elle a des droits sur vos calendriers et vos évènements. Dans les exemples, j’utiliserai la clef ci-dessus qui n’est pas valide pour indiquer que vous devez la remplacer par votre propre clef.

Une fois la clef obtenue, il faut disposer de l’ID du calendrier. Donc soit on le retrouve dans l’URL de partage, soit dans le menu « Paramètres et partage » du calendrier sur le site https://calendar.google.com/.

ID de l’agenda « séminaire » menu « Paramètres et partage »

Ou dans l’URL dans l’attribut src le %40 correspondant au symbole @:

https://calendar.google.com/calendar/embed?src=at9mn12tnpc5p25u6k8l9ksd44%40group.calendar.google.com&ctz=Europe%2FParis

Création du plugin dans WordPress

On peut créer simplement un dossier calendar_short_code dans le dossier wp-content/plugins de notre WordPress pour commencer avec un fichier calendar_short_code.php.

Voici le premier jet du programme minimaliste qui permet d’afficher le titre d’un évènement du Google Agenda :

<?php
/**
 * Plugin Name: Calendar Pierre JEAN
 * Plugin URI: https://pierrejean.wp.imt.fr
 * Description: Google calendar
 * Version: 0.1
 * Text Domain: calendar_short_code
 * Author: Pierre JEAN
 * Author URI: https://pierrejean.wp.imt.fr
 */


 function calendar_short_code($arguments){    
    $API_KEY = "a4db08b757294ba98c08f2df493465a1"; 
    $CALENDRIER = "at9mn12tnpc5p25u6k8l9ksd44@group.calendar.google.com";
    $evenements = json_decode(file_get_contents("https://www.googleapis.com/calendar/v3/calendars/{$CALENDRIER}/events?key={$API_KEY}"));
      
    $items = $evenements->items;


    $content = <<<DOC
<div id="calendar_short_code"> 
   <ul>    
DOC;

    foreach( $items  as $key => $item ):
        $content .= <<<DOC
        <li> $item->summary
        </li>            
DOC;
        
    endforeach;


    $content .= <<<DOC
  </ul>
</div> <!-- /calendar_short_code -->
DOC;

    return $content;
}


add_shortcode('calendar_short_code', 'calendar_short_code');
?>

Pour utiliser ce programme, il faut en premier lieu indiquer une clef API_KEY valide obtenue précédemment, activer le plugin dans le backoffice de WordPress, créer une page avec le shortcode [calendar_short_code] et consulter cette page pour vérifier que tout fonctionne.

Affichage du résultat du Google Agenda dans une page WordPress

Pour minimiser le nombre d’appels à Google Calendar à chaque affichage de la page, on peut faire évoluer le code pour remplacer cette ligne :

    $evenements = json_decode(file_get_contents("https://www.googleapis.com/calendar/v3/calendars/{$CALENDRIER}/events?key={$API_KEY}"));

Par un appel aux fonctions get_transient et set_transient qui conservent les informations pendant un lap de temps (300 secondes) :

    $evenements = get_transient( 'calendar_short_code' );
    if( ( false === $evenements ) || ( "" == $evenements ) ) {
    $evenements = json_decode(file_get_contents("https://www.googleapis.com/calendar/v3/calendars/{$CALENDRIER}/events?key={$API_KEY}"));
        set_transient( 'calendar_short_code', $evenements, 300 );
    }

En effet, Google limite le nombre d’utilisations de l’API_KEY pour facturer en cas de sollicitations importantes. Cette solution permet de conserver les informations en local, ce qui est pratique pour un agenda dont les évènements ne changent pas trop souvent.

On peut consulter l’ensemble des informations de l’API Google Calendar sur le site de l’entreprise : https://developers.google.com/calendar/api/guides/overview.

Publié dans CTN, Développement | Laisser un commentaire

Utilisation de Jenkins avec un simple projet Java en local

L’objectif est de tester l’outil d’intégration Jenkins de manière très simple. Du coup, j’ai choisi de ne pas utiliser d’outils de gestion de code sources de type git, svn ou autre, mais juste de lancer un simple test en automatique.

Une autre contrainte a été d’utiliser Jenkins dans un conteneur Docker qui est démarré simplement via cette commande :

docker run --name=jenkins -p 8080:8080 -p 50000:50000 --restart=on-failure jenkins/jenkins:lts-jdk11

Le conteneur Jenkins est accessible via le navigateur sur l’URL http://127.0.0.1:8080/ avec les plugins recommandés.

Maintenant, on va fabriquer le code java basique qui ne fait que tester une fonction qui double un nombre passé en paramètre, voici le code :

public class Calcul {
	
	public static int doublement(int nombre) {
		return nombre * 2;
	}

}

Et le test avec Junit 5

class CalculTest {

	@Test
	void testDoublement() {		
		assertEquals(Calcul.doublement(0) , 0);
		assertEquals(Calcul.doublement(1) , 2);
	}

}

Le test est vraiment basic juste pour vérifier le fonctionnement. Maintenant pour tester en ligne de commande en pur Java (qui est aussi utiliser avec Jenkins d’ailleurs ), on peut utiliser cette outil de Junit en ligne de commande.

Télécharger le fichier junit-platform-console-standalone-1.8.2.jar de Console Launcher : https://junit.org/junit5/docs/snapshot/user-guide/#running-tests-console-launcher qui permet d’appeler l’outil de test Junit5 via une ligne de commande.

En local on peut donc lancer cette commande, par exemple dans le workspace:

java -jar c:\DEV20\eclipse-workspace-jee\JenkinsDemo\junit-platform-console-standalone-1.8.2.jar -cp c:\DEV20\eclipse-workspace-jee\JenkinsDemo\bin --scan-classpath  --disable-banner

Voici la sortie détaillée :

.
+-- JUnit Jupiter [OK]
| '-- CalculTest [OK]
|   '-- testDoublement() [OK]
'-- JUnit Vintage [OK]

Test run finished after 44 ms
[         3 containers found      ]
[         0 containers skipped    ]
[         3 containers started    ]
[         0 containers aborted    ]
[         3 containers successful ]
[         0 containers failed     ]
[         1 tests found           ]
[         0 tests skipped         ]
[         1 tests started         ]
[         0 tests aborted         ]
[         1 tests successful      ]
[         0 tests failed          ]

Ou la version avec erreur d’un test :

.
+-- JUnit Jupiter [OK]
| '-- CalculTest [OK]
|   '-- testDoublement() [X] expected: <2> but was: <1>
'-- JUnit Vintage [OK]

Failures (1):
  JUnit Jupiter:CalculTest:testDoublement()
    MethodSource [className = 'test.CalculTest', methodName = 'testDoublement', methodParameterTypes = '']
    => org.opentest4j.AssertionFailedError: expected: <2> but was: <1>
       org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
       org.junit.jupiter.api.AssertionUtils.failNotEqual(AssertionUtils.java:62)
       org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:150)
       org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:145)
       org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:527)
       test.CalculTest.testDoublement(CalculTest.java:14)
       java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
       java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
       java.base/java.lang.reflect.Method.invoke(Method.java:568)
       [...]

Test run finished after 47 ms
[         3 containers found      ]
[         0 containers skipped    ]
[         3 containers started    ]
[         0 containers aborted    ]
[         3 containers successful ]
[         0 containers failed     ]
[         1 tests found           ]
[         0 tests skipped         ]
[         1 tests started         ]
[         0 tests aborted         ]
[         0 tests successful      ]
[         1 tests failed          ]

Pour disposer seulement de cette réponse en cas d’erreur, il faut ajouter le paramètre « –details=none » qui n’affichera qu’en cas d’erreur.

À présent, on peut copier tout le dossier du projet dans le conteneur Jenkins, car il n’a pas accès au dossier c:\DEV20\eclipse-workspace-jee\JenkinsDemo\ mais on aurait pu monter dans le conteneur Jenkins le dossier.

docker cp C:\DEV20\eclipse-workspace-jee\JenkinsDemo jenkins:/home

Donc l’ensemble des fichiers du projet et l’outil junit-platform-console-standalone-1.8.2.jar de Console Launcher se trouve dans le dossier /home/JenkinsDemo. On peut donc ensuite tester dans le conteneur comme ceci.

docker exec --user=root --workdir=/home/JenkinsDemo/ -it  jenkins  /bin/bash

On peut donc ensuite tester notre test dans le conteneur :

java -jar /home/JenkinsDemo/junit-platform-console-standalone-1.8.2.jar -cp /home/JenkinsDemo/bin/  --scan-classpath  --disable-banner --deta
ils=none

Passons maintenant dans Jenkins pour créer un job, « Construire un projet free-style » puis il faut utiliser le bouton « Avancé » pour avoir accès au dossier :

Puis, il faut indiquer le dossier de travail :

Maintenant, on va ajouter notre script comme critère de Build :

La commande testée précédemment doit être entrée pour valider le projet:

java -jar /home/JenkinsDemo/junit-platform-console-standalone-1.8.2.jar -cp /home/JenkinsDemo/bin/  --scan-classpath  --disable-banner --details=none

On peut ensuite sauvegarder les modifications et lancer ce job via « Lancer ce build » et on peut vérifier l’exécution dans le résultat de la console :

Cela permet de vérifier que les opérations s’exécutent correctement. A l’inverse voici une sortie de console en erreur après un échec du test :

Pour conclure et simplifié, on aurait pu monter le dossier du projet Eclipse directement dans le /home du conteneur avec cette commande :

docker run -it -v C:\DEV20\eclipse-workspace-jee\JenkinsDemo\:/home/JenkinsDemo/ --name=jenkins -p 8080:8080 -p 50000:50000 --restart=on-failure jenkins/jenkins:lts-jdk11

Le reste serait identique et grâce à Java portable entre Windows et Linux du conteneur, les commandes avec JUnit sont compatibles.

Publié dans Développement, IMT Mines Alès | Laisser un commentaire

Page de Template WordPress 6 thème FSE

Le nouveau modèle de thème de WordPress 6 appelé FSE pour « Full Site Editing » doit permettre d’améliorer l’édition d’un site web WordPress en permettant de modifier l’ensemble du site avec un éditeur dans l’esprit d’outils comme Divi.

L’ancienne technique d’édition de page dans un thème enfant qui était très classiquement la solution va progressivement disparaitre au profit de cette nouvelle technique parfois proche, parfois nouvelle, de création de thème.

Mon premier besoin est de proposer un modèle de page customiser pour par exemple disposer d’une zone à droite de la page avec un flux Twitter.

Je vais en premier m’appuyer sur le thème twentytwentytwo livré avec WordPress 6 pour dupliquer la page wp-content\themes\twentytwentytwo\templates\single.html en single-twitter.html dans le même dossier

Je n’ai pas encore testé, mais si la nouvelle version devait détruire cette page, je pense que le thème enfant sera encore une fois la solution.

Modifions le code initial de la partie tag <main> en ajoutant un attribut style (les puristes ajouterons un code CSS au fichier style.css mais j’ai voulu simplifier)

<main class="wp-block-group" style="background-color:green !important;width:60% !important;float:left;">

Nous avons une zone de blocs de la page qui vont être limité à 60% de la largeur avec un beau fond vert pour bien identifier la zone.

Après le tag de fermeture </main> nous allons ajouter une zone à droite et une zone en bas pour déplacer le reste du contenu de la page au-dessous de notre 2 colonnes, la verte et la jaune :

<!-- /wp:group --></main>

<!-- Ajout d'une zone droite de la page -->
<div id="droite" style="background-color:yellow !important;width:40% !important;float:right;" >
    Zone droite 
    [twitter_short_code]
</div>
<div id="bas" style="clear: both">
    &nbsp;
</div>
Mise en page sur 2 colonnes d’une nouvelle page template

Il faut ensuite ajouter les indications sur cette nouvelle page dans le fichier wp-content\themes\twentytwentytwo\theme.json dans la zone sous « customTemplates » avant la partie pour la page blanck :

"customTemplates": [
		{
			"name": "single-twitter",
			"title": "Page avec Twitter",
			"postTypes": [
				"page",
				"post"
			]
		},
		{
			"name": "blank",
			"title": "Blank",
			"postTypes": [
				"page",
				"post"
			]
		},

Maintenant, nous pouvons créer une page ou un article avec comme modèle de « Page avec Twitter ». Alors cette étape est optionnelle, la simple création du fichier wp-content\themes\twentytwentytwo\templates\single-twitter.html suffit à WordPress pour proposer dans son menu de modèle cette nouvelle page, mais pour les évolutions futures du thème je pense qu’il vaut mieux indiquer « proprement » que cette page est maintenant dans le modèle twentutwentytwo.

Enfin, nous allons éditer la page wp-content\themes\twentytwentytwo\functions.php pour y ajouter notre bout de programme pour Twitter qui ne va qu’afficher le titre du futur plugin.

// Nouveau shortcode twitter_short_code
function twitter_short_code(){
    return "<p>Le compte Twitter</p>";
}

add_shortcode('twitter_short_code', 'twitter_short_code');

Maintenant, modifions le template pour utiliser le shortcode [twitter_short_code] tout simplement en l’inserant dans le template wp-content\themes\twentytwentytwo\templates\single-twitter.html en bonne place :

<div id="droite" style="background-color:yellow !important;width:40% !important;float:right;" >
    Zone droite 
    [twitter_short_code]
</div>
Shortcode appelé depuis une page template créée spécialement

Et voilà, notre shortcode est utilisé comme élément pour construire la page template.

Nous pouvons aussi utiliser ce shortcode dans un bloc d’une page comme n’importe quel autre shortcode tant que notre thème est actif (à la différence d’un plugin). Il suffit de choisir le modèle de bloc de type « code court » (et non pas code comme j’ai fait par erreur).

L’autre option est de faire un plugin dans le dossier wp-content\plugins, il suffit de créer par exemple un dossier twitter_short_code contenant un fichier twitter_short_code.php avec un code presque identique (le short code est différent, car sinon WordPress indique qu’il est déjà existant donc [twitter_short_code_plugin] pour le plugin).

Voici le code de twitter_short_code.php mais n’oubliez pas d’activer le plugin dans le backoffice de WordPress avant de l’utiliser :

<?php
/**
 * Plugin Name: Twitter Pierre JEAN
 * Plugin URI: https://pierrejean.wp.imt.fr
 * Description: Test twitter simplement
 * Version: 0.1
 * Text Domain: twitter_short_code
 * Author: Pierre JEAN
 * Author URI: https://pierrejean.wp.imt.fr
 */


function twitter_short_code_plugin(){
    return "<p>Le compte Twitter</p>";
}

add_shortcode('twitter_short_code_plugin', 'twitter_short_code_plugin');
?>

Bien sûr, il manque l’ensemble du code pour réellement aller chercher les données de l’API Twitter, mais c’est une autre histoire.

Publié dans CTN, Développement | Laisser un commentaire

Ajout d’un dossier de contenu statique à Tomcat 9

Cas pratique, un programme Tomcat doit produire un fichier de données à télécharger, par exemple un fichier backup.csv.

Produire ce dossier dans le dossier WebContent ou webapp n’est pas possible, car à chaque redémarrage d’une nouvelle version de notre application, le contenu d’un de ces dossiers serait régénéré.

La solution vient d’un dossier de contenu dit statique (static en VO), en modifiant le fichier server.xml de notre serveur Tomcat. On identifie le projet qui doit disposer d’un dossier statique (dans l’exemple, c’est le tag <Context> du projet DevWeb) et on peut y ajouter les instructions pour indiquer à Tomcat qu’un URL peut accéder à ce dossier.

Il faut changer le tag <Context/> en tag double <Context></Context> et y ajouter ces informations de ressources. (Les doubles slashs sont à adapter au type de système d’exploitation).

<Context docBase="DevWeb" path="/DevWeb" reloadable="true" 			source="org.eclipse.jst.jee.server:DevWeb">
  <Resources>
    <PreResources
base="C://Users//pierre.jean//Site-Web//data" 							className="org.apache.catalina.webresources.DirResourceSet"		 webAppMount="/static" />
  </Resources>
</Context>

L’URL pour accéder à la ressource est relative à l’URL du <Context> englobant, notre url est donc http://127.0.0.1:8080/DevWeb/static/backup.csv

Pour lister le contenu du dossier, la première solution est de modifier le fonctionnement général de Tomcat en modifiant le fichier web.xml. Il faut changer la valeur de la servlet par défaut gérant la liste des dossiers en passant à la valeur true la propriété listings comme indiqué ci-dessous.

    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

La seconde option est de créer dans le dossier WebContent/WEB-INF/ un fichier tomcat-web.xml (ou web.xml mais Tomcat ne le conseille pas pour éviter de déployer ce fichier spécifique dans un serveur autre que Tomcat).

Le contenu du fichier tomcat-web.xml est donc le suivant pour surcharger les réglages par défaut du fichier web.xml généraliste au niveau du serveur Tomcat:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
	<servlet>
		<servlet-name>default</servlet-name>
		<servlet-class>
			org.apache.catalina.servlets.DefaultServlet
		</servlet-class>
		<init-param>
			<param-name>debug</param-name>
			<param-value>0</param-value>
		</init-param>
		<init-param>
			<param-name>listings</param-name>
			<param-value>true</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>default</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>

Après, il n’est pas forcément recommandé en production de donner des accès à un dossier tout entier, mais dans le contexte du projet de recherche, Tomcat est prévu dans un container en local de la machine.

On peut aussi modifier le rendu par défaut de la liste des contenus d’un dossier dans TOmcat mais je vous renvoie sur la documentation, ce n’est pas un besoin que j’ai eu.

Publié dans Développement | Laisser un commentaire

Émission d’un email en Java via un hébergement OVH

Envoyer un email technique depuis un code Java via un compte configuré chez OVH est assez simple si on a trouvé la bonne combinaison de paramètres…

Voici la liste des réglages pour un compte que l’on va appeler publication@euromov.eu et dont le mot de passe a été généré par la console OVH. Attention, l’envoie d’un trop grand nombre d’emails entrainera le blocage de votre compte par OVH. L’entreprise surveille ce genre de fonctionnalité car régulièrement les sites web et autres serveurs de l’entreprise servent à des pirates pour envoyer des emails en masse souvent à l’insu du propriétaire du compte chez OVH.

Le réglage mail.debug est à mettre à true au besoin pour voir les messages d’échange entre le serveur et votre code Java:

Properties prop = new Properties();
prop.put("mail.debug", "false");
prop.put("mail.smtp.auth", "true");		
prop.put("mail.smtp.ssl.protocols", "TLSv1.2");
prop.put("mail.smtp.host", "ssl0.ovh.net");
prop.put("mail.smtp.starttls.enable", "true"); 
prop.put("mail.smtp.ssl.trust", "ssl0.ovh.net");
prop.put("mail.smtp.port", "587");
prop.put("mail.smtp.socketFactory.port", "587");
prop.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");	Session session = Session.getInstance(prop, new Authenticator() {
  @Override
   protected PasswordAuthentication getPasswordAuthentication() {
	return new PasswordAuthentication("publication@euromov.eu", "MOT_DE_PASSE_A_GENERER_DANS_CONSOLE_OVH");}
   });
		
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("publication@euromov.eu"));
message.setRecipients(
Message.RecipientType.TO, InternetAddress.parse("directeurs@toto.com"));
message.setSubject("Mail Subject");
String msg = "This is my first email using JavaMailer";

MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.setContent(msg, "text/html; charset=utf-8");

Multipart multipart = new MimeMultipart();
multipart.addBodyPart(mimeBodyPart);
message.setContent(multipart);
Transport.send(message);

Pour rappel 2 JARS sont nécessaires pour ce code :

Bon email, mais encore une fois attention aux spams.

Publié dans Développement | Laisser un commentaire

Langage R liaison base de données

Installation de WAMP : https://www.wampserver.com/ ou MAMP : https://www.mamp.info/en/downloads/

Supposons un accès à un fichier « sante.accdb » contenant une table data de cette nature :

id date_analyse      glycemie
1   2022-03-17       10
2   2022-03-18       20

On peut interroger en langage R en SQL vers Microsoft Accces.

En premier lieu il faut installer le module pour R pour accéder à Accces:

install.packages("RODBC")
library(RODBC)

Une fois l’installation réalisée de ce module, on peut ouvrir le fichier Accès et intérroger en SQL la base de données:

con <- odbcConnectExcel2007("C:/Users/utilisateur/Documents/sante.accdb")
resultat <- sqlQuery(con,"select date_analyse from data")
print( resultat )

On peut faire de manière similaire sur MySQL avec des commandes similaires, en premier lieu en installant le module pour la liaison avec le serveur de base de données MySQL :

install.packages("RMySQL")
library(RMySQL)

L’accès à un serveur de base de données Mysql suppose plusieurs informations techniques, l’adresse du serveur de base de données (ici 127.0.0.1), un compte sur cette base de données (ici root), un mot de passe correspondant à ce compte (ici «  » pour indiquer mot de passe vide), un port de base de données (ici et par défaut 3306) et enfin une base de données (ici sante)

DB <- dbConnect(MySQL(), user="root", host="127.0.0.1", password="",dbname="sante" , port=3306)

Une fois la connexion réalisée, on peut lister les tables dans cette base de données sante.

dbListTables(DB)

Et enfin poser des questions en SQL

resultat <- dbGetQuery(DB, "SELECT * FROM data")
print( resultat )

Test unitaire en R

Installation de l’outil de test

install.packages("testthat")
library(testthat)

Test d’une valeur égale via :

expect_equal( 95 , dbGetQuery(DB, "SELECT max(age) from import")[,1] )

Pas de réponse si tout va bien, mais si on test ceci :

expect_equal( 92 , dbGetQuery(DB, "SELECT max(age) from import")[,1] )
Error: 92 not equal to dbGetQuery(DB, "SELECT max(age) from import")[, 1].
1/1 mismatches
[1] 92 - 95 == -3

Publié dans Développement | Laisser un commentaire