Planet

16 Novembre 2013 à 10:45

Rendez-vous à Paris ! via Ubuntu Party

L’Ubuntu Party de Paris, c’est ce weekend. Les portes du Carrefour numérique de la Cité des sciences et de l’industrie viennent d’ouvrir, et les nombreux bénévoles sont fin prêts à vous accueillir, jusqu’à 18h ce soir, puis de nouveau ce Dimanche de 11h à 18h.

Vous n’êtes pas à Paris ? Pas de problème. Suivez les conférences et la radio de l’évènement sur http://ubuntu-paris.org/live ! Certains conférenciers seront interviewés avec vos questions, glanées sur les réseaux sociaux.

 

conferences

 

Le programme est riche et, pris par le temps, nous vous décrirons qu’une partie de celui-ci. Retrouvez le programme complet sur http://ubuntu-paris.org/programme.

Conférences

Samedi 12h00 Introduction au chiffrement et GPG

Qu’est-ce que le chiffrement? Que peut-on chiffrer? Pourquoi doit-on chiffrer? Quels sont les arguments en faveurs du chiffrement ? Qu’est ce que PGP? Destinée au grand public, le but de cette conférence est de répondre à ces questions de façon simple, de lancer une réflexion et un débat sur la problématique du chiffrement. Débat et réflexions se poursuivront ensuite lors de l’atelier avancé « Échangez de manière sécurisée(Seahorse et GPG) » et de la Cryptoparty. Conférence par Genma.

Samedi 12h20 Franciliens.net, FAI associatif

La fédération FDN regroupe des Fournisseurs d’Accès à Internet associatifs se reconnaissant dans des valeurs communes : bénévolat, solidarité, fonctionnement démocratique et à but non lucratif; défense et promotion de la neutralité du Net. Franciliens.net fait partie de cette fédération. L’association à fournit à ses membres les outils pour se développer et répondre aux problématiques qui concernent l’activité de fournisseur d’accès à Internet mais aussi quelques services tels que la redondance DNS, les backups de mails, une connexion par VPN… Conférence par les membres de l’association.

Samedi 13h10 Devenir Traducteur

La traduction des logiciels est importante pour aider la diffusion d’un logiciel puisque notre belle planète comporte de nombreuses langues et qu’aucune n’est universellement comprise. Mais techniquement, le processus va plus loin, on parle de localisation. Ce sont ces aspects qui vous seront présentés et qui pourra être suivi par l’atelier « Traduire Ubuntu ». Conférence par Jean-Marc Gailis.

Samedi 14h10 IBus et les méthodes de saisie

Lors de cet exposé, le système de gestion des saisies au clavier iBus et les méthodes de saisie disponibles seront exposées, afin de mettre en évidence la pertinence d’Ubuntu dès qu’il est question d’expression écrite dans une langue autre que le français, et de la personnalisation des méthodes de saisie, entre le choix du clavier et le choix d’encodage, dans l’ensemble des langues qui sont proposées,tandis qu’Ubuntu participe au maintien de langues en déclin, ce qui sera l’objet de la fin de la conférence. Conférence par Minox.

Samedi 14h50 Boinc, calcul distribué pour la recherche

Si l’ensemble des systèmes d’exploitations GNU/Linux est moins vorace que d’autres en ressources matérielles (processeur, mémoire), Ubuntu offre la possibilité d’utiliser à bon escient votre ordinateur quand il est en veille et/ou quand votre utilisation requiert peu de ressources systèmes, en le faisant participer à des calculs qui permettent de faire avancer la recherche fondamentale en sciences exactes et en sciences du vivant, dont la médecine. Conférence par Minox.

Samedi 16h00 Social Engeeniring et journalisme

Social Engeeniring ou quand les journalistes utilisent des techniques de hackers parfois sans le savoir et pourquoi ils devraient développer cette compétence notamment dans le cadre de leur protection et de la protection des sources à l’étranger. Conférence par @Jujusete, journaliste et @Hi_T_cH du collectif Hackerzvoice.

Samedi 17h00 Occupy Public Domain!

La question du domaine public, de sa défense et de sa valorisation, est intéressante car elle oblige à penser et comprendre pourquoi et comment on en est arrivé là (70 ans après la mort de l’auteur avec des tonnes d’exceptions qui compliquent tout) et à aborder par la bande la question du partage sur Internet (en attendant qu’ils virent Hadopi etc. mettons en avant le domaine public). On va tenter de rendre le propos dynamique et original en proposant quelques exemples pertinents d’oeuvres du domaine public qui méritent d’être (re)découvertes.
Véronique, qui est la littéraire du binôme, présentera ces oeuvres et comme elle fait de la musique et joue au théâtre, elle lira quelques courts extrais et éventuellement jouera également (en acoustique) une ou deux chansons.

Dimanche 11h00 Ubuntu Touch

Présenté en début d’année, Ubuntu Touch est un nouveau système d’exploitation mobile qui reste encore mystérieux pour beaucoup. Cette conférence sera donc l’occasion de présenter le projet, ses origines, son fonctionnement et de répondre à vos questions sur le sujet.

Dimanche 11h00 OpenFoodFacts, le wikipedia de l’alimentation

Open Food Facts est un projet collaboratif pour référencer les produits alimentaires de la planète et les informations qui leur sont associées dont les labels (bio, commerce équitable, etc), les ingrédients, les allergènes, les additifs, la composition nutritionnelle, etc… Conférence par Pierre S.

Dimanche 12h00 Devenir Traducteur

La traduction des logiciels est importante pour aider la diffusion d’un logiciel puisque notre belle planète comporte de nombreuses langues et qu’aucune n’est universellement comprise. Mais techniquement, le processus va plus loin, on parle de localisation. Ce sont ces aspects qui vous seront présentés qui pourra être suivi par l’atelier « Traduire Ubuntu ». Conférence par Jean-Marc Gailis.

Dimanche 14h00 Pourquoi Ubuntu-fr ne gagnera pas de Big Brother Awards

Lorsque Canonical, la société qui gère la partie commerciale d’Ubuntu,a décidé d’introduire un outil de recherche susceptible de laisser fuiter des informations sur la vie privée, l’association Ubuntu-fr a décidé de s’y opposer. Elle aurait pu choisir de retirer la fonction en cause. A la place, elle a décidé d’informer et de laisser choisir l’utilisateur d’utiliser cette fonction. C’est grâce à un outil, développé par la communauté internationale d’Ubuntu, qui vous est présenté aujourd’hui. Conférence par Cm-t.

Dimanche 16h00 Contre les grandes oreilles ? Le logiciel libre !

Sujet d’actualité, avec les révélations de Edouard Snowden. Quels enjeux, quelles solutions contre l’écoute généralisée de nos communications ?
Conférence de deux heures, par Benjamin Sonntag.

Cours d’initiation

Samedi et Dimanche 11h30 Ligne de commande

La richesse de la ligne de commande peut effrayer le débutant qui pense que ce sont des milliers de choses à retenir. Ce n’est pas juste. En fait, on apprend les commandes une par une, on utilise celles que l’on a retenu ou noté. Ce cours a pour but de vous faire découvrir à votre rythme les premières bases. Cours par Heraclide et Roberto.

Samedi et Dimanche 12h30 et 15h30 Premier pas dans Ubuntu

On n’utilise pas un nouveau système d’exploitation comme ceux qu’on connaît depuis plusieurs années. Il y a de nouveaux réflexes à acquérir. Nous vous proposons de découvrir les bases pour profiter d’Ubuntu, de son interface Unity et de quelques-uns des outils les plus utilisés comme la Logithèque qui sert à installer des applications. Cours par Quesh/Roberto/Guillaume Lecocq.

Samedi et Dimanche 13h30 Utilisation avancée d’Ubuntu

Pour les utilisateurs ayant déjà une certaine maîtrise d’Ubuntu, nous allons approfondir divers aspects, comme sa personnalisation ou l’utilisation des Lens et Scopes pour la recherche. Cours par Winaël.

Samedi et Dimanche 14h30 Traduire Ubuntu

Car il est plus facile d’utiliser Ubuntu dans notre propre langue,nous avons besoin de traducteur. Ce cours vous apprendra les procédures pour le faire. Ce n’est pas technique, mais seulement comprendre l’organisation des équipes de traduction et de relectures qui forment un tout appelé localisation. Et une découverte des outils utilisés pour cela. Cours par Jean-Marc Gailis.

Samedi 16h30 LibreOffice, suite bureautique

Ecrire du texte, c’est bien, le corriger et le mettre en forme, c’est mieux. Merci Writer. Ce simplifier la vie grâce aux feuilles de calcul, c’est possible avec le tableur Calc. Faire une présentation comme vous les voyez dans les conférences de cet Ubuntu Party, c’est facile avec Impress. Ce sont une partie des outils composant LibreOffice. Cours par Sophie Gauthier.

Dimanche 16h30 Wikipedia, l’encyclopédie participative

Wikipedia est une encyclopédie qui est enrichi par des milliers de contributeurs à travers le monde. Ce cours va vous apprendre à créer votre compte et comment apporter votre première pierre à cet édifice. Il est très facile de partager vos connaissances au bénéfice de toute l’humanité. Alors n’hésitez pas à rejoindre cette communauté. Cours par Manuel Fauveau.

Ateliers avancés

De nombreux ateliers ouverts, dans la limite des places disponibles, tourneront autour des problématiques de vie privée, avec la mise en pratique de solutions permettant de reprendre le contrôle de ses propres données, grâce au chiffrement et à la décentralisation, notamment. Auto-hébergement de vos mails, anonymisation, chiffrement de vos communications, mais aussi comment bien partager ses données. On ne s’y ennuiera pas !

 

Démonstrations

De nombreux outils, jeux, techniques, feront l’objet de démonstration tout au long de ces deux journées. Vous prendrez ainsi conscience de l’immense potentiel des logiciels libres ;)

 

Entraide / Install-party

Au cœur de l’évènement, un très large espace dédié à l’installation d’Ubuntu sur les ordinateurs des visiteurs, et une entraide sur l’utilisation d’Ubuntu et des logiciels libres en général. Cette activité-ci se déroule à plus petite échelle le premier samedi de chaque mois, dans le même lieu.

 

L’Ubuntu Party est ouvert à tous, de 11h à 18h, au Carrefour numérique de la Cité des sciences et de l’industrie, à Paris. Voir le plan d’accès.

La communauté francophone d’Ubuntu, du haut de ses neuf ans, est bien motivée à continuer de promouvoir Ubuntu et les logiciels libres auprès du grand public !

À Paris, c’est une centaine de bénévoles qui organiseront ce weekend (16 et 17 novembre) le plus grand événement de promotion du Libre de la région. Dans un grand espace dédié au numérique, au sous-sol de la Cité des sciences et de l’industrie, la dix-septième ubuntu party parisienne proposera 25 conférences petites et grandes, 12 cours d’initiation, 28 démonstrations, un micro village associatif, un espace jeunesse, et, bien sûr, une install party où les visiteurs seront accompagnés dans leur passage de Windows/mac à Ubuntu.

À Toulouse, Le Capitole du Libre co-organisé avec Toulibre ces 23 et 24 novembre, accueillera comme toujours une Ubuntu Party aux cotés de nombreuses conférences pour découvrir et comprendre le monde du Logiciel Libre, comprendre ce qu’est l’OpenData, la culture libre et les biens communs. Une LAN Party pour découvrir les jeux libres y est même organisée ! Consultez le programme.

À Sarrebourg, « La journée du Libre » est le nom donné à l’Ubuntu Party qui se tiendra le samedi 23 novembre, organisée par la communauté Ubuntu Sarrebourg. Là aussi, une install party pour le grand public, accompagnée de conférences sur Blender, Gimp, les différents environnements de bureau, OpenStreetMap. Particularité de cet Ubuntu Party, la « bourse informatique » pour redonner vie aux PC à bout de souffle.

Venez et faites venir vos amis aux Ubuntu Party et faites-en la promotion sur les réseaux sociaux ! (@ubuntuparty et +ubuntu-fr)

Premiers pas avec Ubuntu 13.10 - CouvertureLes traductions sont au cœur de la philosophie Ubuntu :

  • chacun doit avoir la liberté de télécharger, exécuter, copier, distribuer, étudier, partager, modifier et améliorer le logiciel ;
  • chacun doit avoir l’opportunité d’utiliser le logiciel, même en cas de handicap ;
  • chacun doit avoir le droit d’utiliser le logiciel dans la langue de son choix.

C’est pour cela qu’aujourd'hui nous sommes heureux et fiers de vous annoncer la sortie de la version française du célèbre Manuel Ubuntu pour Ubuntu 13.10. Le manuel vous fournit de manière claire et structurée tout ce dont vous avez besoin pour débuter puis progresser avec Ubuntu. Le Manuel Ubuntu est aussi la garantie d’instructions pas à pas qui marchent, testées et intégralement en français, sans barbarismes ni mots incompréhensibles.

Pour résumer les avantages du manuel :

  • facile à appréhender – notre manuel comprend des instructions pas à pas et est dénué de jargon technique ;
  • une illustration vaut bien mieux qu’une longue description – beaucoup de captures d’écran illustrent les instructions ;
  • tout au même endroit – vous n’avez pas à parcourir le Web pour trouver de l’aide car tout se trouve dans un seul fichier ;
  • apprentissage progressif – démarrez avec les bases et apprenez au travers des différents chapitres ;
  • des dizaines de langues – traduit en plus de 52 langues, y compris des copies d’écran localisés ;
  • sous licence CC-BY-SA – téléc hargez, modifiez, reproduisez et partagez autant que vous voulez ;
  • aucun coût – nos documents sont tous rédigés par des membres de la communauté Ubuntu et leur utilisation est gratuite ;
  • imprimable – cette version est optimisée pour l’impression afin de sauver les arbres ;
  • section de diagnostic des problèmes – pour vous aider à régler rapidement les problèmes courants sous Ubuntu.

 

Télécharger le Manuel

Télécharger le manuel (13.10)

Liens directs : Ecran - Impression


Commander une version papier (13.10) sur CreateSpace (4,69 $ + frais de port)

Commander une version papier sur amazon.fr (13.10) (bientôt disponible, frais de port inclus)

Contribuer à la traduction d’Ubuntu et de sa documentation

 

 

Image: 

Fork me on GitHub

 

J'ai parlé récemment d'un script qui permet de poster automatiquement un tweet quand je publie un nouvel article sur le blog.

Ce script a été un peu modifié puisqu'il fait aujourd'hui 4 choses :

  1. Il vérifie si un nouvel article a été écrit (en cherchant la présence du message [POST] au début du message de commit Git) ;
  2. Dans ce cas, il envoie les nouveaux commits sur le dépôt Git défini par défaut ;
  3. Il met à jour le blog sur le serveur via SSH (commande make ssh_upload pour les Pelican-eux) ;
  4. Il envoie un tweet.

Tout ça c'est sympa, mais c'est un peu con d'automatiser toutes ces étapes si il faut au final lancer le script à la main. La magie de Git fait qu'on peut automatiser tout ça en utilisant les hooks de Git.

Ces hooks sont des scripts que Git lance après (ou avant) certaines étapes de son processus. Ils sont listés dans le répertoire .git/hooks/ :

╭────<quack@spiderman >───< ~/Documents/writing/blog/quack1_pelican > ‹master*› ╰───[18:52:40] $ ls .git/hooks applypatch-msg.sample post-commit pre-applypatch.sample prepare-commit-msg.sample update.sample commit-msg.sample post-update.sample pre-commit.sample pre-rebase.sample

Je ne vais pas tous les faire, les noms sont assez explicites, mais par exemple pre-commit est lancé avant le commit.

Mon script a besoin que le commit soit terminé, donc j'ai fait pointer le fichier .git/hooks/post-commit sur le script. Toute la configuration nécessaire est placée dans le fichier de conf, donc le script se lance sans souci :

╭────<quack@spiderman >───< ~/Documents/writing/blog/quack1_pelican > ‹master*› ╰───[18:53:14] $ ln -s ~/work/workspace/python/pelican_auto_tweet/pelican_auto_tweet.py .git/hooks/post-commit

Désormais dès que vous ferez un commit dans ce dépôt Git, le script se lancera et si toutes les conditions sont réunies, votre blog se mettra à jour, et un tweet sera posté !

 

Le dépôt GitHub du projet est à jour, et possède déjà quelques issues que j'avais trouvé sur les scripts et que je dois corriger. Si vous utilisez les scripts, et que vous trouvez des bugs, n'hésitez pas à me les remonter, je corrigerais ça rapidement !

 

J'ai parlé récemment d'un script qui permet de poster automatiquement un tweet quand je publie un nouvel article sur le blog.

Ce script a été un peu modifié puisqu'il fait aujourd'hui 4 choses :

  1. Il vérifie si un nouvel article a été écrit (en cherchant la présence du message [POST] au début du message de commit Git) ;
  2. Dans ce cas, il envoie les nouveaux commits sur le dépôt Git défini par défaut ;
  3. Il met à jour le blog sur le serveur via SSH (command make ssh_upload pour les Pelican-eux) ;
  4. Il envoie un tweet.

Tout ça c'est sympa, mais c'est un peu con d'automatiser toutes ces étapes si il faut au final lancer le script à la main. La magie de Git fait qu'on peut automatiser tout ça en utilisant les hooks de Git.

Ces hooks sont des scripts que Git lance après (ou avant) certaines étapes de son processus. Ils sont listés dans le répertoire .git/hooks/ :

╭────<quack@spiderman >───< ~/Documents/writing/blog/quack1_pelican > ‹master*› ╰───[18:52:40] $ ls .git/hooks applypatch-msg.sample post-commit pre-applypatch.sample prepare-commit-msg.sample update.sample commit-msg.sample post-update.sample pre-commit.sample pre-rebase.sample

Je ne vais pas tous les faire, les noms sont assez explicites, mais par exemple pre-commit est lancé avant le commit.

Mon script a besoin que le commit soit terminé, donc j'ai fait pointer le fichier .git/hooks/post-commit sur le script. Toute la configuration nécéssaire est placée dans le fichier de conf, donc le script se lance sans souci :

╭────<quack@spiderman >───< ~/Documents/writing/blog/quack1_pelican > ‹master*› ╰───[18:53:14] $ ln -s ~/work/workspace/python/pelican_auto_tweet/pelican_auto_tweet.py .git/hooks/post-commit

Désormais dès que vous ferez un commit dans ce dépôt Git, le script se lancera et si toutes les conditions sont réunies, votre blog se mettra à jour, et un tweet sera posté !

 

Le dépôt GitHub du projet est à jour, et possède déjà quelques issues que j'avais trouvé sur les scripts et que je dois corriger. Si vous utilisez les scripts, et que vous trouvez des bugs, n'hésitez pas à me les remonter, je corrigerais ça rapidement !

2561885967_f5f0be5834_n.jpgMe voila avec un index flambant neuf ( ou presque) importé en presque 30 minutes. Je n’ai plus qu’à rechercher. Voici ce qu’on peut faire assez simplement "out of the box":

Via l’interface d’administration

L’interface d’administration possède déjà un outil de recherche assez simple d’utilisation. On renseigne le critère de recherche et on obtient la réponse au format souhaité ( JSON, XML, PYTHON, CSV,…)

backup_sonar036.png

Cette option peut être intéressante pour une interface d’administration

Via une requête REST

J’ai fait un simple appel REST avec JERSEY pour effectuer la même requête. J’ai utilisé le mapping des POJO pour mapper la réponse à mon bean.

On retrouve les mêmes paramètres

  1. public class RESTQueryTest {
  2.  
  3. private final static String QUERY_URL = "http://127.0.0.1:8080/customers/customers/select";
  4. public static final int HTTP_STATUS_OK = 200;
  5. private Client client;
  6. private WebResource queryWebResource;
  7. private ClientConfig clientConfig;
  8. private String MAX_ROWS;
  9.  
  10. @Before
  11. public void setUp() throws Exception {
  12. clientConfig = new DefaultClientConfig();
  13. clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
  14. client = Client.create(clientConfig);
  15. queryWebResource = client.resource(QUERY_URL);
  16. }
  17.  
  18. @Test
  19. public void testQueryByLastName() throws Exception {
  20. MultivaluedMap<String, String> parameters = new MultivaluedMapImpl();
  21. parameters.add("q", "lastname:JAN");
  22. parameters.add("wt", "json");
  23.  
  24. ClientResponse response = queryWebResource.queryParams(parameters).type(MediaType.TEXT_PLAIN_TYPE).
  25. accept(MediaType.APPLICATION_JSON_TYPE, MediaType.TEXT_PLAIN_TYPE).get(ClientResponse.class);
  26. assertEquals(response.getStatus(), HTTP_STATUS_OK);
  27. }
  28.  
  29. @Test
  30. public void testQueryFuzzy() throws Exception {
  31. MultivaluedMap<String, String> parameters = new MultivaluedMapImpl();
  32. final String FUZZY_QUERY_BY_LASTNAME = "lastname:JAN~";
  33. parameters.add("q", FUZZY_QUERY_BY_LASTNAME);
  34. parameters.add("wt", "json");
  35. parameters.add("indent", "true");
  36. final int MAX_ROWS = 20;
  37. parameters.add("rows", String.valueOf(MAX_ROWS));
  38.  
  39. ClientResponse response = queryWebResource.queryParams(parameters).type(MediaType.APPLICATION_JSON_TYPE).
  40. accept(MediaType.APPLICATION_JSON_TYPE, MediaType.TEXT_PLAIN_TYPE).get(ClientResponse.class);
  41. assertEquals(response.getStatus(), HTTP_STATUS_OK);
  42. SOLRResponse<CustomerResource> solrResponse=response.getEntity(new GenericType<SOLRResponse<CustomerResource>>(){});
  43. assertNotNull(solrResponse);
  44. assertEquals(solrResponse.getResponse().getDocs().size(), MAX_ROWS);
  45. assertEquals(solrResponse.getResponseHeader().getParams().getQuery(),FUZZY_QUERY_BY_LASTNAME);
  46. }
  47. }

La classe SOLRResponse décrit la réponse JSON, Elle est annotée avec JAXB.

  1. @XmlRootElement
  2. public class SOLRResponse<T> {
  3.  
  4. private SOLRResponseHeader responseHeader ;
  5. private SOLRResponseBody<T> response;
  6.  
  7. public SOLRResponseBody<T> getResponse() {
  8. return response;
  9. }
  10.  
  11. public void setResponse(SOLRResponseBody<T> response) {
  12. this.response = response;
  13. }
  14.  
  15. public SOLRResponseHeader getResponseHeader() {
  16. return responseHeader;
  17. }
  18.  
  19. public void setResponseHeader(SOLRResponseHeader responseHeader) {
  20. this.responseHeader = responseHeader;
  21. }
  22.  
  23.  
  24. }

J’ai rendu cette réponse générique pour ensuite appliquer ce que l’on veut dans les documents (ex. Classe CustomerResource)

Via l’API SOLRJ

Pré-requis

Ajouter la dépendance solr au projet

  1. <dependency>
  2. <groupId>org.apache.solr</groupId>
  3. <artifactId>solr-solrj</artifactId>
  4. <version>${solr.version}</version>
  5. </dependency>

Je trouve cette solution beaucoup plus simple à mettre en oeuvre. Elle prend dynamiquement les champs de la réponse ( qui peuvent changer selon les paramètres d’appels ). De plus il n’y a pas besoin de décrire l’enveloppe de la réponse comme en REST.

  1. public class JavaQueryTest {
  2.  
  3. private final static String QUERY_URL = "http://127.0.0.1:8080/customers/customers";
  4. private HttpSolrServer solrServer;
  5. private SolrQuery solrQuery;
  6.  
  7. @Before
  8. public void setUp() throws Exception {
  9. solrServer = new HttpSolrServer(QUERY_URL);
  10. solrServer.setAllowCompression(true);
  11. solrServer.setMaxRetries(5);
  12. solrQuery = new SolrQuery();
  13. }
  14.  
  15. @Test
  16. public void testQueryFuzzy() throws Exception {
  17. solrQuery.setQuery("TOURET~");
  18. solrQuery.addSort("dtcrea", SolrQuery.ORDER.asc);
  19. QueryResponse response = solrServer.query(solrQuery);
  20. assertNotNull(response);
  21. assertNotNull(response.getResults());
  22. assertFalse(response.getResults().isEmpty());
  23. System.out.println("Premier champ:" + response.getResults().get(1).toString());
  24. List<CustomerResource> customers = response.getBeans(CustomerResource.class);
  25. assertNotNull(customers);
  26. assertFalse(customers.isEmpty());
  27. }
  28. }

Depuis un bon moment déjà j'écris tout en Markdown. Ce blog — et l'autre —, mes notes (avec RedNotebook entre autres), et encore plein d'autres choses de cette façon. Seul le boulot et sa suite Office me résistent encore 😋 !

Pour écrire tout ça j'utilise Sublime Text, qui est un excellent éditeur de texte. Véritable IDE, il est à la base dédié à l'édition de code source.

Du coup, quand on veut écrire du texte dedans, c'est pas super agréable...

L'avantage de Sublime-Text, c'est que chaque utilisateur peut redéfinir des préférences, qui surchargent celles par défaut. Et cerise sur le gâteau, on peut redéfinir des préférences pour chaque extension de fichiers! Et c'est justement cette fonctionnalité qui m'intéresse.

Maintenant, quand j'écris du Markdown, ça ressemble à ça :

Pour modifier la configuration de Sublime Text, ouvrez un fichier Markdown (chez moi avec l'extension .md), et allez dans PréférencesSettings - MoreSyntax Specific - User.

Mon fichier de configuration ressemble à ça :

{ "extensions": [ "md" ], "auto_complete": true, "spell_check": true, "dictionary": "Packages/Language - French - Français/fr_FR (all variants).dic", "draw_centered": true, "word_wrap": "True", "wrap_width": 80, "font_size": 9, "gutter": false, "line_numbers": false, "line_padding_bottom": 2, "line_padding_top": 2, "scroll_past_end": true, "tab_size": 6 }

Ligne par ligne, qu'est ce que ça fait :

  • "extensions" désigne les extensions pour lesquelles ce fichier s'applique ;
  • "auto_complete" active la complétion automatique avec <TAB> ;
  • "spell_check" active la vérification orthographique ;
  • "dictionary" pointe sur le dictionnaire à utiliser pour la vérification orthographique (les dictionnaires proviennent de Libre Office) ;
  • "draw_centered" centre le texte dans la fenêtre ;
  • "word_wrap" coupe les lignes lors de l'affichage après X caractères ;
  • "wrap_width" désigne le nombre de caractères avant de couper la ligne ;
  • "font_size" défini la taille de la police de caractères ;
  • "gutter" je ne sais pas ce que ça fait, mais c'est défini à false dans le mode Distraction Free, donc je pense que ce n'est pas mauvais... ;
  • "line_numbers" désactive l'affichage du nombre de lignes, mais je songe à le réactiver... ;
  • "line_padding_bottom"et "line_padding_top" ajoutent de l'espacement au-dessous et au-dessus des lignes de texte, pour l'aérer ;
  • "scroll_past_end" permet de faire défiler le texte même quand on arrive à la fin du fichier ;
  • "tab_size" augmente le nombre d'espaces à utiliser pour les tabulations (en réalité Sublime Text utilise bien le caractère <TAB>, mais cette tabulation est affichée pour quelle corresponde à 6 espaces).

Plus d'options sont disponibles dans la doc de Sublime Text. Je ne pense pas avoir pensé à tout, si vous trouvez comment améliorer encore cette configuration, n'hésitez pas!

Depuis un bon moment déjà j'écris tout en Markdown. Ce blog — et l'autre —, mes notes (avec RedNotebook entre autres), et encore plein d'autres choses de cette façon. Seul le boulot et sa suite Office me résistent encore 😋 !

Pour écrire tout ça j'utilise Sublime Text, qui est un excellent éditeur de texte. Véritable IDE, il est à la base dédié à l'édition de code source.

Du coup, quand on veut écrire du texte dedans, c'est pas super agréable...

L'avantage de Sublime-Text, c'est que chaque utilisateur peut redéfinir des préférences, qui surchargent celles par défaut. Et cerise sur le gâteau, on peut redéfinir des préférences pour chaque extension de fichiers! Et c'est justement cette fonctionnalité qui m'intéresse.

Maintenant, quand j'écris du Markdown, ça ressemble à ça :

Pour modifier la configuration de Sublime Text, ouvrez un fichier Markdown (chez moi avec l'extension .md), et allez dans PréférencesSettings - MoreSyntax Specific - User.

Mon fichier de configuration ressemble à ça :

{ "extensions": [ "md" ], "auto_complete": true, "spell_check": true, "dictionary": "Packages/Language - French - Français/fr_FR (all variants).dic", "draw_centered": true, "word_wrap": "True", "wrap_width": 80, "font_size": 9, "gutter": false, "line_numbers": false, "line_padding_bottom": 2, "line_padding_top": 2, "scroll_past_end": true, "tab_size": 6 }

Ligne par ligne, qu'est ce que ça fait :

  • "extensions" désigne les extensions pour lesquelles ce fichier s'applique ;
  • "auto_complete" active la complétion automatique avec <TAB> ;
  • "spell_check" active la vérification orthographique ;
  • "dictionary" pointe sur le dictionnaire à utiliser pour la vérification orthographique (les dictionnaires proviennent de Libre Office) ;
  • "draw_centered" centre le texte dans la fenêtre ;
  • "word_wrap" coupe les lignes lors de l'affichage après X caractères ;
  • "wrap_width" désigne le nombre de caractères avant de couper la ligne ;
  • "font_size" défini la taille de la police de caractères ;
  • "gutter" je ne sais pas ce que ça fait, mais c'est défini à false dans le mode Distraction Free, donc je pense que ce n'est pas mauvais... ;
  • "line_numbers" désactive l'affichage du nombre de lignes, mais je songe à le réactiver... ;
  • "line_padding_bottom"et "line_padding_top" ajoutent de l'espacement au-dessous et au-dessus des lignes de texte, pour l'aérer ;
  • "scroll_past_end" permet de faire défiler le texte même quand on arrive à la fin du fichier ;
  • "tab_size" augmente le nombre d'espaces à utiliser pour les tabulations (en réalité Sublime Text utilise bien le caractère <TAB>, mais cette tabulation est affichée pour quelle corresponde à 6 espaces).

Plus d'options sont disponibles dans la doc de Sublime Text. Je ne pense pas avoir pensé à tout, si vous trouvez comment améliorer encore cette configuration, n'hésitez pas!

29 Octobre 2013 à 09:18

Import des données dans un index SOLR via Littlewing

3650487959_d5cac67af6_n.jpg[1]

Comme j’ai pu l’indiquer dans mon précédent billet, je me suis mis en tête d’indexer les données issues d’une base clients. J’ai lancé un simple import . Voici le résultat :

backup_sonar035.png

J’ai donc indexé 19288644 clients en 35 minutes .

Si on regarde du coté de l’espace disque, on obtient la taille suivante :

  1. $ du -h
  2. 592M ./data/index
  3. 3,3M ./data/tlog
  4. 595M ./data
  5. 596M .

Les temps d’exécution des requêtes sont déjà très satisfaisants sans aucune optimisation.

Note

[1] Photo sous licence creative commons

28 Octobre 2013 à 16:23

Premiers pas avec SOLR via Littlewing

Après avoir pas mal touché à Apache Lucene il y a quelques années ce ça ( je vous par le d’un temps que les moins de vingt ans ne peuvent pas connaître…), j’ai décidé de me pencher sur les moteurs de recherche opensource. J’ai donc décidé de me pencher sur SOLR et ElasticSearch. Ces deux projets sont basés sur lucene.

Le cas d’utilisation que je souhaite mettre en œuvre est assez simple pour l’instant : indexer le résultat d’une requête faite dans un SGBD. Celle ci prend énormément de temps ( environ 30 secondes ) et je souhaite avoir un résultat immédiat le tout en REST.

Le cas elasticsearch

J’ai tout d’abord essayé elasticsearch. Ce dernier est le projet qui a le vent en poupe et présente de nombreux sous-projets très intéressants ( logstash, kibana). Le seul moyen d’extraire les données d’un SGBD est le jdbc-river. Ce moyen ne m’a pas trop séduit , il y a pas mal de problèmes liés à la saisie d’une requête complexe. Aussi j’en ai discuté brièvement avec David Pilato ( qui a fait une super présentation sur Kibana) lors du JugSummerCamp . Il m’a confirmé l’extension du scope du projet logstash aux autres sources de données (ex. JDBC). Cette mutation devrait être effective mi 2014. Bref, en attendant j’ai exploré SOLR.

Présentation de SOLR

SOLR est donc un moteur de recherche ( ça vous l’aviez deviné) qui s’appuie sur Apache Lucene ( ça aussi …) . Il présente des fonctionnalités semblables à ElasticSearch. A ce que j’ai pu lire sur le net ici ou , ce dernier est supérieur sur la gestion des recherches distribuées. Je n’aurais pas besoin de cette fonctionnalité dans un premier temps. Les fonctionnalités qui m’intéressent sont les suivantes :

  • Les API JAVA et REST
  • Le facets
  • La mise en avant de certaines recherches
  • Les requêtes geo spatiales
  • La réplication des données

Configuration

Pour mon projet, je me suis basé sur un archetype maven disponible sur le net. Ce dernier crée un exemple de projet qui lance un jetty avec le war de solr

Vous devez également disposer de la distribution de SOLR pour que le livrable soit déployé. C’est la seule solution que j’ai trouvé pour l’instant. Ce n’est pas très élégant, car je préférerai avoir le tout embarqué dans la webapp.

Mon projet s’appelle customer-indexer . Il indexe les données d’une base de clients. Dans le répertoire src/main/resources, j’ai crée un répertoire customers. J’ai copié le contenu du répertoire collection1 présent dans les exemples de la distribution.

J’exposerai ici la configuration indispensable pour mon cas d’étude

le fichier solr.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <solr persistent="true">
  3. <cores adminPath="/admin/cores" defaultCoreName="refper" host="${host:}" hostPort="${jetty.port:}" hostContext="${hostContext:}" zkClientTimeout="${zkClientTimeout:15000}">
  4. <core name="customers" instanceDir="." />
  5. </cores>
  6. </solr>

Dans le répertoire src/main/resources/customers/conf, il faut ajouter a minima les fichiers solrconfig.xml schema.xml et data-config.xml.

solrconfig.xml

Les deux premiers sont déjà présents J’ai modifié le premier avec les informations suivantes :

j’ai mis le chemin en dur de la distribution et non le relatif

  1. <lib dir="c:/java/solr-4.5.0/contrib/extraction/lib" regex=".*\.jar" />
  2. <lib dir="c:/java/solr-4.5.0/dist/" regex="solr-cell-\d.*\.jar" />
  3.  
  4. <lib dir="c:/java/solr-4.5.0/contrib/clustering/lib/" regex=".*\.jar" />
  5. <lib dir="c:/java/solr-4.5.0/dist/" regex="solr-clustering-\d.*\.jar" />
  6. <lib dir="c:/java/solr-4.5.0/dist/" regex="solr-dataimporthandler-\d.*\.jar" />
  7.  
  8. <lib dir="c:/java/solr-4.5.0/contrib/langid/lib/" regex=".*\.jar" />
  9. <lib dir="c:/java/solr-4.5.0/dist/" regex="solr-langid-\d.*\.jar" />
  10.  
  11. <lib dir="c:/java/solr-4.5.0/contrib/velocity/lib" regex=".*\.jar" />
  12. <lib dir="c:/java/solr-4.5.0/dist/" regex="solr-velocity-\d.*\.jar" />

La configuration de l’élément elevator semblait erronée

  1. <searchComponent name="elevator" class="solr.QueryElevationComponent" >
  2. <!-- pick a fieldType to analyze queries -->
  3. <str name="queryFieldType">string</str>
  4. <str name="config-file">elevate.xml</str>
  5. </searchComponent>

J’ai rajouté également le module d’import des données

  1. <requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
  2. <lst name="defaults">
  3. <str name="config">data-config.xml</str>
  4. </lst>
  5. </requestHandler>

schema.xml

Ce fichier décrit la structure des documents présents dans l’index du moteur de recherche. On définit les données à indexer, les types de données et les filtres à appliquer (exemple: tout passer en minuscule)

  1. <schema name="customers" version="1.5">
  2. <fields>
  3.  
  4. <field name="idpp" type="string" indexed="true" stored="true" required="true" multiValued="false"/>
  5.  
  6. <!-- points to the root document of a block of nested documents -->
  7. <field name="_root_" type="string" indexed="true" stored="false"/>
  8.  
  9.  
  10. <field name="dtcrea" type="date" indexed="true" stored="true" omitNorms="true"/>
  11. <field name="dtlastupd" type="date" indexed="true" stored="true"/>
  12. <field name="title" type="lowercase" indexed="true" stored="true" omitNorms="true"/>
  13. <field name="lastname" type="lowercase" indexed="true" stored="true" multiValued="true"/>
  14. <field name="fstname" type="lowercase" indexed="true" stored="true" multiValued="true"/>
  15. <field name="dtbirth" type="date" indexed="true" stored="true" termVectors="true" termPositions="true"
  16. termOffsets="true"/>
  17. <field name="status" type="float" indexed="true" stored="true"/>
  18. <field name="content" type="text_general" indexed="false" stored="true" multiValued="true"/>
  19.  
  20. <!-- catchall field, containing all other searchable text fields (implemented
  21. via copyField further on in this schema -->
  22. <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
  23.  
  24. <!-- catchall text field that indexes tokens both normally and in reverse for efficient
  25. leading wildcard queries. -->
  26. <field name="text_rev" type="text_general_rev" indexed="true" stored="false" multiValued="true"/>
  27. <field name="_version_" type="long" indexed="true" stored="true"/>
  28.  
  29.  
  30. </fields>
  31. <uniqueKey>idpp</uniqueKey>
  32.  
  33. <!-- les copies permettent d'avoir tout le contenu dans un seul champ-->
  34. <copyField source="title" dest="text"/>
  35. <copyField source="lastname" dest="text"/>
  36. <copyField source="firstname" dest="text"/>
  37. <copyField source="birthday" dest="text"/>
  38. </schema>

data-config.xml

Dans ce fichier on spécifie les données récupérées de la base de données

  1. <dataConfig>
  2. <dataSource driver="oracle.jdbc.OracleDriver" url="urljdbc" user="user" password="pwd"/>
  3. <document name="customer">
  4. <entity name="customer" query="Marequete">
  5. <field column="id" name="id" />
  6. <field column="LASTNAME" name="lastname" />
  7. <field column="FIRSTNAME" name="firstname" />
  8. <field column="DTCREATION" name="dtcreation" />
  9. <field column="DTLASTUPDATE" name="dtlastupdate" />
  10. <field column="BIRTHDAY" name="birthday" />
  11. <field column="STATUS" name="status" />
  12. </entity>
  13. </document>
  14. </dataConfig>

Configuration maven

voici le contenu du pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6.  
  7. <groupId>customer-indexer</groupId>
  8. <artifactId>customer-indexer</artifactId>
  9. <version>1.0-SNAPSHOT</version>
  10. <packaging>war</packaging>
  11.  
  12. <properties>
  13. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  14. <slf4j-api.version>1.7.5</slf4j-api.version>
  15. <log4j.version>1.2.17</log4j.version>
  16. <solr.version>4.5.0</solr.version>
  17. <solr.default.core.directory>customers</solr.default.core.directory>
  18. <solr.default.core.name>customers</solr.default.core.name>
  19. <solr.solr.home>c:/java/solr-4.5.0/</solr.solr.home>
  20. </properties>
  21.  
  22. <dependencies>
  23. <!-- SLF4J -->
  24. <dependency>
  25. <groupId>org.slf4j</groupId>
  26. <artifactId>slf4j-api</artifactId>
  27. <version>${slf4j-api.version}</version>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.slf4j</groupId>
  31. <artifactId>jcl-over-slf4j</artifactId>
  32. <version>${slf4j-api.version}</version>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.slf4j</groupId>
  36. <artifactId>jul-to-slf4j</artifactId>
  37. <version>${slf4j-api.version}</version>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.slf4j</groupId>
  41. <artifactId>slf4j-log4j12</artifactId>
  42. <version>${slf4j-api.version}</version>
  43. </dependency>
  44. <!-- Log4j -->
  45. <dependency>
  46. <groupId>log4j</groupId>
  47. <artifactId>log4j</artifactId>
  48. <version>${log4j.version}</version>
  49. </dependency>
  50.  
  51. <dependency>
  52. <groupId>com.oracle.ojdbc</groupId>
  53. <artifactId>ojdbc</artifactId>
  54. <version>10.2.0.2.0</version>
  55.  
  56. </dependency>
  57. <!-- Solr 4.3.0 -->
  58. <dependency>
  59. <groupId>org.apache.solr</groupId>
  60. <artifactId>solr</artifactId>
  61. <version>${solr.version}</version>
  62. <type>war</type>
  63. </dependency>
  64. </dependencies>
  65.  
  66. <build>
  67. <finalName>customers</finalName>
  68. <resources>
  69. <resource>
  70. <filtering>true</filtering>
  71. <directory>src/main/resources</directory>
  72. </resource>
  73. </resources>
  74. <plugins>
  75. <plugin>
  76. <artifactId>maven-antrun-plugin</artifactId>
  77. <version>1.7</version>
  78. <executions>
  79. <execution>
  80. <id>copy-to-solr</id>
  81. <goals>
  82. <goal>run</goal>
  83. </goals>
  84. <phase>package</phase>
  85. <configuration>
  86. <target>
  87. <copy todir="${solr.solr.home}" includeemptydirs="true" overwrite="true">
  88. <fileset dir="${project.build.outputDirectory}">
  89. </fileset>
  90. </copy>
  91. </target>
  92. </configuration>
  93. </execution>
  94. </executions>
  95. </plugin>
  96. <plugin>
  97. <groupId>org.eclipse.jetty</groupId>
  98. <artifactId>jetty-maven-plugin</artifactId>
  99. <version>9.0.4.v20130625</version>
  100. <configuration>
  101. <stopPort>9966</stopPort>
  102. <stopKey>stop</stopKey>
  103. <webApp>
  104. <contextPath>/refper</contextPath>
  105. </webApp>
  106. </configuration>
  107. </plugin>
  108. </plugins>
  109. </build>
  110. </project>

Démarrage

Dans mon cas il me suffit de lancer la commande

  1. mvn clean install jetty:run

Import des données

On peut le faire soit par un appel REST, soit par la console : Sélectionner la collection puis cliquer sur Data Import

backup_sonar034.png

Conclusion

Pour l’instant j’ai rapidement fait une première indexation de mes données. je suis conscient qu’il y a pas mal d’améliorations à apporter, notamment sur la modélisation de mon index avec les bonnes entités (ex. une entité customer, une entité address,…)

Je verrai le requêtage dans un autre post.

Pages