<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://air.imag.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=MatthieuCaneill</id>
	<title>air - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://air.imag.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=MatthieuCaneill"/>
	<link rel="alternate" type="text/html" href="https://air.imag.fr/index.php/Special:Contributions/MatthieuCaneill"/>
	<updated>2026-06-02T11:09:08Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.17</generator>
	<entry>
		<id>https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21492</id>
		<title>TAGL/TP</title>
		<link rel="alternate" type="text/html" href="https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21492"/>
		<updated>2015-02-26T16:52:43Z</updated>

		<summary type="html">&lt;p&gt;MatthieuCaneill: /* Contrôle Continu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Travaux pratiques de l&#039;UE [[TAGL]].&lt;br /&gt;
&lt;br /&gt;
Anciennes versions : [[TAGL/TP 2014]]&lt;br /&gt;
&lt;br /&gt;
=Séance 1 : Gestion de versions=&lt;br /&gt;
==Git==&lt;br /&gt;
&lt;br /&gt;
Création d&#039;un dépôt Git local&lt;br /&gt;
&lt;br /&gt;
===Méthode simple: init first===&lt;br /&gt;
&lt;br /&gt;
Via cette méthode, on crée un dépôt local, avec un répertoire de travail, puis on pousse ses modifications vers un dépôt &amp;quot;bare&amp;quot;.&lt;br /&gt;
Cette méthode est la plus simple, car on dispose immédiatement d&#039;un répertoire de travail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création d&#039;un dépôt Git dans le dossier simple-repo&lt;br /&gt;
git init simple-repo&lt;br /&gt;
&lt;br /&gt;
# Création d&#039;un README&lt;br /&gt;
cd simple-repo&lt;br /&gt;
echo &amp;quot;Hello, World&amp;quot; &amp;gt; README&lt;br /&gt;
&lt;br /&gt;
# Ajout du versionnement du fichier README&lt;br /&gt;
git add README&lt;br /&gt;
&lt;br /&gt;
# Commit&lt;br /&gt;
git commit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À ce niveau, on a un dépôt Git complètement fonctionnel.&lt;br /&gt;
Cependant, il est intéressant de pousser ses modifications vers un autre dépôt, sur une autre machine.&lt;br /&gt;
On va donc créer un dépôt bare sur une autre machine (ou autre dossier pour l&#039;exemple)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que l&#039;URL pour accéder à ce dépôt est URL_REPO.&lt;br /&gt;
On va d&#039;abord ajouter ce dépôt serveur à la liste des dépôts connu-repos de votre dépôt local.&lt;br /&gt;
Étant donné qu&#039;il s&#039;agit du dépôt &amp;quot;principal&amp;quot; à utiliser, on l&#039;appellera //origin//, par convention.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin URL_REPO&lt;br /&gt;
# Récupération de ses informations&lt;br /&gt;
git fetch origin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce serveur distant est &amp;quot;vide&amp;quot;: il n&#039;a aucune branche. On va donc enregistrer notre branche sur le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À partir de cette commande, la branche locale //master// sera liée à la branche distante //origin/master//.&lt;br /&gt;
Lors des prochaines commandes &#039;&#039;git push&#039;&#039;, grâce à cette liaison, tous les commits sur la branche locale //master// seront poussées sur le serveur distant.&lt;br /&gt;
&lt;br /&gt;
===Méthode moins simple: bare first===&lt;br /&gt;
&lt;br /&gt;
Si on commence dans par le serveur &amp;quot;vide&amp;quot;, il faudra le cloner au lieu de le définir comme un dépôt distant.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création du dépôt vide&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que ce dépôt est accessible à l&#039;URL URL_REPO&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clonage du dépôt&lt;br /&gt;
git clone URL_REPO clone-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un avertissement indique que l&#039;on clone un dépôt vide: le dépôt local à donc une branche master, mais elle n&#039;est pas liée au dépôt distant, car celui-ci n&#039;a aucune branche.&lt;br /&gt;
Le dépôt distant est automatiquement appelé //origin//.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Commit dans le dépôt local&lt;br /&gt;
cd clone-repo&lt;br /&gt;
echo hello &amp;gt; readme.rst&lt;br /&gt;
git add readme.rst&lt;br /&gt;
git commit et ses dépendances&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme dans la méthode simple, il faut pousser la branche master vers le dépôt distant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===De l&#039;importance des README===&lt;br /&gt;
&lt;br /&gt;
Il est très important d&#039;avoir au moins 2 fichiers dans votre dépôt Git:&lt;br /&gt;
&lt;br /&gt;
* LICENSE: contenant le texte **complet** de la licence de votre projet&lt;br /&gt;
* README: décrivant votre projet et comment l&#039;utiliser. Ce fichier doit rappeler le nom de la licence de votre projet&lt;br /&gt;
&lt;br /&gt;
Il est aussi recommandé d&#039;avoir les fichiers suivants:&lt;br /&gt;
&lt;br /&gt;
* AUTHORS: contenant la liste des noms/pseudos et e-mails des auteurs de commits ou de code inclus dans ce projet&lt;br /&gt;
* INSTALL: contenant la liste des dépendances de ce projet et des commandes à utiliser pour le compiler et l&#039;installer&lt;br /&gt;
&lt;br /&gt;
Les fichiers LICENSE sont des fichiers textes bruts.&lt;br /&gt;
Les autres fichiers sont généralement dans un format offrant un peu plus de lisibilté, par exemple dans les formats [http://daringfireball.net/projects/markdown/ Markdown] (.md) ou [http://docutils.sourceforge.net/rst.html reStructuredText] (.rst)&lt;br /&gt;
&lt;br /&gt;
Un plug-in existe pour éditer des fichier reStructuredText dans Eclipse: ReST Editor, disponible sur le [https://marketplace.eclipse.org/content/rest-editor Marketplace Eclipse]&lt;br /&gt;
&lt;br /&gt;
=Séance 2a: Intégration en continue=&lt;br /&gt;
&lt;br /&gt;
===GitHub &amp;amp; [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
Travis-CI est un service permettant d&#039;exécuter un script dans une machine virtuelle Ubuntu dès que vous effectuez un push sur un de vos dépôts GitHub.&lt;br /&gt;
L&#039;intérêt est de savoir si la version d&#039;un projet que vous avez rendu publique peut être compilée et si ses tests passent.&lt;br /&gt;
&lt;br /&gt;
La machine virtuelle &amp;quot;offerte&amp;quot; par Travis est préconfigurée pour le language indiqué dans son fichier de configuration (&#039;&#039;&#039;.travis.yml&#039;&#039;&#039;), mais il est possible d&#039;utiliser la commande &#039;&#039;&#039;sudo apt-get install ...&#039;&#039;&#039; pour ajouter vos dépendances.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour utiliser [[Travis-CI]]:&lt;br /&gt;
&lt;br /&gt;
# Créez compte individuel sur GitHub https://github.com&lt;br /&gt;
# &#039;&#039;Fork&#039;&#039;ez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Ajoutez un collaborateur (i.e. votre binôme) au projet &#039;&#039;forké&#039;&#039;, via les paramètres (&#039;&#039;settings&#039;&#039;) de ce projet&lt;br /&gt;
# Pour l&#039;exemple, activez le service (ou hook) &#039;&#039;Email&#039;&#039; depuis les paramètres du dépôt: à chaque fois que vous ou un de vos collaborateurs ferra un &#039;&#039;&#039;git push&#039;&#039;&#039;, vous recevrez une notification par mail.&lt;br /&gt;
# Activez le service Travis-CI: identifiez-vous (&#039;&#039;sign in&#039;&#039;) sur https://travis-ci.org/ avec votre compte GitHub&lt;br /&gt;
# Activez le service pour les projets sur lesquels vous souhaitez appliquer les principes d&#039;intégration continue&lt;br /&gt;
&lt;br /&gt;
[[Travis-CI]] utilise un fichier nommé &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; (attention: fichier caché sous Unix) pour se configurer et choisir les opérations à effectuer.&lt;br /&gt;
Ce fichier doit se trouver à la racine de votre dépôt Git.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; du fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; ci-dessous.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
language: node_js&lt;br /&gt;
node_js:&lt;br /&gt;
  - &amp;quot;0.11&amp;quot;&lt;br /&gt;
  - &amp;quot;0.10&amp;quot;&lt;br /&gt;
  - &amp;quot;0.8&amp;quot;&lt;br /&gt;
  - &amp;quot;0.6&amp;quot;&lt;br /&gt;
  - iojs&lt;br /&gt;
  - iojs-v1.0.2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; indique à [[Travis-CI]] que les scripts de ce projet dans ce dépôt seront exécutés avec plusieurs versions de [[Node.js]].&lt;br /&gt;
&lt;br /&gt;
Ajoutez dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&#039; la section suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;quot;devDependencies&amp;quot;: {&lt;br /&gt;
    &amp;quot;jshint&amp;quot;: &amp;quot;^2.6.0&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;scripts&amp;quot;: {&lt;br /&gt;
    &amp;quot;test&amp;quot;: &amp;quot;./node_modules/jshint/bin/jshint index.js&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
et incrémentez le numéro de version.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Remarque:&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;jshint&#039;&#039;&#039; peut être lancé localement avec les commandes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo npm install jshint&lt;br /&gt;
jshint index.js&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A lire&lt;br /&gt;
* http://docs.travis-ci.com/user/languages/javascript-with-nodejs/&lt;br /&gt;
* https://github.com/docdis/learn-travis/blob/master/README.md&lt;br /&gt;
&lt;br /&gt;
=Séance 2b: Livraison en continue=&lt;br /&gt;
&lt;br /&gt;
==[[Heroku]]==&lt;br /&gt;
[https://www.heroku.com/ Heroku] est une plateforme cloud de type PaaS permettant l&#039;exécution d&#039;applications et de services en ligne écrits dans les langages et plateformes suivantes : Ruby, [[Node.js]], [[Python]], Java, et PHP.&lt;br /&gt;
&lt;br /&gt;
# Créez un compte gratuit sur [https://signup.heroku.com Heroku]&lt;br /&gt;
# Forkez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Dans Heroku, créez une nouvelle app Node.js, et liez-la au repository Github créé à l&#039;étape précédente&lt;br /&gt;
# Choisissez l&#039;option &amp;quot;Déploiement automatique&amp;quot; depuis la branche **master**&lt;br /&gt;
# Modifiez le fichier index.js pour afficher la version de service dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 var fs = require(&#039;fs&#039;);&lt;br /&gt;
 var package = JSON.parse(fs.readFileSync(&#039;./package.json&#039;, &#039;utf8&#039;));&lt;br /&gt;
 var version=package.version;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Hello World! (current version: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
# Modifiez le fichier index.js pour franciser le message dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Bonjour Tout Le Monde! (version courante: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
=Séance 3: Builders=&lt;br /&gt;
&lt;br /&gt;
==[[Ant]]==&lt;br /&gt;
&lt;br /&gt;
==[[Maven]]==&lt;br /&gt;
&lt;br /&gt;
[http://maven.apache.org/download.cgi Charger et installer Maven 3].&lt;br /&gt;
&lt;br /&gt;
Debian/Ubuntu &amp;amp; friends:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install maven&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mvn -version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Faites une copie du projet, basée sur Maven:&lt;br /&gt;
&lt;br /&gt;
# Dans votre dépôt Git, créez un dossier &#039;&#039;&#039;cron4j-mvn&#039;&#039;&#039;: il contiendra le projet Cron4J avec la structure Maven&lt;br /&gt;
# Dans ce dossier, utilisez l&#039;[https://maven.apache.org/guides/introduction/introduction-to-archetypes.html archetype] Maven [http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-quickstart/ maven-archetype-quickstart] (la version des sources de cron4j utilisés est la 2.5.5) (groupId: it.sauronsoftware.cron4j, artifactId: cron4j):&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Cette commande crée un projet avec un fichier &#039;&#039;pom.xml&#039;&#039;, et une classe et un test modèles: supprimez ces modèles&lt;br /&gt;
# Copiez les sources de Cron4J depuis le dossier &#039;&#039;&#039;cron4j-original&#039;&#039;&#039; dans le dossier &#039;&#039;&#039;src/main/java&#039;&#039;&#039; de votre projet Maven&lt;br /&gt;
# Faites un essai de compilation:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Lancez un des exemples avec mvn exec:java -Dexec.mainClass=&amp;quot;com.example.Main&amp;quot; [-Dexec.args=&amp;quot;argument1&amp;quot;] ... ([http://mojo.codehaus.org/exec-maven-plugin/usage.html doc. exec plugin], [http://mojo.codehaus.org/exec-maven-plugin/java-mojo.html doc. Exec:java goal])&lt;br /&gt;
# Enfin modifiez le fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; à la racine de votre dépôt Git afin que Travis exécute la commande &#039;&#039;&#039;mvn clean verify&#039;&#039;&#039; à chaque mise à jour du dépôt GitHub.&lt;br /&gt;
&lt;br /&gt;
==Tests Unitaires avec JUnit 4==&lt;br /&gt;
Survoller le tutoriel [http://www.vogella.com/tutorials/JUnit/article.html Unit Testing with JUnit]&lt;br /&gt;
&lt;br /&gt;
# Veillez à bien utiliser la dépendance JUnit 4.8.2 dans pom.xml&lt;br /&gt;
# Ajouter le test unitaire suivant au projet, dans le fichier &#039;&#039;&#039;src/test/it/sauronsoftware/SchedulingPatternTest.java&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
package it.sauronsoftware;&lt;br /&gt;
&lt;br /&gt;
import it.sauronsoftware.cron4j.SchedulingPattern;&lt;br /&gt;
import it.sauronsoftware.cron4j.InvalidPatternException;&lt;br /&gt;
&lt;br /&gt;
import static org.junit.Assert.assertEquals;&lt;br /&gt;
import static org.junit.Assert.assertTrue;&lt;br /&gt;
&lt;br /&gt;
import org.junit.AfterClass;&lt;br /&gt;
import org.junit.BeforeClass;&lt;br /&gt;
import org.junit.Test;&lt;br /&gt;
&lt;br /&gt;
public class SchedulingPatternTest {&lt;br /&gt;
&lt;br /&gt;
  @BeforeClass&lt;br /&gt;
  public static void testSetup() {&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @AfterClass&lt;br /&gt;
  public static void testCleanup() {&lt;br /&gt;
    // Teardown for data used by the unit tests&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test(expected = InvalidPatternException.class)&lt;br /&gt;
  public void testExceptionIsThrown() {&lt;br /&gt;
    SchedulingPattern sp = new SchedulingPattern(&amp;quot;0 5 * *&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test&lt;br /&gt;
  public void testPattern() {&lt;br /&gt;
    String pattern;&lt;br /&gt;
    pattern=&amp;quot;0 5 * * *|8 10 * * *|22 17 * * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
    pattern=&amp;quot;0 5 * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Committez et Pushez ce nouveau fichier, pour que Travis lance les tests dès que possible&lt;br /&gt;
# Lancez les tests unitaires avec &amp;lt;pre&amp;gt;mvn test&amp;lt;/pre&amp;gt; Ce test va &#039;&#039;&#039;échouer&#039;&#039;&#039;: corrigez le.&lt;br /&gt;
# Committez et Pushez la version corrigée des tests: Travis enverra un mail pour indiquer si les tests échouent ou non&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; Travis va exécuter les tests &#039;&#039;dès que possible&#039;&#039;. Il est possible de recevoir un mail indiquant que les tests du premier &#039;&#039;push&#039;&#039; échouent alors que l&#039;on a déjà &#039;&#039;pushé&#039;&#039; la correction.&lt;br /&gt;
# Naviguez sur http://travis-ci.org pour vérifier les builds effectués.&lt;br /&gt;
# Créez des tests unitaires supplémentaire du i.s.c.CronParser&lt;br /&gt;
&lt;br /&gt;
===[[Maven]] avec [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
===Git (suite)===&lt;br /&gt;
&lt;br /&gt;
# Forkez le projet &#039;&#039;&#039;tagl&#039;&#039;&#039; d&#039;un autre binome (i.e. autre que &#039;&#039;donsez/tagl&#039;&#039;)&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; donnez lui un nom différent (e.g. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Clonez ce nouveau dépôt&lt;br /&gt;
# Lancez une compilation pour valider l&#039;état du projet (bonne pratique)&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Situez vous dans une nouvelle branch git:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;git checkout -b add-license&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Ajoutez une bannière de licence dans le fichier &#039;&#039;&#039;cron4j-mvn/pom.xml&#039;&#039;&#039;&lt;br /&gt;
# Lancez une nouvelle compilation pour valider vos modifications&lt;br /&gt;
# Commitez et pushez (vers votre fork de ce dépôt, i.e. &#039;&#039;tagl-licensing&#039;&#039;) (pour pusher une branche nouvellement créée: git push origin add-license)&lt;br /&gt;
# Via le site de GitHub, proposez un &amp;quot;Pull Request&amp;quot; au projet initial&lt;br /&gt;
&lt;br /&gt;
Vous pouvez ensuite supprimer le clone de ce fork.&lt;br /&gt;
Lorsque le &#039;&#039;pull request&#039;&#039; aura été accepté, vous pourrez supprimer votre fork (&#039;&#039;tagl-licensing&#039;&#039;) de votre compte GitHub.&lt;br /&gt;
&lt;br /&gt;
===Contrôle Continu===&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt &#039;&#039;tagl&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le plugin [http://mojo.codehaus.org/cobertura-maven-plugin/usage.html Cobertura] à votre projet Maven.&lt;br /&gt;
## Configurez le plugin pour [http://mojo.codehaus.org/cobertura-maven-plugin/examples/report-formats.html générer un rapport] HTML. Le résultat se trouvera dans &#039;&#039;target/site/cobertura&#039;&#039;&lt;br /&gt;
## Le plugin ne s&#039;exécute automatiquement pas durant la compilation, il faut utiliser la commande : &amp;lt;pre&amp;gt;mvn cobertura:cobertura&amp;lt;/pre&amp;gt;&lt;br /&gt;
## &#039;&#039;&#039;Bonus:&#039;&#039;&#039; Modifiez le fichier &#039;&#039;pom.xml&#039;&#039; pour que le &#039;&#039;goal&#039;&#039; &#039;&#039;&#039;cobertura&#039;&#039;&#039; soit exécuté pendant la &#039;&#039;phase&#039;&#039; &#039;&#039;&#039;package&#039;&#039;&#039;.&lt;br /&gt;
# Répondez aux questions : &#039;&#039;Mais qu&#039;est ce que la couverture de code ? En quoi c&#039;est utile ?&#039;&#039;&lt;br /&gt;
# Ajoutez au projet Maven les plugins pour la génération d&#039;un site et de rapports (Javadoc, tests unitaires, tags list (FIXME, TODO, ...), ...): voir http://maven.apache.org/plugins/maven-site-plugin/ et d&#039;autres.&lt;br /&gt;
# Regardez les exemples d&#039;utilisation de cron4j dans cron4j-original/examples&lt;br /&gt;
# À rendre : pom.xml&lt;br /&gt;
&lt;br /&gt;
===Bonus Track===&lt;br /&gt;
&lt;br /&gt;
====Clone SVN -&amp;gt; Git====&lt;br /&gt;
&lt;br /&gt;
Source: http://www.yterium.net/Migrer-un-projet-SVN-vers-GIT&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Cloner le dépôt SVN en dépôt Git (conservation historique)&lt;br /&gt;
$ git svn clone  svn://svn.code.sf.net/p/cron4j/code/trunk cron4j-original&lt;br /&gt;
$ cd cron4j-original&lt;br /&gt;
# Test compilation&lt;br /&gt;
$ ant jar&lt;br /&gt;
$ cd ..&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Préparation TAGL====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clone du dépôt TAGL&lt;br /&gt;
$ git clone git@github.com:donsez/tagl.git&lt;br /&gt;
$ cd tagl&lt;br /&gt;
# &amp;quot;Fetch&amp;quot; du dépôt local cloné précédemment&lt;br /&gt;
$ git fetch file://$(pwd)/../cron4j-original&lt;br /&gt;
# Fusion de ce qui vient d&#039;être fetché&lt;br /&gt;
$ git merge FETCH_HEAD&lt;br /&gt;
# Envoi sur le serveur&lt;br /&gt;
$ git push&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Cherry-picking: reprise des modifications d&#039;un collègue====&lt;br /&gt;
&lt;br /&gt;
On considère que:&lt;br /&gt;
&lt;br /&gt;
* votre dépôt Git distant est à l&#039;adresse URL_DEPOT&lt;br /&gt;
* votre collègue a un dépôt Git à l&#039;adresse URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Dossier temporaire&lt;br /&gt;
cd /tmp&lt;br /&gt;
&lt;br /&gt;
# Clone de votre dépôt&lt;br /&gt;
git clone URL_DEPOT mon_depot&lt;br /&gt;
&lt;br /&gt;
# Déplacement dans votre dépôt&lt;br /&gt;
cd mon_depot&lt;br /&gt;
&lt;br /&gt;
# Définition du dépôt distant&lt;br /&gt;
git remote add collegue URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
# Récupération des infos du dépôt du collègue&lt;br /&gt;
git fetch collegue&lt;br /&gt;
&lt;br /&gt;
# Maintenant, on peut voir les branches du collègue&lt;br /&gt;
git branch -a&lt;br /&gt;
&lt;br /&gt;
# On peut fusionner avec une branche&lt;br /&gt;
git merge collegue/master&lt;br /&gt;
&lt;br /&gt;
# Si vous avez des conflits, éditez les fichiers concernés,&lt;br /&gt;
# et committez avec git commit&lt;br /&gt;
&lt;br /&gt;
# Push vers votre dépôt distant&lt;br /&gt;
git push origin&lt;br /&gt;
&lt;br /&gt;
# Optionnel: supprimez la référence vers le dépôt du collègue&lt;br /&gt;
git remote rm collegue&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Archetype webapp====&lt;br /&gt;
L&#039;archetype webapp (http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-webapp/) permet de créer le squelette d&#039;une webapp. Créez un simple webapp monsite en version 0.1.0. (add/commit/push). Vous pourrez tester cette webapp en ajoutant au pom.xml le [https://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin plugin maven Jetty].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mvn -Djetty.port=9999 jetty:run&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naviguez sur http://localhost:9999/monsite&lt;br /&gt;
&lt;br /&gt;
====Scrum tools====&lt;br /&gt;
Ces 3 services peuvent être couplé à votre dépôt GitHub pour votre gestion de projet agile avec [[Scrum]] :&lt;br /&gt;
* http://www.acunote.com/&lt;br /&gt;
* http://backlogtool.com/&lt;br /&gt;
* http://www.scrumdo.com/&lt;br /&gt;
&lt;br /&gt;
L&#039;activation se fait via &#039;&#039;Settings &amp;gt; Webhooks &amp;amp; Services &amp;gt; Configure services&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Séance 4: AOP &amp;amp; AspectJ=&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt Git, projet &#039;&#039;cron4j-mvn&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le [http://mojo.codehaus.org/aspectj-maven-plugin/ plugin Maven pour AspectJ] au pom.xml&lt;br /&gt;
# Ajoutez un aspect de trace à l&#039;invocation des méthodes &#039;&#039;&#039;run()&#039;&#039;&#039; de l&#039;interface java.lang.Runnable (uniquement pour les objets &#039;&#039;schedulé&#039;&#039;s)&lt;br /&gt;
#: Affichez une trace avant et après l&#039;exécution de la tâche&lt;br /&gt;
# Préparez un nouveau test (nouvelle classe) démarrant un Scheduler Cron4j et validant l&#039;exécution d&#039;une tâche au bout d&#039;une minute (pattern &amp;quot;* * * * *&amp;quot;)&lt;br /&gt;
#: Lors de l&#039;exécution de &#039;&#039;&#039;mvn test&#039;&#039;&#039;, vous devez voir apparaître les traces préparées dans votre aspect.&lt;br /&gt;
&lt;br /&gt;
Liens utiles:&lt;br /&gt;
* [http://ridgetopsolutions.com/blog/2013/02/12/getting-started-with-aspectj-and-maven/ Getting started with AspectJ and Maven]&lt;br /&gt;
&lt;br /&gt;
===Contrôle continu===&lt;br /&gt;
&lt;br /&gt;
# Complétez l&#039;aspect de trace avec le positionnement du [http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html java.lang.ThreadLocal] pour passer 1) l&#039;identifiant du job et 2) le compteur des appels de la méthode de l&#039;objet.&lt;br /&gt;
&lt;br /&gt;
=Séance 5: Pelix &amp;amp; iPOPO=&lt;br /&gt;
&lt;br /&gt;
Pelix est une plate-forme d&#039;application à services (SOA).&lt;br /&gt;
iPOPO est un modèle de composants orientés services (SOCM).&lt;br /&gt;
&lt;br /&gt;
La documentation de Pelix et iPOPO est disponible sur https://ipopo.coderxpress.net/&lt;br /&gt;
&lt;br /&gt;
===Installation de iPOPO===&lt;br /&gt;
&lt;br /&gt;
* Cloner le dépôt Git depuis https://github.com/tcalmant/ipopo&lt;br /&gt;
* Se placer dans la branche &#039;&#039;dev&#039;&#039;&lt;br /&gt;
* Pour installer iPOPO, lancer la commande :&lt;br /&gt;
&lt;br /&gt;
   sudo python setup.py install&lt;br /&gt;
&lt;br /&gt;
===Shell Pelix===&lt;br /&gt;
&lt;br /&gt;
Pour lancer un shell Pelix, utilisez la commande:&lt;br /&gt;
&lt;br /&gt;
   python -m pelix.shell.console&lt;br /&gt;
&lt;br /&gt;
Les commandes disponibles sont décrites ici: [https://ipopo.coderxpress.net/wiki/doku.php?id=ipopo:refcards:shell Shell Commands]&lt;br /&gt;
&lt;br /&gt;
===Rappels de Python===&lt;br /&gt;
&lt;br /&gt;
* Pas de déclaration du type d&#039;une variable&lt;br /&gt;
* Les méthodes d&#039;une classe ont toute comme premier paramètre &#039;&#039;self&#039;&#039;, équivalent du &#039;&#039;this&#039;&#039; en Java.&lt;br /&gt;
* Blocs définis par indentation (4 espaces ou 1 tab)&lt;br /&gt;
* Une ligne finissant par &#039;:&#039; démarre toujours un bloc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Import d&#039;un module&lt;br /&gt;
import pelix&lt;br /&gt;
&lt;br /&gt;
# Définition d&#039;une classe&lt;br /&gt;
class MaClasse:&lt;br /&gt;
   # Constructeur&lt;br /&gt;
   def __init__(self):&lt;br /&gt;
       self.default = &amp;quot;stanger&amp;quot;&lt;br /&gt;
       print(&amp;quot;Classe construite&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
   # Méthode, avec un argument&lt;br /&gt;
   def sayHello(self, name):&lt;br /&gt;
       if not name:&lt;br /&gt;
           # Nom vide ou nul&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(self.default)&lt;br /&gt;
       else:&lt;br /&gt;
           # Nom valide&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(name)&lt;br /&gt;
&lt;br /&gt;
objet = MaClasse()&lt;br /&gt;
print(objet.sayHello(&amp;quot;&amp;quot;))&lt;br /&gt;
print(objet.sayHello(&amp;quot;World&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Service Ping-Pong===&lt;br /&gt;
&lt;br /&gt;
1. Écrire un fichier &#039;&#039;pong.py&#039;&#039;, définissant une classe &#039;&#039;Pong&#039;&#039; ayant une méthode &#039;&#039;pong&#039;&#039; prenant en paramètre un message et retournant le message préfixé par &amp;quot;PONG:&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Exemple: &lt;br /&gt;
   &lt;br /&gt;
      pong = Pong()&lt;br /&gt;
      pong.pong(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2. Écrire un fichier &#039;&#039;ping.py&#039;&#039;, définissant une classe &#039;&#039;Ping&#039;&#039; ayant une méthode &#039;&#039;ping&#039;&#039; prenant en paramètre un message, créant un objet Pong et retournant le résultat de Pong.pong(message) préfixé par &amp;quot;PING:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&lt;br /&gt;
      ping = Ping()&lt;br /&gt;
      ping.ping(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PING:PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
3. Transformer le fichier &#039;&#039;pong.py&#039;&#039; pour qu&#039;il devienne un bundle Pelix enregistrant un objet Pong comme étant un service ayant pour spécification &amp;quot;tagl.pong&amp;quot;&lt;br /&gt;
* Définir une classe &#039;&#039;Activator&#039;&#039;, décorée avec &#039;&#039;@BundleActivator&#039;&#039;&lt;br /&gt;
* Enregistrer le service dans la méthode &#039;&#039;Activator.start&#039;&#039; et le désenregistrer dans &#039;&#039;Activator.stop&#039;&#039;&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/provider.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;pong&#039; et vérifier que le service est bien inscrit avec la commande &#039;&#039;sl&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
4.Transformer la classe &#039;&#039;Ping&#039;&#039; dans &#039;&#039;ping.py&#039;&#039; en un composant iPOPO&lt;br /&gt;
* L&#039;objet Pong utilisé dans &#039;&#039;ping()&#039;&#039; doit être un service injecté par iPOPO (&#039;&#039;@Requires&#039;&#039;)&lt;br /&gt;
* Appeler la méthode &#039;&#039;ping()&#039;&#039; dès que le service Pong est injecté (&#039;&#039;@BindField&#039;&#039;) ou disparait (&#039;&#039;@UnbindField&#039;&#039;)&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/consumer.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;ping&#039; et vérifier son comportement si le bundle &#039;&#039;pong&#039;&#039; ou le bundle &#039;&#039;ping&#039;&#039; est arrêté et redémarré.&lt;br /&gt;
&lt;br /&gt;
5. Mettre à jour le bundle &#039;&#039;pong&#039;&#039;&lt;br /&gt;
* Remplacer le préfixe &amp;quot;PONG&amp;quot; par &amp;quot;NI&amp;quot;&lt;br /&gt;
* Dans le shell Pelix, mettre à jour le bundle &#039;&#039;pong&#039;&#039; sans redémarrer la plate-forme (commande &#039;&#039;udpate&#039;&#039;).&lt;br /&gt;
* Vérifier les traces dans le shell pour valider la mise à jour du service.&lt;br /&gt;
&lt;br /&gt;
===Remote Services===&lt;br /&gt;
&lt;br /&gt;
* Ajouter les propriétés permettant l&#039;export du service Pong dans &#039;&#039;pong.py&#039;&#039; (s&#039;inspirer de &#039;&#039;provider.py&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
* Lancer deux shells iPOPO (dans deux terminaux)&lt;br /&gt;
* Dans chaque shell iPOPO, installer les bundles:&lt;br /&gt;
** &#039;&#039;pelix.remote.dispatcher&#039;&#039;: Exportateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.registry&#039;&#039;; Importateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.discovery.multicast&#039;&#039;: Découverte de services via Multicast&lt;br /&gt;
** &#039;&#039;pelix.remote.xml_rpc&#039;&#039;: Transport XML-RPC&lt;br /&gt;
** &#039;&#039;pelix.http.basic&#039;&#039;: Serveur HTTP&lt;br /&gt;
&lt;br /&gt;
Attention: il peut être nécessaire de désactiver votre pare-feu pour que les Remote Services fonctionnent&lt;br /&gt;
&lt;br /&gt;
* Instancier les composants depuis le shell iPOPO, dans chaque framework:&lt;br /&gt;
** Serveur HTTP sur le port 8080: &#039;&#039;instantiate pelix.http.service.basic.factory http-server pelix.http.port=8080&#039;&#039; (penser à changer de port dans chaque framework)&lt;br /&gt;
** Multicast Discovery: &#039;&#039;instantiate pelix-remote-discovery-multicast-factory multicast-discovery&#039;&#039;&lt;br /&gt;
** XML-RPC Exporter: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-exporter&#039;&#039;&lt;br /&gt;
** XML-RPC Importer: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-importer&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Installer le bundle &#039;&#039;ping&#039;&#039; dans un des frameworks et le bundle &#039;&#039;pong&#039;&#039; dans l&#039;autre.&lt;br /&gt;
* Le composant ping peut appeler le service pong, qui est dans l&#039;autre framework.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Voir le code de &#039;&#039;run_remote.py&#039;&#039; pour voir comment démarrer un framework Pelix et installer des bundles depuis Python.&lt;br /&gt;
* Jouer un peu avec &#039;&#039;run_remote.py&#039;&#039; (voir &#039;&#039;run_remote.py --help&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=Séance 6=&lt;br /&gt;
[[Tutorial OSGi avec Apache Felix]]&lt;br /&gt;
&lt;br /&gt;
=Séance 7=&lt;br /&gt;
Faire un projet PDE pour un bundle cron4j.gogo (indépendant de cron4j.bundle)&lt;br /&gt;
&lt;br /&gt;
Utilisation de https://eclipse.org/tycho/&lt;/div&gt;</summary>
		<author><name>MatthieuCaneill</name></author>
	</entry>
	<entry>
		<id>https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21491</id>
		<title>TAGL/TP</title>
		<link rel="alternate" type="text/html" href="https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21491"/>
		<updated>2015-02-26T16:46:49Z</updated>

		<summary type="html">&lt;p&gt;MatthieuCaneill: /* Git (suite) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Travaux pratiques de l&#039;UE [[TAGL]].&lt;br /&gt;
&lt;br /&gt;
Anciennes versions : [[TAGL/TP 2014]]&lt;br /&gt;
&lt;br /&gt;
=Séance 1 : Gestion de versions=&lt;br /&gt;
==Git==&lt;br /&gt;
&lt;br /&gt;
Création d&#039;un dépôt Git local&lt;br /&gt;
&lt;br /&gt;
===Méthode simple: init first===&lt;br /&gt;
&lt;br /&gt;
Via cette méthode, on crée un dépôt local, avec un répertoire de travail, puis on pousse ses modifications vers un dépôt &amp;quot;bare&amp;quot;.&lt;br /&gt;
Cette méthode est la plus simple, car on dispose immédiatement d&#039;un répertoire de travail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création d&#039;un dépôt Git dans le dossier simple-repo&lt;br /&gt;
git init simple-repo&lt;br /&gt;
&lt;br /&gt;
# Création d&#039;un README&lt;br /&gt;
cd simple-repo&lt;br /&gt;
echo &amp;quot;Hello, World&amp;quot; &amp;gt; README&lt;br /&gt;
&lt;br /&gt;
# Ajout du versionnement du fichier README&lt;br /&gt;
git add README&lt;br /&gt;
&lt;br /&gt;
# Commit&lt;br /&gt;
git commit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À ce niveau, on a un dépôt Git complètement fonctionnel.&lt;br /&gt;
Cependant, il est intéressant de pousser ses modifications vers un autre dépôt, sur une autre machine.&lt;br /&gt;
On va donc créer un dépôt bare sur une autre machine (ou autre dossier pour l&#039;exemple)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que l&#039;URL pour accéder à ce dépôt est URL_REPO.&lt;br /&gt;
On va d&#039;abord ajouter ce dépôt serveur à la liste des dépôts connu-repos de votre dépôt local.&lt;br /&gt;
Étant donné qu&#039;il s&#039;agit du dépôt &amp;quot;principal&amp;quot; à utiliser, on l&#039;appellera //origin//, par convention.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin URL_REPO&lt;br /&gt;
# Récupération de ses informations&lt;br /&gt;
git fetch origin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce serveur distant est &amp;quot;vide&amp;quot;: il n&#039;a aucune branche. On va donc enregistrer notre branche sur le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À partir de cette commande, la branche locale //master// sera liée à la branche distante //origin/master//.&lt;br /&gt;
Lors des prochaines commandes &#039;&#039;git push&#039;&#039;, grâce à cette liaison, tous les commits sur la branche locale //master// seront poussées sur le serveur distant.&lt;br /&gt;
&lt;br /&gt;
===Méthode moins simple: bare first===&lt;br /&gt;
&lt;br /&gt;
Si on commence dans par le serveur &amp;quot;vide&amp;quot;, il faudra le cloner au lieu de le définir comme un dépôt distant.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création du dépôt vide&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que ce dépôt est accessible à l&#039;URL URL_REPO&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clonage du dépôt&lt;br /&gt;
git clone URL_REPO clone-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un avertissement indique que l&#039;on clone un dépôt vide: le dépôt local à donc une branche master, mais elle n&#039;est pas liée au dépôt distant, car celui-ci n&#039;a aucune branche.&lt;br /&gt;
Le dépôt distant est automatiquement appelé //origin//.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Commit dans le dépôt local&lt;br /&gt;
cd clone-repo&lt;br /&gt;
echo hello &amp;gt; readme.rst&lt;br /&gt;
git add readme.rst&lt;br /&gt;
git commit et ses dépendances&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme dans la méthode simple, il faut pousser la branche master vers le dépôt distant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===De l&#039;importance des README===&lt;br /&gt;
&lt;br /&gt;
Il est très important d&#039;avoir au moins 2 fichiers dans votre dépôt Git:&lt;br /&gt;
&lt;br /&gt;
* LICENSE: contenant le texte **complet** de la licence de votre projet&lt;br /&gt;
* README: décrivant votre projet et comment l&#039;utiliser. Ce fichier doit rappeler le nom de la licence de votre projet&lt;br /&gt;
&lt;br /&gt;
Il est aussi recommandé d&#039;avoir les fichiers suivants:&lt;br /&gt;
&lt;br /&gt;
* AUTHORS: contenant la liste des noms/pseudos et e-mails des auteurs de commits ou de code inclus dans ce projet&lt;br /&gt;
* INSTALL: contenant la liste des dépendances de ce projet et des commandes à utiliser pour le compiler et l&#039;installer&lt;br /&gt;
&lt;br /&gt;
Les fichiers LICENSE sont des fichiers textes bruts.&lt;br /&gt;
Les autres fichiers sont généralement dans un format offrant un peu plus de lisibilté, par exemple dans les formats [http://daringfireball.net/projects/markdown/ Markdown] (.md) ou [http://docutils.sourceforge.net/rst.html reStructuredText] (.rst)&lt;br /&gt;
&lt;br /&gt;
Un plug-in existe pour éditer des fichier reStructuredText dans Eclipse: ReST Editor, disponible sur le [https://marketplace.eclipse.org/content/rest-editor Marketplace Eclipse]&lt;br /&gt;
&lt;br /&gt;
=Séance 2a: Intégration en continue=&lt;br /&gt;
&lt;br /&gt;
===GitHub &amp;amp; [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
Travis-CI est un service permettant d&#039;exécuter un script dans une machine virtuelle Ubuntu dès que vous effectuez un push sur un de vos dépôts GitHub.&lt;br /&gt;
L&#039;intérêt est de savoir si la version d&#039;un projet que vous avez rendu publique peut être compilée et si ses tests passent.&lt;br /&gt;
&lt;br /&gt;
La machine virtuelle &amp;quot;offerte&amp;quot; par Travis est préconfigurée pour le language indiqué dans son fichier de configuration (&#039;&#039;&#039;.travis.yml&#039;&#039;&#039;), mais il est possible d&#039;utiliser la commande &#039;&#039;&#039;sudo apt-get install ...&#039;&#039;&#039; pour ajouter vos dépendances.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour utiliser [[Travis-CI]]:&lt;br /&gt;
&lt;br /&gt;
# Créez compte individuel sur GitHub https://github.com&lt;br /&gt;
# &#039;&#039;Fork&#039;&#039;ez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Ajoutez un collaborateur (i.e. votre binôme) au projet &#039;&#039;forké&#039;&#039;, via les paramètres (&#039;&#039;settings&#039;&#039;) de ce projet&lt;br /&gt;
# Pour l&#039;exemple, activez le service (ou hook) &#039;&#039;Email&#039;&#039; depuis les paramètres du dépôt: à chaque fois que vous ou un de vos collaborateurs ferra un &#039;&#039;&#039;git push&#039;&#039;&#039;, vous recevrez une notification par mail.&lt;br /&gt;
# Activez le service Travis-CI: identifiez-vous (&#039;&#039;sign in&#039;&#039;) sur https://travis-ci.org/ avec votre compte GitHub&lt;br /&gt;
# Activez le service pour les projets sur lesquels vous souhaitez appliquer les principes d&#039;intégration continue&lt;br /&gt;
&lt;br /&gt;
[[Travis-CI]] utilise un fichier nommé &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; (attention: fichier caché sous Unix) pour se configurer et choisir les opérations à effectuer.&lt;br /&gt;
Ce fichier doit se trouver à la racine de votre dépôt Git.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; du fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; ci-dessous.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
language: node_js&lt;br /&gt;
node_js:&lt;br /&gt;
  - &amp;quot;0.11&amp;quot;&lt;br /&gt;
  - &amp;quot;0.10&amp;quot;&lt;br /&gt;
  - &amp;quot;0.8&amp;quot;&lt;br /&gt;
  - &amp;quot;0.6&amp;quot;&lt;br /&gt;
  - iojs&lt;br /&gt;
  - iojs-v1.0.2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; indique à [[Travis-CI]] que les scripts de ce projet dans ce dépôt seront exécutés avec plusieurs versions de [[Node.js]].&lt;br /&gt;
&lt;br /&gt;
Ajoutez dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&#039; la section suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;quot;devDependencies&amp;quot;: {&lt;br /&gt;
    &amp;quot;jshint&amp;quot;: &amp;quot;^2.6.0&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;scripts&amp;quot;: {&lt;br /&gt;
    &amp;quot;test&amp;quot;: &amp;quot;./node_modules/jshint/bin/jshint index.js&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
et incrémentez le numéro de version.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Remarque:&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;jshint&#039;&#039;&#039; peut être lancé localement avec les commandes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo npm install jshint&lt;br /&gt;
jshint index.js&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A lire&lt;br /&gt;
* http://docs.travis-ci.com/user/languages/javascript-with-nodejs/&lt;br /&gt;
* https://github.com/docdis/learn-travis/blob/master/README.md&lt;br /&gt;
&lt;br /&gt;
=Séance 2b: Livraison en continue=&lt;br /&gt;
&lt;br /&gt;
==[[Heroku]]==&lt;br /&gt;
[https://www.heroku.com/ Heroku] est une plateforme cloud de type PaaS permettant l&#039;exécution d&#039;applications et de services en ligne écrits dans les langages et plateformes suivantes : Ruby, [[Node.js]], [[Python]], Java, et PHP.&lt;br /&gt;
&lt;br /&gt;
# Créez un compte gratuit sur [https://signup.heroku.com Heroku]&lt;br /&gt;
# Forkez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Dans Heroku, créez une nouvelle app Node.js, et liez-la au repository Github créé à l&#039;étape précédente&lt;br /&gt;
# Choisissez l&#039;option &amp;quot;Déploiement automatique&amp;quot; depuis la branche **master**&lt;br /&gt;
# Modifiez le fichier index.js pour afficher la version de service dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 var fs = require(&#039;fs&#039;);&lt;br /&gt;
 var package = JSON.parse(fs.readFileSync(&#039;./package.json&#039;, &#039;utf8&#039;));&lt;br /&gt;
 var version=package.version;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Hello World! (current version: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
# Modifiez le fichier index.js pour franciser le message dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Bonjour Tout Le Monde! (version courante: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
=Séance 3: Builders=&lt;br /&gt;
&lt;br /&gt;
==[[Ant]]==&lt;br /&gt;
&lt;br /&gt;
==[[Maven]]==&lt;br /&gt;
&lt;br /&gt;
[http://maven.apache.org/download.cgi Charger et installer Maven 3].&lt;br /&gt;
&lt;br /&gt;
Debian/Ubuntu &amp;amp; friends:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install maven&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mvn -version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Faites une copie du projet, basée sur Maven:&lt;br /&gt;
&lt;br /&gt;
# Dans votre dépôt Git, créez un dossier &#039;&#039;&#039;cron4j-mvn&#039;&#039;&#039;: il contiendra le projet Cron4J avec la structure Maven&lt;br /&gt;
# Dans ce dossier, utilisez l&#039;[https://maven.apache.org/guides/introduction/introduction-to-archetypes.html archetype] Maven [http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-quickstart/ maven-archetype-quickstart] (la version des sources de cron4j utilisés est la 2.5.5) (groupId: it.sauronsoftware.cron4j, artifactId: cron4j):&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Cette commande crée un projet avec un fichier &#039;&#039;pom.xml&#039;&#039;, et une classe et un test modèles: supprimez ces modèles&lt;br /&gt;
# Copiez les sources de Cron4J depuis le dossier &#039;&#039;&#039;cron4j-original&#039;&#039;&#039; dans le dossier &#039;&#039;&#039;src/main/java&#039;&#039;&#039; de votre projet Maven&lt;br /&gt;
# Faites un essai de compilation:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Lancez un des exemples avec mvn exec:java -Dexec.mainClass=&amp;quot;com.example.Main&amp;quot; [-Dexec.args=&amp;quot;argument1&amp;quot;] ... ([http://mojo.codehaus.org/exec-maven-plugin/usage.html doc. exec plugin], [http://mojo.codehaus.org/exec-maven-plugin/java-mojo.html doc. Exec:java goal])&lt;br /&gt;
# Enfin modifiez le fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; à la racine de votre dépôt Git afin que Travis exécute la commande &#039;&#039;&#039;mvn clean verify&#039;&#039;&#039; à chaque mise à jour du dépôt GitHub.&lt;br /&gt;
&lt;br /&gt;
==Tests Unitaires avec JUnit 4==&lt;br /&gt;
Survoller le tutoriel [http://www.vogella.com/tutorials/JUnit/article.html Unit Testing with JUnit]&lt;br /&gt;
&lt;br /&gt;
# Veillez à bien utiliser la dépendance JUnit 4.8.2 dans pom.xml&lt;br /&gt;
# Ajouter le test unitaire suivant au projet, dans le fichier &#039;&#039;&#039;src/test/it/sauronsoftware/SchedulingPatternTest.java&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
package it.sauronsoftware;&lt;br /&gt;
&lt;br /&gt;
import it.sauronsoftware.cron4j.SchedulingPattern;&lt;br /&gt;
import it.sauronsoftware.cron4j.InvalidPatternException;&lt;br /&gt;
&lt;br /&gt;
import static org.junit.Assert.assertEquals;&lt;br /&gt;
import static org.junit.Assert.assertTrue;&lt;br /&gt;
&lt;br /&gt;
import org.junit.AfterClass;&lt;br /&gt;
import org.junit.BeforeClass;&lt;br /&gt;
import org.junit.Test;&lt;br /&gt;
&lt;br /&gt;
public class SchedulingPatternTest {&lt;br /&gt;
&lt;br /&gt;
  @BeforeClass&lt;br /&gt;
  public static void testSetup() {&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @AfterClass&lt;br /&gt;
  public static void testCleanup() {&lt;br /&gt;
    // Teardown for data used by the unit tests&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test(expected = InvalidPatternException.class)&lt;br /&gt;
  public void testExceptionIsThrown() {&lt;br /&gt;
    SchedulingPattern sp = new SchedulingPattern(&amp;quot;0 5 * *&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test&lt;br /&gt;
  public void testPattern() {&lt;br /&gt;
    String pattern;&lt;br /&gt;
    pattern=&amp;quot;0 5 * * *|8 10 * * *|22 17 * * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
    pattern=&amp;quot;0 5 * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Committez et Pushez ce nouveau fichier, pour que Travis lance les tests dès que possible&lt;br /&gt;
# Lancez les tests unitaires avec &amp;lt;pre&amp;gt;mvn test&amp;lt;/pre&amp;gt; Ce test va &#039;&#039;&#039;échouer&#039;&#039;&#039;: corrigez le.&lt;br /&gt;
# Committez et Pushez la version corrigée des tests: Travis enverra un mail pour indiquer si les tests échouent ou non&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; Travis va exécuter les tests &#039;&#039;dès que possible&#039;&#039;. Il est possible de recevoir un mail indiquant que les tests du premier &#039;&#039;push&#039;&#039; échouent alors que l&#039;on a déjà &#039;&#039;pushé&#039;&#039; la correction.&lt;br /&gt;
# Naviguez sur http://travis-ci.org pour vérifier les builds effectués.&lt;br /&gt;
# Créez des tests unitaires supplémentaire du i.s.c.CronParser&lt;br /&gt;
&lt;br /&gt;
===[[Maven]] avec [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
===Git (suite)===&lt;br /&gt;
&lt;br /&gt;
# Forkez le projet &#039;&#039;&#039;tagl&#039;&#039;&#039; d&#039;un autre binome (i.e. autre que &#039;&#039;donsez/tagl&#039;&#039;)&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; donnez lui un nom différent (e.g. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Clonez ce nouveau dépôt&lt;br /&gt;
# Lancez une compilation pour valider l&#039;état du projet (bonne pratique)&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Situez vous dans une nouvelle branch git:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;git checkout -b add-license&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Ajoutez une bannière de licence dans le fichier &#039;&#039;&#039;cron4j-mvn/pom.xml&#039;&#039;&#039;&lt;br /&gt;
# Lancez une nouvelle compilation pour valider vos modifications&lt;br /&gt;
# Commitez et pushez (vers votre fork de ce dépôt, i.e. &#039;&#039;tagl-licensing&#039;&#039;) (pour pusher une branche nouvellement créée: git push origin add-license)&lt;br /&gt;
# Via le site de GitHub, proposez un &amp;quot;Pull Request&amp;quot; au projet initial&lt;br /&gt;
&lt;br /&gt;
Vous pouvez ensuite supprimer le clone de ce fork.&lt;br /&gt;
Lorsque le &#039;&#039;pull request&#039;&#039; aura été accepté, vous pourrez supprimer votre fork (&#039;&#039;tagl-licensing&#039;&#039;) de votre compte GitHub.&lt;br /&gt;
&lt;br /&gt;
===Contrôle Continu===&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt &#039;&#039;tagl&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le plugin [http://mojo.codehaus.org/cobertura-maven-plugin/usage.html Cobertura] à votre projet Maven.&lt;br /&gt;
## Configurez le plugin pour [http://mojo.codehaus.org/cobertura-maven-plugin/examples/report-formats.html générer un rapport] HTML. Le résultat se trouvera dans &#039;&#039;target/site/cobertura&#039;&#039;&lt;br /&gt;
## Le plugin ne s&#039;exécute automatiquement pas durant la compilation, il faut utiliser la commande : &amp;lt;pre&amp;gt;mvn cobertura:cobertura&amp;lt;/pre&amp;gt;&lt;br /&gt;
## &#039;&#039;&#039;Bonus:&#039;&#039;&#039; Modifiez le fichier &#039;&#039;pom.xml&#039;&#039; pour que le &#039;&#039;goal&#039;&#039; &#039;&#039;&#039;cobertura&#039;&#039;&#039; soit exécuté pendant la &#039;&#039;phase&#039;&#039; &#039;&#039;&#039;package&#039;&#039;&#039;.&lt;br /&gt;
# Répondez aux questions : &#039;&#039;Mais qu&#039;est ce que la couverture de code ? En quoi c&#039;est utile ?&#039;&#039;&lt;br /&gt;
# Ajoutez au projet Maven les plugins pour la génération d&#039;un site et de rapports (Javadoc, tests unitaires, tags list (FIXME, TODO, ...), ...): voir http://maven.apache.org/plugins/maven-site-plugin/ et d&#039;autres.&lt;br /&gt;
# Regardez les exemples d&#039;utilisation de cron4j dans cron4j-original/examples&lt;br /&gt;
&lt;br /&gt;
===Bonus Track===&lt;br /&gt;
&lt;br /&gt;
====Clone SVN -&amp;gt; Git====&lt;br /&gt;
&lt;br /&gt;
Source: http://www.yterium.net/Migrer-un-projet-SVN-vers-GIT&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Cloner le dépôt SVN en dépôt Git (conservation historique)&lt;br /&gt;
$ git svn clone  svn://svn.code.sf.net/p/cron4j/code/trunk cron4j-original&lt;br /&gt;
$ cd cron4j-original&lt;br /&gt;
# Test compilation&lt;br /&gt;
$ ant jar&lt;br /&gt;
$ cd ..&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Préparation TAGL====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clone du dépôt TAGL&lt;br /&gt;
$ git clone git@github.com:donsez/tagl.git&lt;br /&gt;
$ cd tagl&lt;br /&gt;
# &amp;quot;Fetch&amp;quot; du dépôt local cloné précédemment&lt;br /&gt;
$ git fetch file://$(pwd)/../cron4j-original&lt;br /&gt;
# Fusion de ce qui vient d&#039;être fetché&lt;br /&gt;
$ git merge FETCH_HEAD&lt;br /&gt;
# Envoi sur le serveur&lt;br /&gt;
$ git push&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Cherry-picking: reprise des modifications d&#039;un collègue====&lt;br /&gt;
&lt;br /&gt;
On considère que:&lt;br /&gt;
&lt;br /&gt;
* votre dépôt Git distant est à l&#039;adresse URL_DEPOT&lt;br /&gt;
* votre collègue a un dépôt Git à l&#039;adresse URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Dossier temporaire&lt;br /&gt;
cd /tmp&lt;br /&gt;
&lt;br /&gt;
# Clone de votre dépôt&lt;br /&gt;
git clone URL_DEPOT mon_depot&lt;br /&gt;
&lt;br /&gt;
# Déplacement dans votre dépôt&lt;br /&gt;
cd mon_depot&lt;br /&gt;
&lt;br /&gt;
# Définition du dépôt distant&lt;br /&gt;
git remote add collegue URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
# Récupération des infos du dépôt du collègue&lt;br /&gt;
git fetch collegue&lt;br /&gt;
&lt;br /&gt;
# Maintenant, on peut voir les branches du collègue&lt;br /&gt;
git branch -a&lt;br /&gt;
&lt;br /&gt;
# On peut fusionner avec une branche&lt;br /&gt;
git merge collegue/master&lt;br /&gt;
&lt;br /&gt;
# Si vous avez des conflits, éditez les fichiers concernés,&lt;br /&gt;
# et committez avec git commit&lt;br /&gt;
&lt;br /&gt;
# Push vers votre dépôt distant&lt;br /&gt;
git push origin&lt;br /&gt;
&lt;br /&gt;
# Optionnel: supprimez la référence vers le dépôt du collègue&lt;br /&gt;
git remote rm collegue&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Archetype webapp====&lt;br /&gt;
L&#039;archetype webapp (http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-webapp/) permet de créer le squelette d&#039;une webapp. Créez un simple webapp monsite en version 0.1.0. (add/commit/push). Vous pourrez tester cette webapp en ajoutant au pom.xml le [https://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin plugin maven Jetty].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mvn -Djetty.port=9999 jetty:run&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naviguez sur http://localhost:9999/monsite&lt;br /&gt;
&lt;br /&gt;
====Scrum tools====&lt;br /&gt;
Ces 3 services peuvent être couplé à votre dépôt GitHub pour votre gestion de projet agile avec [[Scrum]] :&lt;br /&gt;
* http://www.acunote.com/&lt;br /&gt;
* http://backlogtool.com/&lt;br /&gt;
* http://www.scrumdo.com/&lt;br /&gt;
&lt;br /&gt;
L&#039;activation se fait via &#039;&#039;Settings &amp;gt; Webhooks &amp;amp; Services &amp;gt; Configure services&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Séance 4: AOP &amp;amp; AspectJ=&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt Git, projet &#039;&#039;cron4j-mvn&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le [http://mojo.codehaus.org/aspectj-maven-plugin/ plugin Maven pour AspectJ] au pom.xml&lt;br /&gt;
# Ajoutez un aspect de trace à l&#039;invocation des méthodes &#039;&#039;&#039;run()&#039;&#039;&#039; de l&#039;interface java.lang.Runnable (uniquement pour les objets &#039;&#039;schedulé&#039;&#039;s)&lt;br /&gt;
#: Affichez une trace avant et après l&#039;exécution de la tâche&lt;br /&gt;
# Préparez un nouveau test (nouvelle classe) démarrant un Scheduler Cron4j et validant l&#039;exécution d&#039;une tâche au bout d&#039;une minute (pattern &amp;quot;* * * * *&amp;quot;)&lt;br /&gt;
#: Lors de l&#039;exécution de &#039;&#039;&#039;mvn test&#039;&#039;&#039;, vous devez voir apparaître les traces préparées dans votre aspect.&lt;br /&gt;
&lt;br /&gt;
Liens utiles:&lt;br /&gt;
* [http://ridgetopsolutions.com/blog/2013/02/12/getting-started-with-aspectj-and-maven/ Getting started with AspectJ and Maven]&lt;br /&gt;
&lt;br /&gt;
===Contrôle continu===&lt;br /&gt;
&lt;br /&gt;
# Complétez l&#039;aspect de trace avec le positionnement du [http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html java.lang.ThreadLocal] pour passer 1) l&#039;identifiant du job et 2) le compteur des appels de la méthode de l&#039;objet.&lt;br /&gt;
&lt;br /&gt;
=Séance 5: Pelix &amp;amp; iPOPO=&lt;br /&gt;
&lt;br /&gt;
Pelix est une plate-forme d&#039;application à services (SOA).&lt;br /&gt;
iPOPO est un modèle de composants orientés services (SOCM).&lt;br /&gt;
&lt;br /&gt;
La documentation de Pelix et iPOPO est disponible sur https://ipopo.coderxpress.net/&lt;br /&gt;
&lt;br /&gt;
===Installation de iPOPO===&lt;br /&gt;
&lt;br /&gt;
* Cloner le dépôt Git depuis https://github.com/tcalmant/ipopo&lt;br /&gt;
* Se placer dans la branche &#039;&#039;dev&#039;&#039;&lt;br /&gt;
* Pour installer iPOPO, lancer la commande :&lt;br /&gt;
&lt;br /&gt;
   sudo python setup.py install&lt;br /&gt;
&lt;br /&gt;
===Shell Pelix===&lt;br /&gt;
&lt;br /&gt;
Pour lancer un shell Pelix, utilisez la commande:&lt;br /&gt;
&lt;br /&gt;
   python -m pelix.shell.console&lt;br /&gt;
&lt;br /&gt;
Les commandes disponibles sont décrites ici: [https://ipopo.coderxpress.net/wiki/doku.php?id=ipopo:refcards:shell Shell Commands]&lt;br /&gt;
&lt;br /&gt;
===Rappels de Python===&lt;br /&gt;
&lt;br /&gt;
* Pas de déclaration du type d&#039;une variable&lt;br /&gt;
* Les méthodes d&#039;une classe ont toute comme premier paramètre &#039;&#039;self&#039;&#039;, équivalent du &#039;&#039;this&#039;&#039; en Java.&lt;br /&gt;
* Blocs définis par indentation (4 espaces ou 1 tab)&lt;br /&gt;
* Une ligne finissant par &#039;:&#039; démarre toujours un bloc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Import d&#039;un module&lt;br /&gt;
import pelix&lt;br /&gt;
&lt;br /&gt;
# Définition d&#039;une classe&lt;br /&gt;
class MaClasse:&lt;br /&gt;
   # Constructeur&lt;br /&gt;
   def __init__(self):&lt;br /&gt;
       self.default = &amp;quot;stanger&amp;quot;&lt;br /&gt;
       print(&amp;quot;Classe construite&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
   # Méthode, avec un argument&lt;br /&gt;
   def sayHello(self, name):&lt;br /&gt;
       if not name:&lt;br /&gt;
           # Nom vide ou nul&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(self.default)&lt;br /&gt;
       else:&lt;br /&gt;
           # Nom valide&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(name)&lt;br /&gt;
&lt;br /&gt;
objet = MaClasse()&lt;br /&gt;
print(objet.sayHello(&amp;quot;&amp;quot;))&lt;br /&gt;
print(objet.sayHello(&amp;quot;World&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Service Ping-Pong===&lt;br /&gt;
&lt;br /&gt;
1. Écrire un fichier &#039;&#039;pong.py&#039;&#039;, définissant une classe &#039;&#039;Pong&#039;&#039; ayant une méthode &#039;&#039;pong&#039;&#039; prenant en paramètre un message et retournant le message préfixé par &amp;quot;PONG:&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Exemple: &lt;br /&gt;
   &lt;br /&gt;
      pong = Pong()&lt;br /&gt;
      pong.pong(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2. Écrire un fichier &#039;&#039;ping.py&#039;&#039;, définissant une classe &#039;&#039;Ping&#039;&#039; ayant une méthode &#039;&#039;ping&#039;&#039; prenant en paramètre un message, créant un objet Pong et retournant le résultat de Pong.pong(message) préfixé par &amp;quot;PING:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&lt;br /&gt;
      ping = Ping()&lt;br /&gt;
      ping.ping(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PING:PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
3. Transformer le fichier &#039;&#039;pong.py&#039;&#039; pour qu&#039;il devienne un bundle Pelix enregistrant un objet Pong comme étant un service ayant pour spécification &amp;quot;tagl.pong&amp;quot;&lt;br /&gt;
* Définir une classe &#039;&#039;Activator&#039;&#039;, décorée avec &#039;&#039;@BundleActivator&#039;&#039;&lt;br /&gt;
* Enregistrer le service dans la méthode &#039;&#039;Activator.start&#039;&#039; et le désenregistrer dans &#039;&#039;Activator.stop&#039;&#039;&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/provider.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;pong&#039; et vérifier que le service est bien inscrit avec la commande &#039;&#039;sl&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
4.Transformer la classe &#039;&#039;Ping&#039;&#039; dans &#039;&#039;ping.py&#039;&#039; en un composant iPOPO&lt;br /&gt;
* L&#039;objet Pong utilisé dans &#039;&#039;ping()&#039;&#039; doit être un service injecté par iPOPO (&#039;&#039;@Requires&#039;&#039;)&lt;br /&gt;
* Appeler la méthode &#039;&#039;ping()&#039;&#039; dès que le service Pong est injecté (&#039;&#039;@BindField&#039;&#039;) ou disparait (&#039;&#039;@UnbindField&#039;&#039;)&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/consumer.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;ping&#039; et vérifier son comportement si le bundle &#039;&#039;pong&#039;&#039; ou le bundle &#039;&#039;ping&#039;&#039; est arrêté et redémarré.&lt;br /&gt;
&lt;br /&gt;
5. Mettre à jour le bundle &#039;&#039;pong&#039;&#039;&lt;br /&gt;
* Remplacer le préfixe &amp;quot;PONG&amp;quot; par &amp;quot;NI&amp;quot;&lt;br /&gt;
* Dans le shell Pelix, mettre à jour le bundle &#039;&#039;pong&#039;&#039; sans redémarrer la plate-forme (commande &#039;&#039;udpate&#039;&#039;).&lt;br /&gt;
* Vérifier les traces dans le shell pour valider la mise à jour du service.&lt;br /&gt;
&lt;br /&gt;
===Remote Services===&lt;br /&gt;
&lt;br /&gt;
* Ajouter les propriétés permettant l&#039;export du service Pong dans &#039;&#039;pong.py&#039;&#039; (s&#039;inspirer de &#039;&#039;provider.py&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
* Lancer deux shells iPOPO (dans deux terminaux)&lt;br /&gt;
* Dans chaque shell iPOPO, installer les bundles:&lt;br /&gt;
** &#039;&#039;pelix.remote.dispatcher&#039;&#039;: Exportateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.registry&#039;&#039;; Importateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.discovery.multicast&#039;&#039;: Découverte de services via Multicast&lt;br /&gt;
** &#039;&#039;pelix.remote.xml_rpc&#039;&#039;: Transport XML-RPC&lt;br /&gt;
** &#039;&#039;pelix.http.basic&#039;&#039;: Serveur HTTP&lt;br /&gt;
&lt;br /&gt;
Attention: il peut être nécessaire de désactiver votre pare-feu pour que les Remote Services fonctionnent&lt;br /&gt;
&lt;br /&gt;
* Instancier les composants depuis le shell iPOPO, dans chaque framework:&lt;br /&gt;
** Serveur HTTP sur le port 8080: &#039;&#039;instantiate pelix.http.service.basic.factory http-server pelix.http.port=8080&#039;&#039; (penser à changer de port dans chaque framework)&lt;br /&gt;
** Multicast Discovery: &#039;&#039;instantiate pelix-remote-discovery-multicast-factory multicast-discovery&#039;&#039;&lt;br /&gt;
** XML-RPC Exporter: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-exporter&#039;&#039;&lt;br /&gt;
** XML-RPC Importer: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-importer&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Installer le bundle &#039;&#039;ping&#039;&#039; dans un des frameworks et le bundle &#039;&#039;pong&#039;&#039; dans l&#039;autre.&lt;br /&gt;
* Le composant ping peut appeler le service pong, qui est dans l&#039;autre framework.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Voir le code de &#039;&#039;run_remote.py&#039;&#039; pour voir comment démarrer un framework Pelix et installer des bundles depuis Python.&lt;br /&gt;
* Jouer un peu avec &#039;&#039;run_remote.py&#039;&#039; (voir &#039;&#039;run_remote.py --help&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=Séance 6=&lt;br /&gt;
[[Tutorial OSGi avec Apache Felix]]&lt;br /&gt;
&lt;br /&gt;
=Séance 7=&lt;br /&gt;
Faire un projet PDE pour un bundle cron4j.gogo (indépendant de cron4j.bundle)&lt;br /&gt;
&lt;br /&gt;
Utilisation de https://eclipse.org/tycho/&lt;/div&gt;</summary>
		<author><name>MatthieuCaneill</name></author>
	</entry>
	<entry>
		<id>https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21490</id>
		<title>TAGL/TP</title>
		<link rel="alternate" type="text/html" href="https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21490"/>
		<updated>2015-02-26T16:46:08Z</updated>

		<summary type="html">&lt;p&gt;MatthieuCaneill: /* Git (suite) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Travaux pratiques de l&#039;UE [[TAGL]].&lt;br /&gt;
&lt;br /&gt;
Anciennes versions : [[TAGL/TP 2014]]&lt;br /&gt;
&lt;br /&gt;
=Séance 1 : Gestion de versions=&lt;br /&gt;
==Git==&lt;br /&gt;
&lt;br /&gt;
Création d&#039;un dépôt Git local&lt;br /&gt;
&lt;br /&gt;
===Méthode simple: init first===&lt;br /&gt;
&lt;br /&gt;
Via cette méthode, on crée un dépôt local, avec un répertoire de travail, puis on pousse ses modifications vers un dépôt &amp;quot;bare&amp;quot;.&lt;br /&gt;
Cette méthode est la plus simple, car on dispose immédiatement d&#039;un répertoire de travail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création d&#039;un dépôt Git dans le dossier simple-repo&lt;br /&gt;
git init simple-repo&lt;br /&gt;
&lt;br /&gt;
# Création d&#039;un README&lt;br /&gt;
cd simple-repo&lt;br /&gt;
echo &amp;quot;Hello, World&amp;quot; &amp;gt; README&lt;br /&gt;
&lt;br /&gt;
# Ajout du versionnement du fichier README&lt;br /&gt;
git add README&lt;br /&gt;
&lt;br /&gt;
# Commit&lt;br /&gt;
git commit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À ce niveau, on a un dépôt Git complètement fonctionnel.&lt;br /&gt;
Cependant, il est intéressant de pousser ses modifications vers un autre dépôt, sur une autre machine.&lt;br /&gt;
On va donc créer un dépôt bare sur une autre machine (ou autre dossier pour l&#039;exemple)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que l&#039;URL pour accéder à ce dépôt est URL_REPO.&lt;br /&gt;
On va d&#039;abord ajouter ce dépôt serveur à la liste des dépôts connu-repos de votre dépôt local.&lt;br /&gt;
Étant donné qu&#039;il s&#039;agit du dépôt &amp;quot;principal&amp;quot; à utiliser, on l&#039;appellera //origin//, par convention.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin URL_REPO&lt;br /&gt;
# Récupération de ses informations&lt;br /&gt;
git fetch origin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce serveur distant est &amp;quot;vide&amp;quot;: il n&#039;a aucune branche. On va donc enregistrer notre branche sur le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À partir de cette commande, la branche locale //master// sera liée à la branche distante //origin/master//.&lt;br /&gt;
Lors des prochaines commandes &#039;&#039;git push&#039;&#039;, grâce à cette liaison, tous les commits sur la branche locale //master// seront poussées sur le serveur distant.&lt;br /&gt;
&lt;br /&gt;
===Méthode moins simple: bare first===&lt;br /&gt;
&lt;br /&gt;
Si on commence dans par le serveur &amp;quot;vide&amp;quot;, il faudra le cloner au lieu de le définir comme un dépôt distant.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création du dépôt vide&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que ce dépôt est accessible à l&#039;URL URL_REPO&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clonage du dépôt&lt;br /&gt;
git clone URL_REPO clone-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un avertissement indique que l&#039;on clone un dépôt vide: le dépôt local à donc une branche master, mais elle n&#039;est pas liée au dépôt distant, car celui-ci n&#039;a aucune branche.&lt;br /&gt;
Le dépôt distant est automatiquement appelé //origin//.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Commit dans le dépôt local&lt;br /&gt;
cd clone-repo&lt;br /&gt;
echo hello &amp;gt; readme.rst&lt;br /&gt;
git add readme.rst&lt;br /&gt;
git commit et ses dépendances&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme dans la méthode simple, il faut pousser la branche master vers le dépôt distant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===De l&#039;importance des README===&lt;br /&gt;
&lt;br /&gt;
Il est très important d&#039;avoir au moins 2 fichiers dans votre dépôt Git:&lt;br /&gt;
&lt;br /&gt;
* LICENSE: contenant le texte **complet** de la licence de votre projet&lt;br /&gt;
* README: décrivant votre projet et comment l&#039;utiliser. Ce fichier doit rappeler le nom de la licence de votre projet&lt;br /&gt;
&lt;br /&gt;
Il est aussi recommandé d&#039;avoir les fichiers suivants:&lt;br /&gt;
&lt;br /&gt;
* AUTHORS: contenant la liste des noms/pseudos et e-mails des auteurs de commits ou de code inclus dans ce projet&lt;br /&gt;
* INSTALL: contenant la liste des dépendances de ce projet et des commandes à utiliser pour le compiler et l&#039;installer&lt;br /&gt;
&lt;br /&gt;
Les fichiers LICENSE sont des fichiers textes bruts.&lt;br /&gt;
Les autres fichiers sont généralement dans un format offrant un peu plus de lisibilté, par exemple dans les formats [http://daringfireball.net/projects/markdown/ Markdown] (.md) ou [http://docutils.sourceforge.net/rst.html reStructuredText] (.rst)&lt;br /&gt;
&lt;br /&gt;
Un plug-in existe pour éditer des fichier reStructuredText dans Eclipse: ReST Editor, disponible sur le [https://marketplace.eclipse.org/content/rest-editor Marketplace Eclipse]&lt;br /&gt;
&lt;br /&gt;
=Séance 2a: Intégration en continue=&lt;br /&gt;
&lt;br /&gt;
===GitHub &amp;amp; [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
Travis-CI est un service permettant d&#039;exécuter un script dans une machine virtuelle Ubuntu dès que vous effectuez un push sur un de vos dépôts GitHub.&lt;br /&gt;
L&#039;intérêt est de savoir si la version d&#039;un projet que vous avez rendu publique peut être compilée et si ses tests passent.&lt;br /&gt;
&lt;br /&gt;
La machine virtuelle &amp;quot;offerte&amp;quot; par Travis est préconfigurée pour le language indiqué dans son fichier de configuration (&#039;&#039;&#039;.travis.yml&#039;&#039;&#039;), mais il est possible d&#039;utiliser la commande &#039;&#039;&#039;sudo apt-get install ...&#039;&#039;&#039; pour ajouter vos dépendances.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour utiliser [[Travis-CI]]:&lt;br /&gt;
&lt;br /&gt;
# Créez compte individuel sur GitHub https://github.com&lt;br /&gt;
# &#039;&#039;Fork&#039;&#039;ez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Ajoutez un collaborateur (i.e. votre binôme) au projet &#039;&#039;forké&#039;&#039;, via les paramètres (&#039;&#039;settings&#039;&#039;) de ce projet&lt;br /&gt;
# Pour l&#039;exemple, activez le service (ou hook) &#039;&#039;Email&#039;&#039; depuis les paramètres du dépôt: à chaque fois que vous ou un de vos collaborateurs ferra un &#039;&#039;&#039;git push&#039;&#039;&#039;, vous recevrez une notification par mail.&lt;br /&gt;
# Activez le service Travis-CI: identifiez-vous (&#039;&#039;sign in&#039;&#039;) sur https://travis-ci.org/ avec votre compte GitHub&lt;br /&gt;
# Activez le service pour les projets sur lesquels vous souhaitez appliquer les principes d&#039;intégration continue&lt;br /&gt;
&lt;br /&gt;
[[Travis-CI]] utilise un fichier nommé &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; (attention: fichier caché sous Unix) pour se configurer et choisir les opérations à effectuer.&lt;br /&gt;
Ce fichier doit se trouver à la racine de votre dépôt Git.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; du fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; ci-dessous.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
language: node_js&lt;br /&gt;
node_js:&lt;br /&gt;
  - &amp;quot;0.11&amp;quot;&lt;br /&gt;
  - &amp;quot;0.10&amp;quot;&lt;br /&gt;
  - &amp;quot;0.8&amp;quot;&lt;br /&gt;
  - &amp;quot;0.6&amp;quot;&lt;br /&gt;
  - iojs&lt;br /&gt;
  - iojs-v1.0.2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; indique à [[Travis-CI]] que les scripts de ce projet dans ce dépôt seront exécutés avec plusieurs versions de [[Node.js]].&lt;br /&gt;
&lt;br /&gt;
Ajoutez dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&#039; la section suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;quot;devDependencies&amp;quot;: {&lt;br /&gt;
    &amp;quot;jshint&amp;quot;: &amp;quot;^2.6.0&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;scripts&amp;quot;: {&lt;br /&gt;
    &amp;quot;test&amp;quot;: &amp;quot;./node_modules/jshint/bin/jshint index.js&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
et incrémentez le numéro de version.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Remarque:&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;jshint&#039;&#039;&#039; peut être lancé localement avec les commandes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo npm install jshint&lt;br /&gt;
jshint index.js&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A lire&lt;br /&gt;
* http://docs.travis-ci.com/user/languages/javascript-with-nodejs/&lt;br /&gt;
* https://github.com/docdis/learn-travis/blob/master/README.md&lt;br /&gt;
&lt;br /&gt;
=Séance 2b: Livraison en continue=&lt;br /&gt;
&lt;br /&gt;
==[[Heroku]]==&lt;br /&gt;
[https://www.heroku.com/ Heroku] est une plateforme cloud de type PaaS permettant l&#039;exécution d&#039;applications et de services en ligne écrits dans les langages et plateformes suivantes : Ruby, [[Node.js]], [[Python]], Java, et PHP.&lt;br /&gt;
&lt;br /&gt;
# Créez un compte gratuit sur [https://signup.heroku.com Heroku]&lt;br /&gt;
# Forkez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Dans Heroku, créez une nouvelle app Node.js, et liez-la au repository Github créé à l&#039;étape précédente&lt;br /&gt;
# Choisissez l&#039;option &amp;quot;Déploiement automatique&amp;quot; depuis la branche **master**&lt;br /&gt;
# Modifiez le fichier index.js pour afficher la version de service dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 var fs = require(&#039;fs&#039;);&lt;br /&gt;
 var package = JSON.parse(fs.readFileSync(&#039;./package.json&#039;, &#039;utf8&#039;));&lt;br /&gt;
 var version=package.version;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Hello World! (current version: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
# Modifiez le fichier index.js pour franciser le message dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Bonjour Tout Le Monde! (version courante: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
=Séance 3: Builders=&lt;br /&gt;
&lt;br /&gt;
==[[Ant]]==&lt;br /&gt;
&lt;br /&gt;
==[[Maven]]==&lt;br /&gt;
&lt;br /&gt;
[http://maven.apache.org/download.cgi Charger et installer Maven 3].&lt;br /&gt;
&lt;br /&gt;
Debian/Ubuntu &amp;amp; friends:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install maven&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mvn -version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Faites une copie du projet, basée sur Maven:&lt;br /&gt;
&lt;br /&gt;
# Dans votre dépôt Git, créez un dossier &#039;&#039;&#039;cron4j-mvn&#039;&#039;&#039;: il contiendra le projet Cron4J avec la structure Maven&lt;br /&gt;
# Dans ce dossier, utilisez l&#039;[https://maven.apache.org/guides/introduction/introduction-to-archetypes.html archetype] Maven [http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-quickstart/ maven-archetype-quickstart] (la version des sources de cron4j utilisés est la 2.5.5) (groupId: it.sauronsoftware.cron4j, artifactId: cron4j):&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Cette commande crée un projet avec un fichier &#039;&#039;pom.xml&#039;&#039;, et une classe et un test modèles: supprimez ces modèles&lt;br /&gt;
# Copiez les sources de Cron4J depuis le dossier &#039;&#039;&#039;cron4j-original&#039;&#039;&#039; dans le dossier &#039;&#039;&#039;src/main/java&#039;&#039;&#039; de votre projet Maven&lt;br /&gt;
# Faites un essai de compilation:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Lancez un des exemples avec mvn exec:java -Dexec.mainClass=&amp;quot;com.example.Main&amp;quot; [-Dexec.args=&amp;quot;argument1&amp;quot;] ... ([http://mojo.codehaus.org/exec-maven-plugin/usage.html doc. exec plugin], [http://mojo.codehaus.org/exec-maven-plugin/java-mojo.html doc. Exec:java goal])&lt;br /&gt;
# Enfin modifiez le fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; à la racine de votre dépôt Git afin que Travis exécute la commande &#039;&#039;&#039;mvn clean verify&#039;&#039;&#039; à chaque mise à jour du dépôt GitHub.&lt;br /&gt;
&lt;br /&gt;
==Tests Unitaires avec JUnit 4==&lt;br /&gt;
Survoller le tutoriel [http://www.vogella.com/tutorials/JUnit/article.html Unit Testing with JUnit]&lt;br /&gt;
&lt;br /&gt;
# Veillez à bien utiliser la dépendance JUnit 4.8.2 dans pom.xml&lt;br /&gt;
# Ajouter le test unitaire suivant au projet, dans le fichier &#039;&#039;&#039;src/test/it/sauronsoftware/SchedulingPatternTest.java&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
package it.sauronsoftware;&lt;br /&gt;
&lt;br /&gt;
import it.sauronsoftware.cron4j.SchedulingPattern;&lt;br /&gt;
import it.sauronsoftware.cron4j.InvalidPatternException;&lt;br /&gt;
&lt;br /&gt;
import static org.junit.Assert.assertEquals;&lt;br /&gt;
import static org.junit.Assert.assertTrue;&lt;br /&gt;
&lt;br /&gt;
import org.junit.AfterClass;&lt;br /&gt;
import org.junit.BeforeClass;&lt;br /&gt;
import org.junit.Test;&lt;br /&gt;
&lt;br /&gt;
public class SchedulingPatternTest {&lt;br /&gt;
&lt;br /&gt;
  @BeforeClass&lt;br /&gt;
  public static void testSetup() {&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @AfterClass&lt;br /&gt;
  public static void testCleanup() {&lt;br /&gt;
    // Teardown for data used by the unit tests&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test(expected = InvalidPatternException.class)&lt;br /&gt;
  public void testExceptionIsThrown() {&lt;br /&gt;
    SchedulingPattern sp = new SchedulingPattern(&amp;quot;0 5 * *&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test&lt;br /&gt;
  public void testPattern() {&lt;br /&gt;
    String pattern;&lt;br /&gt;
    pattern=&amp;quot;0 5 * * *|8 10 * * *|22 17 * * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
    pattern=&amp;quot;0 5 * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Committez et Pushez ce nouveau fichier, pour que Travis lance les tests dès que possible&lt;br /&gt;
# Lancez les tests unitaires avec &amp;lt;pre&amp;gt;mvn test&amp;lt;/pre&amp;gt; Ce test va &#039;&#039;&#039;échouer&#039;&#039;&#039;: corrigez le.&lt;br /&gt;
# Committez et Pushez la version corrigée des tests: Travis enverra un mail pour indiquer si les tests échouent ou non&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; Travis va exécuter les tests &#039;&#039;dès que possible&#039;&#039;. Il est possible de recevoir un mail indiquant que les tests du premier &#039;&#039;push&#039;&#039; échouent alors que l&#039;on a déjà &#039;&#039;pushé&#039;&#039; la correction.&lt;br /&gt;
# Naviguez sur http://travis-ci.org pour vérifier les builds effectués.&lt;br /&gt;
# Créez des tests unitaires supplémentaire du i.s.c.CronParser&lt;br /&gt;
&lt;br /&gt;
===[[Maven]] avec [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
===Git (suite)===&lt;br /&gt;
&lt;br /&gt;
# Forkez le projet &#039;&#039;&#039;tagl&#039;&#039;&#039; d&#039;un autre binome (i.e. autre que &#039;&#039;donsez/tagl&#039;&#039;)&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; donnez lui un nom différent (e.g. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Clonez ce nouveau dépôt&lt;br /&gt;
# Lancez une compilation pour valider l&#039;état du projet (bonne pratique)&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Situez vous dans une nouvelle branch git:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;git checkout -b add-license&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Ajoutez une bannière de licence dans le fichier &#039;&#039;&#039;cron4j-mvn/pom.xml&#039;&#039;&#039;&lt;br /&gt;
# Lancez une nouvelle compilation pour valider vos modifications&lt;br /&gt;
# Commitez et pushez (vers votre fork de ce dépôt, i.e. &#039;&#039;tagl-licensing&#039;&#039;) (pour pusher une branche nouvellement créée: git push -u origin add-license)&lt;br /&gt;
# Via le site de GitHub, proposez un &amp;quot;Pull Request&amp;quot; au projet initial&lt;br /&gt;
&lt;br /&gt;
Vous pouvez ensuite supprimer le clone de ce fork.&lt;br /&gt;
Lorsque le &#039;&#039;pull request&#039;&#039; aura été accepté, vous pourrez supprimer votre fork (&#039;&#039;tagl-licensing&#039;&#039;) de votre compte GitHub.&lt;br /&gt;
&lt;br /&gt;
===Contrôle Continu===&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt &#039;&#039;tagl&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le plugin [http://mojo.codehaus.org/cobertura-maven-plugin/usage.html Cobertura] à votre projet Maven.&lt;br /&gt;
## Configurez le plugin pour [http://mojo.codehaus.org/cobertura-maven-plugin/examples/report-formats.html générer un rapport] HTML. Le résultat se trouvera dans &#039;&#039;target/site/cobertura&#039;&#039;&lt;br /&gt;
## Le plugin ne s&#039;exécute automatiquement pas durant la compilation, il faut utiliser la commande : &amp;lt;pre&amp;gt;mvn cobertura:cobertura&amp;lt;/pre&amp;gt;&lt;br /&gt;
## &#039;&#039;&#039;Bonus:&#039;&#039;&#039; Modifiez le fichier &#039;&#039;pom.xml&#039;&#039; pour que le &#039;&#039;goal&#039;&#039; &#039;&#039;&#039;cobertura&#039;&#039;&#039; soit exécuté pendant la &#039;&#039;phase&#039;&#039; &#039;&#039;&#039;package&#039;&#039;&#039;.&lt;br /&gt;
# Répondez aux questions : &#039;&#039;Mais qu&#039;est ce que la couverture de code ? En quoi c&#039;est utile ?&#039;&#039;&lt;br /&gt;
# Ajoutez au projet Maven les plugins pour la génération d&#039;un site et de rapports (Javadoc, tests unitaires, tags list (FIXME, TODO, ...), ...): voir http://maven.apache.org/plugins/maven-site-plugin/ et d&#039;autres.&lt;br /&gt;
# Regardez les exemples d&#039;utilisation de cron4j dans cron4j-original/examples&lt;br /&gt;
&lt;br /&gt;
===Bonus Track===&lt;br /&gt;
&lt;br /&gt;
====Clone SVN -&amp;gt; Git====&lt;br /&gt;
&lt;br /&gt;
Source: http://www.yterium.net/Migrer-un-projet-SVN-vers-GIT&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Cloner le dépôt SVN en dépôt Git (conservation historique)&lt;br /&gt;
$ git svn clone  svn://svn.code.sf.net/p/cron4j/code/trunk cron4j-original&lt;br /&gt;
$ cd cron4j-original&lt;br /&gt;
# Test compilation&lt;br /&gt;
$ ant jar&lt;br /&gt;
$ cd ..&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Préparation TAGL====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clone du dépôt TAGL&lt;br /&gt;
$ git clone git@github.com:donsez/tagl.git&lt;br /&gt;
$ cd tagl&lt;br /&gt;
# &amp;quot;Fetch&amp;quot; du dépôt local cloné précédemment&lt;br /&gt;
$ git fetch file://$(pwd)/../cron4j-original&lt;br /&gt;
# Fusion de ce qui vient d&#039;être fetché&lt;br /&gt;
$ git merge FETCH_HEAD&lt;br /&gt;
# Envoi sur le serveur&lt;br /&gt;
$ git push&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Cherry-picking: reprise des modifications d&#039;un collègue====&lt;br /&gt;
&lt;br /&gt;
On considère que:&lt;br /&gt;
&lt;br /&gt;
* votre dépôt Git distant est à l&#039;adresse URL_DEPOT&lt;br /&gt;
* votre collègue a un dépôt Git à l&#039;adresse URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Dossier temporaire&lt;br /&gt;
cd /tmp&lt;br /&gt;
&lt;br /&gt;
# Clone de votre dépôt&lt;br /&gt;
git clone URL_DEPOT mon_depot&lt;br /&gt;
&lt;br /&gt;
# Déplacement dans votre dépôt&lt;br /&gt;
cd mon_depot&lt;br /&gt;
&lt;br /&gt;
# Définition du dépôt distant&lt;br /&gt;
git remote add collegue URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
# Récupération des infos du dépôt du collègue&lt;br /&gt;
git fetch collegue&lt;br /&gt;
&lt;br /&gt;
# Maintenant, on peut voir les branches du collègue&lt;br /&gt;
git branch -a&lt;br /&gt;
&lt;br /&gt;
# On peut fusionner avec une branche&lt;br /&gt;
git merge collegue/master&lt;br /&gt;
&lt;br /&gt;
# Si vous avez des conflits, éditez les fichiers concernés,&lt;br /&gt;
# et committez avec git commit&lt;br /&gt;
&lt;br /&gt;
# Push vers votre dépôt distant&lt;br /&gt;
git push origin&lt;br /&gt;
&lt;br /&gt;
# Optionnel: supprimez la référence vers le dépôt du collègue&lt;br /&gt;
git remote rm collegue&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Archetype webapp====&lt;br /&gt;
L&#039;archetype webapp (http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-webapp/) permet de créer le squelette d&#039;une webapp. Créez un simple webapp monsite en version 0.1.0. (add/commit/push). Vous pourrez tester cette webapp en ajoutant au pom.xml le [https://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin plugin maven Jetty].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mvn -Djetty.port=9999 jetty:run&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naviguez sur http://localhost:9999/monsite&lt;br /&gt;
&lt;br /&gt;
====Scrum tools====&lt;br /&gt;
Ces 3 services peuvent être couplé à votre dépôt GitHub pour votre gestion de projet agile avec [[Scrum]] :&lt;br /&gt;
* http://www.acunote.com/&lt;br /&gt;
* http://backlogtool.com/&lt;br /&gt;
* http://www.scrumdo.com/&lt;br /&gt;
&lt;br /&gt;
L&#039;activation se fait via &#039;&#039;Settings &amp;gt; Webhooks &amp;amp; Services &amp;gt; Configure services&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Séance 4: AOP &amp;amp; AspectJ=&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt Git, projet &#039;&#039;cron4j-mvn&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le [http://mojo.codehaus.org/aspectj-maven-plugin/ plugin Maven pour AspectJ] au pom.xml&lt;br /&gt;
# Ajoutez un aspect de trace à l&#039;invocation des méthodes &#039;&#039;&#039;run()&#039;&#039;&#039; de l&#039;interface java.lang.Runnable (uniquement pour les objets &#039;&#039;schedulé&#039;&#039;s)&lt;br /&gt;
#: Affichez une trace avant et après l&#039;exécution de la tâche&lt;br /&gt;
# Préparez un nouveau test (nouvelle classe) démarrant un Scheduler Cron4j et validant l&#039;exécution d&#039;une tâche au bout d&#039;une minute (pattern &amp;quot;* * * * *&amp;quot;)&lt;br /&gt;
#: Lors de l&#039;exécution de &#039;&#039;&#039;mvn test&#039;&#039;&#039;, vous devez voir apparaître les traces préparées dans votre aspect.&lt;br /&gt;
&lt;br /&gt;
Liens utiles:&lt;br /&gt;
* [http://ridgetopsolutions.com/blog/2013/02/12/getting-started-with-aspectj-and-maven/ Getting started with AspectJ and Maven]&lt;br /&gt;
&lt;br /&gt;
===Contrôle continu===&lt;br /&gt;
&lt;br /&gt;
# Complétez l&#039;aspect de trace avec le positionnement du [http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html java.lang.ThreadLocal] pour passer 1) l&#039;identifiant du job et 2) le compteur des appels de la méthode de l&#039;objet.&lt;br /&gt;
&lt;br /&gt;
=Séance 5: Pelix &amp;amp; iPOPO=&lt;br /&gt;
&lt;br /&gt;
Pelix est une plate-forme d&#039;application à services (SOA).&lt;br /&gt;
iPOPO est un modèle de composants orientés services (SOCM).&lt;br /&gt;
&lt;br /&gt;
La documentation de Pelix et iPOPO est disponible sur https://ipopo.coderxpress.net/&lt;br /&gt;
&lt;br /&gt;
===Installation de iPOPO===&lt;br /&gt;
&lt;br /&gt;
* Cloner le dépôt Git depuis https://github.com/tcalmant/ipopo&lt;br /&gt;
* Se placer dans la branche &#039;&#039;dev&#039;&#039;&lt;br /&gt;
* Pour installer iPOPO, lancer la commande :&lt;br /&gt;
&lt;br /&gt;
   sudo python setup.py install&lt;br /&gt;
&lt;br /&gt;
===Shell Pelix===&lt;br /&gt;
&lt;br /&gt;
Pour lancer un shell Pelix, utilisez la commande:&lt;br /&gt;
&lt;br /&gt;
   python -m pelix.shell.console&lt;br /&gt;
&lt;br /&gt;
Les commandes disponibles sont décrites ici: [https://ipopo.coderxpress.net/wiki/doku.php?id=ipopo:refcards:shell Shell Commands]&lt;br /&gt;
&lt;br /&gt;
===Rappels de Python===&lt;br /&gt;
&lt;br /&gt;
* Pas de déclaration du type d&#039;une variable&lt;br /&gt;
* Les méthodes d&#039;une classe ont toute comme premier paramètre &#039;&#039;self&#039;&#039;, équivalent du &#039;&#039;this&#039;&#039; en Java.&lt;br /&gt;
* Blocs définis par indentation (4 espaces ou 1 tab)&lt;br /&gt;
* Une ligne finissant par &#039;:&#039; démarre toujours un bloc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Import d&#039;un module&lt;br /&gt;
import pelix&lt;br /&gt;
&lt;br /&gt;
# Définition d&#039;une classe&lt;br /&gt;
class MaClasse:&lt;br /&gt;
   # Constructeur&lt;br /&gt;
   def __init__(self):&lt;br /&gt;
       self.default = &amp;quot;stanger&amp;quot;&lt;br /&gt;
       print(&amp;quot;Classe construite&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
   # Méthode, avec un argument&lt;br /&gt;
   def sayHello(self, name):&lt;br /&gt;
       if not name:&lt;br /&gt;
           # Nom vide ou nul&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(self.default)&lt;br /&gt;
       else:&lt;br /&gt;
           # Nom valide&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(name)&lt;br /&gt;
&lt;br /&gt;
objet = MaClasse()&lt;br /&gt;
print(objet.sayHello(&amp;quot;&amp;quot;))&lt;br /&gt;
print(objet.sayHello(&amp;quot;World&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Service Ping-Pong===&lt;br /&gt;
&lt;br /&gt;
1. Écrire un fichier &#039;&#039;pong.py&#039;&#039;, définissant une classe &#039;&#039;Pong&#039;&#039; ayant une méthode &#039;&#039;pong&#039;&#039; prenant en paramètre un message et retournant le message préfixé par &amp;quot;PONG:&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Exemple: &lt;br /&gt;
   &lt;br /&gt;
      pong = Pong()&lt;br /&gt;
      pong.pong(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2. Écrire un fichier &#039;&#039;ping.py&#039;&#039;, définissant une classe &#039;&#039;Ping&#039;&#039; ayant une méthode &#039;&#039;ping&#039;&#039; prenant en paramètre un message, créant un objet Pong et retournant le résultat de Pong.pong(message) préfixé par &amp;quot;PING:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&lt;br /&gt;
      ping = Ping()&lt;br /&gt;
      ping.ping(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PING:PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
3. Transformer le fichier &#039;&#039;pong.py&#039;&#039; pour qu&#039;il devienne un bundle Pelix enregistrant un objet Pong comme étant un service ayant pour spécification &amp;quot;tagl.pong&amp;quot;&lt;br /&gt;
* Définir une classe &#039;&#039;Activator&#039;&#039;, décorée avec &#039;&#039;@BundleActivator&#039;&#039;&lt;br /&gt;
* Enregistrer le service dans la méthode &#039;&#039;Activator.start&#039;&#039; et le désenregistrer dans &#039;&#039;Activator.stop&#039;&#039;&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/provider.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;pong&#039; et vérifier que le service est bien inscrit avec la commande &#039;&#039;sl&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
4.Transformer la classe &#039;&#039;Ping&#039;&#039; dans &#039;&#039;ping.py&#039;&#039; en un composant iPOPO&lt;br /&gt;
* L&#039;objet Pong utilisé dans &#039;&#039;ping()&#039;&#039; doit être un service injecté par iPOPO (&#039;&#039;@Requires&#039;&#039;)&lt;br /&gt;
* Appeler la méthode &#039;&#039;ping()&#039;&#039; dès que le service Pong est injecté (&#039;&#039;@BindField&#039;&#039;) ou disparait (&#039;&#039;@UnbindField&#039;&#039;)&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/consumer.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;ping&#039; et vérifier son comportement si le bundle &#039;&#039;pong&#039;&#039; ou le bundle &#039;&#039;ping&#039;&#039; est arrêté et redémarré.&lt;br /&gt;
&lt;br /&gt;
5. Mettre à jour le bundle &#039;&#039;pong&#039;&#039;&lt;br /&gt;
* Remplacer le préfixe &amp;quot;PONG&amp;quot; par &amp;quot;NI&amp;quot;&lt;br /&gt;
* Dans le shell Pelix, mettre à jour le bundle &#039;&#039;pong&#039;&#039; sans redémarrer la plate-forme (commande &#039;&#039;udpate&#039;&#039;).&lt;br /&gt;
* Vérifier les traces dans le shell pour valider la mise à jour du service.&lt;br /&gt;
&lt;br /&gt;
===Remote Services===&lt;br /&gt;
&lt;br /&gt;
* Ajouter les propriétés permettant l&#039;export du service Pong dans &#039;&#039;pong.py&#039;&#039; (s&#039;inspirer de &#039;&#039;provider.py&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
* Lancer deux shells iPOPO (dans deux terminaux)&lt;br /&gt;
* Dans chaque shell iPOPO, installer les bundles:&lt;br /&gt;
** &#039;&#039;pelix.remote.dispatcher&#039;&#039;: Exportateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.registry&#039;&#039;; Importateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.discovery.multicast&#039;&#039;: Découverte de services via Multicast&lt;br /&gt;
** &#039;&#039;pelix.remote.xml_rpc&#039;&#039;: Transport XML-RPC&lt;br /&gt;
** &#039;&#039;pelix.http.basic&#039;&#039;: Serveur HTTP&lt;br /&gt;
&lt;br /&gt;
Attention: il peut être nécessaire de désactiver votre pare-feu pour que les Remote Services fonctionnent&lt;br /&gt;
&lt;br /&gt;
* Instancier les composants depuis le shell iPOPO, dans chaque framework:&lt;br /&gt;
** Serveur HTTP sur le port 8080: &#039;&#039;instantiate pelix.http.service.basic.factory http-server pelix.http.port=8080&#039;&#039; (penser à changer de port dans chaque framework)&lt;br /&gt;
** Multicast Discovery: &#039;&#039;instantiate pelix-remote-discovery-multicast-factory multicast-discovery&#039;&#039;&lt;br /&gt;
** XML-RPC Exporter: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-exporter&#039;&#039;&lt;br /&gt;
** XML-RPC Importer: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-importer&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Installer le bundle &#039;&#039;ping&#039;&#039; dans un des frameworks et le bundle &#039;&#039;pong&#039;&#039; dans l&#039;autre.&lt;br /&gt;
* Le composant ping peut appeler le service pong, qui est dans l&#039;autre framework.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Voir le code de &#039;&#039;run_remote.py&#039;&#039; pour voir comment démarrer un framework Pelix et installer des bundles depuis Python.&lt;br /&gt;
* Jouer un peu avec &#039;&#039;run_remote.py&#039;&#039; (voir &#039;&#039;run_remote.py --help&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=Séance 6=&lt;br /&gt;
[[Tutorial OSGi avec Apache Felix]]&lt;br /&gt;
&lt;br /&gt;
=Séance 7=&lt;br /&gt;
Faire un projet PDE pour un bundle cron4j.gogo (indépendant de cron4j.bundle)&lt;br /&gt;
&lt;br /&gt;
Utilisation de https://eclipse.org/tycho/&lt;/div&gt;</summary>
		<author><name>MatthieuCaneill</name></author>
	</entry>
	<entry>
		<id>https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21489</id>
		<title>TAGL/TP</title>
		<link rel="alternate" type="text/html" href="https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21489"/>
		<updated>2015-02-26T16:38:30Z</updated>

		<summary type="html">&lt;p&gt;MatthieuCaneill: /* Tests Unitaires avec JUnit 4 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Travaux pratiques de l&#039;UE [[TAGL]].&lt;br /&gt;
&lt;br /&gt;
Anciennes versions : [[TAGL/TP 2014]]&lt;br /&gt;
&lt;br /&gt;
=Séance 1 : Gestion de versions=&lt;br /&gt;
==Git==&lt;br /&gt;
&lt;br /&gt;
Création d&#039;un dépôt Git local&lt;br /&gt;
&lt;br /&gt;
===Méthode simple: init first===&lt;br /&gt;
&lt;br /&gt;
Via cette méthode, on crée un dépôt local, avec un répertoire de travail, puis on pousse ses modifications vers un dépôt &amp;quot;bare&amp;quot;.&lt;br /&gt;
Cette méthode est la plus simple, car on dispose immédiatement d&#039;un répertoire de travail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création d&#039;un dépôt Git dans le dossier simple-repo&lt;br /&gt;
git init simple-repo&lt;br /&gt;
&lt;br /&gt;
# Création d&#039;un README&lt;br /&gt;
cd simple-repo&lt;br /&gt;
echo &amp;quot;Hello, World&amp;quot; &amp;gt; README&lt;br /&gt;
&lt;br /&gt;
# Ajout du versionnement du fichier README&lt;br /&gt;
git add README&lt;br /&gt;
&lt;br /&gt;
# Commit&lt;br /&gt;
git commit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À ce niveau, on a un dépôt Git complètement fonctionnel.&lt;br /&gt;
Cependant, il est intéressant de pousser ses modifications vers un autre dépôt, sur une autre machine.&lt;br /&gt;
On va donc créer un dépôt bare sur une autre machine (ou autre dossier pour l&#039;exemple)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que l&#039;URL pour accéder à ce dépôt est URL_REPO.&lt;br /&gt;
On va d&#039;abord ajouter ce dépôt serveur à la liste des dépôts connu-repos de votre dépôt local.&lt;br /&gt;
Étant donné qu&#039;il s&#039;agit du dépôt &amp;quot;principal&amp;quot; à utiliser, on l&#039;appellera //origin//, par convention.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin URL_REPO&lt;br /&gt;
# Récupération de ses informations&lt;br /&gt;
git fetch origin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce serveur distant est &amp;quot;vide&amp;quot;: il n&#039;a aucune branche. On va donc enregistrer notre branche sur le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À partir de cette commande, la branche locale //master// sera liée à la branche distante //origin/master//.&lt;br /&gt;
Lors des prochaines commandes &#039;&#039;git push&#039;&#039;, grâce à cette liaison, tous les commits sur la branche locale //master// seront poussées sur le serveur distant.&lt;br /&gt;
&lt;br /&gt;
===Méthode moins simple: bare first===&lt;br /&gt;
&lt;br /&gt;
Si on commence dans par le serveur &amp;quot;vide&amp;quot;, il faudra le cloner au lieu de le définir comme un dépôt distant.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création du dépôt vide&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que ce dépôt est accessible à l&#039;URL URL_REPO&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clonage du dépôt&lt;br /&gt;
git clone URL_REPO clone-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un avertissement indique que l&#039;on clone un dépôt vide: le dépôt local à donc une branche master, mais elle n&#039;est pas liée au dépôt distant, car celui-ci n&#039;a aucune branche.&lt;br /&gt;
Le dépôt distant est automatiquement appelé //origin//.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Commit dans le dépôt local&lt;br /&gt;
cd clone-repo&lt;br /&gt;
echo hello &amp;gt; readme.rst&lt;br /&gt;
git add readme.rst&lt;br /&gt;
git commit et ses dépendances&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme dans la méthode simple, il faut pousser la branche master vers le dépôt distant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===De l&#039;importance des README===&lt;br /&gt;
&lt;br /&gt;
Il est très important d&#039;avoir au moins 2 fichiers dans votre dépôt Git:&lt;br /&gt;
&lt;br /&gt;
* LICENSE: contenant le texte **complet** de la licence de votre projet&lt;br /&gt;
* README: décrivant votre projet et comment l&#039;utiliser. Ce fichier doit rappeler le nom de la licence de votre projet&lt;br /&gt;
&lt;br /&gt;
Il est aussi recommandé d&#039;avoir les fichiers suivants:&lt;br /&gt;
&lt;br /&gt;
* AUTHORS: contenant la liste des noms/pseudos et e-mails des auteurs de commits ou de code inclus dans ce projet&lt;br /&gt;
* INSTALL: contenant la liste des dépendances de ce projet et des commandes à utiliser pour le compiler et l&#039;installer&lt;br /&gt;
&lt;br /&gt;
Les fichiers LICENSE sont des fichiers textes bruts.&lt;br /&gt;
Les autres fichiers sont généralement dans un format offrant un peu plus de lisibilté, par exemple dans les formats [http://daringfireball.net/projects/markdown/ Markdown] (.md) ou [http://docutils.sourceforge.net/rst.html reStructuredText] (.rst)&lt;br /&gt;
&lt;br /&gt;
Un plug-in existe pour éditer des fichier reStructuredText dans Eclipse: ReST Editor, disponible sur le [https://marketplace.eclipse.org/content/rest-editor Marketplace Eclipse]&lt;br /&gt;
&lt;br /&gt;
=Séance 2a: Intégration en continue=&lt;br /&gt;
&lt;br /&gt;
===GitHub &amp;amp; [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
Travis-CI est un service permettant d&#039;exécuter un script dans une machine virtuelle Ubuntu dès que vous effectuez un push sur un de vos dépôts GitHub.&lt;br /&gt;
L&#039;intérêt est de savoir si la version d&#039;un projet que vous avez rendu publique peut être compilée et si ses tests passent.&lt;br /&gt;
&lt;br /&gt;
La machine virtuelle &amp;quot;offerte&amp;quot; par Travis est préconfigurée pour le language indiqué dans son fichier de configuration (&#039;&#039;&#039;.travis.yml&#039;&#039;&#039;), mais il est possible d&#039;utiliser la commande &#039;&#039;&#039;sudo apt-get install ...&#039;&#039;&#039; pour ajouter vos dépendances.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour utiliser [[Travis-CI]]:&lt;br /&gt;
&lt;br /&gt;
# Créez compte individuel sur GitHub https://github.com&lt;br /&gt;
# &#039;&#039;Fork&#039;&#039;ez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Ajoutez un collaborateur (i.e. votre binôme) au projet &#039;&#039;forké&#039;&#039;, via les paramètres (&#039;&#039;settings&#039;&#039;) de ce projet&lt;br /&gt;
# Pour l&#039;exemple, activez le service (ou hook) &#039;&#039;Email&#039;&#039; depuis les paramètres du dépôt: à chaque fois que vous ou un de vos collaborateurs ferra un &#039;&#039;&#039;git push&#039;&#039;&#039;, vous recevrez une notification par mail.&lt;br /&gt;
# Activez le service Travis-CI: identifiez-vous (&#039;&#039;sign in&#039;&#039;) sur https://travis-ci.org/ avec votre compte GitHub&lt;br /&gt;
# Activez le service pour les projets sur lesquels vous souhaitez appliquer les principes d&#039;intégration continue&lt;br /&gt;
&lt;br /&gt;
[[Travis-CI]] utilise un fichier nommé &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; (attention: fichier caché sous Unix) pour se configurer et choisir les opérations à effectuer.&lt;br /&gt;
Ce fichier doit se trouver à la racine de votre dépôt Git.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; du fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; ci-dessous.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
language: node_js&lt;br /&gt;
node_js:&lt;br /&gt;
  - &amp;quot;0.11&amp;quot;&lt;br /&gt;
  - &amp;quot;0.10&amp;quot;&lt;br /&gt;
  - &amp;quot;0.8&amp;quot;&lt;br /&gt;
  - &amp;quot;0.6&amp;quot;&lt;br /&gt;
  - iojs&lt;br /&gt;
  - iojs-v1.0.2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; indique à [[Travis-CI]] que les scripts de ce projet dans ce dépôt seront exécutés avec plusieurs versions de [[Node.js]].&lt;br /&gt;
&lt;br /&gt;
Ajoutez dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&#039; la section suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;quot;devDependencies&amp;quot;: {&lt;br /&gt;
    &amp;quot;jshint&amp;quot;: &amp;quot;^2.6.0&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;scripts&amp;quot;: {&lt;br /&gt;
    &amp;quot;test&amp;quot;: &amp;quot;./node_modules/jshint/bin/jshint index.js&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
et incrémentez le numéro de version.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Remarque:&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;jshint&#039;&#039;&#039; peut être lancé localement avec les commandes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo npm install jshint&lt;br /&gt;
jshint index.js&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A lire&lt;br /&gt;
* http://docs.travis-ci.com/user/languages/javascript-with-nodejs/&lt;br /&gt;
* https://github.com/docdis/learn-travis/blob/master/README.md&lt;br /&gt;
&lt;br /&gt;
=Séance 2b: Livraison en continue=&lt;br /&gt;
&lt;br /&gt;
==[[Heroku]]==&lt;br /&gt;
[https://www.heroku.com/ Heroku] est une plateforme cloud de type PaaS permettant l&#039;exécution d&#039;applications et de services en ligne écrits dans les langages et plateformes suivantes : Ruby, [[Node.js]], [[Python]], Java, et PHP.&lt;br /&gt;
&lt;br /&gt;
# Créez un compte gratuit sur [https://signup.heroku.com Heroku]&lt;br /&gt;
# Forkez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Dans Heroku, créez une nouvelle app Node.js, et liez-la au repository Github créé à l&#039;étape précédente&lt;br /&gt;
# Choisissez l&#039;option &amp;quot;Déploiement automatique&amp;quot; depuis la branche **master**&lt;br /&gt;
# Modifiez le fichier index.js pour afficher la version de service dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 var fs = require(&#039;fs&#039;);&lt;br /&gt;
 var package = JSON.parse(fs.readFileSync(&#039;./package.json&#039;, &#039;utf8&#039;));&lt;br /&gt;
 var version=package.version;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Hello World! (current version: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
# Modifiez le fichier index.js pour franciser le message dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Bonjour Tout Le Monde! (version courante: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
=Séance 3: Builders=&lt;br /&gt;
&lt;br /&gt;
==[[Ant]]==&lt;br /&gt;
&lt;br /&gt;
==[[Maven]]==&lt;br /&gt;
&lt;br /&gt;
[http://maven.apache.org/download.cgi Charger et installer Maven 3].&lt;br /&gt;
&lt;br /&gt;
Debian/Ubuntu &amp;amp; friends:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install maven&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mvn -version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Faites une copie du projet, basée sur Maven:&lt;br /&gt;
&lt;br /&gt;
# Dans votre dépôt Git, créez un dossier &#039;&#039;&#039;cron4j-mvn&#039;&#039;&#039;: il contiendra le projet Cron4J avec la structure Maven&lt;br /&gt;
# Dans ce dossier, utilisez l&#039;[https://maven.apache.org/guides/introduction/introduction-to-archetypes.html archetype] Maven [http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-quickstart/ maven-archetype-quickstart] (la version des sources de cron4j utilisés est la 2.5.5) (groupId: it.sauronsoftware.cron4j, artifactId: cron4j):&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Cette commande crée un projet avec un fichier &#039;&#039;pom.xml&#039;&#039;, et une classe et un test modèles: supprimez ces modèles&lt;br /&gt;
# Copiez les sources de Cron4J depuis le dossier &#039;&#039;&#039;cron4j-original&#039;&#039;&#039; dans le dossier &#039;&#039;&#039;src/main/java&#039;&#039;&#039; de votre projet Maven&lt;br /&gt;
# Faites un essai de compilation:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Lancez un des exemples avec mvn exec:java -Dexec.mainClass=&amp;quot;com.example.Main&amp;quot; [-Dexec.args=&amp;quot;argument1&amp;quot;] ... ([http://mojo.codehaus.org/exec-maven-plugin/usage.html doc. exec plugin], [http://mojo.codehaus.org/exec-maven-plugin/java-mojo.html doc. Exec:java goal])&lt;br /&gt;
# Enfin modifiez le fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; à la racine de votre dépôt Git afin que Travis exécute la commande &#039;&#039;&#039;mvn clean verify&#039;&#039;&#039; à chaque mise à jour du dépôt GitHub.&lt;br /&gt;
&lt;br /&gt;
==Tests Unitaires avec JUnit 4==&lt;br /&gt;
Survoller le tutoriel [http://www.vogella.com/tutorials/JUnit/article.html Unit Testing with JUnit]&lt;br /&gt;
&lt;br /&gt;
# Veillez à bien utiliser la dépendance JUnit 4.8.2 dans pom.xml&lt;br /&gt;
# Ajouter le test unitaire suivant au projet, dans le fichier &#039;&#039;&#039;src/test/it/sauronsoftware/SchedulingPatternTest.java&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
package it.sauronsoftware;&lt;br /&gt;
&lt;br /&gt;
import it.sauronsoftware.cron4j.SchedulingPattern;&lt;br /&gt;
import it.sauronsoftware.cron4j.InvalidPatternException;&lt;br /&gt;
&lt;br /&gt;
import static org.junit.Assert.assertEquals;&lt;br /&gt;
import static org.junit.Assert.assertTrue;&lt;br /&gt;
&lt;br /&gt;
import org.junit.AfterClass;&lt;br /&gt;
import org.junit.BeforeClass;&lt;br /&gt;
import org.junit.Test;&lt;br /&gt;
&lt;br /&gt;
public class SchedulingPatternTest {&lt;br /&gt;
&lt;br /&gt;
  @BeforeClass&lt;br /&gt;
  public static void testSetup() {&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @AfterClass&lt;br /&gt;
  public static void testCleanup() {&lt;br /&gt;
    // Teardown for data used by the unit tests&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test(expected = InvalidPatternException.class)&lt;br /&gt;
  public void testExceptionIsThrown() {&lt;br /&gt;
    SchedulingPattern sp = new SchedulingPattern(&amp;quot;0 5 * *&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test&lt;br /&gt;
  public void testPattern() {&lt;br /&gt;
    String pattern;&lt;br /&gt;
    pattern=&amp;quot;0 5 * * *|8 10 * * *|22 17 * * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
    pattern=&amp;quot;0 5 * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Committez et Pushez ce nouveau fichier, pour que Travis lance les tests dès que possible&lt;br /&gt;
# Lancez les tests unitaires avec &amp;lt;pre&amp;gt;mvn test&amp;lt;/pre&amp;gt; Ce test va &#039;&#039;&#039;échouer&#039;&#039;&#039;: corrigez le.&lt;br /&gt;
# Committez et Pushez la version corrigée des tests: Travis enverra un mail pour indiquer si les tests échouent ou non&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; Travis va exécuter les tests &#039;&#039;dès que possible&#039;&#039;. Il est possible de recevoir un mail indiquant que les tests du premier &#039;&#039;push&#039;&#039; échouent alors que l&#039;on a déjà &#039;&#039;pushé&#039;&#039; la correction.&lt;br /&gt;
# Naviguez sur http://travis-ci.org pour vérifier les builds effectués.&lt;br /&gt;
# Créez des tests unitaires supplémentaire du i.s.c.CronParser&lt;br /&gt;
&lt;br /&gt;
===[[Maven]] avec [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
===Git (suite)===&lt;br /&gt;
&lt;br /&gt;
# Forkez le projet &#039;&#039;&#039;tagl&#039;&#039;&#039; d&#039;un autre binome (i.e. autre que &#039;&#039;donsez/tagl&#039;&#039;)&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; donnez lui un nom différent (e.g. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Clonez ce nouveau dépôt&lt;br /&gt;
# Lancez une compilation pour valider l&#039;état du projet (bonne pratique)&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Ajoutez une bannière de licence dans le fichier &#039;&#039;&#039;cron4j-mvn/pom.xml&#039;&#039;&#039;&lt;br /&gt;
# Lancez une nouvelle compilation pour valider vos modifications&lt;br /&gt;
# Commitez et pushez (vers votre fork de ce dépôt, i.e. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Via le site de GitHub, proposez un &amp;quot;Pull Request&amp;quot; au projet initial&lt;br /&gt;
&lt;br /&gt;
Vous pouvez ensuite supprimer le clone de ce fork.&lt;br /&gt;
Lorsque le &#039;&#039;pull request&#039;&#039; aura été accepté, vous pourrez supprimer votre fork (&#039;&#039;tagl-licensing&#039;&#039;) de votre compte GitHub.&lt;br /&gt;
&lt;br /&gt;
===Contrôle Continu===&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt &#039;&#039;tagl&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le plugin [http://mojo.codehaus.org/cobertura-maven-plugin/usage.html Cobertura] à votre projet Maven.&lt;br /&gt;
## Configurez le plugin pour [http://mojo.codehaus.org/cobertura-maven-plugin/examples/report-formats.html générer un rapport] HTML. Le résultat se trouvera dans &#039;&#039;target/site/cobertura&#039;&#039;&lt;br /&gt;
## Le plugin ne s&#039;exécute automatiquement pas durant la compilation, il faut utiliser la commande : &amp;lt;pre&amp;gt;mvn cobertura:cobertura&amp;lt;/pre&amp;gt;&lt;br /&gt;
## &#039;&#039;&#039;Bonus:&#039;&#039;&#039; Modifiez le fichier &#039;&#039;pom.xml&#039;&#039; pour que le &#039;&#039;goal&#039;&#039; &#039;&#039;&#039;cobertura&#039;&#039;&#039; soit exécuté pendant la &#039;&#039;phase&#039;&#039; &#039;&#039;&#039;package&#039;&#039;&#039;.&lt;br /&gt;
# Répondez aux questions : &#039;&#039;Mais qu&#039;est ce que la couverture de code ? En quoi c&#039;est utile ?&#039;&#039;&lt;br /&gt;
# Ajoutez au projet Maven les plugins pour la génération d&#039;un site et de rapports (Javadoc, tests unitaires, tags list (FIXME, TODO, ...), ...): voir http://maven.apache.org/plugins/maven-site-plugin/ et d&#039;autres.&lt;br /&gt;
# Regardez les exemples d&#039;utilisation de cron4j dans cron4j-original/examples&lt;br /&gt;
&lt;br /&gt;
===Bonus Track===&lt;br /&gt;
&lt;br /&gt;
====Clone SVN -&amp;gt; Git====&lt;br /&gt;
&lt;br /&gt;
Source: http://www.yterium.net/Migrer-un-projet-SVN-vers-GIT&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Cloner le dépôt SVN en dépôt Git (conservation historique)&lt;br /&gt;
$ git svn clone  svn://svn.code.sf.net/p/cron4j/code/trunk cron4j-original&lt;br /&gt;
$ cd cron4j-original&lt;br /&gt;
# Test compilation&lt;br /&gt;
$ ant jar&lt;br /&gt;
$ cd ..&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Préparation TAGL====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clone du dépôt TAGL&lt;br /&gt;
$ git clone git@github.com:donsez/tagl.git&lt;br /&gt;
$ cd tagl&lt;br /&gt;
# &amp;quot;Fetch&amp;quot; du dépôt local cloné précédemment&lt;br /&gt;
$ git fetch file://$(pwd)/../cron4j-original&lt;br /&gt;
# Fusion de ce qui vient d&#039;être fetché&lt;br /&gt;
$ git merge FETCH_HEAD&lt;br /&gt;
# Envoi sur le serveur&lt;br /&gt;
$ git push&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Cherry-picking: reprise des modifications d&#039;un collègue====&lt;br /&gt;
&lt;br /&gt;
On considère que:&lt;br /&gt;
&lt;br /&gt;
* votre dépôt Git distant est à l&#039;adresse URL_DEPOT&lt;br /&gt;
* votre collègue a un dépôt Git à l&#039;adresse URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Dossier temporaire&lt;br /&gt;
cd /tmp&lt;br /&gt;
&lt;br /&gt;
# Clone de votre dépôt&lt;br /&gt;
git clone URL_DEPOT mon_depot&lt;br /&gt;
&lt;br /&gt;
# Déplacement dans votre dépôt&lt;br /&gt;
cd mon_depot&lt;br /&gt;
&lt;br /&gt;
# Définition du dépôt distant&lt;br /&gt;
git remote add collegue URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
# Récupération des infos du dépôt du collègue&lt;br /&gt;
git fetch collegue&lt;br /&gt;
&lt;br /&gt;
# Maintenant, on peut voir les branches du collègue&lt;br /&gt;
git branch -a&lt;br /&gt;
&lt;br /&gt;
# On peut fusionner avec une branche&lt;br /&gt;
git merge collegue/master&lt;br /&gt;
&lt;br /&gt;
# Si vous avez des conflits, éditez les fichiers concernés,&lt;br /&gt;
# et committez avec git commit&lt;br /&gt;
&lt;br /&gt;
# Push vers votre dépôt distant&lt;br /&gt;
git push origin&lt;br /&gt;
&lt;br /&gt;
# Optionnel: supprimez la référence vers le dépôt du collègue&lt;br /&gt;
git remote rm collegue&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Archetype webapp====&lt;br /&gt;
L&#039;archetype webapp (http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-webapp/) permet de créer le squelette d&#039;une webapp. Créez un simple webapp monsite en version 0.1.0. (add/commit/push). Vous pourrez tester cette webapp en ajoutant au pom.xml le [https://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin plugin maven Jetty].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mvn -Djetty.port=9999 jetty:run&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naviguez sur http://localhost:9999/monsite&lt;br /&gt;
&lt;br /&gt;
====Scrum tools====&lt;br /&gt;
Ces 3 services peuvent être couplé à votre dépôt GitHub pour votre gestion de projet agile avec [[Scrum]] :&lt;br /&gt;
* http://www.acunote.com/&lt;br /&gt;
* http://backlogtool.com/&lt;br /&gt;
* http://www.scrumdo.com/&lt;br /&gt;
&lt;br /&gt;
L&#039;activation se fait via &#039;&#039;Settings &amp;gt; Webhooks &amp;amp; Services &amp;gt; Configure services&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Séance 4: AOP &amp;amp; AspectJ=&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt Git, projet &#039;&#039;cron4j-mvn&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le [http://mojo.codehaus.org/aspectj-maven-plugin/ plugin Maven pour AspectJ] au pom.xml&lt;br /&gt;
# Ajoutez un aspect de trace à l&#039;invocation des méthodes &#039;&#039;&#039;run()&#039;&#039;&#039; de l&#039;interface java.lang.Runnable (uniquement pour les objets &#039;&#039;schedulé&#039;&#039;s)&lt;br /&gt;
#: Affichez une trace avant et après l&#039;exécution de la tâche&lt;br /&gt;
# Préparez un nouveau test (nouvelle classe) démarrant un Scheduler Cron4j et validant l&#039;exécution d&#039;une tâche au bout d&#039;une minute (pattern &amp;quot;* * * * *&amp;quot;)&lt;br /&gt;
#: Lors de l&#039;exécution de &#039;&#039;&#039;mvn test&#039;&#039;&#039;, vous devez voir apparaître les traces préparées dans votre aspect.&lt;br /&gt;
&lt;br /&gt;
Liens utiles:&lt;br /&gt;
* [http://ridgetopsolutions.com/blog/2013/02/12/getting-started-with-aspectj-and-maven/ Getting started with AspectJ and Maven]&lt;br /&gt;
&lt;br /&gt;
===Contrôle continu===&lt;br /&gt;
&lt;br /&gt;
# Complétez l&#039;aspect de trace avec le positionnement du [http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html java.lang.ThreadLocal] pour passer 1) l&#039;identifiant du job et 2) le compteur des appels de la méthode de l&#039;objet.&lt;br /&gt;
&lt;br /&gt;
=Séance 5: Pelix &amp;amp; iPOPO=&lt;br /&gt;
&lt;br /&gt;
Pelix est une plate-forme d&#039;application à services (SOA).&lt;br /&gt;
iPOPO est un modèle de composants orientés services (SOCM).&lt;br /&gt;
&lt;br /&gt;
La documentation de Pelix et iPOPO est disponible sur https://ipopo.coderxpress.net/&lt;br /&gt;
&lt;br /&gt;
===Installation de iPOPO===&lt;br /&gt;
&lt;br /&gt;
* Cloner le dépôt Git depuis https://github.com/tcalmant/ipopo&lt;br /&gt;
* Se placer dans la branche &#039;&#039;dev&#039;&#039;&lt;br /&gt;
* Pour installer iPOPO, lancer la commande :&lt;br /&gt;
&lt;br /&gt;
   sudo python setup.py install&lt;br /&gt;
&lt;br /&gt;
===Shell Pelix===&lt;br /&gt;
&lt;br /&gt;
Pour lancer un shell Pelix, utilisez la commande:&lt;br /&gt;
&lt;br /&gt;
   python -m pelix.shell.console&lt;br /&gt;
&lt;br /&gt;
Les commandes disponibles sont décrites ici: [https://ipopo.coderxpress.net/wiki/doku.php?id=ipopo:refcards:shell Shell Commands]&lt;br /&gt;
&lt;br /&gt;
===Rappels de Python===&lt;br /&gt;
&lt;br /&gt;
* Pas de déclaration du type d&#039;une variable&lt;br /&gt;
* Les méthodes d&#039;une classe ont toute comme premier paramètre &#039;&#039;self&#039;&#039;, équivalent du &#039;&#039;this&#039;&#039; en Java.&lt;br /&gt;
* Blocs définis par indentation (4 espaces ou 1 tab)&lt;br /&gt;
* Une ligne finissant par &#039;:&#039; démarre toujours un bloc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Import d&#039;un module&lt;br /&gt;
import pelix&lt;br /&gt;
&lt;br /&gt;
# Définition d&#039;une classe&lt;br /&gt;
class MaClasse:&lt;br /&gt;
   # Constructeur&lt;br /&gt;
   def __init__(self):&lt;br /&gt;
       self.default = &amp;quot;stanger&amp;quot;&lt;br /&gt;
       print(&amp;quot;Classe construite&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
   # Méthode, avec un argument&lt;br /&gt;
   def sayHello(self, name):&lt;br /&gt;
       if not name:&lt;br /&gt;
           # Nom vide ou nul&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(self.default)&lt;br /&gt;
       else:&lt;br /&gt;
           # Nom valide&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(name)&lt;br /&gt;
&lt;br /&gt;
objet = MaClasse()&lt;br /&gt;
print(objet.sayHello(&amp;quot;&amp;quot;))&lt;br /&gt;
print(objet.sayHello(&amp;quot;World&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Service Ping-Pong===&lt;br /&gt;
&lt;br /&gt;
1. Écrire un fichier &#039;&#039;pong.py&#039;&#039;, définissant une classe &#039;&#039;Pong&#039;&#039; ayant une méthode &#039;&#039;pong&#039;&#039; prenant en paramètre un message et retournant le message préfixé par &amp;quot;PONG:&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Exemple: &lt;br /&gt;
   &lt;br /&gt;
      pong = Pong()&lt;br /&gt;
      pong.pong(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2. Écrire un fichier &#039;&#039;ping.py&#039;&#039;, définissant une classe &#039;&#039;Ping&#039;&#039; ayant une méthode &#039;&#039;ping&#039;&#039; prenant en paramètre un message, créant un objet Pong et retournant le résultat de Pong.pong(message) préfixé par &amp;quot;PING:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&lt;br /&gt;
      ping = Ping()&lt;br /&gt;
      ping.ping(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PING:PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
3. Transformer le fichier &#039;&#039;pong.py&#039;&#039; pour qu&#039;il devienne un bundle Pelix enregistrant un objet Pong comme étant un service ayant pour spécification &amp;quot;tagl.pong&amp;quot;&lt;br /&gt;
* Définir une classe &#039;&#039;Activator&#039;&#039;, décorée avec &#039;&#039;@BundleActivator&#039;&#039;&lt;br /&gt;
* Enregistrer le service dans la méthode &#039;&#039;Activator.start&#039;&#039; et le désenregistrer dans &#039;&#039;Activator.stop&#039;&#039;&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/provider.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;pong&#039; et vérifier que le service est bien inscrit avec la commande &#039;&#039;sl&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
4.Transformer la classe &#039;&#039;Ping&#039;&#039; dans &#039;&#039;ping.py&#039;&#039; en un composant iPOPO&lt;br /&gt;
* L&#039;objet Pong utilisé dans &#039;&#039;ping()&#039;&#039; doit être un service injecté par iPOPO (&#039;&#039;@Requires&#039;&#039;)&lt;br /&gt;
* Appeler la méthode &#039;&#039;ping()&#039;&#039; dès que le service Pong est injecté (&#039;&#039;@BindField&#039;&#039;) ou disparait (&#039;&#039;@UnbindField&#039;&#039;)&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/consumer.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;ping&#039; et vérifier son comportement si le bundle &#039;&#039;pong&#039;&#039; ou le bundle &#039;&#039;ping&#039;&#039; est arrêté et redémarré.&lt;br /&gt;
&lt;br /&gt;
5. Mettre à jour le bundle &#039;&#039;pong&#039;&#039;&lt;br /&gt;
* Remplacer le préfixe &amp;quot;PONG&amp;quot; par &amp;quot;NI&amp;quot;&lt;br /&gt;
* Dans le shell Pelix, mettre à jour le bundle &#039;&#039;pong&#039;&#039; sans redémarrer la plate-forme (commande &#039;&#039;udpate&#039;&#039;).&lt;br /&gt;
* Vérifier les traces dans le shell pour valider la mise à jour du service.&lt;br /&gt;
&lt;br /&gt;
===Remote Services===&lt;br /&gt;
&lt;br /&gt;
* Ajouter les propriétés permettant l&#039;export du service Pong dans &#039;&#039;pong.py&#039;&#039; (s&#039;inspirer de &#039;&#039;provider.py&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
* Lancer deux shells iPOPO (dans deux terminaux)&lt;br /&gt;
* Dans chaque shell iPOPO, installer les bundles:&lt;br /&gt;
** &#039;&#039;pelix.remote.dispatcher&#039;&#039;: Exportateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.registry&#039;&#039;; Importateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.discovery.multicast&#039;&#039;: Découverte de services via Multicast&lt;br /&gt;
** &#039;&#039;pelix.remote.xml_rpc&#039;&#039;: Transport XML-RPC&lt;br /&gt;
** &#039;&#039;pelix.http.basic&#039;&#039;: Serveur HTTP&lt;br /&gt;
&lt;br /&gt;
Attention: il peut être nécessaire de désactiver votre pare-feu pour que les Remote Services fonctionnent&lt;br /&gt;
&lt;br /&gt;
* Instancier les composants depuis le shell iPOPO, dans chaque framework:&lt;br /&gt;
** Serveur HTTP sur le port 8080: &#039;&#039;instantiate pelix.http.service.basic.factory http-server pelix.http.port=8080&#039;&#039; (penser à changer de port dans chaque framework)&lt;br /&gt;
** Multicast Discovery: &#039;&#039;instantiate pelix-remote-discovery-multicast-factory multicast-discovery&#039;&#039;&lt;br /&gt;
** XML-RPC Exporter: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-exporter&#039;&#039;&lt;br /&gt;
** XML-RPC Importer: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-importer&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Installer le bundle &#039;&#039;ping&#039;&#039; dans un des frameworks et le bundle &#039;&#039;pong&#039;&#039; dans l&#039;autre.&lt;br /&gt;
* Le composant ping peut appeler le service pong, qui est dans l&#039;autre framework.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Voir le code de &#039;&#039;run_remote.py&#039;&#039; pour voir comment démarrer un framework Pelix et installer des bundles depuis Python.&lt;br /&gt;
* Jouer un peu avec &#039;&#039;run_remote.py&#039;&#039; (voir &#039;&#039;run_remote.py --help&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=Séance 6=&lt;br /&gt;
[[Tutorial OSGi avec Apache Felix]]&lt;br /&gt;
&lt;br /&gt;
=Séance 7=&lt;br /&gt;
Faire un projet PDE pour un bundle cron4j.gogo (indépendant de cron4j.bundle)&lt;br /&gt;
&lt;br /&gt;
Utilisation de https://eclipse.org/tycho/&lt;/div&gt;</summary>
		<author><name>MatthieuCaneill</name></author>
	</entry>
	<entry>
		<id>https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21488</id>
		<title>TAGL/TP</title>
		<link rel="alternate" type="text/html" href="https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21488"/>
		<updated>2015-02-26T16:21:30Z</updated>

		<summary type="html">&lt;p&gt;MatthieuCaneill: /* Maven */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Travaux pratiques de l&#039;UE [[TAGL]].&lt;br /&gt;
&lt;br /&gt;
Anciennes versions : [[TAGL/TP 2014]]&lt;br /&gt;
&lt;br /&gt;
=Séance 1 : Gestion de versions=&lt;br /&gt;
==Git==&lt;br /&gt;
&lt;br /&gt;
Création d&#039;un dépôt Git local&lt;br /&gt;
&lt;br /&gt;
===Méthode simple: init first===&lt;br /&gt;
&lt;br /&gt;
Via cette méthode, on crée un dépôt local, avec un répertoire de travail, puis on pousse ses modifications vers un dépôt &amp;quot;bare&amp;quot;.&lt;br /&gt;
Cette méthode est la plus simple, car on dispose immédiatement d&#039;un répertoire de travail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création d&#039;un dépôt Git dans le dossier simple-repo&lt;br /&gt;
git init simple-repo&lt;br /&gt;
&lt;br /&gt;
# Création d&#039;un README&lt;br /&gt;
cd simple-repo&lt;br /&gt;
echo &amp;quot;Hello, World&amp;quot; &amp;gt; README&lt;br /&gt;
&lt;br /&gt;
# Ajout du versionnement du fichier README&lt;br /&gt;
git add README&lt;br /&gt;
&lt;br /&gt;
# Commit&lt;br /&gt;
git commit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À ce niveau, on a un dépôt Git complètement fonctionnel.&lt;br /&gt;
Cependant, il est intéressant de pousser ses modifications vers un autre dépôt, sur une autre machine.&lt;br /&gt;
On va donc créer un dépôt bare sur une autre machine (ou autre dossier pour l&#039;exemple)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que l&#039;URL pour accéder à ce dépôt est URL_REPO.&lt;br /&gt;
On va d&#039;abord ajouter ce dépôt serveur à la liste des dépôts connu-repos de votre dépôt local.&lt;br /&gt;
Étant donné qu&#039;il s&#039;agit du dépôt &amp;quot;principal&amp;quot; à utiliser, on l&#039;appellera //origin//, par convention.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin URL_REPO&lt;br /&gt;
# Récupération de ses informations&lt;br /&gt;
git fetch origin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce serveur distant est &amp;quot;vide&amp;quot;: il n&#039;a aucune branche. On va donc enregistrer notre branche sur le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À partir de cette commande, la branche locale //master// sera liée à la branche distante //origin/master//.&lt;br /&gt;
Lors des prochaines commandes &#039;&#039;git push&#039;&#039;, grâce à cette liaison, tous les commits sur la branche locale //master// seront poussées sur le serveur distant.&lt;br /&gt;
&lt;br /&gt;
===Méthode moins simple: bare first===&lt;br /&gt;
&lt;br /&gt;
Si on commence dans par le serveur &amp;quot;vide&amp;quot;, il faudra le cloner au lieu de le définir comme un dépôt distant.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création du dépôt vide&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que ce dépôt est accessible à l&#039;URL URL_REPO&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clonage du dépôt&lt;br /&gt;
git clone URL_REPO clone-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un avertissement indique que l&#039;on clone un dépôt vide: le dépôt local à donc une branche master, mais elle n&#039;est pas liée au dépôt distant, car celui-ci n&#039;a aucune branche.&lt;br /&gt;
Le dépôt distant est automatiquement appelé //origin//.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Commit dans le dépôt local&lt;br /&gt;
cd clone-repo&lt;br /&gt;
echo hello &amp;gt; readme.rst&lt;br /&gt;
git add readme.rst&lt;br /&gt;
git commit et ses dépendances&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme dans la méthode simple, il faut pousser la branche master vers le dépôt distant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===De l&#039;importance des README===&lt;br /&gt;
&lt;br /&gt;
Il est très important d&#039;avoir au moins 2 fichiers dans votre dépôt Git:&lt;br /&gt;
&lt;br /&gt;
* LICENSE: contenant le texte **complet** de la licence de votre projet&lt;br /&gt;
* README: décrivant votre projet et comment l&#039;utiliser. Ce fichier doit rappeler le nom de la licence de votre projet&lt;br /&gt;
&lt;br /&gt;
Il est aussi recommandé d&#039;avoir les fichiers suivants:&lt;br /&gt;
&lt;br /&gt;
* AUTHORS: contenant la liste des noms/pseudos et e-mails des auteurs de commits ou de code inclus dans ce projet&lt;br /&gt;
* INSTALL: contenant la liste des dépendances de ce projet et des commandes à utiliser pour le compiler et l&#039;installer&lt;br /&gt;
&lt;br /&gt;
Les fichiers LICENSE sont des fichiers textes bruts.&lt;br /&gt;
Les autres fichiers sont généralement dans un format offrant un peu plus de lisibilté, par exemple dans les formats [http://daringfireball.net/projects/markdown/ Markdown] (.md) ou [http://docutils.sourceforge.net/rst.html reStructuredText] (.rst)&lt;br /&gt;
&lt;br /&gt;
Un plug-in existe pour éditer des fichier reStructuredText dans Eclipse: ReST Editor, disponible sur le [https://marketplace.eclipse.org/content/rest-editor Marketplace Eclipse]&lt;br /&gt;
&lt;br /&gt;
=Séance 2a: Intégration en continue=&lt;br /&gt;
&lt;br /&gt;
===GitHub &amp;amp; [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
Travis-CI est un service permettant d&#039;exécuter un script dans une machine virtuelle Ubuntu dès que vous effectuez un push sur un de vos dépôts GitHub.&lt;br /&gt;
L&#039;intérêt est de savoir si la version d&#039;un projet que vous avez rendu publique peut être compilée et si ses tests passent.&lt;br /&gt;
&lt;br /&gt;
La machine virtuelle &amp;quot;offerte&amp;quot; par Travis est préconfigurée pour le language indiqué dans son fichier de configuration (&#039;&#039;&#039;.travis.yml&#039;&#039;&#039;), mais il est possible d&#039;utiliser la commande &#039;&#039;&#039;sudo apt-get install ...&#039;&#039;&#039; pour ajouter vos dépendances.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour utiliser [[Travis-CI]]:&lt;br /&gt;
&lt;br /&gt;
# Créez compte individuel sur GitHub https://github.com&lt;br /&gt;
# &#039;&#039;Fork&#039;&#039;ez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Ajoutez un collaborateur (i.e. votre binôme) au projet &#039;&#039;forké&#039;&#039;, via les paramètres (&#039;&#039;settings&#039;&#039;) de ce projet&lt;br /&gt;
# Pour l&#039;exemple, activez le service (ou hook) &#039;&#039;Email&#039;&#039; depuis les paramètres du dépôt: à chaque fois que vous ou un de vos collaborateurs ferra un &#039;&#039;&#039;git push&#039;&#039;&#039;, vous recevrez une notification par mail.&lt;br /&gt;
# Activez le service Travis-CI: identifiez-vous (&#039;&#039;sign in&#039;&#039;) sur https://travis-ci.org/ avec votre compte GitHub&lt;br /&gt;
# Activez le service pour les projets sur lesquels vous souhaitez appliquer les principes d&#039;intégration continue&lt;br /&gt;
&lt;br /&gt;
[[Travis-CI]] utilise un fichier nommé &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; (attention: fichier caché sous Unix) pour se configurer et choisir les opérations à effectuer.&lt;br /&gt;
Ce fichier doit se trouver à la racine de votre dépôt Git.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; du fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; ci-dessous.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
language: node_js&lt;br /&gt;
node_js:&lt;br /&gt;
  - &amp;quot;0.11&amp;quot;&lt;br /&gt;
  - &amp;quot;0.10&amp;quot;&lt;br /&gt;
  - &amp;quot;0.8&amp;quot;&lt;br /&gt;
  - &amp;quot;0.6&amp;quot;&lt;br /&gt;
  - iojs&lt;br /&gt;
  - iojs-v1.0.2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; indique à [[Travis-CI]] que les scripts de ce projet dans ce dépôt seront exécutés avec plusieurs versions de [[Node.js]].&lt;br /&gt;
&lt;br /&gt;
Ajoutez dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&#039; la section suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;quot;devDependencies&amp;quot;: {&lt;br /&gt;
    &amp;quot;jshint&amp;quot;: &amp;quot;^2.6.0&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;scripts&amp;quot;: {&lt;br /&gt;
    &amp;quot;test&amp;quot;: &amp;quot;./node_modules/jshint/bin/jshint index.js&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
et incrémentez le numéro de version.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Remarque:&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;jshint&#039;&#039;&#039; peut être lancé localement avec les commandes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo npm install jshint&lt;br /&gt;
jshint index.js&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A lire&lt;br /&gt;
* http://docs.travis-ci.com/user/languages/javascript-with-nodejs/&lt;br /&gt;
* https://github.com/docdis/learn-travis/blob/master/README.md&lt;br /&gt;
&lt;br /&gt;
=Séance 2b: Livraison en continue=&lt;br /&gt;
&lt;br /&gt;
==[[Heroku]]==&lt;br /&gt;
[https://www.heroku.com/ Heroku] est une plateforme cloud de type PaaS permettant l&#039;exécution d&#039;applications et de services en ligne écrits dans les langages et plateformes suivantes : Ruby, [[Node.js]], [[Python]], Java, et PHP.&lt;br /&gt;
&lt;br /&gt;
# Créez un compte gratuit sur [https://signup.heroku.com Heroku]&lt;br /&gt;
# Forkez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Dans Heroku, créez une nouvelle app Node.js, et liez-la au repository Github créé à l&#039;étape précédente&lt;br /&gt;
# Choisissez l&#039;option &amp;quot;Déploiement automatique&amp;quot; depuis la branche **master**&lt;br /&gt;
# Modifiez le fichier index.js pour afficher la version de service dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 var fs = require(&#039;fs&#039;);&lt;br /&gt;
 var package = JSON.parse(fs.readFileSync(&#039;./package.json&#039;, &#039;utf8&#039;));&lt;br /&gt;
 var version=package.version;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Hello World! (current version: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
# Modifiez le fichier index.js pour franciser le message dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Bonjour Tout Le Monde! (version courante: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
=Séance 3: Builders=&lt;br /&gt;
&lt;br /&gt;
==[[Ant]]==&lt;br /&gt;
&lt;br /&gt;
==[[Maven]]==&lt;br /&gt;
&lt;br /&gt;
[http://maven.apache.org/download.cgi Charger et installer Maven 3].&lt;br /&gt;
&lt;br /&gt;
Debian/Ubuntu &amp;amp; friends:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install maven&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mvn -version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Faites une copie du projet, basée sur Maven:&lt;br /&gt;
&lt;br /&gt;
# Dans votre dépôt Git, créez un dossier &#039;&#039;&#039;cron4j-mvn&#039;&#039;&#039;: il contiendra le projet Cron4J avec la structure Maven&lt;br /&gt;
# Dans ce dossier, utilisez l&#039;[https://maven.apache.org/guides/introduction/introduction-to-archetypes.html archetype] Maven [http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-quickstart/ maven-archetype-quickstart] (la version des sources de cron4j utilisés est la 2.5.5) (groupId: it.sauronsoftware.cron4j, artifactId: cron4j):&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Cette commande crée un projet avec un fichier &#039;&#039;pom.xml&#039;&#039;, et une classe et un test modèles: supprimez ces modèles&lt;br /&gt;
# Copiez les sources de Cron4J depuis le dossier &#039;&#039;&#039;cron4j-original&#039;&#039;&#039; dans le dossier &#039;&#039;&#039;src/main/java&#039;&#039;&#039; de votre projet Maven&lt;br /&gt;
# Faites un essai de compilation:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Lancez un des exemples avec mvn exec:java -Dexec.mainClass=&amp;quot;com.example.Main&amp;quot; [-Dexec.args=&amp;quot;argument1&amp;quot;] ... ([http://mojo.codehaus.org/exec-maven-plugin/usage.html doc. exec plugin], [http://mojo.codehaus.org/exec-maven-plugin/java-mojo.html doc. Exec:java goal])&lt;br /&gt;
# Enfin modifiez le fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; à la racine de votre dépôt Git afin que Travis exécute la commande &#039;&#039;&#039;mvn clean verify&#039;&#039;&#039; à chaque mise à jour du dépôt GitHub.&lt;br /&gt;
&lt;br /&gt;
==Tests Unitaires avec JUnit 4==&lt;br /&gt;
Survoller le tutoriel [http://www.vogella.com/tutorials/JUnit/article.html Unit Testing with JUnit]&lt;br /&gt;
&lt;br /&gt;
# Ajouter le test unitaire suivant au projet, dans le fichier &#039;&#039;&#039;src/test/it/sauronsoftware/SchedulingPatternTest.java&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
package it.sauronsoftware;&lt;br /&gt;
&lt;br /&gt;
import it.sauronsoftware.cron4j.SchedulingPattern;&lt;br /&gt;
import it.sauronsoftware.cron4j.InvalidPatternException;&lt;br /&gt;
&lt;br /&gt;
import static org.junit.Assert.assertEquals;&lt;br /&gt;
import static org.junit.Assert.assertTrue;&lt;br /&gt;
&lt;br /&gt;
import org.junit.AfterClass;&lt;br /&gt;
import org.junit.BeforeClass;&lt;br /&gt;
import org.junit.Test;&lt;br /&gt;
&lt;br /&gt;
public class SchedulingPatternTest {&lt;br /&gt;
&lt;br /&gt;
  @BeforeClass&lt;br /&gt;
  public static void testSetup() {&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @AfterClass&lt;br /&gt;
  public static void testCleanup() {&lt;br /&gt;
    // Teardown for data used by the unit tests&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test(expected = InvalidPatternException.class)&lt;br /&gt;
  public void testExceptionIsThrown() {&lt;br /&gt;
    SchedulingPattern sp = new SchedulingPattern(&amp;quot;0 5 * *&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test&lt;br /&gt;
  public void testPattern() {&lt;br /&gt;
    String pattern;&lt;br /&gt;
    pattern=&amp;quot;0 5 * * *|8 10 * * *|22 17 * * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
    pattern=&amp;quot;0 5 * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Committez et Pushez ce nouveau fichier, pour que Travis lance les tests dès que possible&lt;br /&gt;
# Lancez les tests unitaires avec &amp;lt;pre&amp;gt;mvn test&amp;lt;/pre&amp;gt; Ce test va &#039;&#039;&#039;échouer&#039;&#039;&#039;: corrigez le.&lt;br /&gt;
# Committez et Pushez la version corrigée des tests: Travis enverra un mail pour indiquer si les tests échouent ou non&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; Travis va exécuter les tests &#039;&#039;dès que possible&#039;&#039;. Il est possible de recevoir un mail indiquant que les tests du premier &#039;&#039;push&#039;&#039; échouent alors que l&#039;on a déjà &#039;&#039;pushé&#039;&#039; la correction.&lt;br /&gt;
# Naviguez sur http://travis-ci.org pour vérifier les builds effectués.&lt;br /&gt;
# Créez des tests unitaires supplémentaire du i.s.c.CronParser&lt;br /&gt;
&lt;br /&gt;
===[[Maven]] avec [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
===Git (suite)===&lt;br /&gt;
&lt;br /&gt;
# Forkez le projet &#039;&#039;&#039;tagl&#039;&#039;&#039; d&#039;un autre binome (i.e. autre que &#039;&#039;donsez/tagl&#039;&#039;)&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; donnez lui un nom différent (e.g. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Clonez ce nouveau dépôt&lt;br /&gt;
# Lancez une compilation pour valider l&#039;état du projet (bonne pratique)&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Ajoutez une bannière de licence dans le fichier &#039;&#039;&#039;cron4j-mvn/pom.xml&#039;&#039;&#039;&lt;br /&gt;
# Lancez une nouvelle compilation pour valider vos modifications&lt;br /&gt;
# Commitez et pushez (vers votre fork de ce dépôt, i.e. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Via le site de GitHub, proposez un &amp;quot;Pull Request&amp;quot; au projet initial&lt;br /&gt;
&lt;br /&gt;
Vous pouvez ensuite supprimer le clone de ce fork.&lt;br /&gt;
Lorsque le &#039;&#039;pull request&#039;&#039; aura été accepté, vous pourrez supprimer votre fork (&#039;&#039;tagl-licensing&#039;&#039;) de votre compte GitHub.&lt;br /&gt;
&lt;br /&gt;
===Contrôle Continu===&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt &#039;&#039;tagl&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le plugin [http://mojo.codehaus.org/cobertura-maven-plugin/usage.html Cobertura] à votre projet Maven.&lt;br /&gt;
## Configurez le plugin pour [http://mojo.codehaus.org/cobertura-maven-plugin/examples/report-formats.html générer un rapport] HTML. Le résultat se trouvera dans &#039;&#039;target/site/cobertura&#039;&#039;&lt;br /&gt;
## Le plugin ne s&#039;exécute automatiquement pas durant la compilation, il faut utiliser la commande : &amp;lt;pre&amp;gt;mvn cobertura:cobertura&amp;lt;/pre&amp;gt;&lt;br /&gt;
## &#039;&#039;&#039;Bonus:&#039;&#039;&#039; Modifiez le fichier &#039;&#039;pom.xml&#039;&#039; pour que le &#039;&#039;goal&#039;&#039; &#039;&#039;&#039;cobertura&#039;&#039;&#039; soit exécuté pendant la &#039;&#039;phase&#039;&#039; &#039;&#039;&#039;package&#039;&#039;&#039;.&lt;br /&gt;
# Répondez aux questions : &#039;&#039;Mais qu&#039;est ce que la couverture de code ? En quoi c&#039;est utile ?&#039;&#039;&lt;br /&gt;
# Ajoutez au projet Maven les plugins pour la génération d&#039;un site et de rapports (Javadoc, tests unitaires, tags list (FIXME, TODO, ...), ...): voir http://maven.apache.org/plugins/maven-site-plugin/ et d&#039;autres.&lt;br /&gt;
# Regardez les exemples d&#039;utilisation de cron4j dans cron4j-original/examples&lt;br /&gt;
&lt;br /&gt;
===Bonus Track===&lt;br /&gt;
&lt;br /&gt;
====Clone SVN -&amp;gt; Git====&lt;br /&gt;
&lt;br /&gt;
Source: http://www.yterium.net/Migrer-un-projet-SVN-vers-GIT&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Cloner le dépôt SVN en dépôt Git (conservation historique)&lt;br /&gt;
$ git svn clone  svn://svn.code.sf.net/p/cron4j/code/trunk cron4j-original&lt;br /&gt;
$ cd cron4j-original&lt;br /&gt;
# Test compilation&lt;br /&gt;
$ ant jar&lt;br /&gt;
$ cd ..&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Préparation TAGL====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clone du dépôt TAGL&lt;br /&gt;
$ git clone git@github.com:donsez/tagl.git&lt;br /&gt;
$ cd tagl&lt;br /&gt;
# &amp;quot;Fetch&amp;quot; du dépôt local cloné précédemment&lt;br /&gt;
$ git fetch file://$(pwd)/../cron4j-original&lt;br /&gt;
# Fusion de ce qui vient d&#039;être fetché&lt;br /&gt;
$ git merge FETCH_HEAD&lt;br /&gt;
# Envoi sur le serveur&lt;br /&gt;
$ git push&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Cherry-picking: reprise des modifications d&#039;un collègue====&lt;br /&gt;
&lt;br /&gt;
On considère que:&lt;br /&gt;
&lt;br /&gt;
* votre dépôt Git distant est à l&#039;adresse URL_DEPOT&lt;br /&gt;
* votre collègue a un dépôt Git à l&#039;adresse URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Dossier temporaire&lt;br /&gt;
cd /tmp&lt;br /&gt;
&lt;br /&gt;
# Clone de votre dépôt&lt;br /&gt;
git clone URL_DEPOT mon_depot&lt;br /&gt;
&lt;br /&gt;
# Déplacement dans votre dépôt&lt;br /&gt;
cd mon_depot&lt;br /&gt;
&lt;br /&gt;
# Définition du dépôt distant&lt;br /&gt;
git remote add collegue URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
# Récupération des infos du dépôt du collègue&lt;br /&gt;
git fetch collegue&lt;br /&gt;
&lt;br /&gt;
# Maintenant, on peut voir les branches du collègue&lt;br /&gt;
git branch -a&lt;br /&gt;
&lt;br /&gt;
# On peut fusionner avec une branche&lt;br /&gt;
git merge collegue/master&lt;br /&gt;
&lt;br /&gt;
# Si vous avez des conflits, éditez les fichiers concernés,&lt;br /&gt;
# et committez avec git commit&lt;br /&gt;
&lt;br /&gt;
# Push vers votre dépôt distant&lt;br /&gt;
git push origin&lt;br /&gt;
&lt;br /&gt;
# Optionnel: supprimez la référence vers le dépôt du collègue&lt;br /&gt;
git remote rm collegue&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Archetype webapp====&lt;br /&gt;
L&#039;archetype webapp (http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-webapp/) permet de créer le squelette d&#039;une webapp. Créez un simple webapp monsite en version 0.1.0. (add/commit/push). Vous pourrez tester cette webapp en ajoutant au pom.xml le [https://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin plugin maven Jetty].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mvn -Djetty.port=9999 jetty:run&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naviguez sur http://localhost:9999/monsite&lt;br /&gt;
&lt;br /&gt;
====Scrum tools====&lt;br /&gt;
Ces 3 services peuvent être couplé à votre dépôt GitHub pour votre gestion de projet agile avec [[Scrum]] :&lt;br /&gt;
* http://www.acunote.com/&lt;br /&gt;
* http://backlogtool.com/&lt;br /&gt;
* http://www.scrumdo.com/&lt;br /&gt;
&lt;br /&gt;
L&#039;activation se fait via &#039;&#039;Settings &amp;gt; Webhooks &amp;amp; Services &amp;gt; Configure services&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Séance 4: AOP &amp;amp; AspectJ=&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt Git, projet &#039;&#039;cron4j-mvn&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le [http://mojo.codehaus.org/aspectj-maven-plugin/ plugin Maven pour AspectJ] au pom.xml&lt;br /&gt;
# Ajoutez un aspect de trace à l&#039;invocation des méthodes &#039;&#039;&#039;run()&#039;&#039;&#039; de l&#039;interface java.lang.Runnable (uniquement pour les objets &#039;&#039;schedulé&#039;&#039;s)&lt;br /&gt;
#: Affichez une trace avant et après l&#039;exécution de la tâche&lt;br /&gt;
# Préparez un nouveau test (nouvelle classe) démarrant un Scheduler Cron4j et validant l&#039;exécution d&#039;une tâche au bout d&#039;une minute (pattern &amp;quot;* * * * *&amp;quot;)&lt;br /&gt;
#: Lors de l&#039;exécution de &#039;&#039;&#039;mvn test&#039;&#039;&#039;, vous devez voir apparaître les traces préparées dans votre aspect.&lt;br /&gt;
&lt;br /&gt;
Liens utiles:&lt;br /&gt;
* [http://ridgetopsolutions.com/blog/2013/02/12/getting-started-with-aspectj-and-maven/ Getting started with AspectJ and Maven]&lt;br /&gt;
&lt;br /&gt;
===Contrôle continu===&lt;br /&gt;
&lt;br /&gt;
# Complétez l&#039;aspect de trace avec le positionnement du [http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html java.lang.ThreadLocal] pour passer 1) l&#039;identifiant du job et 2) le compteur des appels de la méthode de l&#039;objet.&lt;br /&gt;
&lt;br /&gt;
=Séance 5: Pelix &amp;amp; iPOPO=&lt;br /&gt;
&lt;br /&gt;
Pelix est une plate-forme d&#039;application à services (SOA).&lt;br /&gt;
iPOPO est un modèle de composants orientés services (SOCM).&lt;br /&gt;
&lt;br /&gt;
La documentation de Pelix et iPOPO est disponible sur https://ipopo.coderxpress.net/&lt;br /&gt;
&lt;br /&gt;
===Installation de iPOPO===&lt;br /&gt;
&lt;br /&gt;
* Cloner le dépôt Git depuis https://github.com/tcalmant/ipopo&lt;br /&gt;
* Se placer dans la branche &#039;&#039;dev&#039;&#039;&lt;br /&gt;
* Pour installer iPOPO, lancer la commande :&lt;br /&gt;
&lt;br /&gt;
   sudo python setup.py install&lt;br /&gt;
&lt;br /&gt;
===Shell Pelix===&lt;br /&gt;
&lt;br /&gt;
Pour lancer un shell Pelix, utilisez la commande:&lt;br /&gt;
&lt;br /&gt;
   python -m pelix.shell.console&lt;br /&gt;
&lt;br /&gt;
Les commandes disponibles sont décrites ici: [https://ipopo.coderxpress.net/wiki/doku.php?id=ipopo:refcards:shell Shell Commands]&lt;br /&gt;
&lt;br /&gt;
===Rappels de Python===&lt;br /&gt;
&lt;br /&gt;
* Pas de déclaration du type d&#039;une variable&lt;br /&gt;
* Les méthodes d&#039;une classe ont toute comme premier paramètre &#039;&#039;self&#039;&#039;, équivalent du &#039;&#039;this&#039;&#039; en Java.&lt;br /&gt;
* Blocs définis par indentation (4 espaces ou 1 tab)&lt;br /&gt;
* Une ligne finissant par &#039;:&#039; démarre toujours un bloc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Import d&#039;un module&lt;br /&gt;
import pelix&lt;br /&gt;
&lt;br /&gt;
# Définition d&#039;une classe&lt;br /&gt;
class MaClasse:&lt;br /&gt;
   # Constructeur&lt;br /&gt;
   def __init__(self):&lt;br /&gt;
       self.default = &amp;quot;stanger&amp;quot;&lt;br /&gt;
       print(&amp;quot;Classe construite&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
   # Méthode, avec un argument&lt;br /&gt;
   def sayHello(self, name):&lt;br /&gt;
       if not name:&lt;br /&gt;
           # Nom vide ou nul&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(self.default)&lt;br /&gt;
       else:&lt;br /&gt;
           # Nom valide&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(name)&lt;br /&gt;
&lt;br /&gt;
objet = MaClasse()&lt;br /&gt;
print(objet.sayHello(&amp;quot;&amp;quot;))&lt;br /&gt;
print(objet.sayHello(&amp;quot;World&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Service Ping-Pong===&lt;br /&gt;
&lt;br /&gt;
1. Écrire un fichier &#039;&#039;pong.py&#039;&#039;, définissant une classe &#039;&#039;Pong&#039;&#039; ayant une méthode &#039;&#039;pong&#039;&#039; prenant en paramètre un message et retournant le message préfixé par &amp;quot;PONG:&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Exemple: &lt;br /&gt;
   &lt;br /&gt;
      pong = Pong()&lt;br /&gt;
      pong.pong(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2. Écrire un fichier &#039;&#039;ping.py&#039;&#039;, définissant une classe &#039;&#039;Ping&#039;&#039; ayant une méthode &#039;&#039;ping&#039;&#039; prenant en paramètre un message, créant un objet Pong et retournant le résultat de Pong.pong(message) préfixé par &amp;quot;PING:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&lt;br /&gt;
      ping = Ping()&lt;br /&gt;
      ping.ping(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PING:PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
3. Transformer le fichier &#039;&#039;pong.py&#039;&#039; pour qu&#039;il devienne un bundle Pelix enregistrant un objet Pong comme étant un service ayant pour spécification &amp;quot;tagl.pong&amp;quot;&lt;br /&gt;
* Définir une classe &#039;&#039;Activator&#039;&#039;, décorée avec &#039;&#039;@BundleActivator&#039;&#039;&lt;br /&gt;
* Enregistrer le service dans la méthode &#039;&#039;Activator.start&#039;&#039; et le désenregistrer dans &#039;&#039;Activator.stop&#039;&#039;&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/provider.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;pong&#039; et vérifier que le service est bien inscrit avec la commande &#039;&#039;sl&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
4.Transformer la classe &#039;&#039;Ping&#039;&#039; dans &#039;&#039;ping.py&#039;&#039; en un composant iPOPO&lt;br /&gt;
* L&#039;objet Pong utilisé dans &#039;&#039;ping()&#039;&#039; doit être un service injecté par iPOPO (&#039;&#039;@Requires&#039;&#039;)&lt;br /&gt;
* Appeler la méthode &#039;&#039;ping()&#039;&#039; dès que le service Pong est injecté (&#039;&#039;@BindField&#039;&#039;) ou disparait (&#039;&#039;@UnbindField&#039;&#039;)&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/consumer.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;ping&#039; et vérifier son comportement si le bundle &#039;&#039;pong&#039;&#039; ou le bundle &#039;&#039;ping&#039;&#039; est arrêté et redémarré.&lt;br /&gt;
&lt;br /&gt;
5. Mettre à jour le bundle &#039;&#039;pong&#039;&#039;&lt;br /&gt;
* Remplacer le préfixe &amp;quot;PONG&amp;quot; par &amp;quot;NI&amp;quot;&lt;br /&gt;
* Dans le shell Pelix, mettre à jour le bundle &#039;&#039;pong&#039;&#039; sans redémarrer la plate-forme (commande &#039;&#039;udpate&#039;&#039;).&lt;br /&gt;
* Vérifier les traces dans le shell pour valider la mise à jour du service.&lt;br /&gt;
&lt;br /&gt;
===Remote Services===&lt;br /&gt;
&lt;br /&gt;
* Ajouter les propriétés permettant l&#039;export du service Pong dans &#039;&#039;pong.py&#039;&#039; (s&#039;inspirer de &#039;&#039;provider.py&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
* Lancer deux shells iPOPO (dans deux terminaux)&lt;br /&gt;
* Dans chaque shell iPOPO, installer les bundles:&lt;br /&gt;
** &#039;&#039;pelix.remote.dispatcher&#039;&#039;: Exportateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.registry&#039;&#039;; Importateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.discovery.multicast&#039;&#039;: Découverte de services via Multicast&lt;br /&gt;
** &#039;&#039;pelix.remote.xml_rpc&#039;&#039;: Transport XML-RPC&lt;br /&gt;
** &#039;&#039;pelix.http.basic&#039;&#039;: Serveur HTTP&lt;br /&gt;
&lt;br /&gt;
Attention: il peut être nécessaire de désactiver votre pare-feu pour que les Remote Services fonctionnent&lt;br /&gt;
&lt;br /&gt;
* Instancier les composants depuis le shell iPOPO, dans chaque framework:&lt;br /&gt;
** Serveur HTTP sur le port 8080: &#039;&#039;instantiate pelix.http.service.basic.factory http-server pelix.http.port=8080&#039;&#039; (penser à changer de port dans chaque framework)&lt;br /&gt;
** Multicast Discovery: &#039;&#039;instantiate pelix-remote-discovery-multicast-factory multicast-discovery&#039;&#039;&lt;br /&gt;
** XML-RPC Exporter: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-exporter&#039;&#039;&lt;br /&gt;
** XML-RPC Importer: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-importer&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Installer le bundle &#039;&#039;ping&#039;&#039; dans un des frameworks et le bundle &#039;&#039;pong&#039;&#039; dans l&#039;autre.&lt;br /&gt;
* Le composant ping peut appeler le service pong, qui est dans l&#039;autre framework.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Voir le code de &#039;&#039;run_remote.py&#039;&#039; pour voir comment démarrer un framework Pelix et installer des bundles depuis Python.&lt;br /&gt;
* Jouer un peu avec &#039;&#039;run_remote.py&#039;&#039; (voir &#039;&#039;run_remote.py --help&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=Séance 6=&lt;br /&gt;
[[Tutorial OSGi avec Apache Felix]]&lt;br /&gt;
&lt;br /&gt;
=Séance 7=&lt;br /&gt;
Faire un projet PDE pour un bundle cron4j.gogo (indépendant de cron4j.bundle)&lt;br /&gt;
&lt;br /&gt;
Utilisation de https://eclipse.org/tycho/&lt;/div&gt;</summary>
		<author><name>MatthieuCaneill</name></author>
	</entry>
	<entry>
		<id>https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21487</id>
		<title>TAGL/TP</title>
		<link rel="alternate" type="text/html" href="https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21487"/>
		<updated>2015-02-26T16:20:23Z</updated>

		<summary type="html">&lt;p&gt;MatthieuCaneill: /* Maven */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Travaux pratiques de l&#039;UE [[TAGL]].&lt;br /&gt;
&lt;br /&gt;
Anciennes versions : [[TAGL/TP 2014]]&lt;br /&gt;
&lt;br /&gt;
=Séance 1 : Gestion de versions=&lt;br /&gt;
==Git==&lt;br /&gt;
&lt;br /&gt;
Création d&#039;un dépôt Git local&lt;br /&gt;
&lt;br /&gt;
===Méthode simple: init first===&lt;br /&gt;
&lt;br /&gt;
Via cette méthode, on crée un dépôt local, avec un répertoire de travail, puis on pousse ses modifications vers un dépôt &amp;quot;bare&amp;quot;.&lt;br /&gt;
Cette méthode est la plus simple, car on dispose immédiatement d&#039;un répertoire de travail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création d&#039;un dépôt Git dans le dossier simple-repo&lt;br /&gt;
git init simple-repo&lt;br /&gt;
&lt;br /&gt;
# Création d&#039;un README&lt;br /&gt;
cd simple-repo&lt;br /&gt;
echo &amp;quot;Hello, World&amp;quot; &amp;gt; README&lt;br /&gt;
&lt;br /&gt;
# Ajout du versionnement du fichier README&lt;br /&gt;
git add README&lt;br /&gt;
&lt;br /&gt;
# Commit&lt;br /&gt;
git commit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À ce niveau, on a un dépôt Git complètement fonctionnel.&lt;br /&gt;
Cependant, il est intéressant de pousser ses modifications vers un autre dépôt, sur une autre machine.&lt;br /&gt;
On va donc créer un dépôt bare sur une autre machine (ou autre dossier pour l&#039;exemple)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que l&#039;URL pour accéder à ce dépôt est URL_REPO.&lt;br /&gt;
On va d&#039;abord ajouter ce dépôt serveur à la liste des dépôts connu-repos de votre dépôt local.&lt;br /&gt;
Étant donné qu&#039;il s&#039;agit du dépôt &amp;quot;principal&amp;quot; à utiliser, on l&#039;appellera //origin//, par convention.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin URL_REPO&lt;br /&gt;
# Récupération de ses informations&lt;br /&gt;
git fetch origin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce serveur distant est &amp;quot;vide&amp;quot;: il n&#039;a aucune branche. On va donc enregistrer notre branche sur le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À partir de cette commande, la branche locale //master// sera liée à la branche distante //origin/master//.&lt;br /&gt;
Lors des prochaines commandes &#039;&#039;git push&#039;&#039;, grâce à cette liaison, tous les commits sur la branche locale //master// seront poussées sur le serveur distant.&lt;br /&gt;
&lt;br /&gt;
===Méthode moins simple: bare first===&lt;br /&gt;
&lt;br /&gt;
Si on commence dans par le serveur &amp;quot;vide&amp;quot;, il faudra le cloner au lieu de le définir comme un dépôt distant.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création du dépôt vide&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que ce dépôt est accessible à l&#039;URL URL_REPO&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clonage du dépôt&lt;br /&gt;
git clone URL_REPO clone-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un avertissement indique que l&#039;on clone un dépôt vide: le dépôt local à donc une branche master, mais elle n&#039;est pas liée au dépôt distant, car celui-ci n&#039;a aucune branche.&lt;br /&gt;
Le dépôt distant est automatiquement appelé //origin//.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Commit dans le dépôt local&lt;br /&gt;
cd clone-repo&lt;br /&gt;
echo hello &amp;gt; readme.rst&lt;br /&gt;
git add readme.rst&lt;br /&gt;
git commit et ses dépendances&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme dans la méthode simple, il faut pousser la branche master vers le dépôt distant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===De l&#039;importance des README===&lt;br /&gt;
&lt;br /&gt;
Il est très important d&#039;avoir au moins 2 fichiers dans votre dépôt Git:&lt;br /&gt;
&lt;br /&gt;
* LICENSE: contenant le texte **complet** de la licence de votre projet&lt;br /&gt;
* README: décrivant votre projet et comment l&#039;utiliser. Ce fichier doit rappeler le nom de la licence de votre projet&lt;br /&gt;
&lt;br /&gt;
Il est aussi recommandé d&#039;avoir les fichiers suivants:&lt;br /&gt;
&lt;br /&gt;
* AUTHORS: contenant la liste des noms/pseudos et e-mails des auteurs de commits ou de code inclus dans ce projet&lt;br /&gt;
* INSTALL: contenant la liste des dépendances de ce projet et des commandes à utiliser pour le compiler et l&#039;installer&lt;br /&gt;
&lt;br /&gt;
Les fichiers LICENSE sont des fichiers textes bruts.&lt;br /&gt;
Les autres fichiers sont généralement dans un format offrant un peu plus de lisibilté, par exemple dans les formats [http://daringfireball.net/projects/markdown/ Markdown] (.md) ou [http://docutils.sourceforge.net/rst.html reStructuredText] (.rst)&lt;br /&gt;
&lt;br /&gt;
Un plug-in existe pour éditer des fichier reStructuredText dans Eclipse: ReST Editor, disponible sur le [https://marketplace.eclipse.org/content/rest-editor Marketplace Eclipse]&lt;br /&gt;
&lt;br /&gt;
=Séance 2a: Intégration en continue=&lt;br /&gt;
&lt;br /&gt;
===GitHub &amp;amp; [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
Travis-CI est un service permettant d&#039;exécuter un script dans une machine virtuelle Ubuntu dès que vous effectuez un push sur un de vos dépôts GitHub.&lt;br /&gt;
L&#039;intérêt est de savoir si la version d&#039;un projet que vous avez rendu publique peut être compilée et si ses tests passent.&lt;br /&gt;
&lt;br /&gt;
La machine virtuelle &amp;quot;offerte&amp;quot; par Travis est préconfigurée pour le language indiqué dans son fichier de configuration (&#039;&#039;&#039;.travis.yml&#039;&#039;&#039;), mais il est possible d&#039;utiliser la commande &#039;&#039;&#039;sudo apt-get install ...&#039;&#039;&#039; pour ajouter vos dépendances.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour utiliser [[Travis-CI]]:&lt;br /&gt;
&lt;br /&gt;
# Créez compte individuel sur GitHub https://github.com&lt;br /&gt;
# &#039;&#039;Fork&#039;&#039;ez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Ajoutez un collaborateur (i.e. votre binôme) au projet &#039;&#039;forké&#039;&#039;, via les paramètres (&#039;&#039;settings&#039;&#039;) de ce projet&lt;br /&gt;
# Pour l&#039;exemple, activez le service (ou hook) &#039;&#039;Email&#039;&#039; depuis les paramètres du dépôt: à chaque fois que vous ou un de vos collaborateurs ferra un &#039;&#039;&#039;git push&#039;&#039;&#039;, vous recevrez une notification par mail.&lt;br /&gt;
# Activez le service Travis-CI: identifiez-vous (&#039;&#039;sign in&#039;&#039;) sur https://travis-ci.org/ avec votre compte GitHub&lt;br /&gt;
# Activez le service pour les projets sur lesquels vous souhaitez appliquer les principes d&#039;intégration continue&lt;br /&gt;
&lt;br /&gt;
[[Travis-CI]] utilise un fichier nommé &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; (attention: fichier caché sous Unix) pour se configurer et choisir les opérations à effectuer.&lt;br /&gt;
Ce fichier doit se trouver à la racine de votre dépôt Git.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; du fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; ci-dessous.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
language: node_js&lt;br /&gt;
node_js:&lt;br /&gt;
  - &amp;quot;0.11&amp;quot;&lt;br /&gt;
  - &amp;quot;0.10&amp;quot;&lt;br /&gt;
  - &amp;quot;0.8&amp;quot;&lt;br /&gt;
  - &amp;quot;0.6&amp;quot;&lt;br /&gt;
  - iojs&lt;br /&gt;
  - iojs-v1.0.2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; indique à [[Travis-CI]] que les scripts de ce projet dans ce dépôt seront exécutés avec plusieurs versions de [[Node.js]].&lt;br /&gt;
&lt;br /&gt;
Ajoutez dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&#039; la section suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;quot;devDependencies&amp;quot;: {&lt;br /&gt;
    &amp;quot;jshint&amp;quot;: &amp;quot;^2.6.0&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;scripts&amp;quot;: {&lt;br /&gt;
    &amp;quot;test&amp;quot;: &amp;quot;./node_modules/jshint/bin/jshint index.js&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
et incrémentez le numéro de version.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Remarque:&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;jshint&#039;&#039;&#039; peut être lancé localement avec les commandes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo npm install jshint&lt;br /&gt;
jshint index.js&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A lire&lt;br /&gt;
* http://docs.travis-ci.com/user/languages/javascript-with-nodejs/&lt;br /&gt;
* https://github.com/docdis/learn-travis/blob/master/README.md&lt;br /&gt;
&lt;br /&gt;
=Séance 2b: Livraison en continue=&lt;br /&gt;
&lt;br /&gt;
==[[Heroku]]==&lt;br /&gt;
[https://www.heroku.com/ Heroku] est une plateforme cloud de type PaaS permettant l&#039;exécution d&#039;applications et de services en ligne écrits dans les langages et plateformes suivantes : Ruby, [[Node.js]], [[Python]], Java, et PHP.&lt;br /&gt;
&lt;br /&gt;
# Créez un compte gratuit sur [https://signup.heroku.com Heroku]&lt;br /&gt;
# Forkez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Dans Heroku, créez une nouvelle app Node.js, et liez-la au repository Github créé à l&#039;étape précédente&lt;br /&gt;
# Choisissez l&#039;option &amp;quot;Déploiement automatique&amp;quot; depuis la branche **master**&lt;br /&gt;
# Modifiez le fichier index.js pour afficher la version de service dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 var fs = require(&#039;fs&#039;);&lt;br /&gt;
 var package = JSON.parse(fs.readFileSync(&#039;./package.json&#039;, &#039;utf8&#039;));&lt;br /&gt;
 var version=package.version;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Hello World! (current version: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
# Modifiez le fichier index.js pour franciser le message dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Bonjour Tout Le Monde! (version courante: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
=Séance 3: Builders=&lt;br /&gt;
&lt;br /&gt;
==[[Ant]]==&lt;br /&gt;
&lt;br /&gt;
==[[Maven]]==&lt;br /&gt;
&lt;br /&gt;
[http://maven.apache.org/download.cgi Charger et installer Maven 3].&lt;br /&gt;
&lt;br /&gt;
Debian/Ubuntu &amp;amp; friends:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install maven&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mvn -version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Faites une copie du projet, basée sur Maven:&lt;br /&gt;
&lt;br /&gt;
# Dans votre dépôt Git, créez un dossier &#039;&#039;&#039;cron4j-mvn&#039;&#039;&#039;: il contiendra le projet Cron4J avec la structure Maven&lt;br /&gt;
# Dans ce dossier, utilisez l&#039;[https://maven.apache.org/guides/introduction/introduction-to-archetypes.html archetype] Maven [http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-quickstart/ maven-archetype-quickstart] (la version des sources de cron4j utilisés est la 2.5.5):&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart&amp;lt;/pre&amp;gt;&lt;br /&gt;
groupId: it.sauronsoftware.cron4j, artifactId: cron4j&lt;br /&gt;
# Cette commande crée un projet avec un fichier &#039;&#039;pom.xml&#039;&#039;, et une classe et un test modèles: supprimez ces modèles&lt;br /&gt;
# Copiez les sources de Cron4J depuis le dossier &#039;&#039;&#039;cron4j-original&#039;&#039;&#039; dans le dossier &#039;&#039;&#039;src/main/java&#039;&#039;&#039; de votre projet Maven&lt;br /&gt;
# Faites un essai de compilation:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Lancez un des exemples avec mvn exec:java -Dexec.mainClass=&amp;quot;com.example.Main&amp;quot; [-Dexec.args=&amp;quot;argument1&amp;quot;] ... ([http://mojo.codehaus.org/exec-maven-plugin/usage.html doc. exec plugin], [http://mojo.codehaus.org/exec-maven-plugin/java-mojo.html doc. Exec:java goal])&lt;br /&gt;
# Enfin modifiez le fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; à la racine de votre dépôt Git afin que Travis exécute la commande &#039;&#039;&#039;mvn clean verify&#039;&#039;&#039; à chaque mise à jour du dépôt GitHub.&lt;br /&gt;
&lt;br /&gt;
==Tests Unitaires avec JUnit 4==&lt;br /&gt;
Survoller le tutoriel [http://www.vogella.com/tutorials/JUnit/article.html Unit Testing with JUnit]&lt;br /&gt;
&lt;br /&gt;
# Ajouter le test unitaire suivant au projet, dans le fichier &#039;&#039;&#039;src/test/it/sauronsoftware/SchedulingPatternTest.java&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
package it.sauronsoftware;&lt;br /&gt;
&lt;br /&gt;
import it.sauronsoftware.cron4j.SchedulingPattern;&lt;br /&gt;
import it.sauronsoftware.cron4j.InvalidPatternException;&lt;br /&gt;
&lt;br /&gt;
import static org.junit.Assert.assertEquals;&lt;br /&gt;
import static org.junit.Assert.assertTrue;&lt;br /&gt;
&lt;br /&gt;
import org.junit.AfterClass;&lt;br /&gt;
import org.junit.BeforeClass;&lt;br /&gt;
import org.junit.Test;&lt;br /&gt;
&lt;br /&gt;
public class SchedulingPatternTest {&lt;br /&gt;
&lt;br /&gt;
  @BeforeClass&lt;br /&gt;
  public static void testSetup() {&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @AfterClass&lt;br /&gt;
  public static void testCleanup() {&lt;br /&gt;
    // Teardown for data used by the unit tests&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test(expected = InvalidPatternException.class)&lt;br /&gt;
  public void testExceptionIsThrown() {&lt;br /&gt;
    SchedulingPattern sp = new SchedulingPattern(&amp;quot;0 5 * *&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test&lt;br /&gt;
  public void testPattern() {&lt;br /&gt;
    String pattern;&lt;br /&gt;
    pattern=&amp;quot;0 5 * * *|8 10 * * *|22 17 * * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
    pattern=&amp;quot;0 5 * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Committez et Pushez ce nouveau fichier, pour que Travis lance les tests dès que possible&lt;br /&gt;
# Lancez les tests unitaires avec &amp;lt;pre&amp;gt;mvn test&amp;lt;/pre&amp;gt; Ce test va &#039;&#039;&#039;échouer&#039;&#039;&#039;: corrigez le.&lt;br /&gt;
# Committez et Pushez la version corrigée des tests: Travis enverra un mail pour indiquer si les tests échouent ou non&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; Travis va exécuter les tests &#039;&#039;dès que possible&#039;&#039;. Il est possible de recevoir un mail indiquant que les tests du premier &#039;&#039;push&#039;&#039; échouent alors que l&#039;on a déjà &#039;&#039;pushé&#039;&#039; la correction.&lt;br /&gt;
# Naviguez sur http://travis-ci.org pour vérifier les builds effectués.&lt;br /&gt;
# Créez des tests unitaires supplémentaire du i.s.c.CronParser&lt;br /&gt;
&lt;br /&gt;
===[[Maven]] avec [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
===Git (suite)===&lt;br /&gt;
&lt;br /&gt;
# Forkez le projet &#039;&#039;&#039;tagl&#039;&#039;&#039; d&#039;un autre binome (i.e. autre que &#039;&#039;donsez/tagl&#039;&#039;)&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; donnez lui un nom différent (e.g. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Clonez ce nouveau dépôt&lt;br /&gt;
# Lancez une compilation pour valider l&#039;état du projet (bonne pratique)&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Ajoutez une bannière de licence dans le fichier &#039;&#039;&#039;cron4j-mvn/pom.xml&#039;&#039;&#039;&lt;br /&gt;
# Lancez une nouvelle compilation pour valider vos modifications&lt;br /&gt;
# Commitez et pushez (vers votre fork de ce dépôt, i.e. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Via le site de GitHub, proposez un &amp;quot;Pull Request&amp;quot; au projet initial&lt;br /&gt;
&lt;br /&gt;
Vous pouvez ensuite supprimer le clone de ce fork.&lt;br /&gt;
Lorsque le &#039;&#039;pull request&#039;&#039; aura été accepté, vous pourrez supprimer votre fork (&#039;&#039;tagl-licensing&#039;&#039;) de votre compte GitHub.&lt;br /&gt;
&lt;br /&gt;
===Contrôle Continu===&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt &#039;&#039;tagl&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le plugin [http://mojo.codehaus.org/cobertura-maven-plugin/usage.html Cobertura] à votre projet Maven.&lt;br /&gt;
## Configurez le plugin pour [http://mojo.codehaus.org/cobertura-maven-plugin/examples/report-formats.html générer un rapport] HTML. Le résultat se trouvera dans &#039;&#039;target/site/cobertura&#039;&#039;&lt;br /&gt;
## Le plugin ne s&#039;exécute automatiquement pas durant la compilation, il faut utiliser la commande : &amp;lt;pre&amp;gt;mvn cobertura:cobertura&amp;lt;/pre&amp;gt;&lt;br /&gt;
## &#039;&#039;&#039;Bonus:&#039;&#039;&#039; Modifiez le fichier &#039;&#039;pom.xml&#039;&#039; pour que le &#039;&#039;goal&#039;&#039; &#039;&#039;&#039;cobertura&#039;&#039;&#039; soit exécuté pendant la &#039;&#039;phase&#039;&#039; &#039;&#039;&#039;package&#039;&#039;&#039;.&lt;br /&gt;
# Répondez aux questions : &#039;&#039;Mais qu&#039;est ce que la couverture de code ? En quoi c&#039;est utile ?&#039;&#039;&lt;br /&gt;
# Ajoutez au projet Maven les plugins pour la génération d&#039;un site et de rapports (Javadoc, tests unitaires, tags list (FIXME, TODO, ...), ...): voir http://maven.apache.org/plugins/maven-site-plugin/ et d&#039;autres.&lt;br /&gt;
# Regardez les exemples d&#039;utilisation de cron4j dans cron4j-original/examples&lt;br /&gt;
&lt;br /&gt;
===Bonus Track===&lt;br /&gt;
&lt;br /&gt;
====Clone SVN -&amp;gt; Git====&lt;br /&gt;
&lt;br /&gt;
Source: http://www.yterium.net/Migrer-un-projet-SVN-vers-GIT&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Cloner le dépôt SVN en dépôt Git (conservation historique)&lt;br /&gt;
$ git svn clone  svn://svn.code.sf.net/p/cron4j/code/trunk cron4j-original&lt;br /&gt;
$ cd cron4j-original&lt;br /&gt;
# Test compilation&lt;br /&gt;
$ ant jar&lt;br /&gt;
$ cd ..&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Préparation TAGL====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clone du dépôt TAGL&lt;br /&gt;
$ git clone git@github.com:donsez/tagl.git&lt;br /&gt;
$ cd tagl&lt;br /&gt;
# &amp;quot;Fetch&amp;quot; du dépôt local cloné précédemment&lt;br /&gt;
$ git fetch file://$(pwd)/../cron4j-original&lt;br /&gt;
# Fusion de ce qui vient d&#039;être fetché&lt;br /&gt;
$ git merge FETCH_HEAD&lt;br /&gt;
# Envoi sur le serveur&lt;br /&gt;
$ git push&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Cherry-picking: reprise des modifications d&#039;un collègue====&lt;br /&gt;
&lt;br /&gt;
On considère que:&lt;br /&gt;
&lt;br /&gt;
* votre dépôt Git distant est à l&#039;adresse URL_DEPOT&lt;br /&gt;
* votre collègue a un dépôt Git à l&#039;adresse URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Dossier temporaire&lt;br /&gt;
cd /tmp&lt;br /&gt;
&lt;br /&gt;
# Clone de votre dépôt&lt;br /&gt;
git clone URL_DEPOT mon_depot&lt;br /&gt;
&lt;br /&gt;
# Déplacement dans votre dépôt&lt;br /&gt;
cd mon_depot&lt;br /&gt;
&lt;br /&gt;
# Définition du dépôt distant&lt;br /&gt;
git remote add collegue URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
# Récupération des infos du dépôt du collègue&lt;br /&gt;
git fetch collegue&lt;br /&gt;
&lt;br /&gt;
# Maintenant, on peut voir les branches du collègue&lt;br /&gt;
git branch -a&lt;br /&gt;
&lt;br /&gt;
# On peut fusionner avec une branche&lt;br /&gt;
git merge collegue/master&lt;br /&gt;
&lt;br /&gt;
# Si vous avez des conflits, éditez les fichiers concernés,&lt;br /&gt;
# et committez avec git commit&lt;br /&gt;
&lt;br /&gt;
# Push vers votre dépôt distant&lt;br /&gt;
git push origin&lt;br /&gt;
&lt;br /&gt;
# Optionnel: supprimez la référence vers le dépôt du collègue&lt;br /&gt;
git remote rm collegue&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Archetype webapp====&lt;br /&gt;
L&#039;archetype webapp (http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-webapp/) permet de créer le squelette d&#039;une webapp. Créez un simple webapp monsite en version 0.1.0. (add/commit/push). Vous pourrez tester cette webapp en ajoutant au pom.xml le [https://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin plugin maven Jetty].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mvn -Djetty.port=9999 jetty:run&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naviguez sur http://localhost:9999/monsite&lt;br /&gt;
&lt;br /&gt;
====Scrum tools====&lt;br /&gt;
Ces 3 services peuvent être couplé à votre dépôt GitHub pour votre gestion de projet agile avec [[Scrum]] :&lt;br /&gt;
* http://www.acunote.com/&lt;br /&gt;
* http://backlogtool.com/&lt;br /&gt;
* http://www.scrumdo.com/&lt;br /&gt;
&lt;br /&gt;
L&#039;activation se fait via &#039;&#039;Settings &amp;gt; Webhooks &amp;amp; Services &amp;gt; Configure services&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Séance 4: AOP &amp;amp; AspectJ=&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt Git, projet &#039;&#039;cron4j-mvn&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le [http://mojo.codehaus.org/aspectj-maven-plugin/ plugin Maven pour AspectJ] au pom.xml&lt;br /&gt;
# Ajoutez un aspect de trace à l&#039;invocation des méthodes &#039;&#039;&#039;run()&#039;&#039;&#039; de l&#039;interface java.lang.Runnable (uniquement pour les objets &#039;&#039;schedulé&#039;&#039;s)&lt;br /&gt;
#: Affichez une trace avant et après l&#039;exécution de la tâche&lt;br /&gt;
# Préparez un nouveau test (nouvelle classe) démarrant un Scheduler Cron4j et validant l&#039;exécution d&#039;une tâche au bout d&#039;une minute (pattern &amp;quot;* * * * *&amp;quot;)&lt;br /&gt;
#: Lors de l&#039;exécution de &#039;&#039;&#039;mvn test&#039;&#039;&#039;, vous devez voir apparaître les traces préparées dans votre aspect.&lt;br /&gt;
&lt;br /&gt;
Liens utiles:&lt;br /&gt;
* [http://ridgetopsolutions.com/blog/2013/02/12/getting-started-with-aspectj-and-maven/ Getting started with AspectJ and Maven]&lt;br /&gt;
&lt;br /&gt;
===Contrôle continu===&lt;br /&gt;
&lt;br /&gt;
# Complétez l&#039;aspect de trace avec le positionnement du [http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html java.lang.ThreadLocal] pour passer 1) l&#039;identifiant du job et 2) le compteur des appels de la méthode de l&#039;objet.&lt;br /&gt;
&lt;br /&gt;
=Séance 5: Pelix &amp;amp; iPOPO=&lt;br /&gt;
&lt;br /&gt;
Pelix est une plate-forme d&#039;application à services (SOA).&lt;br /&gt;
iPOPO est un modèle de composants orientés services (SOCM).&lt;br /&gt;
&lt;br /&gt;
La documentation de Pelix et iPOPO est disponible sur https://ipopo.coderxpress.net/&lt;br /&gt;
&lt;br /&gt;
===Installation de iPOPO===&lt;br /&gt;
&lt;br /&gt;
* Cloner le dépôt Git depuis https://github.com/tcalmant/ipopo&lt;br /&gt;
* Se placer dans la branche &#039;&#039;dev&#039;&#039;&lt;br /&gt;
* Pour installer iPOPO, lancer la commande :&lt;br /&gt;
&lt;br /&gt;
   sudo python setup.py install&lt;br /&gt;
&lt;br /&gt;
===Shell Pelix===&lt;br /&gt;
&lt;br /&gt;
Pour lancer un shell Pelix, utilisez la commande:&lt;br /&gt;
&lt;br /&gt;
   python -m pelix.shell.console&lt;br /&gt;
&lt;br /&gt;
Les commandes disponibles sont décrites ici: [https://ipopo.coderxpress.net/wiki/doku.php?id=ipopo:refcards:shell Shell Commands]&lt;br /&gt;
&lt;br /&gt;
===Rappels de Python===&lt;br /&gt;
&lt;br /&gt;
* Pas de déclaration du type d&#039;une variable&lt;br /&gt;
* Les méthodes d&#039;une classe ont toute comme premier paramètre &#039;&#039;self&#039;&#039;, équivalent du &#039;&#039;this&#039;&#039; en Java.&lt;br /&gt;
* Blocs définis par indentation (4 espaces ou 1 tab)&lt;br /&gt;
* Une ligne finissant par &#039;:&#039; démarre toujours un bloc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Import d&#039;un module&lt;br /&gt;
import pelix&lt;br /&gt;
&lt;br /&gt;
# Définition d&#039;une classe&lt;br /&gt;
class MaClasse:&lt;br /&gt;
   # Constructeur&lt;br /&gt;
   def __init__(self):&lt;br /&gt;
       self.default = &amp;quot;stanger&amp;quot;&lt;br /&gt;
       print(&amp;quot;Classe construite&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
   # Méthode, avec un argument&lt;br /&gt;
   def sayHello(self, name):&lt;br /&gt;
       if not name:&lt;br /&gt;
           # Nom vide ou nul&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(self.default)&lt;br /&gt;
       else:&lt;br /&gt;
           # Nom valide&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(name)&lt;br /&gt;
&lt;br /&gt;
objet = MaClasse()&lt;br /&gt;
print(objet.sayHello(&amp;quot;&amp;quot;))&lt;br /&gt;
print(objet.sayHello(&amp;quot;World&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Service Ping-Pong===&lt;br /&gt;
&lt;br /&gt;
1. Écrire un fichier &#039;&#039;pong.py&#039;&#039;, définissant une classe &#039;&#039;Pong&#039;&#039; ayant une méthode &#039;&#039;pong&#039;&#039; prenant en paramètre un message et retournant le message préfixé par &amp;quot;PONG:&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Exemple: &lt;br /&gt;
   &lt;br /&gt;
      pong = Pong()&lt;br /&gt;
      pong.pong(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2. Écrire un fichier &#039;&#039;ping.py&#039;&#039;, définissant une classe &#039;&#039;Ping&#039;&#039; ayant une méthode &#039;&#039;ping&#039;&#039; prenant en paramètre un message, créant un objet Pong et retournant le résultat de Pong.pong(message) préfixé par &amp;quot;PING:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&lt;br /&gt;
      ping = Ping()&lt;br /&gt;
      ping.ping(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PING:PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
3. Transformer le fichier &#039;&#039;pong.py&#039;&#039; pour qu&#039;il devienne un bundle Pelix enregistrant un objet Pong comme étant un service ayant pour spécification &amp;quot;tagl.pong&amp;quot;&lt;br /&gt;
* Définir une classe &#039;&#039;Activator&#039;&#039;, décorée avec &#039;&#039;@BundleActivator&#039;&#039;&lt;br /&gt;
* Enregistrer le service dans la méthode &#039;&#039;Activator.start&#039;&#039; et le désenregistrer dans &#039;&#039;Activator.stop&#039;&#039;&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/provider.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;pong&#039; et vérifier que le service est bien inscrit avec la commande &#039;&#039;sl&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
4.Transformer la classe &#039;&#039;Ping&#039;&#039; dans &#039;&#039;ping.py&#039;&#039; en un composant iPOPO&lt;br /&gt;
* L&#039;objet Pong utilisé dans &#039;&#039;ping()&#039;&#039; doit être un service injecté par iPOPO (&#039;&#039;@Requires&#039;&#039;)&lt;br /&gt;
* Appeler la méthode &#039;&#039;ping()&#039;&#039; dès que le service Pong est injecté (&#039;&#039;@BindField&#039;&#039;) ou disparait (&#039;&#039;@UnbindField&#039;&#039;)&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/consumer.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;ping&#039; et vérifier son comportement si le bundle &#039;&#039;pong&#039;&#039; ou le bundle &#039;&#039;ping&#039;&#039; est arrêté et redémarré.&lt;br /&gt;
&lt;br /&gt;
5. Mettre à jour le bundle &#039;&#039;pong&#039;&#039;&lt;br /&gt;
* Remplacer le préfixe &amp;quot;PONG&amp;quot; par &amp;quot;NI&amp;quot;&lt;br /&gt;
* Dans le shell Pelix, mettre à jour le bundle &#039;&#039;pong&#039;&#039; sans redémarrer la plate-forme (commande &#039;&#039;udpate&#039;&#039;).&lt;br /&gt;
* Vérifier les traces dans le shell pour valider la mise à jour du service.&lt;br /&gt;
&lt;br /&gt;
===Remote Services===&lt;br /&gt;
&lt;br /&gt;
* Ajouter les propriétés permettant l&#039;export du service Pong dans &#039;&#039;pong.py&#039;&#039; (s&#039;inspirer de &#039;&#039;provider.py&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
* Lancer deux shells iPOPO (dans deux terminaux)&lt;br /&gt;
* Dans chaque shell iPOPO, installer les bundles:&lt;br /&gt;
** &#039;&#039;pelix.remote.dispatcher&#039;&#039;: Exportateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.registry&#039;&#039;; Importateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.discovery.multicast&#039;&#039;: Découverte de services via Multicast&lt;br /&gt;
** &#039;&#039;pelix.remote.xml_rpc&#039;&#039;: Transport XML-RPC&lt;br /&gt;
** &#039;&#039;pelix.http.basic&#039;&#039;: Serveur HTTP&lt;br /&gt;
&lt;br /&gt;
Attention: il peut être nécessaire de désactiver votre pare-feu pour que les Remote Services fonctionnent&lt;br /&gt;
&lt;br /&gt;
* Instancier les composants depuis le shell iPOPO, dans chaque framework:&lt;br /&gt;
** Serveur HTTP sur le port 8080: &#039;&#039;instantiate pelix.http.service.basic.factory http-server pelix.http.port=8080&#039;&#039; (penser à changer de port dans chaque framework)&lt;br /&gt;
** Multicast Discovery: &#039;&#039;instantiate pelix-remote-discovery-multicast-factory multicast-discovery&#039;&#039;&lt;br /&gt;
** XML-RPC Exporter: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-exporter&#039;&#039;&lt;br /&gt;
** XML-RPC Importer: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-importer&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Installer le bundle &#039;&#039;ping&#039;&#039; dans un des frameworks et le bundle &#039;&#039;pong&#039;&#039; dans l&#039;autre.&lt;br /&gt;
* Le composant ping peut appeler le service pong, qui est dans l&#039;autre framework.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Voir le code de &#039;&#039;run_remote.py&#039;&#039; pour voir comment démarrer un framework Pelix et installer des bundles depuis Python.&lt;br /&gt;
* Jouer un peu avec &#039;&#039;run_remote.py&#039;&#039; (voir &#039;&#039;run_remote.py --help&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=Séance 6=&lt;br /&gt;
[[Tutorial OSGi avec Apache Felix]]&lt;br /&gt;
&lt;br /&gt;
=Séance 7=&lt;br /&gt;
Faire un projet PDE pour un bundle cron4j.gogo (indépendant de cron4j.bundle)&lt;br /&gt;
&lt;br /&gt;
Utilisation de https://eclipse.org/tycho/&lt;/div&gt;</summary>
		<author><name>MatthieuCaneill</name></author>
	</entry>
	<entry>
		<id>https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21486</id>
		<title>TAGL/TP</title>
		<link rel="alternate" type="text/html" href="https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21486"/>
		<updated>2015-02-26T14:38:01Z</updated>

		<summary type="html">&lt;p&gt;MatthieuCaneill: /* Maven */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Travaux pratiques de l&#039;UE [[TAGL]].&lt;br /&gt;
&lt;br /&gt;
Anciennes versions : [[TAGL/TP 2014]]&lt;br /&gt;
&lt;br /&gt;
=Séance 1 : Gestion de versions=&lt;br /&gt;
==Git==&lt;br /&gt;
&lt;br /&gt;
Création d&#039;un dépôt Git local&lt;br /&gt;
&lt;br /&gt;
===Méthode simple: init first===&lt;br /&gt;
&lt;br /&gt;
Via cette méthode, on crée un dépôt local, avec un répertoire de travail, puis on pousse ses modifications vers un dépôt &amp;quot;bare&amp;quot;.&lt;br /&gt;
Cette méthode est la plus simple, car on dispose immédiatement d&#039;un répertoire de travail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création d&#039;un dépôt Git dans le dossier simple-repo&lt;br /&gt;
git init simple-repo&lt;br /&gt;
&lt;br /&gt;
# Création d&#039;un README&lt;br /&gt;
cd simple-repo&lt;br /&gt;
echo &amp;quot;Hello, World&amp;quot; &amp;gt; README&lt;br /&gt;
&lt;br /&gt;
# Ajout du versionnement du fichier README&lt;br /&gt;
git add README&lt;br /&gt;
&lt;br /&gt;
# Commit&lt;br /&gt;
git commit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À ce niveau, on a un dépôt Git complètement fonctionnel.&lt;br /&gt;
Cependant, il est intéressant de pousser ses modifications vers un autre dépôt, sur une autre machine.&lt;br /&gt;
On va donc créer un dépôt bare sur une autre machine (ou autre dossier pour l&#039;exemple)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que l&#039;URL pour accéder à ce dépôt est URL_REPO.&lt;br /&gt;
On va d&#039;abord ajouter ce dépôt serveur à la liste des dépôts connu-repos de votre dépôt local.&lt;br /&gt;
Étant donné qu&#039;il s&#039;agit du dépôt &amp;quot;principal&amp;quot; à utiliser, on l&#039;appellera //origin//, par convention.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin URL_REPO&lt;br /&gt;
# Récupération de ses informations&lt;br /&gt;
git fetch origin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce serveur distant est &amp;quot;vide&amp;quot;: il n&#039;a aucune branche. On va donc enregistrer notre branche sur le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À partir de cette commande, la branche locale //master// sera liée à la branche distante //origin/master//.&lt;br /&gt;
Lors des prochaines commandes &#039;&#039;git push&#039;&#039;, grâce à cette liaison, tous les commits sur la branche locale //master// seront poussées sur le serveur distant.&lt;br /&gt;
&lt;br /&gt;
===Méthode moins simple: bare first===&lt;br /&gt;
&lt;br /&gt;
Si on commence dans par le serveur &amp;quot;vide&amp;quot;, il faudra le cloner au lieu de le définir comme un dépôt distant.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création du dépôt vide&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que ce dépôt est accessible à l&#039;URL URL_REPO&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clonage du dépôt&lt;br /&gt;
git clone URL_REPO clone-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un avertissement indique que l&#039;on clone un dépôt vide: le dépôt local à donc une branche master, mais elle n&#039;est pas liée au dépôt distant, car celui-ci n&#039;a aucune branche.&lt;br /&gt;
Le dépôt distant est automatiquement appelé //origin//.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Commit dans le dépôt local&lt;br /&gt;
cd clone-repo&lt;br /&gt;
echo hello &amp;gt; readme.rst&lt;br /&gt;
git add readme.rst&lt;br /&gt;
git commit et ses dépendances&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme dans la méthode simple, il faut pousser la branche master vers le dépôt distant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===De l&#039;importance des README===&lt;br /&gt;
&lt;br /&gt;
Il est très important d&#039;avoir au moins 2 fichiers dans votre dépôt Git:&lt;br /&gt;
&lt;br /&gt;
* LICENSE: contenant le texte **complet** de la licence de votre projet&lt;br /&gt;
* README: décrivant votre projet et comment l&#039;utiliser. Ce fichier doit rappeler le nom de la licence de votre projet&lt;br /&gt;
&lt;br /&gt;
Il est aussi recommandé d&#039;avoir les fichiers suivants:&lt;br /&gt;
&lt;br /&gt;
* AUTHORS: contenant la liste des noms/pseudos et e-mails des auteurs de commits ou de code inclus dans ce projet&lt;br /&gt;
* INSTALL: contenant la liste des dépendances de ce projet et des commandes à utiliser pour le compiler et l&#039;installer&lt;br /&gt;
&lt;br /&gt;
Les fichiers LICENSE sont des fichiers textes bruts.&lt;br /&gt;
Les autres fichiers sont généralement dans un format offrant un peu plus de lisibilté, par exemple dans les formats [http://daringfireball.net/projects/markdown/ Markdown] (.md) ou [http://docutils.sourceforge.net/rst.html reStructuredText] (.rst)&lt;br /&gt;
&lt;br /&gt;
Un plug-in existe pour éditer des fichier reStructuredText dans Eclipse: ReST Editor, disponible sur le [https://marketplace.eclipse.org/content/rest-editor Marketplace Eclipse]&lt;br /&gt;
&lt;br /&gt;
=Séance 2a: Intégration en continue=&lt;br /&gt;
&lt;br /&gt;
===GitHub &amp;amp; [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
Travis-CI est un service permettant d&#039;exécuter un script dans une machine virtuelle Ubuntu dès que vous effectuez un push sur un de vos dépôts GitHub.&lt;br /&gt;
L&#039;intérêt est de savoir si la version d&#039;un projet que vous avez rendu publique peut être compilée et si ses tests passent.&lt;br /&gt;
&lt;br /&gt;
La machine virtuelle &amp;quot;offerte&amp;quot; par Travis est préconfigurée pour le language indiqué dans son fichier de configuration (&#039;&#039;&#039;.travis.yml&#039;&#039;&#039;), mais il est possible d&#039;utiliser la commande &#039;&#039;&#039;sudo apt-get install ...&#039;&#039;&#039; pour ajouter vos dépendances.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour utiliser [[Travis-CI]]:&lt;br /&gt;
&lt;br /&gt;
# Créez compte individuel sur GitHub https://github.com&lt;br /&gt;
# &#039;&#039;Fork&#039;&#039;ez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Ajoutez un collaborateur (i.e. votre binôme) au projet &#039;&#039;forké&#039;&#039;, via les paramètres (&#039;&#039;settings&#039;&#039;) de ce projet&lt;br /&gt;
# Pour l&#039;exemple, activez le service (ou hook) &#039;&#039;Email&#039;&#039; depuis les paramètres du dépôt: à chaque fois que vous ou un de vos collaborateurs ferra un &#039;&#039;&#039;git push&#039;&#039;&#039;, vous recevrez une notification par mail.&lt;br /&gt;
# Activez le service Travis-CI: identifiez-vous (&#039;&#039;sign in&#039;&#039;) sur https://travis-ci.org/ avec votre compte GitHub&lt;br /&gt;
# Activez le service pour les projets sur lesquels vous souhaitez appliquer les principes d&#039;intégration continue&lt;br /&gt;
&lt;br /&gt;
[[Travis-CI]] utilise un fichier nommé &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; (attention: fichier caché sous Unix) pour se configurer et choisir les opérations à effectuer.&lt;br /&gt;
Ce fichier doit se trouver à la racine de votre dépôt Git.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; du fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; ci-dessous.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
language: node_js&lt;br /&gt;
node_js:&lt;br /&gt;
  - &amp;quot;0.11&amp;quot;&lt;br /&gt;
  - &amp;quot;0.10&amp;quot;&lt;br /&gt;
  - &amp;quot;0.8&amp;quot;&lt;br /&gt;
  - &amp;quot;0.6&amp;quot;&lt;br /&gt;
  - iojs&lt;br /&gt;
  - iojs-v1.0.2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; indique à [[Travis-CI]] que les scripts de ce projet dans ce dépôt seront exécutés avec plusieurs versions de [[Node.js]].&lt;br /&gt;
&lt;br /&gt;
Ajoutez dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&#039; la section suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;quot;devDependencies&amp;quot;: {&lt;br /&gt;
    &amp;quot;jshint&amp;quot;: &amp;quot;^2.6.0&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;scripts&amp;quot;: {&lt;br /&gt;
    &amp;quot;test&amp;quot;: &amp;quot;./node_modules/jshint/bin/jshint index.js&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
et incrémentez le numéro de version.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Remarque:&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;jshint&#039;&#039;&#039; peut être lancé localement avec les commandes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo npm install jshint&lt;br /&gt;
jshint index.js&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A lire&lt;br /&gt;
* http://docs.travis-ci.com/user/languages/javascript-with-nodejs/&lt;br /&gt;
* https://github.com/docdis/learn-travis/blob/master/README.md&lt;br /&gt;
&lt;br /&gt;
=Séance 2b: Livraison en continue=&lt;br /&gt;
&lt;br /&gt;
==[[Heroku]]==&lt;br /&gt;
[https://www.heroku.com/ Heroku] est une plateforme cloud de type PaaS permettant l&#039;exécution d&#039;applications et de services en ligne écrits dans les langages et plateformes suivantes : Ruby, [[Node.js]], [[Python]], Java, et PHP.&lt;br /&gt;
&lt;br /&gt;
# Créez un compte gratuit sur [https://signup.heroku.com Heroku]&lt;br /&gt;
# Forkez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Dans Heroku, créez une nouvelle app Node.js, et liez-la au repository Github créé à l&#039;étape précédente&lt;br /&gt;
# Choisissez l&#039;option &amp;quot;Déploiement automatique&amp;quot; depuis la branche **master**&lt;br /&gt;
# Modifiez le fichier index.js pour afficher la version de service dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 var fs = require(&#039;fs&#039;);&lt;br /&gt;
 var package = JSON.parse(fs.readFileSync(&#039;./package.json&#039;, &#039;utf8&#039;));&lt;br /&gt;
 var version=package.version;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Hello World! (current version: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
# Modifiez le fichier index.js pour franciser le message dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Bonjour Tout Le Monde! (version courante: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incrémentez le numéro de version dans le fichier &#039;&#039;&#039;package.json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; des fichiers touchés.&lt;br /&gt;
&lt;br /&gt;
Naviguez l&#039;application sur Heroku&lt;br /&gt;
&lt;br /&gt;
=Séance 3: Builders=&lt;br /&gt;
&lt;br /&gt;
==[[Ant]]==&lt;br /&gt;
&lt;br /&gt;
==[[Maven]]==&lt;br /&gt;
&lt;br /&gt;
[http://maven.apache.org/download.cgi Charger et installer Maven 3].&lt;br /&gt;
&lt;br /&gt;
Debian/Ubuntu &amp;amp; friends:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install maven&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mvn -version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Faites une copie du projet, basée sur Maven:&lt;br /&gt;
&lt;br /&gt;
# Dans votre dépôt Git, créez un dossier &#039;&#039;&#039;cron4j-mvn&#039;&#039;&#039;: il contiendra le projet Cron4J avec la structure Maven&lt;br /&gt;
# Dans ce dossier, utilisez l&#039;[https://maven.apache.org/guides/introduction/introduction-to-archetypes.html archetype] Maven [http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-quickstart/ maven-archetype-quickstart] (la version des sources de cron4j utilisés est la 2.5.5):&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Cette commande crée un projet avec un fichier &#039;&#039;pom.xml&#039;&#039;, et une classe et un test modèles: supprimez ces modèles&lt;br /&gt;
# Copiez les sources de Cron4J depuis le dossier &#039;&#039;&#039;cron4j-original&#039;&#039;&#039; dans le dossier &#039;&#039;&#039;src/main/java&#039;&#039;&#039; de votre projet Maven&lt;br /&gt;
# Faites un essai de compilation:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Lancez un des exemples avec mvn exec:java -Dexec.mainClass=&amp;quot;com.example.Main&amp;quot; [-Dexec.args=&amp;quot;argument1&amp;quot;] ... ([http://mojo.codehaus.org/exec-maven-plugin/usage.html doc. exec plugin], [http://mojo.codehaus.org/exec-maven-plugin/java-mojo.html doc. Exec:java goal])&lt;br /&gt;
# Enfin modifiez le fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; à la racine de votre dépôt Git afin que Travis exécute la commande &#039;&#039;&#039;mvn clean verify&#039;&#039;&#039; à chaque mise à jour du dépôt GitHub.&lt;br /&gt;
&lt;br /&gt;
==Tests Unitaires avec JUnit 4==&lt;br /&gt;
Survoller le tutoriel [http://www.vogella.com/tutorials/JUnit/article.html Unit Testing with JUnit]&lt;br /&gt;
&lt;br /&gt;
# Ajouter le test unitaire suivant au projet, dans le fichier &#039;&#039;&#039;src/test/it/sauronsoftware/SchedulingPatternTest.java&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
package it.sauronsoftware;&lt;br /&gt;
&lt;br /&gt;
import it.sauronsoftware.cron4j.SchedulingPattern;&lt;br /&gt;
import it.sauronsoftware.cron4j.InvalidPatternException;&lt;br /&gt;
&lt;br /&gt;
import static org.junit.Assert.assertEquals;&lt;br /&gt;
import static org.junit.Assert.assertTrue;&lt;br /&gt;
&lt;br /&gt;
import org.junit.AfterClass;&lt;br /&gt;
import org.junit.BeforeClass;&lt;br /&gt;
import org.junit.Test;&lt;br /&gt;
&lt;br /&gt;
public class SchedulingPatternTest {&lt;br /&gt;
&lt;br /&gt;
  @BeforeClass&lt;br /&gt;
  public static void testSetup() {&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @AfterClass&lt;br /&gt;
  public static void testCleanup() {&lt;br /&gt;
    // Teardown for data used by the unit tests&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test(expected = InvalidPatternException.class)&lt;br /&gt;
  public void testExceptionIsThrown() {&lt;br /&gt;
    SchedulingPattern sp = new SchedulingPattern(&amp;quot;0 5 * *&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test&lt;br /&gt;
  public void testPattern() {&lt;br /&gt;
    String pattern;&lt;br /&gt;
    pattern=&amp;quot;0 5 * * *|8 10 * * *|22 17 * * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
    pattern=&amp;quot;0 5 * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Committez et Pushez ce nouveau fichier, pour que Travis lance les tests dès que possible&lt;br /&gt;
# Lancez les tests unitaires avec &amp;lt;pre&amp;gt;mvn test&amp;lt;/pre&amp;gt; Ce test va &#039;&#039;&#039;échouer&#039;&#039;&#039;: corrigez le.&lt;br /&gt;
# Committez et Pushez la version corrigée des tests: Travis enverra un mail pour indiquer si les tests échouent ou non&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; Travis va exécuter les tests &#039;&#039;dès que possible&#039;&#039;. Il est possible de recevoir un mail indiquant que les tests du premier &#039;&#039;push&#039;&#039; échouent alors que l&#039;on a déjà &#039;&#039;pushé&#039;&#039; la correction.&lt;br /&gt;
# Naviguez sur http://travis-ci.org pour vérifier les builds effectués.&lt;br /&gt;
# Créez des tests unitaires supplémentaire du i.s.c.CronParser&lt;br /&gt;
&lt;br /&gt;
===[[Maven]] avec [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
===Git (suite)===&lt;br /&gt;
&lt;br /&gt;
# Forkez le projet &#039;&#039;&#039;tagl&#039;&#039;&#039; d&#039;un autre binome (i.e. autre que &#039;&#039;donsez/tagl&#039;&#039;)&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; donnez lui un nom différent (e.g. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Clonez ce nouveau dépôt&lt;br /&gt;
# Lancez une compilation pour valider l&#039;état du projet (bonne pratique)&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Ajoutez une bannière de licence dans le fichier &#039;&#039;&#039;cron4j-mvn/pom.xml&#039;&#039;&#039;&lt;br /&gt;
# Lancez une nouvelle compilation pour valider vos modifications&lt;br /&gt;
# Commitez et pushez (vers votre fork de ce dépôt, i.e. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Via le site de GitHub, proposez un &amp;quot;Pull Request&amp;quot; au projet initial&lt;br /&gt;
&lt;br /&gt;
Vous pouvez ensuite supprimer le clone de ce fork.&lt;br /&gt;
Lorsque le &#039;&#039;pull request&#039;&#039; aura été accepté, vous pourrez supprimer votre fork (&#039;&#039;tagl-licensing&#039;&#039;) de votre compte GitHub.&lt;br /&gt;
&lt;br /&gt;
===Contrôle Continu===&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt &#039;&#039;tagl&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le plugin [http://mojo.codehaus.org/cobertura-maven-plugin/usage.html Cobertura] à votre projet Maven.&lt;br /&gt;
## Configurez le plugin pour [http://mojo.codehaus.org/cobertura-maven-plugin/examples/report-formats.html générer un rapport] HTML. Le résultat se trouvera dans &#039;&#039;target/site/cobertura&#039;&#039;&lt;br /&gt;
## Le plugin ne s&#039;exécute automatiquement pas durant la compilation, il faut utiliser la commande : &amp;lt;pre&amp;gt;mvn cobertura:cobertura&amp;lt;/pre&amp;gt;&lt;br /&gt;
## &#039;&#039;&#039;Bonus:&#039;&#039;&#039; Modifiez le fichier &#039;&#039;pom.xml&#039;&#039; pour que le &#039;&#039;goal&#039;&#039; &#039;&#039;&#039;cobertura&#039;&#039;&#039; soit exécuté pendant la &#039;&#039;phase&#039;&#039; &#039;&#039;&#039;package&#039;&#039;&#039;.&lt;br /&gt;
# Répondez aux questions : &#039;&#039;Mais qu&#039;est ce que la couverture de code ? En quoi c&#039;est utile ?&#039;&#039;&lt;br /&gt;
# Ajoutez au projet Maven les plugins pour la génération d&#039;un site et de rapports (Javadoc, tests unitaires, tags list (FIXME, TODO, ...), ...): voir http://maven.apache.org/plugins/maven-site-plugin/ et d&#039;autres.&lt;br /&gt;
# Regardez les exemples d&#039;utilisation de cron4j dans cron4j-original/examples&lt;br /&gt;
&lt;br /&gt;
===Bonus Track===&lt;br /&gt;
&lt;br /&gt;
====Clone SVN -&amp;gt; Git====&lt;br /&gt;
&lt;br /&gt;
Source: http://www.yterium.net/Migrer-un-projet-SVN-vers-GIT&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Cloner le dépôt SVN en dépôt Git (conservation historique)&lt;br /&gt;
$ git svn clone  svn://svn.code.sf.net/p/cron4j/code/trunk cron4j-original&lt;br /&gt;
$ cd cron4j-original&lt;br /&gt;
# Test compilation&lt;br /&gt;
$ ant jar&lt;br /&gt;
$ cd ..&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Préparation TAGL====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clone du dépôt TAGL&lt;br /&gt;
$ git clone git@github.com:donsez/tagl.git&lt;br /&gt;
$ cd tagl&lt;br /&gt;
# &amp;quot;Fetch&amp;quot; du dépôt local cloné précédemment&lt;br /&gt;
$ git fetch file://$(pwd)/../cron4j-original&lt;br /&gt;
# Fusion de ce qui vient d&#039;être fetché&lt;br /&gt;
$ git merge FETCH_HEAD&lt;br /&gt;
# Envoi sur le serveur&lt;br /&gt;
$ git push&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Cherry-picking: reprise des modifications d&#039;un collègue====&lt;br /&gt;
&lt;br /&gt;
On considère que:&lt;br /&gt;
&lt;br /&gt;
* votre dépôt Git distant est à l&#039;adresse URL_DEPOT&lt;br /&gt;
* votre collègue a un dépôt Git à l&#039;adresse URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Dossier temporaire&lt;br /&gt;
cd /tmp&lt;br /&gt;
&lt;br /&gt;
# Clone de votre dépôt&lt;br /&gt;
git clone URL_DEPOT mon_depot&lt;br /&gt;
&lt;br /&gt;
# Déplacement dans votre dépôt&lt;br /&gt;
cd mon_depot&lt;br /&gt;
&lt;br /&gt;
# Définition du dépôt distant&lt;br /&gt;
git remote add collegue URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
# Récupération des infos du dépôt du collègue&lt;br /&gt;
git fetch collegue&lt;br /&gt;
&lt;br /&gt;
# Maintenant, on peut voir les branches du collègue&lt;br /&gt;
git branch -a&lt;br /&gt;
&lt;br /&gt;
# On peut fusionner avec une branche&lt;br /&gt;
git merge collegue/master&lt;br /&gt;
&lt;br /&gt;
# Si vous avez des conflits, éditez les fichiers concernés,&lt;br /&gt;
# et committez avec git commit&lt;br /&gt;
&lt;br /&gt;
# Push vers votre dépôt distant&lt;br /&gt;
git push origin&lt;br /&gt;
&lt;br /&gt;
# Optionnel: supprimez la référence vers le dépôt du collègue&lt;br /&gt;
git remote rm collegue&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Archetype webapp====&lt;br /&gt;
L&#039;archetype webapp (http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-webapp/) permet de créer le squelette d&#039;une webapp. Créez un simple webapp monsite en version 0.1.0. (add/commit/push). Vous pourrez tester cette webapp en ajoutant au pom.xml le [https://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin plugin maven Jetty].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mvn -Djetty.port=9999 jetty:run&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naviguez sur http://localhost:9999/monsite&lt;br /&gt;
&lt;br /&gt;
====Scrum tools====&lt;br /&gt;
Ces 3 services peuvent être couplé à votre dépôt GitHub pour votre gestion de projet agile avec [[Scrum]] :&lt;br /&gt;
* http://www.acunote.com/&lt;br /&gt;
* http://backlogtool.com/&lt;br /&gt;
* http://www.scrumdo.com/&lt;br /&gt;
&lt;br /&gt;
L&#039;activation se fait via &#039;&#039;Settings &amp;gt; Webhooks &amp;amp; Services &amp;gt; Configure services&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Séance 4: AOP &amp;amp; AspectJ=&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt Git, projet &#039;&#039;cron4j-mvn&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le [http://mojo.codehaus.org/aspectj-maven-plugin/ plugin Maven pour AspectJ] au pom.xml&lt;br /&gt;
# Ajoutez un aspect de trace à l&#039;invocation des méthodes &#039;&#039;&#039;run()&#039;&#039;&#039; de l&#039;interface java.lang.Runnable (uniquement pour les objets &#039;&#039;schedulé&#039;&#039;s)&lt;br /&gt;
#: Affichez une trace avant et après l&#039;exécution de la tâche&lt;br /&gt;
# Préparez un nouveau test (nouvelle classe) démarrant un Scheduler Cron4j et validant l&#039;exécution d&#039;une tâche au bout d&#039;une minute (pattern &amp;quot;* * * * *&amp;quot;)&lt;br /&gt;
#: Lors de l&#039;exécution de &#039;&#039;&#039;mvn test&#039;&#039;&#039;, vous devez voir apparaître les traces préparées dans votre aspect.&lt;br /&gt;
&lt;br /&gt;
Liens utiles:&lt;br /&gt;
* [http://ridgetopsolutions.com/blog/2013/02/12/getting-started-with-aspectj-and-maven/ Getting started with AspectJ and Maven]&lt;br /&gt;
&lt;br /&gt;
===Contrôle continu===&lt;br /&gt;
&lt;br /&gt;
# Complétez l&#039;aspect de trace avec le positionnement du [http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html java.lang.ThreadLocal] pour passer 1) l&#039;identifiant du job et 2) le compteur des appels de la méthode de l&#039;objet.&lt;br /&gt;
&lt;br /&gt;
=Séance 5: Pelix &amp;amp; iPOPO=&lt;br /&gt;
&lt;br /&gt;
Pelix est une plate-forme d&#039;application à services (SOA).&lt;br /&gt;
iPOPO est un modèle de composants orientés services (SOCM).&lt;br /&gt;
&lt;br /&gt;
La documentation de Pelix et iPOPO est disponible sur https://ipopo.coderxpress.net/&lt;br /&gt;
&lt;br /&gt;
===Installation de iPOPO===&lt;br /&gt;
&lt;br /&gt;
* Cloner le dépôt Git depuis https://github.com/tcalmant/ipopo&lt;br /&gt;
* Se placer dans la branche &#039;&#039;dev&#039;&#039;&lt;br /&gt;
* Pour installer iPOPO, lancer la commande :&lt;br /&gt;
&lt;br /&gt;
   sudo python setup.py install&lt;br /&gt;
&lt;br /&gt;
===Shell Pelix===&lt;br /&gt;
&lt;br /&gt;
Pour lancer un shell Pelix, utilisez la commande:&lt;br /&gt;
&lt;br /&gt;
   python -m pelix.shell.console&lt;br /&gt;
&lt;br /&gt;
Les commandes disponibles sont décrites ici: [https://ipopo.coderxpress.net/wiki/doku.php?id=ipopo:refcards:shell Shell Commands]&lt;br /&gt;
&lt;br /&gt;
===Rappels de Python===&lt;br /&gt;
&lt;br /&gt;
* Pas de déclaration du type d&#039;une variable&lt;br /&gt;
* Les méthodes d&#039;une classe ont toute comme premier paramètre &#039;&#039;self&#039;&#039;, équivalent du &#039;&#039;this&#039;&#039; en Java.&lt;br /&gt;
* Blocs définis par indentation (4 espaces ou 1 tab)&lt;br /&gt;
* Une ligne finissant par &#039;:&#039; démarre toujours un bloc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Import d&#039;un module&lt;br /&gt;
import pelix&lt;br /&gt;
&lt;br /&gt;
# Définition d&#039;une classe&lt;br /&gt;
class MaClasse:&lt;br /&gt;
   # Constructeur&lt;br /&gt;
   def __init__(self):&lt;br /&gt;
       self.default = &amp;quot;stanger&amp;quot;&lt;br /&gt;
       print(&amp;quot;Classe construite&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
   # Méthode, avec un argument&lt;br /&gt;
   def sayHello(self, name):&lt;br /&gt;
       if not name:&lt;br /&gt;
           # Nom vide ou nul&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(self.default)&lt;br /&gt;
       else:&lt;br /&gt;
           # Nom valide&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(name)&lt;br /&gt;
&lt;br /&gt;
objet = MaClasse()&lt;br /&gt;
print(objet.sayHello(&amp;quot;&amp;quot;))&lt;br /&gt;
print(objet.sayHello(&amp;quot;World&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Service Ping-Pong===&lt;br /&gt;
&lt;br /&gt;
1. Écrire un fichier &#039;&#039;pong.py&#039;&#039;, définissant une classe &#039;&#039;Pong&#039;&#039; ayant une méthode &#039;&#039;pong&#039;&#039; prenant en paramètre un message et retournant le message préfixé par &amp;quot;PONG:&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Exemple: &lt;br /&gt;
   &lt;br /&gt;
      pong = Pong()&lt;br /&gt;
      pong.pong(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2. Écrire un fichier &#039;&#039;ping.py&#039;&#039;, définissant une classe &#039;&#039;Ping&#039;&#039; ayant une méthode &#039;&#039;ping&#039;&#039; prenant en paramètre un message, créant un objet Pong et retournant le résultat de Pong.pong(message) préfixé par &amp;quot;PING:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&lt;br /&gt;
      ping = Ping()&lt;br /&gt;
      ping.ping(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PING:PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
3. Transformer le fichier &#039;&#039;pong.py&#039;&#039; pour qu&#039;il devienne un bundle Pelix enregistrant un objet Pong comme étant un service ayant pour spécification &amp;quot;tagl.pong&amp;quot;&lt;br /&gt;
* Définir une classe &#039;&#039;Activator&#039;&#039;, décorée avec &#039;&#039;@BundleActivator&#039;&#039;&lt;br /&gt;
* Enregistrer le service dans la méthode &#039;&#039;Activator.start&#039;&#039; et le désenregistrer dans &#039;&#039;Activator.stop&#039;&#039;&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/provider.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;pong&#039; et vérifier que le service est bien inscrit avec la commande &#039;&#039;sl&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
4.Transformer la classe &#039;&#039;Ping&#039;&#039; dans &#039;&#039;ping.py&#039;&#039; en un composant iPOPO&lt;br /&gt;
* L&#039;objet Pong utilisé dans &#039;&#039;ping()&#039;&#039; doit être un service injecté par iPOPO (&#039;&#039;@Requires&#039;&#039;)&lt;br /&gt;
* Appeler la méthode &#039;&#039;ping()&#039;&#039; dès que le service Pong est injecté (&#039;&#039;@BindField&#039;&#039;) ou disparait (&#039;&#039;@UnbindField&#039;&#039;)&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/consumer.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;ping&#039; et vérifier son comportement si le bundle &#039;&#039;pong&#039;&#039; ou le bundle &#039;&#039;ping&#039;&#039; est arrêté et redémarré.&lt;br /&gt;
&lt;br /&gt;
5. Mettre à jour le bundle &#039;&#039;pong&#039;&#039;&lt;br /&gt;
* Remplacer le préfixe &amp;quot;PONG&amp;quot; par &amp;quot;NI&amp;quot;&lt;br /&gt;
* Dans le shell Pelix, mettre à jour le bundle &#039;&#039;pong&#039;&#039; sans redémarrer la plate-forme (commande &#039;&#039;udpate&#039;&#039;).&lt;br /&gt;
* Vérifier les traces dans le shell pour valider la mise à jour du service.&lt;br /&gt;
&lt;br /&gt;
===Remote Services===&lt;br /&gt;
&lt;br /&gt;
* Ajouter les propriétés permettant l&#039;export du service Pong dans &#039;&#039;pong.py&#039;&#039; (s&#039;inspirer de &#039;&#039;provider.py&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
* Lancer deux shells iPOPO (dans deux terminaux)&lt;br /&gt;
* Dans chaque shell iPOPO, installer les bundles:&lt;br /&gt;
** &#039;&#039;pelix.remote.dispatcher&#039;&#039;: Exportateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.registry&#039;&#039;; Importateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.discovery.multicast&#039;&#039;: Découverte de services via Multicast&lt;br /&gt;
** &#039;&#039;pelix.remote.xml_rpc&#039;&#039;: Transport XML-RPC&lt;br /&gt;
** &#039;&#039;pelix.http.basic&#039;&#039;: Serveur HTTP&lt;br /&gt;
&lt;br /&gt;
Attention: il peut être nécessaire de désactiver votre pare-feu pour que les Remote Services fonctionnent&lt;br /&gt;
&lt;br /&gt;
* Instancier les composants depuis le shell iPOPO, dans chaque framework:&lt;br /&gt;
** Serveur HTTP sur le port 8080: &#039;&#039;instantiate pelix.http.service.basic.factory http-server pelix.http.port=8080&#039;&#039; (penser à changer de port dans chaque framework)&lt;br /&gt;
** Multicast Discovery: &#039;&#039;instantiate pelix-remote-discovery-multicast-factory multicast-discovery&#039;&#039;&lt;br /&gt;
** XML-RPC Exporter: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-exporter&#039;&#039;&lt;br /&gt;
** XML-RPC Importer: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-importer&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Installer le bundle &#039;&#039;ping&#039;&#039; dans un des frameworks et le bundle &#039;&#039;pong&#039;&#039; dans l&#039;autre.&lt;br /&gt;
* Le composant ping peut appeler le service pong, qui est dans l&#039;autre framework.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Voir le code de &#039;&#039;run_remote.py&#039;&#039; pour voir comment démarrer un framework Pelix et installer des bundles depuis Python.&lt;br /&gt;
* Jouer un peu avec &#039;&#039;run_remote.py&#039;&#039; (voir &#039;&#039;run_remote.py --help&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=Séance 6=&lt;br /&gt;
[[Tutorial OSGi avec Apache Felix]]&lt;br /&gt;
&lt;br /&gt;
=Séance 7=&lt;br /&gt;
Faire un projet PDE pour un bundle cron4j.gogo (indépendant de cron4j.bundle)&lt;br /&gt;
&lt;br /&gt;
Utilisation de https://eclipse.org/tycho/&lt;/div&gt;</summary>
		<author><name>MatthieuCaneill</name></author>
	</entry>
	<entry>
		<id>https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21268</id>
		<title>TAGL/TP</title>
		<link rel="alternate" type="text/html" href="https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21268"/>
		<updated>2015-02-17T09:41:35Z</updated>

		<summary type="html">&lt;p&gt;MatthieuCaneill: /* Heruko */ lol heruko&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Travaux pratiques de l&#039;UE [[TAGL]].&lt;br /&gt;
&lt;br /&gt;
Anciennes versions : [[TAGL/TP 2014]]&lt;br /&gt;
&lt;br /&gt;
=Séance 1 : Gestion de versions=&lt;br /&gt;
==Git==&lt;br /&gt;
&lt;br /&gt;
Création d&#039;un dépôt Git local&lt;br /&gt;
&lt;br /&gt;
===Méthode simple: init first===&lt;br /&gt;
&lt;br /&gt;
Via cette méthode, on crée un dépôt local, avec un répertoire de travail, puis on pousse ses modifications vers un dépôt &amp;quot;bare&amp;quot;.&lt;br /&gt;
Cette méthode est la plus simple, car on dispose immédiatement d&#039;un répertoire de travail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création d&#039;un dépôt Git dans le dossier simple-repo&lt;br /&gt;
git init simple-repo&lt;br /&gt;
&lt;br /&gt;
# Création d&#039;un README&lt;br /&gt;
cd simple-repo&lt;br /&gt;
echo &amp;quot;Hello, World&amp;quot; &amp;gt; README&lt;br /&gt;
&lt;br /&gt;
# Ajout du versionnement du fichier README&lt;br /&gt;
git add README&lt;br /&gt;
&lt;br /&gt;
# Commit&lt;br /&gt;
git commit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À ce niveau, on a un dépôt Git complètement fonctionnel.&lt;br /&gt;
Cependant, il est intéressant de pousser ses modifications vers un autre dépôt, sur une autre machine.&lt;br /&gt;
On va donc créer un dépôt bare sur une autre machine (ou autre dossier pour l&#039;exemple)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que l&#039;URL pour accéder à ce dépôt est URL_REPO.&lt;br /&gt;
On va d&#039;abord ajouter ce dépôt serveur à la liste des dépôts connu-repos de votre dépôt local.&lt;br /&gt;
Étant donné qu&#039;il s&#039;agit du dépôt &amp;quot;principal&amp;quot; à utiliser, on l&#039;appellera //origin//, par convention.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin URL_REPO&lt;br /&gt;
# Récupération de ses informations&lt;br /&gt;
git fetch origin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce serveur distant est &amp;quot;vide&amp;quot;: il n&#039;a aucune branche. On va donc enregistrer notre branche sur le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À partir de cette commande, la branche locale //master// sera liée à la branche distante //origin/master//.&lt;br /&gt;
Lors des prochaines commandes &#039;&#039;git push&#039;&#039;, grâce à cette liaison, tous les commits sur la branche locale //master// seront poussées sur le serveur distant.&lt;br /&gt;
&lt;br /&gt;
===Méthode moins simple: bare first===&lt;br /&gt;
&lt;br /&gt;
Si on commence dans par le serveur &amp;quot;vide&amp;quot;, il faudra le cloner au lieu de le définir comme un dépôt distant.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création du dépôt vide&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que ce dépôt est accessible à l&#039;URL URL_REPO&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clonage du dépôt&lt;br /&gt;
git clone URL_REPO clone-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un avertissement indique que l&#039;on clone un dépôt vide: le dépôt local à donc une branche master, mais elle n&#039;est pas liée au dépôt distant, car celui-ci n&#039;a aucune branche.&lt;br /&gt;
Le dépôt distant est automatiquement appelé //origin//.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Commit dans le dépôt local&lt;br /&gt;
cd clone-repo&lt;br /&gt;
echo hello &amp;gt; readme.rst&lt;br /&gt;
git add readme.rst&lt;br /&gt;
git commit et ses dépendances&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme dans la méthode simple, il faut pousser la branche master vers le dépôt distant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===De l&#039;importance des README===&lt;br /&gt;
&lt;br /&gt;
Il est très important d&#039;avoir au moins 2 fichiers dans votre dépôt Git:&lt;br /&gt;
&lt;br /&gt;
* LICENSE: contenant le texte **complet** de la licence de votre projet&lt;br /&gt;
* README: décrivant votre projet et comment l&#039;utiliser. Ce fichier doit rappeler le nom de la licence de votre projet&lt;br /&gt;
&lt;br /&gt;
Il est aussi recommandé d&#039;avoir les fichiers suivants:&lt;br /&gt;
&lt;br /&gt;
* AUTHORS: contenant la liste des noms/pseudos et e-mails des auteurs de commits ou de code inclus dans ce projet&lt;br /&gt;
* INSTALL: contenant la liste des dépendances de ce projet et des commandes à utiliser pour le compiler et l&#039;installer&lt;br /&gt;
&lt;br /&gt;
Les fichiers LICENSE sont des fichiers textes bruts.&lt;br /&gt;
Les autres fichiers sont généralement dans un format offrant un peu plus de lisibilté, par exemple dans les formats [http://daringfireball.net/projects/markdown/ Markdown] (.md) ou [http://docutils.sourceforge.net/rst.html reStructuredText] (.rst)&lt;br /&gt;
&lt;br /&gt;
Un plug-in existe pour éditer des fichier reStructuredText dans Eclipse: ReST Editor, disponible sur le [https://marketplace.eclipse.org/content/rest-editor Marketplace Eclipse]&lt;br /&gt;
&lt;br /&gt;
=Séance 2a: Intégration en continue=&lt;br /&gt;
&lt;br /&gt;
===GitHub &amp;amp; [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
Travis-CI est un service permettant d&#039;exécuter un script dans une machine virtuelle Ubuntu dès que vous effectuez un push sur un de vos dépôts GitHub.&lt;br /&gt;
L&#039;intérêt est de savoir si la version d&#039;un projet que vous avez rendu publique peut être compilée et si ses tests passent.&lt;br /&gt;
&lt;br /&gt;
La machine virtuelle &amp;quot;offerte&amp;quot; par Travis est préconfigurée pour le language indiqué dans son fichier de configuration (&#039;&#039;&#039;.travis.yml&#039;&#039;&#039;), mais il est possible d&#039;utiliser la commande &#039;&#039;&#039;sudo apt-get install ...&#039;&#039;&#039; pour ajouter vos dépendances.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour utiliser [[Travis-CI]]:&lt;br /&gt;
&lt;br /&gt;
# Créez compte individuel sur GitHub https://github.com&lt;br /&gt;
# &#039;&#039;Fork&#039;&#039;ez le projet TAGL &#039;&#039;&#039;cron4j&#039;&#039;&#039; depuis https://github.com/donsez/tagl&lt;br /&gt;
# Ajoutez un collaborateur (i.e. votre binôme) au projet &#039;&#039;forké&#039;&#039;, via les paramètres (&#039;&#039;settings&#039;&#039;) de ce projet&lt;br /&gt;
# Pour l&#039;exemple, activez le service (ou hook) &#039;&#039;Email&#039;&#039; depuis les paramètres du dépôt: à chaque fois que vous ou un de vos collaborateurs ferra un &#039;&#039;&#039;git push&#039;&#039;&#039;, vous recevrez une notification par mail.&lt;br /&gt;
# Activez le service Travis-CI: identifiez-vous (&#039;&#039;sign in&#039;&#039;) sur https://travis-ci.org/ avec votre compte GitHub&lt;br /&gt;
# Activez le service pour les projets sur lesquels vous souhaitez appliquer les principes d&#039;intégration continue&lt;br /&gt;
&lt;br /&gt;
[[Travis-CI]] utilise un fichier nommé &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; (attention: fichier caché sous Unix) pour se configurer et choisir les opérations à effectuer.&lt;br /&gt;
Ce fichier doit se trouver à la racine de votre dépôt Git.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; du fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; ci-dessous.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
language: node_js&lt;br /&gt;
node_js:&lt;br /&gt;
  - &amp;quot;0.11&amp;quot;&lt;br /&gt;
  - &amp;quot;0.10&amp;quot;&lt;br /&gt;
  - &amp;quot;0.8&amp;quot;&lt;br /&gt;
  - &amp;quot;0.6&amp;quot;&lt;br /&gt;
  - iojs&lt;br /&gt;
  - iojs-v1.0.2&lt;br /&gt;
&lt;br /&gt;
script:&lt;br /&gt;
        - pushd cron4j-original &amp;amp;&amp;amp; ant rel &amp;amp;&amp;amp; popd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(voir http://docs.travis-ci.com/user/languages/javascript-with-nodejs/)&lt;br /&gt;
&lt;br /&gt;
Ce fichier indique que le projet dans ce dépôt doit être testé sur plusieurs versions de [[Node.js]], et que le script à exécuter pour lancer les tests est &#039;&#039;&#039;pushd cron4j-original &amp;amp;&amp;amp; ant rel &amp;amp;&amp;amp; popd&#039;&#039;&#039;.&lt;br /&gt;
[[Travis-CI]] peut exécuter plusieurs commandes dans script, chacune d&#039;entre elles devant démarrer par un &#039;-&#039; (élément dans une liste de &#039;scripts&#039;).&lt;br /&gt;
&lt;br /&gt;
Attention: il n&#039;est pas possible d&#039;utiliser &#039;&#039;&#039;cd&#039;&#039;&#039; pour changer de répertoire, il faut utiliser &#039;&#039;&#039;pushd&#039;&#039;&#039; (déplacement dans un dossier) et &#039;&#039;&#039;popd&#039;&#039;&#039; (retour au dossier précédent) à la place.&lt;br /&gt;
&lt;br /&gt;
Une fois ce fichier de configuration &#039;&#039;&#039;pushé&#039;&#039;&#039;, Travis-CI se mettra en route dès le prochain &#039;&#039;&#039;push&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Séance 2b: Livraison en continue=&lt;br /&gt;
&lt;br /&gt;
==[[Heroku]]==&lt;br /&gt;
[https://www.heroku.com/ Heroku] est une plateforme cloud de type PaaS permettant l&#039;exécution d&#039;applications et de services en ligne écrits dans les langages et plateformes suivantes : Ruby, [[Node.js]], [[Python]], Java, et PHP.&lt;br /&gt;
&lt;br /&gt;
# Créez un compte gratuit sur [https://signup.heroku.com Heroku]&lt;br /&gt;
# Forkez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Dans Heroku, créez une nouvelle app Node.js, et liez-la au repository Github créé à l&#039;étape précédente&lt;br /&gt;
# Choisissez l&#039;option &amp;quot;Déploiement automatique&amp;quot; depuis la branche **master**&lt;br /&gt;
# Modifiez le fichier index.js pour afficher la version de service dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 var fs = require(&#039;fs&#039;);&lt;br /&gt;
 var package = JSON.parse(fs.readFileSync(&#039;./package.json&#039;, &#039;utf8&#039;));&lt;br /&gt;
 var version=package.version;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Hello World! (current version: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Séance 3: Builders=&lt;br /&gt;
&lt;br /&gt;
==[[Ant]]==&lt;br /&gt;
&lt;br /&gt;
==[[Maven]]==&lt;br /&gt;
&lt;br /&gt;
[http://maven.apache.org/download.cgi Charger et installer Maven 3].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mvn -version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Faites une copie du projet, basée sur Maven:&lt;br /&gt;
&lt;br /&gt;
# Dans votre dépôt Git, créez un dossier &#039;&#039;&#039;cron4j-mvn&#039;&#039;&#039;: il contiendra le projet Cron4J avec la structure Maven&lt;br /&gt;
# Dans ce dossier, utilisez l&#039;[https://maven.apache.org/guides/introduction/introduction-to-archetypes.html archetype] Maven [http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-quickstart/ maven-archetype-quickstart] (la version des sources de cron4j utilisés est la 2.5.5):&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Cette commande crée un projet avec un fichier &#039;&#039;pom.xml&#039;&#039;, et une classe et un test modèles: supprimez ces modèles&lt;br /&gt;
# Copiez les sources de Cron4J depuis le dossier &#039;&#039;&#039;cron4j-original&#039;&#039;&#039; dans le dossier &#039;&#039;&#039;src/main/java&#039;&#039;&#039; de votre projet Maven&lt;br /&gt;
# Faites un essai de compilation:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Lancez un des exemples avec mvn exec:java -Dexec.mainClass=&amp;quot;com.example.Main&amp;quot; [-Dexec.args=&amp;quot;argument1&amp;quot;] ... ([http://mojo.codehaus.org/exec-maven-plugin/usage.html doc. exec plugin], [http://mojo.codehaus.org/exec-maven-plugin/java-mojo.html doc. Exec:java goal])&lt;br /&gt;
# Enfin modifiez le fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; à la racine de votre dépôt Git afin que Travis exécute la commande &#039;&#039;&#039;mvn clean verify&#039;&#039;&#039; à chaque mise à jour du dépôt GitHub.&lt;br /&gt;
&lt;br /&gt;
==Tests Unitaires avec JUnit 4==&lt;br /&gt;
Survoller le tutoriel [http://www.vogella.com/tutorials/JUnit/article.html Unit Testing with JUnit]&lt;br /&gt;
&lt;br /&gt;
# Ajouter le test unitaire suivant au projet, dans le fichier &#039;&#039;&#039;src/test/it/sauronsoftware/SchedulingPatternTest.java&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
package it.sauronsoftware;&lt;br /&gt;
&lt;br /&gt;
import it.sauronsoftware.cron4j.SchedulingPattern;&lt;br /&gt;
import it.sauronsoftware.cron4j.InvalidPatternException;&lt;br /&gt;
&lt;br /&gt;
import static org.junit.Assert.assertEquals;&lt;br /&gt;
import static org.junit.Assert.assertTrue;&lt;br /&gt;
&lt;br /&gt;
import org.junit.AfterClass;&lt;br /&gt;
import org.junit.BeforeClass;&lt;br /&gt;
import org.junit.Test;&lt;br /&gt;
&lt;br /&gt;
public class SchedulingPatternTest {&lt;br /&gt;
&lt;br /&gt;
  @BeforeClass&lt;br /&gt;
  public static void testSetup() {&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @AfterClass&lt;br /&gt;
  public static void testCleanup() {&lt;br /&gt;
    // Teardown for data used by the unit tests&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test(expected = InvalidPatternException.class)&lt;br /&gt;
  public void testExceptionIsThrown() {&lt;br /&gt;
    SchedulingPattern sp = new SchedulingPattern(&amp;quot;0 5 * *&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test&lt;br /&gt;
  public void testPattern() {&lt;br /&gt;
    String pattern;&lt;br /&gt;
    pattern=&amp;quot;0 5 * * *|8 10 * * *|22 17 * * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
    pattern=&amp;quot;0 5 * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Committez et Pushez ce nouveau fichier, pour que Travis lance les tests dès que possible&lt;br /&gt;
# Lancez les tests unitaires avec &amp;lt;pre&amp;gt;mvn test&amp;lt;/pre&amp;gt; Ce test va &#039;&#039;&#039;échouer&#039;&#039;&#039;: corrigez le.&lt;br /&gt;
# Committez et Pushez la version corrigée des tests: Travis enverra un mail pour indiquer si les tests échouent ou non&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; Travis va exécuter les tests &#039;&#039;dès que possible&#039;&#039;. Il est possible de recevoir un mail indiquant que les tests du premier &#039;&#039;push&#039;&#039; échouent alors que l&#039;on a déjà &#039;&#039;pushé&#039;&#039; la correction.&lt;br /&gt;
# Naviguez sur http://travis-ci.org pour vérifier les builds effectués.&lt;br /&gt;
# Créez des tests unitaires supplémentaire du i.s.c.CronParser&lt;br /&gt;
&lt;br /&gt;
===[[Maven]] avec [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
===Git (suite)===&lt;br /&gt;
&lt;br /&gt;
# Forkez le projet &#039;&#039;&#039;tagl&#039;&#039;&#039; d&#039;un autre binome (i.e. autre que &#039;&#039;donsez/tagl&#039;&#039;)&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; donnez lui un nom différent (e.g. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Clonez ce nouveau dépôt&lt;br /&gt;
# Lancez une compilation pour valider l&#039;état du projet (bonne pratique)&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Ajoutez une bannière de licence dans le fichier &#039;&#039;&#039;cron4j-mvn/pom.xml&#039;&#039;&#039;&lt;br /&gt;
# Lancez une nouvelle compilation pour valider vos modifications&lt;br /&gt;
# Commitez et pushez (vers votre fork de ce dépôt, i.e. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Via le site de GitHub, proposez un &amp;quot;Pull Request&amp;quot; au projet initial&lt;br /&gt;
&lt;br /&gt;
Vous pouvez ensuite supprimer le clone de ce fork.&lt;br /&gt;
Lorsque le &#039;&#039;pull request&#039;&#039; aura été accepté, vous pourrez supprimer votre fork (&#039;&#039;tagl-licensing&#039;&#039;) de votre compte GitHub.&lt;br /&gt;
&lt;br /&gt;
===Contrôle Continu===&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt &#039;&#039;tagl&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le plugin [http://mojo.codehaus.org/cobertura-maven-plugin/usage.html Cobertura] à votre projet Maven.&lt;br /&gt;
## Configurez le plugin pour [http://mojo.codehaus.org/cobertura-maven-plugin/examples/report-formats.html générer un rapport] HTML. Le résultat se trouvera dans &#039;&#039;target/site/cobertura&#039;&#039;&lt;br /&gt;
## Le plugin ne s&#039;exécute automatiquement pas durant la compilation, il faut utiliser la commande : &amp;lt;pre&amp;gt;mvn cobertura:cobertura&amp;lt;/pre&amp;gt;&lt;br /&gt;
## &#039;&#039;&#039;Bonus:&#039;&#039;&#039; Modifiez le fichier &#039;&#039;pom.xml&#039;&#039; pour que le &#039;&#039;goal&#039;&#039; &#039;&#039;&#039;cobertura&#039;&#039;&#039; soit exécuté pendant la &#039;&#039;phase&#039;&#039; &#039;&#039;&#039;package&#039;&#039;&#039;.&lt;br /&gt;
# Répondez aux questions : &#039;&#039;Mais qu&#039;est ce que la couverture de code ? En quoi c&#039;est utile ?&#039;&#039;&lt;br /&gt;
# Ajoutez au projet Maven les plugins pour la génération d&#039;un site et de rapports (Javadoc, tests unitaires, tags list (FIXME, TODO, ...), ...): voir http://maven.apache.org/plugins/maven-site-plugin/ et d&#039;autres.&lt;br /&gt;
# Regardez les exemples d&#039;utilisation de cron4j dans cron4j-original/examples&lt;br /&gt;
&lt;br /&gt;
===Bonus Track===&lt;br /&gt;
&lt;br /&gt;
====Clone SVN -&amp;gt; Git====&lt;br /&gt;
&lt;br /&gt;
Source: http://www.yterium.net/Migrer-un-projet-SVN-vers-GIT&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Cloner le dépôt SVN en dépôt Git (conservation historique)&lt;br /&gt;
$ git svn clone  svn://svn.code.sf.net/p/cron4j/code/trunk cron4j-original&lt;br /&gt;
$ cd cron4j-original&lt;br /&gt;
# Test compilation&lt;br /&gt;
$ ant jar&lt;br /&gt;
$ cd ..&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Préparation TAGL====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clone du dépôt TAGL&lt;br /&gt;
$ git clone git@github.com:donsez/tagl.git&lt;br /&gt;
$ cd tagl&lt;br /&gt;
# &amp;quot;Fetch&amp;quot; du dépôt local cloné précédemment&lt;br /&gt;
$ git fetch file://$(pwd)/../cron4j-original&lt;br /&gt;
# Fusion de ce qui vient d&#039;être fetché&lt;br /&gt;
$ git merge FETCH_HEAD&lt;br /&gt;
# Envoi sur le serveur&lt;br /&gt;
$ git push&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Cherry-picking: reprise des modifications d&#039;un collègue====&lt;br /&gt;
&lt;br /&gt;
On considère que:&lt;br /&gt;
&lt;br /&gt;
* votre dépôt Git distant est à l&#039;adresse URL_DEPOT&lt;br /&gt;
* votre collègue a un dépôt Git à l&#039;adresse URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Dossier temporaire&lt;br /&gt;
cd /tmp&lt;br /&gt;
&lt;br /&gt;
# Clone de votre dépôt&lt;br /&gt;
git clone URL_DEPOT mon_depot&lt;br /&gt;
&lt;br /&gt;
# Déplacement dans votre dépôt&lt;br /&gt;
cd mon_depot&lt;br /&gt;
&lt;br /&gt;
# Définition du dépôt distant&lt;br /&gt;
git remote add collegue URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
# Récupération des infos du dépôt du collègue&lt;br /&gt;
git fetch collegue&lt;br /&gt;
&lt;br /&gt;
# Maintenant, on peut voir les branches du collègue&lt;br /&gt;
git branch -a&lt;br /&gt;
&lt;br /&gt;
# On peut fusionner avec une branche&lt;br /&gt;
git merge collegue/master&lt;br /&gt;
&lt;br /&gt;
# Si vous avez des conflits, éditez les fichiers concernés,&lt;br /&gt;
# et committez avec git commit&lt;br /&gt;
&lt;br /&gt;
# Push vers votre dépôt distant&lt;br /&gt;
git push origin&lt;br /&gt;
&lt;br /&gt;
# Optionnel: supprimez la référence vers le dépôt du collègue&lt;br /&gt;
git remote rm collegue&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Archetype webapp====&lt;br /&gt;
L&#039;archetype webapp (http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-webapp/) permet de créer le squelette d&#039;une webapp. Créez un simple webapp monsite en version 0.1.0. (add/commit/push). Vous pourrez tester cette webapp en ajoutant au pom.xml le [https://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin plugin maven Jetty].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mvn -Djetty.port=9999 jetty:run&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naviguez sur http://localhost:9999/monsite&lt;br /&gt;
&lt;br /&gt;
====Scrum tools====&lt;br /&gt;
Ces 3 services peuvent être couplé à votre dépôt GitHub pour votre gestion de projet agile avec [[Scrum]] :&lt;br /&gt;
* http://www.acunote.com/&lt;br /&gt;
* http://backlogtool.com/&lt;br /&gt;
* http://www.scrumdo.com/&lt;br /&gt;
&lt;br /&gt;
L&#039;activation se fait via &#039;&#039;Settings &amp;gt; Webhooks &amp;amp; Services &amp;gt; Configure services&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Séance 4: AOP &amp;amp; AspectJ=&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt Git, projet &#039;&#039;cron4j-mvn&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le [http://mojo.codehaus.org/aspectj-maven-plugin/ plugin Maven pour AspectJ] au pom.xml&lt;br /&gt;
# Ajoutez un aspect de trace à l&#039;invocation des méthodes &#039;&#039;&#039;run()&#039;&#039;&#039; de l&#039;interface java.lang.Runnable (uniquement pour les objets &#039;&#039;schedulé&#039;&#039;s)&lt;br /&gt;
#: Affichez une trace avant et après l&#039;exécution de la tâche&lt;br /&gt;
# Préparez un nouveau test (nouvelle classe) démarrant un Scheduler Cron4j et validant l&#039;exécution d&#039;une tâche au bout d&#039;une minute (pattern &amp;quot;* * * * *&amp;quot;)&lt;br /&gt;
#: Lors de l&#039;exécution de &#039;&#039;&#039;mvn test&#039;&#039;&#039;, vous devez voir apparaître les traces préparées dans votre aspect.&lt;br /&gt;
&lt;br /&gt;
Liens utiles:&lt;br /&gt;
* [http://ridgetopsolutions.com/blog/2013/02/12/getting-started-with-aspectj-and-maven/ Getting started with AspectJ and Maven]&lt;br /&gt;
&lt;br /&gt;
===Contrôle continu===&lt;br /&gt;
&lt;br /&gt;
# Complétez l&#039;aspect de trace avec le positionnement du [http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html java.lang.ThreadLocal] pour passer 1) l&#039;identifiant du job et 2) le compteur des appels de la méthode de l&#039;objet.&lt;br /&gt;
&lt;br /&gt;
=Séance 5: Pelix &amp;amp; iPOPO=&lt;br /&gt;
&lt;br /&gt;
Pelix est une plate-forme d&#039;application à services (SOA).&lt;br /&gt;
iPOPO est un modèle de composants orientés services (SOCM).&lt;br /&gt;
&lt;br /&gt;
La documentation de Pelix et iPOPO est disponible sur https://ipopo.coderxpress.net/&lt;br /&gt;
&lt;br /&gt;
===Installation de iPOPO===&lt;br /&gt;
&lt;br /&gt;
* Cloner le dépôt Git depuis https://github.com/tcalmant/ipopo&lt;br /&gt;
* Se placer dans la branche &#039;&#039;dev&#039;&#039;&lt;br /&gt;
* Pour installer iPOPO, lancer la commande :&lt;br /&gt;
&lt;br /&gt;
   sudo python setup.py install&lt;br /&gt;
&lt;br /&gt;
===Shell Pelix===&lt;br /&gt;
&lt;br /&gt;
Pour lancer un shell Pelix, utilisez la commande:&lt;br /&gt;
&lt;br /&gt;
   python -m pelix.shell.console&lt;br /&gt;
&lt;br /&gt;
Les commandes disponibles sont décrites ici: [https://ipopo.coderxpress.net/wiki/doku.php?id=ipopo:refcards:shell Shell Commands]&lt;br /&gt;
&lt;br /&gt;
===Rappels de Python===&lt;br /&gt;
&lt;br /&gt;
* Pas de déclaration du type d&#039;une variable&lt;br /&gt;
* Les méthodes d&#039;une classe ont toute comme premier paramètre &#039;&#039;self&#039;&#039;, équivalent du &#039;&#039;this&#039;&#039; en Java.&lt;br /&gt;
* Blocs définis par indentation (4 espaces ou 1 tab)&lt;br /&gt;
* Une ligne finissant par &#039;:&#039; démarre toujours un bloc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Import d&#039;un module&lt;br /&gt;
import pelix&lt;br /&gt;
&lt;br /&gt;
# Définition d&#039;une classe&lt;br /&gt;
class MaClasse:&lt;br /&gt;
   # Constructeur&lt;br /&gt;
   def __init__(self):&lt;br /&gt;
       self.default = &amp;quot;stanger&amp;quot;&lt;br /&gt;
       print(&amp;quot;Classe construite&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
   # Méthode, avec un argument&lt;br /&gt;
   def sayHello(self, name):&lt;br /&gt;
       if not name:&lt;br /&gt;
           # Nom vide ou nul&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(self.default)&lt;br /&gt;
       else:&lt;br /&gt;
           # Nom valide&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(name)&lt;br /&gt;
&lt;br /&gt;
objet = MaClasse()&lt;br /&gt;
print(objet.sayHello(&amp;quot;&amp;quot;))&lt;br /&gt;
print(objet.sayHello(&amp;quot;World&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Service Ping-Pong===&lt;br /&gt;
&lt;br /&gt;
1. Écrire un fichier &#039;&#039;pong.py&#039;&#039;, définissant une classe &#039;&#039;Pong&#039;&#039; ayant une méthode &#039;&#039;pong&#039;&#039; prenant en paramètre un message et retournant le message préfixé par &amp;quot;PONG:&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Exemple: &lt;br /&gt;
   &lt;br /&gt;
      pong = Pong()&lt;br /&gt;
      pong.pong(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2. Écrire un fichier &#039;&#039;ping.py&#039;&#039;, définissant une classe &#039;&#039;Ping&#039;&#039; ayant une méthode &#039;&#039;ping&#039;&#039; prenant en paramètre un message, créant un objet Pong et retournant le résultat de Pong.pong(message) préfixé par &amp;quot;PING:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&lt;br /&gt;
      ping = Ping()&lt;br /&gt;
      ping.ping(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PING:PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
3. Transformer le fichier &#039;&#039;pong.py&#039;&#039; pour qu&#039;il devienne un bundle Pelix enregistrant un objet Pong comme étant un service ayant pour spécification &amp;quot;tagl.pong&amp;quot;&lt;br /&gt;
* Définir une classe &#039;&#039;Activator&#039;&#039;, décorée avec &#039;&#039;@BundleActivator&#039;&#039;&lt;br /&gt;
* Enregistrer le service dans la méthode &#039;&#039;Activator.start&#039;&#039; et le désenregistrer dans &#039;&#039;Activator.stop&#039;&#039;&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/provider.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;pong&#039; et vérifier que le service est bien inscrit avec la commande &#039;&#039;sl&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
4.Transformer la classe &#039;&#039;Ping&#039;&#039; dans &#039;&#039;ping.py&#039;&#039; en un composant iPOPO&lt;br /&gt;
* L&#039;objet Pong utilisé dans &#039;&#039;ping()&#039;&#039; doit être un service injecté par iPOPO (&#039;&#039;@Requires&#039;&#039;)&lt;br /&gt;
* Appeler la méthode &#039;&#039;ping()&#039;&#039; dès que le service Pong est injecté (&#039;&#039;@BindField&#039;&#039;) ou disparait (&#039;&#039;@UnbindField&#039;&#039;)&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/consumer.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;ping&#039; et vérifier son comportement si le bundle &#039;&#039;pong&#039;&#039; ou le bundle &#039;&#039;ping&#039;&#039; est arrêté et redémarré.&lt;br /&gt;
&lt;br /&gt;
5. Mettre à jour le bundle &#039;&#039;pong&#039;&#039;&lt;br /&gt;
* Remplacer le préfixe &amp;quot;PONG&amp;quot; par &amp;quot;NI&amp;quot;&lt;br /&gt;
* Dans le shell Pelix, mettre à jour le bundle &#039;&#039;pong&#039;&#039; sans redémarrer la plate-forme (commande &#039;&#039;udpate&#039;&#039;).&lt;br /&gt;
* Vérifier les traces dans le shell pour valider la mise à jour du service.&lt;br /&gt;
&lt;br /&gt;
===Remote Services===&lt;br /&gt;
&lt;br /&gt;
* Ajouter les propriétés permettant l&#039;export du service Pong dans &#039;&#039;pong.py&#039;&#039; (s&#039;inspirer de &#039;&#039;provider.py&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
* Lancer deux shells iPOPO (dans deux terminaux)&lt;br /&gt;
* Dans chaque shell iPOPO, installer les bundles:&lt;br /&gt;
** &#039;&#039;pelix.remote.dispatcher&#039;&#039;: Exportateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.registry&#039;&#039;; Importateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.discovery.multicast&#039;&#039;: Découverte de services via Multicast&lt;br /&gt;
** &#039;&#039;pelix.remote.xml_rpc&#039;&#039;: Transport XML-RPC&lt;br /&gt;
** &#039;&#039;pelix.http.basic&#039;&#039;: Serveur HTTP&lt;br /&gt;
&lt;br /&gt;
Attention: il peut être nécessaire de désactiver votre pare-feu pour que les Remote Services fonctionnent&lt;br /&gt;
&lt;br /&gt;
* Instancier les composants depuis le shell iPOPO, dans chaque framework:&lt;br /&gt;
** Serveur HTTP sur le port 8080: &#039;&#039;instantiate pelix.http.service.basic.factory http-server pelix.http.port=8080&#039;&#039; (penser à changer de port dans chaque framework)&lt;br /&gt;
** Multicast Discovery: &#039;&#039;instantiate pelix-remote-discovery-multicast-factory multicast-discovery&#039;&#039;&lt;br /&gt;
** XML-RPC Exporter: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-exporter&#039;&#039;&lt;br /&gt;
** XML-RPC Importer: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-importer&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Installer le bundle &#039;&#039;ping&#039;&#039; dans un des frameworks et le bundle &#039;&#039;pong&#039;&#039; dans l&#039;autre.&lt;br /&gt;
* Le composant ping peut appeler le service pong, qui est dans l&#039;autre framework.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Voir le code de &#039;&#039;run_remote.py&#039;&#039; pour voir comment démarrer un framework Pelix et installer des bundles depuis Python.&lt;br /&gt;
* Jouer un peu avec &#039;&#039;run_remote.py&#039;&#039; (voir &#039;&#039;run_remote.py --help&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=Séance 6=&lt;br /&gt;
[[Tutorial OSGi avec Apache Felix]]&lt;br /&gt;
&lt;br /&gt;
=Séance 7=&lt;br /&gt;
Faire un projet PDE pour un bundle cron4j.gogo (indépendant de cron4j.bundle)&lt;br /&gt;
&lt;br /&gt;
Utilisation de https://eclipse.org/tycho/&lt;/div&gt;</summary>
		<author><name>MatthieuCaneill</name></author>
	</entry>
	<entry>
		<id>https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21267</id>
		<title>TAGL/TP</title>
		<link rel="alternate" type="text/html" href="https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21267"/>
		<updated>2015-02-17T09:40:55Z</updated>

		<summary type="html">&lt;p&gt;MatthieuCaneill: /* Heruko */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Travaux pratiques de l&#039;UE [[TAGL]].&lt;br /&gt;
&lt;br /&gt;
Anciennes versions : [[TAGL/TP 2014]]&lt;br /&gt;
&lt;br /&gt;
=Séance 1 : Gestion de versions=&lt;br /&gt;
==Git==&lt;br /&gt;
&lt;br /&gt;
Création d&#039;un dépôt Git local&lt;br /&gt;
&lt;br /&gt;
===Méthode simple: init first===&lt;br /&gt;
&lt;br /&gt;
Via cette méthode, on crée un dépôt local, avec un répertoire de travail, puis on pousse ses modifications vers un dépôt &amp;quot;bare&amp;quot;.&lt;br /&gt;
Cette méthode est la plus simple, car on dispose immédiatement d&#039;un répertoire de travail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création d&#039;un dépôt Git dans le dossier simple-repo&lt;br /&gt;
git init simple-repo&lt;br /&gt;
&lt;br /&gt;
# Création d&#039;un README&lt;br /&gt;
cd simple-repo&lt;br /&gt;
echo &amp;quot;Hello, World&amp;quot; &amp;gt; README&lt;br /&gt;
&lt;br /&gt;
# Ajout du versionnement du fichier README&lt;br /&gt;
git add README&lt;br /&gt;
&lt;br /&gt;
# Commit&lt;br /&gt;
git commit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À ce niveau, on a un dépôt Git complètement fonctionnel.&lt;br /&gt;
Cependant, il est intéressant de pousser ses modifications vers un autre dépôt, sur une autre machine.&lt;br /&gt;
On va donc créer un dépôt bare sur une autre machine (ou autre dossier pour l&#039;exemple)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que l&#039;URL pour accéder à ce dépôt est URL_REPO.&lt;br /&gt;
On va d&#039;abord ajouter ce dépôt serveur à la liste des dépôts connu-repos de votre dépôt local.&lt;br /&gt;
Étant donné qu&#039;il s&#039;agit du dépôt &amp;quot;principal&amp;quot; à utiliser, on l&#039;appellera //origin//, par convention.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin URL_REPO&lt;br /&gt;
# Récupération de ses informations&lt;br /&gt;
git fetch origin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce serveur distant est &amp;quot;vide&amp;quot;: il n&#039;a aucune branche. On va donc enregistrer notre branche sur le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À partir de cette commande, la branche locale //master// sera liée à la branche distante //origin/master//.&lt;br /&gt;
Lors des prochaines commandes &#039;&#039;git push&#039;&#039;, grâce à cette liaison, tous les commits sur la branche locale //master// seront poussées sur le serveur distant.&lt;br /&gt;
&lt;br /&gt;
===Méthode moins simple: bare first===&lt;br /&gt;
&lt;br /&gt;
Si on commence dans par le serveur &amp;quot;vide&amp;quot;, il faudra le cloner au lieu de le définir comme un dépôt distant.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création du dépôt vide&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que ce dépôt est accessible à l&#039;URL URL_REPO&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clonage du dépôt&lt;br /&gt;
git clone URL_REPO clone-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un avertissement indique que l&#039;on clone un dépôt vide: le dépôt local à donc une branche master, mais elle n&#039;est pas liée au dépôt distant, car celui-ci n&#039;a aucune branche.&lt;br /&gt;
Le dépôt distant est automatiquement appelé //origin//.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Commit dans le dépôt local&lt;br /&gt;
cd clone-repo&lt;br /&gt;
echo hello &amp;gt; readme.rst&lt;br /&gt;
git add readme.rst&lt;br /&gt;
git commit et ses dépendances&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme dans la méthode simple, il faut pousser la branche master vers le dépôt distant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===De l&#039;importance des README===&lt;br /&gt;
&lt;br /&gt;
Il est très important d&#039;avoir au moins 2 fichiers dans votre dépôt Git:&lt;br /&gt;
&lt;br /&gt;
* LICENSE: contenant le texte **complet** de la licence de votre projet&lt;br /&gt;
* README: décrivant votre projet et comment l&#039;utiliser. Ce fichier doit rappeler le nom de la licence de votre projet&lt;br /&gt;
&lt;br /&gt;
Il est aussi recommandé d&#039;avoir les fichiers suivants:&lt;br /&gt;
&lt;br /&gt;
* AUTHORS: contenant la liste des noms/pseudos et e-mails des auteurs de commits ou de code inclus dans ce projet&lt;br /&gt;
* INSTALL: contenant la liste des dépendances de ce projet et des commandes à utiliser pour le compiler et l&#039;installer&lt;br /&gt;
&lt;br /&gt;
Les fichiers LICENSE sont des fichiers textes bruts.&lt;br /&gt;
Les autres fichiers sont généralement dans un format offrant un peu plus de lisibilté, par exemple dans les formats [http://daringfireball.net/projects/markdown/ Markdown] (.md) ou [http://docutils.sourceforge.net/rst.html reStructuredText] (.rst)&lt;br /&gt;
&lt;br /&gt;
Un plug-in existe pour éditer des fichier reStructuredText dans Eclipse: ReST Editor, disponible sur le [https://marketplace.eclipse.org/content/rest-editor Marketplace Eclipse]&lt;br /&gt;
&lt;br /&gt;
=Séance 2a: Intégration en continue=&lt;br /&gt;
&lt;br /&gt;
===GitHub &amp;amp; [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
Travis-CI est un service permettant d&#039;exécuter un script dans une machine virtuelle Ubuntu dès que vous effectuez un push sur un de vos dépôts GitHub.&lt;br /&gt;
L&#039;intérêt est de savoir si la version d&#039;un projet que vous avez rendu publique peut être compilée et si ses tests passent.&lt;br /&gt;
&lt;br /&gt;
La machine virtuelle &amp;quot;offerte&amp;quot; par Travis est préconfigurée pour le language indiqué dans son fichier de configuration (&#039;&#039;&#039;.travis.yml&#039;&#039;&#039;), mais il est possible d&#039;utiliser la commande &#039;&#039;&#039;sudo apt-get install ...&#039;&#039;&#039; pour ajouter vos dépendances.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour utiliser [[Travis-CI]]:&lt;br /&gt;
&lt;br /&gt;
# Créez compte individuel sur GitHub https://github.com&lt;br /&gt;
# &#039;&#039;Fork&#039;&#039;ez le projet TAGL &#039;&#039;&#039;cron4j&#039;&#039;&#039; depuis https://github.com/donsez/tagl&lt;br /&gt;
# Ajoutez un collaborateur (i.e. votre binôme) au projet &#039;&#039;forké&#039;&#039;, via les paramètres (&#039;&#039;settings&#039;&#039;) de ce projet&lt;br /&gt;
# Pour l&#039;exemple, activez le service (ou hook) &#039;&#039;Email&#039;&#039; depuis les paramètres du dépôt: à chaque fois que vous ou un de vos collaborateurs ferra un &#039;&#039;&#039;git push&#039;&#039;&#039;, vous recevrez une notification par mail.&lt;br /&gt;
# Activez le service Travis-CI: identifiez-vous (&#039;&#039;sign in&#039;&#039;) sur https://travis-ci.org/ avec votre compte GitHub&lt;br /&gt;
# Activez le service pour les projets sur lesquels vous souhaitez appliquer les principes d&#039;intégration continue&lt;br /&gt;
&lt;br /&gt;
[[Travis-CI]] utilise un fichier nommé &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; (attention: fichier caché sous Unix) pour se configurer et choisir les opérations à effectuer.&lt;br /&gt;
Ce fichier doit se trouver à la racine de votre dépôt Git.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; du fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; ci-dessous.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
language: node_js&lt;br /&gt;
node_js:&lt;br /&gt;
  - &amp;quot;0.11&amp;quot;&lt;br /&gt;
  - &amp;quot;0.10&amp;quot;&lt;br /&gt;
  - &amp;quot;0.8&amp;quot;&lt;br /&gt;
  - &amp;quot;0.6&amp;quot;&lt;br /&gt;
  - iojs&lt;br /&gt;
  - iojs-v1.0.2&lt;br /&gt;
&lt;br /&gt;
script:&lt;br /&gt;
        - pushd cron4j-original &amp;amp;&amp;amp; ant rel &amp;amp;&amp;amp; popd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(voir http://docs.travis-ci.com/user/languages/javascript-with-nodejs/)&lt;br /&gt;
&lt;br /&gt;
Ce fichier indique que le projet dans ce dépôt doit être testé sur plusieurs versions de [[Node.js]], et que le script à exécuter pour lancer les tests est &#039;&#039;&#039;pushd cron4j-original &amp;amp;&amp;amp; ant rel &amp;amp;&amp;amp; popd&#039;&#039;&#039;.&lt;br /&gt;
[[Travis-CI]] peut exécuter plusieurs commandes dans script, chacune d&#039;entre elles devant démarrer par un &#039;-&#039; (élément dans une liste de &#039;scripts&#039;).&lt;br /&gt;
&lt;br /&gt;
Attention: il n&#039;est pas possible d&#039;utiliser &#039;&#039;&#039;cd&#039;&#039;&#039; pour changer de répertoire, il faut utiliser &#039;&#039;&#039;pushd&#039;&#039;&#039; (déplacement dans un dossier) et &#039;&#039;&#039;popd&#039;&#039;&#039; (retour au dossier précédent) à la place.&lt;br /&gt;
&lt;br /&gt;
Une fois ce fichier de configuration &#039;&#039;&#039;pushé&#039;&#039;&#039;, Travis-CI se mettra en route dès le prochain &#039;&#039;&#039;push&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Séance 2b: Livraison en continue=&lt;br /&gt;
&lt;br /&gt;
==[[Heruko]]==&lt;br /&gt;
[https://www.heroku.com/ Heruko] est une plateforme cloud de type PaaS permettant l&#039;exécution d&#039;applications et de services en ligne écrits dans les langages et plateformes suivantes : Ruby, [[Node.js]], [[Python]], Java, et PHP.&lt;br /&gt;
&lt;br /&gt;
# Créez un compte gratuit sur [https://signup.heroku.com Heruko]&lt;br /&gt;
# Forkez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Dans Heroku, créez une nouvelle app Node.js, et liez-la au repository Github créé à l&#039;étape précédente&lt;br /&gt;
# Choisissez l&#039;option &amp;quot;Déploiement automatique&amp;quot; depuis la branche **master**&lt;br /&gt;
# Modifiez le fichier index.js pour afficher la version de service dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 var fs = require(&#039;fs&#039;);&lt;br /&gt;
 var package = JSON.parse(fs.readFileSync(&#039;./package.json&#039;, &#039;utf8&#039;));&lt;br /&gt;
 var version=package.version;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Hello World! (current version: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Séance 3: Builders=&lt;br /&gt;
&lt;br /&gt;
==[[Ant]]==&lt;br /&gt;
&lt;br /&gt;
==[[Maven]]==&lt;br /&gt;
&lt;br /&gt;
[http://maven.apache.org/download.cgi Charger et installer Maven 3].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mvn -version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Faites une copie du projet, basée sur Maven:&lt;br /&gt;
&lt;br /&gt;
# Dans votre dépôt Git, créez un dossier &#039;&#039;&#039;cron4j-mvn&#039;&#039;&#039;: il contiendra le projet Cron4J avec la structure Maven&lt;br /&gt;
# Dans ce dossier, utilisez l&#039;[https://maven.apache.org/guides/introduction/introduction-to-archetypes.html archetype] Maven [http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-quickstart/ maven-archetype-quickstart] (la version des sources de cron4j utilisés est la 2.5.5):&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Cette commande crée un projet avec un fichier &#039;&#039;pom.xml&#039;&#039;, et une classe et un test modèles: supprimez ces modèles&lt;br /&gt;
# Copiez les sources de Cron4J depuis le dossier &#039;&#039;&#039;cron4j-original&#039;&#039;&#039; dans le dossier &#039;&#039;&#039;src/main/java&#039;&#039;&#039; de votre projet Maven&lt;br /&gt;
# Faites un essai de compilation:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Lancez un des exemples avec mvn exec:java -Dexec.mainClass=&amp;quot;com.example.Main&amp;quot; [-Dexec.args=&amp;quot;argument1&amp;quot;] ... ([http://mojo.codehaus.org/exec-maven-plugin/usage.html doc. exec plugin], [http://mojo.codehaus.org/exec-maven-plugin/java-mojo.html doc. Exec:java goal])&lt;br /&gt;
# Enfin modifiez le fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; à la racine de votre dépôt Git afin que Travis exécute la commande &#039;&#039;&#039;mvn clean verify&#039;&#039;&#039; à chaque mise à jour du dépôt GitHub.&lt;br /&gt;
&lt;br /&gt;
==Tests Unitaires avec JUnit 4==&lt;br /&gt;
Survoller le tutoriel [http://www.vogella.com/tutorials/JUnit/article.html Unit Testing with JUnit]&lt;br /&gt;
&lt;br /&gt;
# Ajouter le test unitaire suivant au projet, dans le fichier &#039;&#039;&#039;src/test/it/sauronsoftware/SchedulingPatternTest.java&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
package it.sauronsoftware;&lt;br /&gt;
&lt;br /&gt;
import it.sauronsoftware.cron4j.SchedulingPattern;&lt;br /&gt;
import it.sauronsoftware.cron4j.InvalidPatternException;&lt;br /&gt;
&lt;br /&gt;
import static org.junit.Assert.assertEquals;&lt;br /&gt;
import static org.junit.Assert.assertTrue;&lt;br /&gt;
&lt;br /&gt;
import org.junit.AfterClass;&lt;br /&gt;
import org.junit.BeforeClass;&lt;br /&gt;
import org.junit.Test;&lt;br /&gt;
&lt;br /&gt;
public class SchedulingPatternTest {&lt;br /&gt;
&lt;br /&gt;
  @BeforeClass&lt;br /&gt;
  public static void testSetup() {&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @AfterClass&lt;br /&gt;
  public static void testCleanup() {&lt;br /&gt;
    // Teardown for data used by the unit tests&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test(expected = InvalidPatternException.class)&lt;br /&gt;
  public void testExceptionIsThrown() {&lt;br /&gt;
    SchedulingPattern sp = new SchedulingPattern(&amp;quot;0 5 * *&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test&lt;br /&gt;
  public void testPattern() {&lt;br /&gt;
    String pattern;&lt;br /&gt;
    pattern=&amp;quot;0 5 * * *|8 10 * * *|22 17 * * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
    pattern=&amp;quot;0 5 * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Committez et Pushez ce nouveau fichier, pour que Travis lance les tests dès que possible&lt;br /&gt;
# Lancez les tests unitaires avec &amp;lt;pre&amp;gt;mvn test&amp;lt;/pre&amp;gt; Ce test va &#039;&#039;&#039;échouer&#039;&#039;&#039;: corrigez le.&lt;br /&gt;
# Committez et Pushez la version corrigée des tests: Travis enverra un mail pour indiquer si les tests échouent ou non&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; Travis va exécuter les tests &#039;&#039;dès que possible&#039;&#039;. Il est possible de recevoir un mail indiquant que les tests du premier &#039;&#039;push&#039;&#039; échouent alors que l&#039;on a déjà &#039;&#039;pushé&#039;&#039; la correction.&lt;br /&gt;
# Naviguez sur http://travis-ci.org pour vérifier les builds effectués.&lt;br /&gt;
# Créez des tests unitaires supplémentaire du i.s.c.CronParser&lt;br /&gt;
&lt;br /&gt;
===[[Maven]] avec [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
===Git (suite)===&lt;br /&gt;
&lt;br /&gt;
# Forkez le projet &#039;&#039;&#039;tagl&#039;&#039;&#039; d&#039;un autre binome (i.e. autre que &#039;&#039;donsez/tagl&#039;&#039;)&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; donnez lui un nom différent (e.g. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Clonez ce nouveau dépôt&lt;br /&gt;
# Lancez une compilation pour valider l&#039;état du projet (bonne pratique)&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Ajoutez une bannière de licence dans le fichier &#039;&#039;&#039;cron4j-mvn/pom.xml&#039;&#039;&#039;&lt;br /&gt;
# Lancez une nouvelle compilation pour valider vos modifications&lt;br /&gt;
# Commitez et pushez (vers votre fork de ce dépôt, i.e. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Via le site de GitHub, proposez un &amp;quot;Pull Request&amp;quot; au projet initial&lt;br /&gt;
&lt;br /&gt;
Vous pouvez ensuite supprimer le clone de ce fork.&lt;br /&gt;
Lorsque le &#039;&#039;pull request&#039;&#039; aura été accepté, vous pourrez supprimer votre fork (&#039;&#039;tagl-licensing&#039;&#039;) de votre compte GitHub.&lt;br /&gt;
&lt;br /&gt;
===Contrôle Continu===&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt &#039;&#039;tagl&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le plugin [http://mojo.codehaus.org/cobertura-maven-plugin/usage.html Cobertura] à votre projet Maven.&lt;br /&gt;
## Configurez le plugin pour [http://mojo.codehaus.org/cobertura-maven-plugin/examples/report-formats.html générer un rapport] HTML. Le résultat se trouvera dans &#039;&#039;target/site/cobertura&#039;&#039;&lt;br /&gt;
## Le plugin ne s&#039;exécute automatiquement pas durant la compilation, il faut utiliser la commande : &amp;lt;pre&amp;gt;mvn cobertura:cobertura&amp;lt;/pre&amp;gt;&lt;br /&gt;
## &#039;&#039;&#039;Bonus:&#039;&#039;&#039; Modifiez le fichier &#039;&#039;pom.xml&#039;&#039; pour que le &#039;&#039;goal&#039;&#039; &#039;&#039;&#039;cobertura&#039;&#039;&#039; soit exécuté pendant la &#039;&#039;phase&#039;&#039; &#039;&#039;&#039;package&#039;&#039;&#039;.&lt;br /&gt;
# Répondez aux questions : &#039;&#039;Mais qu&#039;est ce que la couverture de code ? En quoi c&#039;est utile ?&#039;&#039;&lt;br /&gt;
# Ajoutez au projet Maven les plugins pour la génération d&#039;un site et de rapports (Javadoc, tests unitaires, tags list (FIXME, TODO, ...), ...): voir http://maven.apache.org/plugins/maven-site-plugin/ et d&#039;autres.&lt;br /&gt;
# Regardez les exemples d&#039;utilisation de cron4j dans cron4j-original/examples&lt;br /&gt;
&lt;br /&gt;
===Bonus Track===&lt;br /&gt;
&lt;br /&gt;
====Clone SVN -&amp;gt; Git====&lt;br /&gt;
&lt;br /&gt;
Source: http://www.yterium.net/Migrer-un-projet-SVN-vers-GIT&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Cloner le dépôt SVN en dépôt Git (conservation historique)&lt;br /&gt;
$ git svn clone  svn://svn.code.sf.net/p/cron4j/code/trunk cron4j-original&lt;br /&gt;
$ cd cron4j-original&lt;br /&gt;
# Test compilation&lt;br /&gt;
$ ant jar&lt;br /&gt;
$ cd ..&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Préparation TAGL====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clone du dépôt TAGL&lt;br /&gt;
$ git clone git@github.com:donsez/tagl.git&lt;br /&gt;
$ cd tagl&lt;br /&gt;
# &amp;quot;Fetch&amp;quot; du dépôt local cloné précédemment&lt;br /&gt;
$ git fetch file://$(pwd)/../cron4j-original&lt;br /&gt;
# Fusion de ce qui vient d&#039;être fetché&lt;br /&gt;
$ git merge FETCH_HEAD&lt;br /&gt;
# Envoi sur le serveur&lt;br /&gt;
$ git push&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Cherry-picking: reprise des modifications d&#039;un collègue====&lt;br /&gt;
&lt;br /&gt;
On considère que:&lt;br /&gt;
&lt;br /&gt;
* votre dépôt Git distant est à l&#039;adresse URL_DEPOT&lt;br /&gt;
* votre collègue a un dépôt Git à l&#039;adresse URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Dossier temporaire&lt;br /&gt;
cd /tmp&lt;br /&gt;
&lt;br /&gt;
# Clone de votre dépôt&lt;br /&gt;
git clone URL_DEPOT mon_depot&lt;br /&gt;
&lt;br /&gt;
# Déplacement dans votre dépôt&lt;br /&gt;
cd mon_depot&lt;br /&gt;
&lt;br /&gt;
# Définition du dépôt distant&lt;br /&gt;
git remote add collegue URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
# Récupération des infos du dépôt du collègue&lt;br /&gt;
git fetch collegue&lt;br /&gt;
&lt;br /&gt;
# Maintenant, on peut voir les branches du collègue&lt;br /&gt;
git branch -a&lt;br /&gt;
&lt;br /&gt;
# On peut fusionner avec une branche&lt;br /&gt;
git merge collegue/master&lt;br /&gt;
&lt;br /&gt;
# Si vous avez des conflits, éditez les fichiers concernés,&lt;br /&gt;
# et committez avec git commit&lt;br /&gt;
&lt;br /&gt;
# Push vers votre dépôt distant&lt;br /&gt;
git push origin&lt;br /&gt;
&lt;br /&gt;
# Optionnel: supprimez la référence vers le dépôt du collègue&lt;br /&gt;
git remote rm collegue&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Archetype webapp====&lt;br /&gt;
L&#039;archetype webapp (http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-webapp/) permet de créer le squelette d&#039;une webapp. Créez un simple webapp monsite en version 0.1.0. (add/commit/push). Vous pourrez tester cette webapp en ajoutant au pom.xml le [https://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin plugin maven Jetty].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mvn -Djetty.port=9999 jetty:run&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naviguez sur http://localhost:9999/monsite&lt;br /&gt;
&lt;br /&gt;
====Scrum tools====&lt;br /&gt;
Ces 3 services peuvent être couplé à votre dépôt GitHub pour votre gestion de projet agile avec [[Scrum]] :&lt;br /&gt;
* http://www.acunote.com/&lt;br /&gt;
* http://backlogtool.com/&lt;br /&gt;
* http://www.scrumdo.com/&lt;br /&gt;
&lt;br /&gt;
L&#039;activation se fait via &#039;&#039;Settings &amp;gt; Webhooks &amp;amp; Services &amp;gt; Configure services&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Séance 4: AOP &amp;amp; AspectJ=&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt Git, projet &#039;&#039;cron4j-mvn&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le [http://mojo.codehaus.org/aspectj-maven-plugin/ plugin Maven pour AspectJ] au pom.xml&lt;br /&gt;
# Ajoutez un aspect de trace à l&#039;invocation des méthodes &#039;&#039;&#039;run()&#039;&#039;&#039; de l&#039;interface java.lang.Runnable (uniquement pour les objets &#039;&#039;schedulé&#039;&#039;s)&lt;br /&gt;
#: Affichez une trace avant et après l&#039;exécution de la tâche&lt;br /&gt;
# Préparez un nouveau test (nouvelle classe) démarrant un Scheduler Cron4j et validant l&#039;exécution d&#039;une tâche au bout d&#039;une minute (pattern &amp;quot;* * * * *&amp;quot;)&lt;br /&gt;
#: Lors de l&#039;exécution de &#039;&#039;&#039;mvn test&#039;&#039;&#039;, vous devez voir apparaître les traces préparées dans votre aspect.&lt;br /&gt;
&lt;br /&gt;
Liens utiles:&lt;br /&gt;
* [http://ridgetopsolutions.com/blog/2013/02/12/getting-started-with-aspectj-and-maven/ Getting started with AspectJ and Maven]&lt;br /&gt;
&lt;br /&gt;
===Contrôle continu===&lt;br /&gt;
&lt;br /&gt;
# Complétez l&#039;aspect de trace avec le positionnement du [http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html java.lang.ThreadLocal] pour passer 1) l&#039;identifiant du job et 2) le compteur des appels de la méthode de l&#039;objet.&lt;br /&gt;
&lt;br /&gt;
=Séance 5: Pelix &amp;amp; iPOPO=&lt;br /&gt;
&lt;br /&gt;
Pelix est une plate-forme d&#039;application à services (SOA).&lt;br /&gt;
iPOPO est un modèle de composants orientés services (SOCM).&lt;br /&gt;
&lt;br /&gt;
La documentation de Pelix et iPOPO est disponible sur https://ipopo.coderxpress.net/&lt;br /&gt;
&lt;br /&gt;
===Installation de iPOPO===&lt;br /&gt;
&lt;br /&gt;
* Cloner le dépôt Git depuis https://github.com/tcalmant/ipopo&lt;br /&gt;
* Se placer dans la branche &#039;&#039;dev&#039;&#039;&lt;br /&gt;
* Pour installer iPOPO, lancer la commande :&lt;br /&gt;
&lt;br /&gt;
   sudo python setup.py install&lt;br /&gt;
&lt;br /&gt;
===Shell Pelix===&lt;br /&gt;
&lt;br /&gt;
Pour lancer un shell Pelix, utilisez la commande:&lt;br /&gt;
&lt;br /&gt;
   python -m pelix.shell.console&lt;br /&gt;
&lt;br /&gt;
Les commandes disponibles sont décrites ici: [https://ipopo.coderxpress.net/wiki/doku.php?id=ipopo:refcards:shell Shell Commands]&lt;br /&gt;
&lt;br /&gt;
===Rappels de Python===&lt;br /&gt;
&lt;br /&gt;
* Pas de déclaration du type d&#039;une variable&lt;br /&gt;
* Les méthodes d&#039;une classe ont toute comme premier paramètre &#039;&#039;self&#039;&#039;, équivalent du &#039;&#039;this&#039;&#039; en Java.&lt;br /&gt;
* Blocs définis par indentation (4 espaces ou 1 tab)&lt;br /&gt;
* Une ligne finissant par &#039;:&#039; démarre toujours un bloc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Import d&#039;un module&lt;br /&gt;
import pelix&lt;br /&gt;
&lt;br /&gt;
# Définition d&#039;une classe&lt;br /&gt;
class MaClasse:&lt;br /&gt;
   # Constructeur&lt;br /&gt;
   def __init__(self):&lt;br /&gt;
       self.default = &amp;quot;stanger&amp;quot;&lt;br /&gt;
       print(&amp;quot;Classe construite&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
   # Méthode, avec un argument&lt;br /&gt;
   def sayHello(self, name):&lt;br /&gt;
       if not name:&lt;br /&gt;
           # Nom vide ou nul&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(self.default)&lt;br /&gt;
       else:&lt;br /&gt;
           # Nom valide&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(name)&lt;br /&gt;
&lt;br /&gt;
objet = MaClasse()&lt;br /&gt;
print(objet.sayHello(&amp;quot;&amp;quot;))&lt;br /&gt;
print(objet.sayHello(&amp;quot;World&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Service Ping-Pong===&lt;br /&gt;
&lt;br /&gt;
1. Écrire un fichier &#039;&#039;pong.py&#039;&#039;, définissant une classe &#039;&#039;Pong&#039;&#039; ayant une méthode &#039;&#039;pong&#039;&#039; prenant en paramètre un message et retournant le message préfixé par &amp;quot;PONG:&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Exemple: &lt;br /&gt;
   &lt;br /&gt;
      pong = Pong()&lt;br /&gt;
      pong.pong(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2. Écrire un fichier &#039;&#039;ping.py&#039;&#039;, définissant une classe &#039;&#039;Ping&#039;&#039; ayant une méthode &#039;&#039;ping&#039;&#039; prenant en paramètre un message, créant un objet Pong et retournant le résultat de Pong.pong(message) préfixé par &amp;quot;PING:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&lt;br /&gt;
      ping = Ping()&lt;br /&gt;
      ping.ping(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PING:PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
3. Transformer le fichier &#039;&#039;pong.py&#039;&#039; pour qu&#039;il devienne un bundle Pelix enregistrant un objet Pong comme étant un service ayant pour spécification &amp;quot;tagl.pong&amp;quot;&lt;br /&gt;
* Définir une classe &#039;&#039;Activator&#039;&#039;, décorée avec &#039;&#039;@BundleActivator&#039;&#039;&lt;br /&gt;
* Enregistrer le service dans la méthode &#039;&#039;Activator.start&#039;&#039; et le désenregistrer dans &#039;&#039;Activator.stop&#039;&#039;&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/provider.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;pong&#039; et vérifier que le service est bien inscrit avec la commande &#039;&#039;sl&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
4.Transformer la classe &#039;&#039;Ping&#039;&#039; dans &#039;&#039;ping.py&#039;&#039; en un composant iPOPO&lt;br /&gt;
* L&#039;objet Pong utilisé dans &#039;&#039;ping()&#039;&#039; doit être un service injecté par iPOPO (&#039;&#039;@Requires&#039;&#039;)&lt;br /&gt;
* Appeler la méthode &#039;&#039;ping()&#039;&#039; dès que le service Pong est injecté (&#039;&#039;@BindField&#039;&#039;) ou disparait (&#039;&#039;@UnbindField&#039;&#039;)&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/consumer.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;ping&#039; et vérifier son comportement si le bundle &#039;&#039;pong&#039;&#039; ou le bundle &#039;&#039;ping&#039;&#039; est arrêté et redémarré.&lt;br /&gt;
&lt;br /&gt;
5. Mettre à jour le bundle &#039;&#039;pong&#039;&#039;&lt;br /&gt;
* Remplacer le préfixe &amp;quot;PONG&amp;quot; par &amp;quot;NI&amp;quot;&lt;br /&gt;
* Dans le shell Pelix, mettre à jour le bundle &#039;&#039;pong&#039;&#039; sans redémarrer la plate-forme (commande &#039;&#039;udpate&#039;&#039;).&lt;br /&gt;
* Vérifier les traces dans le shell pour valider la mise à jour du service.&lt;br /&gt;
&lt;br /&gt;
===Remote Services===&lt;br /&gt;
&lt;br /&gt;
* Ajouter les propriétés permettant l&#039;export du service Pong dans &#039;&#039;pong.py&#039;&#039; (s&#039;inspirer de &#039;&#039;provider.py&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
* Lancer deux shells iPOPO (dans deux terminaux)&lt;br /&gt;
* Dans chaque shell iPOPO, installer les bundles:&lt;br /&gt;
** &#039;&#039;pelix.remote.dispatcher&#039;&#039;: Exportateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.registry&#039;&#039;; Importateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.discovery.multicast&#039;&#039;: Découverte de services via Multicast&lt;br /&gt;
** &#039;&#039;pelix.remote.xml_rpc&#039;&#039;: Transport XML-RPC&lt;br /&gt;
** &#039;&#039;pelix.http.basic&#039;&#039;: Serveur HTTP&lt;br /&gt;
&lt;br /&gt;
Attention: il peut être nécessaire de désactiver votre pare-feu pour que les Remote Services fonctionnent&lt;br /&gt;
&lt;br /&gt;
* Instancier les composants depuis le shell iPOPO, dans chaque framework:&lt;br /&gt;
** Serveur HTTP sur le port 8080: &#039;&#039;instantiate pelix.http.service.basic.factory http-server pelix.http.port=8080&#039;&#039; (penser à changer de port dans chaque framework)&lt;br /&gt;
** Multicast Discovery: &#039;&#039;instantiate pelix-remote-discovery-multicast-factory multicast-discovery&#039;&#039;&lt;br /&gt;
** XML-RPC Exporter: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-exporter&#039;&#039;&lt;br /&gt;
** XML-RPC Importer: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-importer&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Installer le bundle &#039;&#039;ping&#039;&#039; dans un des frameworks et le bundle &#039;&#039;pong&#039;&#039; dans l&#039;autre.&lt;br /&gt;
* Le composant ping peut appeler le service pong, qui est dans l&#039;autre framework.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Voir le code de &#039;&#039;run_remote.py&#039;&#039; pour voir comment démarrer un framework Pelix et installer des bundles depuis Python.&lt;br /&gt;
* Jouer un peu avec &#039;&#039;run_remote.py&#039;&#039; (voir &#039;&#039;run_remote.py --help&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=Séance 6=&lt;br /&gt;
[[Tutorial OSGi avec Apache Felix]]&lt;br /&gt;
&lt;br /&gt;
=Séance 7=&lt;br /&gt;
Faire un projet PDE pour un bundle cron4j.gogo (indépendant de cron4j.bundle)&lt;br /&gt;
&lt;br /&gt;
Utilisation de https://eclipse.org/tycho/&lt;/div&gt;</summary>
		<author><name>MatthieuCaneill</name></author>
	</entry>
	<entry>
		<id>https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21266</id>
		<title>TAGL/TP</title>
		<link rel="alternate" type="text/html" href="https://air.imag.fr/index.php?title=TAGL/TP&amp;diff=21266"/>
		<updated>2015-02-17T09:38:57Z</updated>

		<summary type="html">&lt;p&gt;MatthieuCaneill: /* GitHub &amp;amp; Travis-CI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Travaux pratiques de l&#039;UE [[TAGL]].&lt;br /&gt;
&lt;br /&gt;
Anciennes versions : [[TAGL/TP 2014]]&lt;br /&gt;
&lt;br /&gt;
=Séance 1 : Gestion de versions=&lt;br /&gt;
==Git==&lt;br /&gt;
&lt;br /&gt;
Création d&#039;un dépôt Git local&lt;br /&gt;
&lt;br /&gt;
===Méthode simple: init first===&lt;br /&gt;
&lt;br /&gt;
Via cette méthode, on crée un dépôt local, avec un répertoire de travail, puis on pousse ses modifications vers un dépôt &amp;quot;bare&amp;quot;.&lt;br /&gt;
Cette méthode est la plus simple, car on dispose immédiatement d&#039;un répertoire de travail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création d&#039;un dépôt Git dans le dossier simple-repo&lt;br /&gt;
git init simple-repo&lt;br /&gt;
&lt;br /&gt;
# Création d&#039;un README&lt;br /&gt;
cd simple-repo&lt;br /&gt;
echo &amp;quot;Hello, World&amp;quot; &amp;gt; README&lt;br /&gt;
&lt;br /&gt;
# Ajout du versionnement du fichier README&lt;br /&gt;
git add README&lt;br /&gt;
&lt;br /&gt;
# Commit&lt;br /&gt;
git commit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À ce niveau, on a un dépôt Git complètement fonctionnel.&lt;br /&gt;
Cependant, il est intéressant de pousser ses modifications vers un autre dépôt, sur une autre machine.&lt;br /&gt;
On va donc créer un dépôt bare sur une autre machine (ou autre dossier pour l&#039;exemple)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que l&#039;URL pour accéder à ce dépôt est URL_REPO.&lt;br /&gt;
On va d&#039;abord ajouter ce dépôt serveur à la liste des dépôts connu-repos de votre dépôt local.&lt;br /&gt;
Étant donné qu&#039;il s&#039;agit du dépôt &amp;quot;principal&amp;quot; à utiliser, on l&#039;appellera //origin//, par convention.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin URL_REPO&lt;br /&gt;
# Récupération de ses informations&lt;br /&gt;
git fetch origin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce serveur distant est &amp;quot;vide&amp;quot;: il n&#039;a aucune branche. On va donc enregistrer notre branche sur le serveur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
À partir de cette commande, la branche locale //master// sera liée à la branche distante //origin/master//.&lt;br /&gt;
Lors des prochaines commandes &#039;&#039;git push&#039;&#039;, grâce à cette liaison, tous les commits sur la branche locale //master// seront poussées sur le serveur distant.&lt;br /&gt;
&lt;br /&gt;
===Méthode moins simple: bare first===&lt;br /&gt;
&lt;br /&gt;
Si on commence dans par le serveur &amp;quot;vide&amp;quot;, il faudra le cloner au lieu de le définir comme un dépôt distant.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Création du dépôt vide&lt;br /&gt;
git init --bare server-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On considère que ce dépôt est accessible à l&#039;URL URL_REPO&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clonage du dépôt&lt;br /&gt;
git clone URL_REPO clone-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un avertissement indique que l&#039;on clone un dépôt vide: le dépôt local à donc une branche master, mais elle n&#039;est pas liée au dépôt distant, car celui-ci n&#039;a aucune branche.&lt;br /&gt;
Le dépôt distant est automatiquement appelé //origin//.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Commit dans le dépôt local&lt;br /&gt;
cd clone-repo&lt;br /&gt;
echo hello &amp;gt; readme.rst&lt;br /&gt;
git add readme.rst&lt;br /&gt;
git commit et ses dépendances&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme dans la méthode simple, il faut pousser la branche master vers le dépôt distant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push origin master&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===De l&#039;importance des README===&lt;br /&gt;
&lt;br /&gt;
Il est très important d&#039;avoir au moins 2 fichiers dans votre dépôt Git:&lt;br /&gt;
&lt;br /&gt;
* LICENSE: contenant le texte **complet** de la licence de votre projet&lt;br /&gt;
* README: décrivant votre projet et comment l&#039;utiliser. Ce fichier doit rappeler le nom de la licence de votre projet&lt;br /&gt;
&lt;br /&gt;
Il est aussi recommandé d&#039;avoir les fichiers suivants:&lt;br /&gt;
&lt;br /&gt;
* AUTHORS: contenant la liste des noms/pseudos et e-mails des auteurs de commits ou de code inclus dans ce projet&lt;br /&gt;
* INSTALL: contenant la liste des dépendances de ce projet et des commandes à utiliser pour le compiler et l&#039;installer&lt;br /&gt;
&lt;br /&gt;
Les fichiers LICENSE sont des fichiers textes bruts.&lt;br /&gt;
Les autres fichiers sont généralement dans un format offrant un peu plus de lisibilté, par exemple dans les formats [http://daringfireball.net/projects/markdown/ Markdown] (.md) ou [http://docutils.sourceforge.net/rst.html reStructuredText] (.rst)&lt;br /&gt;
&lt;br /&gt;
Un plug-in existe pour éditer des fichier reStructuredText dans Eclipse: ReST Editor, disponible sur le [https://marketplace.eclipse.org/content/rest-editor Marketplace Eclipse]&lt;br /&gt;
&lt;br /&gt;
=Séance 2a: Intégration en continue=&lt;br /&gt;
&lt;br /&gt;
===GitHub &amp;amp; [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
Travis-CI est un service permettant d&#039;exécuter un script dans une machine virtuelle Ubuntu dès que vous effectuez un push sur un de vos dépôts GitHub.&lt;br /&gt;
L&#039;intérêt est de savoir si la version d&#039;un projet que vous avez rendu publique peut être compilée et si ses tests passent.&lt;br /&gt;
&lt;br /&gt;
La machine virtuelle &amp;quot;offerte&amp;quot; par Travis est préconfigurée pour le language indiqué dans son fichier de configuration (&#039;&#039;&#039;.travis.yml&#039;&#039;&#039;), mais il est possible d&#039;utiliser la commande &#039;&#039;&#039;sudo apt-get install ...&#039;&#039;&#039; pour ajouter vos dépendances.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour utiliser [[Travis-CI]]:&lt;br /&gt;
&lt;br /&gt;
# Créez compte individuel sur GitHub https://github.com&lt;br /&gt;
# &#039;&#039;Fork&#039;&#039;ez le projet TAGL &#039;&#039;&#039;cron4j&#039;&#039;&#039; depuis https://github.com/donsez/tagl&lt;br /&gt;
# Ajoutez un collaborateur (i.e. votre binôme) au projet &#039;&#039;forké&#039;&#039;, via les paramètres (&#039;&#039;settings&#039;&#039;) de ce projet&lt;br /&gt;
# Pour l&#039;exemple, activez le service (ou hook) &#039;&#039;Email&#039;&#039; depuis les paramètres du dépôt: à chaque fois que vous ou un de vos collaborateurs ferra un &#039;&#039;&#039;git push&#039;&#039;&#039;, vous recevrez une notification par mail.&lt;br /&gt;
# Activez le service Travis-CI: identifiez-vous (&#039;&#039;sign in&#039;&#039;) sur https://travis-ci.org/ avec votre compte GitHub&lt;br /&gt;
# Activez le service pour les projets sur lesquels vous souhaitez appliquer les principes d&#039;intégration continue&lt;br /&gt;
&lt;br /&gt;
[[Travis-CI]] utilise un fichier nommé &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; (attention: fichier caché sous Unix) pour se configurer et choisir les opérations à effectuer.&lt;br /&gt;
Ce fichier doit se trouver à la racine de votre dépôt Git.&lt;br /&gt;
&lt;br /&gt;
Faites un &#039;&#039;&#039;Commit&#039;&#039;&#039; puis un &#039;&#039;&#039;Push&#039;&#039;&#039; du fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; ci-dessous.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
language: node_js&lt;br /&gt;
node_js:&lt;br /&gt;
  - &amp;quot;0.11&amp;quot;&lt;br /&gt;
  - &amp;quot;0.10&amp;quot;&lt;br /&gt;
  - &amp;quot;0.8&amp;quot;&lt;br /&gt;
  - &amp;quot;0.6&amp;quot;&lt;br /&gt;
  - iojs&lt;br /&gt;
  - iojs-v1.0.2&lt;br /&gt;
&lt;br /&gt;
script:&lt;br /&gt;
        - pushd cron4j-original &amp;amp;&amp;amp; ant rel &amp;amp;&amp;amp; popd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(voir http://docs.travis-ci.com/user/languages/javascript-with-nodejs/)&lt;br /&gt;
&lt;br /&gt;
Ce fichier indique que le projet dans ce dépôt doit être testé sur plusieurs versions de [[Node.js]], et que le script à exécuter pour lancer les tests est &#039;&#039;&#039;pushd cron4j-original &amp;amp;&amp;amp; ant rel &amp;amp;&amp;amp; popd&#039;&#039;&#039;.&lt;br /&gt;
[[Travis-CI]] peut exécuter plusieurs commandes dans script, chacune d&#039;entre elles devant démarrer par un &#039;-&#039; (élément dans une liste de &#039;scripts&#039;).&lt;br /&gt;
&lt;br /&gt;
Attention: il n&#039;est pas possible d&#039;utiliser &#039;&#039;&#039;cd&#039;&#039;&#039; pour changer de répertoire, il faut utiliser &#039;&#039;&#039;pushd&#039;&#039;&#039; (déplacement dans un dossier) et &#039;&#039;&#039;popd&#039;&#039;&#039; (retour au dossier précédent) à la place.&lt;br /&gt;
&lt;br /&gt;
Une fois ce fichier de configuration &#039;&#039;&#039;pushé&#039;&#039;&#039;, Travis-CI se mettra en route dès le prochain &#039;&#039;&#039;push&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Séance 2b: Livraison en continue=&lt;br /&gt;
&lt;br /&gt;
==[[Heruko]]==&lt;br /&gt;
[https://www.heroku.com/ Heruko] est une plateforme cloud de type PaaS permettant l&#039;exécution d&#039;applications et de services en ligne écrits dans les langages et plateformes suivantes : Ruby, [[Node.js]], [[Python]], Java, et PHP.&lt;br /&gt;
&lt;br /&gt;
# Créez un compte gratuit sur [https://signup.heroku.com Heruko]&lt;br /&gt;
# Installez les lignes de commandes d&#039;Heroku ([https://devcenter.heroku.com/articles/getting-started-with-nodejs#set-up Setup]).&lt;br /&gt;
# Ajoutez votre compte Heroku aux &#039;&#039;hooks&#039;&#039; de votre compte Github.&lt;br /&gt;
# Forkez le dépôt https://github.com/heroku/node-js-getting-started&lt;br /&gt;
# Modifiez le fichier index.js pour afficher la version de service dans la page HTML&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 var fs = require(&#039;fs&#039;);&lt;br /&gt;
 var package = JSON.parse(fs.readFileSync(&#039;./package.json&#039;, &#039;utf8&#039;));&lt;br /&gt;
 var version=package.version;&lt;br /&gt;
...&lt;br /&gt;
 response.send(&#039;Hello World! (current version: &#039;+version+&#039;)&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Matthieu : à toi de rédiger, notamment le livraison automatique avec Travis-CI&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Séance 3: Builders=&lt;br /&gt;
&lt;br /&gt;
==[[Ant]]==&lt;br /&gt;
&lt;br /&gt;
==[[Maven]]==&lt;br /&gt;
&lt;br /&gt;
[http://maven.apache.org/download.cgi Charger et installer Maven 3].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mvn -version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Faites une copie du projet, basée sur Maven:&lt;br /&gt;
&lt;br /&gt;
# Dans votre dépôt Git, créez un dossier &#039;&#039;&#039;cron4j-mvn&#039;&#039;&#039;: il contiendra le projet Cron4J avec la structure Maven&lt;br /&gt;
# Dans ce dossier, utilisez l&#039;[https://maven.apache.org/guides/introduction/introduction-to-archetypes.html archetype] Maven [http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-quickstart/ maven-archetype-quickstart] (la version des sources de cron4j utilisés est la 2.5.5):&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Cette commande crée un projet avec un fichier &#039;&#039;pom.xml&#039;&#039;, et une classe et un test modèles: supprimez ces modèles&lt;br /&gt;
# Copiez les sources de Cron4J depuis le dossier &#039;&#039;&#039;cron4j-original&#039;&#039;&#039; dans le dossier &#039;&#039;&#039;src/main/java&#039;&#039;&#039; de votre projet Maven&lt;br /&gt;
# Faites un essai de compilation:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Lancez un des exemples avec mvn exec:java -Dexec.mainClass=&amp;quot;com.example.Main&amp;quot; [-Dexec.args=&amp;quot;argument1&amp;quot;] ... ([http://mojo.codehaus.org/exec-maven-plugin/usage.html doc. exec plugin], [http://mojo.codehaus.org/exec-maven-plugin/java-mojo.html doc. Exec:java goal])&lt;br /&gt;
# Enfin modifiez le fichier &#039;&#039;&#039;.travis.yml&#039;&#039;&#039; à la racine de votre dépôt Git afin que Travis exécute la commande &#039;&#039;&#039;mvn clean verify&#039;&#039;&#039; à chaque mise à jour du dépôt GitHub.&lt;br /&gt;
&lt;br /&gt;
==Tests Unitaires avec JUnit 4==&lt;br /&gt;
Survoller le tutoriel [http://www.vogella.com/tutorials/JUnit/article.html Unit Testing with JUnit]&lt;br /&gt;
&lt;br /&gt;
# Ajouter le test unitaire suivant au projet, dans le fichier &#039;&#039;&#039;src/test/it/sauronsoftware/SchedulingPatternTest.java&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
package it.sauronsoftware;&lt;br /&gt;
&lt;br /&gt;
import it.sauronsoftware.cron4j.SchedulingPattern;&lt;br /&gt;
import it.sauronsoftware.cron4j.InvalidPatternException;&lt;br /&gt;
&lt;br /&gt;
import static org.junit.Assert.assertEquals;&lt;br /&gt;
import static org.junit.Assert.assertTrue;&lt;br /&gt;
&lt;br /&gt;
import org.junit.AfterClass;&lt;br /&gt;
import org.junit.BeforeClass;&lt;br /&gt;
import org.junit.Test;&lt;br /&gt;
&lt;br /&gt;
public class SchedulingPatternTest {&lt;br /&gt;
&lt;br /&gt;
  @BeforeClass&lt;br /&gt;
  public static void testSetup() {&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @AfterClass&lt;br /&gt;
  public static void testCleanup() {&lt;br /&gt;
    // Teardown for data used by the unit tests&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test(expected = InvalidPatternException.class)&lt;br /&gt;
  public void testExceptionIsThrown() {&lt;br /&gt;
    SchedulingPattern sp = new SchedulingPattern(&amp;quot;0 5 * *&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Test&lt;br /&gt;
  public void testPattern() {&lt;br /&gt;
    String pattern;&lt;br /&gt;
    pattern=&amp;quot;0 5 * * *|8 10 * * *|22 17 * * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
    pattern=&amp;quot;0 5 * *&amp;quot;;&lt;br /&gt;
    assertTrue(pattern + &amp;quot;is correct&amp;quot;, SchedulingPattern.validate(pattern));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Committez et Pushez ce nouveau fichier, pour que Travis lance les tests dès que possible&lt;br /&gt;
# Lancez les tests unitaires avec &amp;lt;pre&amp;gt;mvn test&amp;lt;/pre&amp;gt; Ce test va &#039;&#039;&#039;échouer&#039;&#039;&#039;: corrigez le.&lt;br /&gt;
# Committez et Pushez la version corrigée des tests: Travis enverra un mail pour indiquer si les tests échouent ou non&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; Travis va exécuter les tests &#039;&#039;dès que possible&#039;&#039;. Il est possible de recevoir un mail indiquant que les tests du premier &#039;&#039;push&#039;&#039; échouent alors que l&#039;on a déjà &#039;&#039;pushé&#039;&#039; la correction.&lt;br /&gt;
# Naviguez sur http://travis-ci.org pour vérifier les builds effectués.&lt;br /&gt;
# Créez des tests unitaires supplémentaire du i.s.c.CronParser&lt;br /&gt;
&lt;br /&gt;
===[[Maven]] avec [[Travis-CI]]===&lt;br /&gt;
&lt;br /&gt;
===Git (suite)===&lt;br /&gt;
&lt;br /&gt;
# Forkez le projet &#039;&#039;&#039;tagl&#039;&#039;&#039; d&#039;un autre binome (i.e. autre que &#039;&#039;donsez/tagl&#039;&#039;)&lt;br /&gt;
#: &#039;&#039;&#039;Attention:&#039;&#039;&#039; donnez lui un nom différent (e.g. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Clonez ce nouveau dépôt&lt;br /&gt;
# Lancez une compilation pour valider l&#039;état du projet (bonne pratique)&lt;br /&gt;
#:&amp;lt;pre&amp;gt;mvn clean verify&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Ajoutez une bannière de licence dans le fichier &#039;&#039;&#039;cron4j-mvn/pom.xml&#039;&#039;&#039;&lt;br /&gt;
# Lancez une nouvelle compilation pour valider vos modifications&lt;br /&gt;
# Commitez et pushez (vers votre fork de ce dépôt, i.e. &#039;&#039;tagl-licensing&#039;&#039;)&lt;br /&gt;
# Via le site de GitHub, proposez un &amp;quot;Pull Request&amp;quot; au projet initial&lt;br /&gt;
&lt;br /&gt;
Vous pouvez ensuite supprimer le clone de ce fork.&lt;br /&gt;
Lorsque le &#039;&#039;pull request&#039;&#039; aura été accepté, vous pourrez supprimer votre fork (&#039;&#039;tagl-licensing&#039;&#039;) de votre compte GitHub.&lt;br /&gt;
&lt;br /&gt;
===Contrôle Continu===&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt &#039;&#039;tagl&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le plugin [http://mojo.codehaus.org/cobertura-maven-plugin/usage.html Cobertura] à votre projet Maven.&lt;br /&gt;
## Configurez le plugin pour [http://mojo.codehaus.org/cobertura-maven-plugin/examples/report-formats.html générer un rapport] HTML. Le résultat se trouvera dans &#039;&#039;target/site/cobertura&#039;&#039;&lt;br /&gt;
## Le plugin ne s&#039;exécute automatiquement pas durant la compilation, il faut utiliser la commande : &amp;lt;pre&amp;gt;mvn cobertura:cobertura&amp;lt;/pre&amp;gt;&lt;br /&gt;
## &#039;&#039;&#039;Bonus:&#039;&#039;&#039; Modifiez le fichier &#039;&#039;pom.xml&#039;&#039; pour que le &#039;&#039;goal&#039;&#039; &#039;&#039;&#039;cobertura&#039;&#039;&#039; soit exécuté pendant la &#039;&#039;phase&#039;&#039; &#039;&#039;&#039;package&#039;&#039;&#039;.&lt;br /&gt;
# Répondez aux questions : &#039;&#039;Mais qu&#039;est ce que la couverture de code ? En quoi c&#039;est utile ?&#039;&#039;&lt;br /&gt;
# Ajoutez au projet Maven les plugins pour la génération d&#039;un site et de rapports (Javadoc, tests unitaires, tags list (FIXME, TODO, ...), ...): voir http://maven.apache.org/plugins/maven-site-plugin/ et d&#039;autres.&lt;br /&gt;
# Regardez les exemples d&#039;utilisation de cron4j dans cron4j-original/examples&lt;br /&gt;
&lt;br /&gt;
===Bonus Track===&lt;br /&gt;
&lt;br /&gt;
====Clone SVN -&amp;gt; Git====&lt;br /&gt;
&lt;br /&gt;
Source: http://www.yterium.net/Migrer-un-projet-SVN-vers-GIT&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Cloner le dépôt SVN en dépôt Git (conservation historique)&lt;br /&gt;
$ git svn clone  svn://svn.code.sf.net/p/cron4j/code/trunk cron4j-original&lt;br /&gt;
$ cd cron4j-original&lt;br /&gt;
# Test compilation&lt;br /&gt;
$ ant jar&lt;br /&gt;
$ cd ..&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Préparation TAGL====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Clone du dépôt TAGL&lt;br /&gt;
$ git clone git@github.com:donsez/tagl.git&lt;br /&gt;
$ cd tagl&lt;br /&gt;
# &amp;quot;Fetch&amp;quot; du dépôt local cloné précédemment&lt;br /&gt;
$ git fetch file://$(pwd)/../cron4j-original&lt;br /&gt;
# Fusion de ce qui vient d&#039;être fetché&lt;br /&gt;
$ git merge FETCH_HEAD&lt;br /&gt;
# Envoi sur le serveur&lt;br /&gt;
$ git push&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Cherry-picking: reprise des modifications d&#039;un collègue====&lt;br /&gt;
&lt;br /&gt;
On considère que:&lt;br /&gt;
&lt;br /&gt;
* votre dépôt Git distant est à l&#039;adresse URL_DEPOT&lt;br /&gt;
* votre collègue a un dépôt Git à l&#039;adresse URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Dossier temporaire&lt;br /&gt;
cd /tmp&lt;br /&gt;
&lt;br /&gt;
# Clone de votre dépôt&lt;br /&gt;
git clone URL_DEPOT mon_depot&lt;br /&gt;
&lt;br /&gt;
# Déplacement dans votre dépôt&lt;br /&gt;
cd mon_depot&lt;br /&gt;
&lt;br /&gt;
# Définition du dépôt distant&lt;br /&gt;
git remote add collegue URL_COLLEGUE&lt;br /&gt;
&lt;br /&gt;
# Récupération des infos du dépôt du collègue&lt;br /&gt;
git fetch collegue&lt;br /&gt;
&lt;br /&gt;
# Maintenant, on peut voir les branches du collègue&lt;br /&gt;
git branch -a&lt;br /&gt;
&lt;br /&gt;
# On peut fusionner avec une branche&lt;br /&gt;
git merge collegue/master&lt;br /&gt;
&lt;br /&gt;
# Si vous avez des conflits, éditez les fichiers concernés,&lt;br /&gt;
# et committez avec git commit&lt;br /&gt;
&lt;br /&gt;
# Push vers votre dépôt distant&lt;br /&gt;
git push origin&lt;br /&gt;
&lt;br /&gt;
# Optionnel: supprimez la référence vers le dépôt du collègue&lt;br /&gt;
git remote rm collegue&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Archetype webapp====&lt;br /&gt;
L&#039;archetype webapp (http://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-webapp/) permet de créer le squelette d&#039;une webapp. Créez un simple webapp monsite en version 0.1.0. (add/commit/push). Vous pourrez tester cette webapp en ajoutant au pom.xml le [https://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin plugin maven Jetty].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mvn -Djetty.port=9999 jetty:run&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naviguez sur http://localhost:9999/monsite&lt;br /&gt;
&lt;br /&gt;
====Scrum tools====&lt;br /&gt;
Ces 3 services peuvent être couplé à votre dépôt GitHub pour votre gestion de projet agile avec [[Scrum]] :&lt;br /&gt;
* http://www.acunote.com/&lt;br /&gt;
* http://backlogtool.com/&lt;br /&gt;
* http://www.scrumdo.com/&lt;br /&gt;
&lt;br /&gt;
L&#039;activation se fait via &#039;&#039;Settings &amp;gt; Webhooks &amp;amp; Services &amp;gt; Configure services&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Séance 4: AOP &amp;amp; AspectJ=&lt;br /&gt;
&lt;br /&gt;
Dans votre dépôt Git, projet &#039;&#039;cron4j-mvn&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
# Ajoutez le [http://mojo.codehaus.org/aspectj-maven-plugin/ plugin Maven pour AspectJ] au pom.xml&lt;br /&gt;
# Ajoutez un aspect de trace à l&#039;invocation des méthodes &#039;&#039;&#039;run()&#039;&#039;&#039; de l&#039;interface java.lang.Runnable (uniquement pour les objets &#039;&#039;schedulé&#039;&#039;s)&lt;br /&gt;
#: Affichez une trace avant et après l&#039;exécution de la tâche&lt;br /&gt;
# Préparez un nouveau test (nouvelle classe) démarrant un Scheduler Cron4j et validant l&#039;exécution d&#039;une tâche au bout d&#039;une minute (pattern &amp;quot;* * * * *&amp;quot;)&lt;br /&gt;
#: Lors de l&#039;exécution de &#039;&#039;&#039;mvn test&#039;&#039;&#039;, vous devez voir apparaître les traces préparées dans votre aspect.&lt;br /&gt;
&lt;br /&gt;
Liens utiles:&lt;br /&gt;
* [http://ridgetopsolutions.com/blog/2013/02/12/getting-started-with-aspectj-and-maven/ Getting started with AspectJ and Maven]&lt;br /&gt;
&lt;br /&gt;
===Contrôle continu===&lt;br /&gt;
&lt;br /&gt;
# Complétez l&#039;aspect de trace avec le positionnement du [http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html java.lang.ThreadLocal] pour passer 1) l&#039;identifiant du job et 2) le compteur des appels de la méthode de l&#039;objet.&lt;br /&gt;
&lt;br /&gt;
=Séance 5: Pelix &amp;amp; iPOPO=&lt;br /&gt;
&lt;br /&gt;
Pelix est une plate-forme d&#039;application à services (SOA).&lt;br /&gt;
iPOPO est un modèle de composants orientés services (SOCM).&lt;br /&gt;
&lt;br /&gt;
La documentation de Pelix et iPOPO est disponible sur https://ipopo.coderxpress.net/&lt;br /&gt;
&lt;br /&gt;
===Installation de iPOPO===&lt;br /&gt;
&lt;br /&gt;
* Cloner le dépôt Git depuis https://github.com/tcalmant/ipopo&lt;br /&gt;
* Se placer dans la branche &#039;&#039;dev&#039;&#039;&lt;br /&gt;
* Pour installer iPOPO, lancer la commande :&lt;br /&gt;
&lt;br /&gt;
   sudo python setup.py install&lt;br /&gt;
&lt;br /&gt;
===Shell Pelix===&lt;br /&gt;
&lt;br /&gt;
Pour lancer un shell Pelix, utilisez la commande:&lt;br /&gt;
&lt;br /&gt;
   python -m pelix.shell.console&lt;br /&gt;
&lt;br /&gt;
Les commandes disponibles sont décrites ici: [https://ipopo.coderxpress.net/wiki/doku.php?id=ipopo:refcards:shell Shell Commands]&lt;br /&gt;
&lt;br /&gt;
===Rappels de Python===&lt;br /&gt;
&lt;br /&gt;
* Pas de déclaration du type d&#039;une variable&lt;br /&gt;
* Les méthodes d&#039;une classe ont toute comme premier paramètre &#039;&#039;self&#039;&#039;, équivalent du &#039;&#039;this&#039;&#039; en Java.&lt;br /&gt;
* Blocs définis par indentation (4 espaces ou 1 tab)&lt;br /&gt;
* Une ligne finissant par &#039;:&#039; démarre toujours un bloc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Import d&#039;un module&lt;br /&gt;
import pelix&lt;br /&gt;
&lt;br /&gt;
# Définition d&#039;une classe&lt;br /&gt;
class MaClasse:&lt;br /&gt;
   # Constructeur&lt;br /&gt;
   def __init__(self):&lt;br /&gt;
       self.default = &amp;quot;stanger&amp;quot;&lt;br /&gt;
       print(&amp;quot;Classe construite&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
   # Méthode, avec un argument&lt;br /&gt;
   def sayHello(self, name):&lt;br /&gt;
       if not name:&lt;br /&gt;
           # Nom vide ou nul&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(self.default)&lt;br /&gt;
       else:&lt;br /&gt;
           # Nom valide&lt;br /&gt;
           return &amp;quot;Hello, &amp;quot; + str(name)&lt;br /&gt;
&lt;br /&gt;
objet = MaClasse()&lt;br /&gt;
print(objet.sayHello(&amp;quot;&amp;quot;))&lt;br /&gt;
print(objet.sayHello(&amp;quot;World&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Service Ping-Pong===&lt;br /&gt;
&lt;br /&gt;
1. Écrire un fichier &#039;&#039;pong.py&#039;&#039;, définissant une classe &#039;&#039;Pong&#039;&#039; ayant une méthode &#039;&#039;pong&#039;&#039; prenant en paramètre un message et retournant le message préfixé par &amp;quot;PONG:&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Exemple: &lt;br /&gt;
   &lt;br /&gt;
      pong = Pong()&lt;br /&gt;
      pong.pong(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2. Écrire un fichier &#039;&#039;ping.py&#039;&#039;, définissant une classe &#039;&#039;Ping&#039;&#039; ayant une méthode &#039;&#039;ping&#039;&#039; prenant en paramètre un message, créant un objet Pong et retournant le résultat de Pong.pong(message) préfixé par &amp;quot;PING:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&lt;br /&gt;
      ping = Ping()&lt;br /&gt;
      ping.ping(&amp;quot;Hello&amp;quot;) # &amp;lt;-- Retourne &amp;quot;PING:PONG:Hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
3. Transformer le fichier &#039;&#039;pong.py&#039;&#039; pour qu&#039;il devienne un bundle Pelix enregistrant un objet Pong comme étant un service ayant pour spécification &amp;quot;tagl.pong&amp;quot;&lt;br /&gt;
* Définir une classe &#039;&#039;Activator&#039;&#039;, décorée avec &#039;&#039;@BundleActivator&#039;&#039;&lt;br /&gt;
* Enregistrer le service dans la méthode &#039;&#039;Activator.start&#039;&#039; et le désenregistrer dans &#039;&#039;Activator.stop&#039;&#039;&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/provider.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;pong&#039; et vérifier que le service est bien inscrit avec la commande &#039;&#039;sl&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
4.Transformer la classe &#039;&#039;Ping&#039;&#039; dans &#039;&#039;ping.py&#039;&#039; en un composant iPOPO&lt;br /&gt;
* L&#039;objet Pong utilisé dans &#039;&#039;ping()&#039;&#039; doit être un service injecté par iPOPO (&#039;&#039;@Requires&#039;&#039;)&lt;br /&gt;
* Appeler la méthode &#039;&#039;ping()&#039;&#039; dès que le service Pong est injecté (&#039;&#039;@BindField&#039;&#039;) ou disparait (&#039;&#039;@UnbindField&#039;&#039;)&lt;br /&gt;
* S&#039;inspirer du fichier &amp;quot;ipopo/samples/remote/consumer.py&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Dans un shell Pelix, installer et démarrer le bundle &#039;ping&#039; et vérifier son comportement si le bundle &#039;&#039;pong&#039;&#039; ou le bundle &#039;&#039;ping&#039;&#039; est arrêté et redémarré.&lt;br /&gt;
&lt;br /&gt;
5. Mettre à jour le bundle &#039;&#039;pong&#039;&#039;&lt;br /&gt;
* Remplacer le préfixe &amp;quot;PONG&amp;quot; par &amp;quot;NI&amp;quot;&lt;br /&gt;
* Dans le shell Pelix, mettre à jour le bundle &#039;&#039;pong&#039;&#039; sans redémarrer la plate-forme (commande &#039;&#039;udpate&#039;&#039;).&lt;br /&gt;
* Vérifier les traces dans le shell pour valider la mise à jour du service.&lt;br /&gt;
&lt;br /&gt;
===Remote Services===&lt;br /&gt;
&lt;br /&gt;
* Ajouter les propriétés permettant l&#039;export du service Pong dans &#039;&#039;pong.py&#039;&#039; (s&#039;inspirer de &#039;&#039;provider.py&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
* Lancer deux shells iPOPO (dans deux terminaux)&lt;br /&gt;
* Dans chaque shell iPOPO, installer les bundles:&lt;br /&gt;
** &#039;&#039;pelix.remote.dispatcher&#039;&#039;: Exportateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.registry&#039;&#039;; Importateur de services&lt;br /&gt;
** &#039;&#039;pelix.remote.discovery.multicast&#039;&#039;: Découverte de services via Multicast&lt;br /&gt;
** &#039;&#039;pelix.remote.xml_rpc&#039;&#039;: Transport XML-RPC&lt;br /&gt;
** &#039;&#039;pelix.http.basic&#039;&#039;: Serveur HTTP&lt;br /&gt;
&lt;br /&gt;
Attention: il peut être nécessaire de désactiver votre pare-feu pour que les Remote Services fonctionnent&lt;br /&gt;
&lt;br /&gt;
* Instancier les composants depuis le shell iPOPO, dans chaque framework:&lt;br /&gt;
** Serveur HTTP sur le port 8080: &#039;&#039;instantiate pelix.http.service.basic.factory http-server pelix.http.port=8080&#039;&#039; (penser à changer de port dans chaque framework)&lt;br /&gt;
** Multicast Discovery: &#039;&#039;instantiate pelix-remote-discovery-multicast-factory multicast-discovery&#039;&#039;&lt;br /&gt;
** XML-RPC Exporter: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-exporter&#039;&#039;&lt;br /&gt;
** XML-RPC Importer: &#039;&#039;instantiate pelix-xmlrpc-exporter-factory xml-rpc-importer&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Installer le bundle &#039;&#039;ping&#039;&#039; dans un des frameworks et le bundle &#039;&#039;pong&#039;&#039; dans l&#039;autre.&lt;br /&gt;
* Le composant ping peut appeler le service pong, qui est dans l&#039;autre framework.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Voir le code de &#039;&#039;run_remote.py&#039;&#039; pour voir comment démarrer un framework Pelix et installer des bundles depuis Python.&lt;br /&gt;
* Jouer un peu avec &#039;&#039;run_remote.py&#039;&#039; (voir &#039;&#039;run_remote.py --help&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=Séance 6=&lt;br /&gt;
[[Tutorial OSGi avec Apache Felix]]&lt;br /&gt;
&lt;br /&gt;
=Séance 7=&lt;br /&gt;
Faire un projet PDE pour un bundle cron4j.gogo (indépendant de cron4j.bundle)&lt;br /&gt;
&lt;br /&gt;
Utilisation de https://eclipse.org/tycho/&lt;/div&gt;</summary>
		<author><name>MatthieuCaneill</name></author>
	</entry>
</feed>