samedi 4 juillet 2015

TET102 : cours du CNAM sur le management social


Voici un billet qui sort un peu de l'ordinaire.Dans le cadre des cours du CNAM, j'ai suivi le cours TET102 sur le management social en entreprise.L'objectif de cet article est de vous présenter ce cours pour vous aider à faire votre choix et vous donnez quelques conseils pour réussir l'examen.

Résumé

Durant ce cours, vous allez apprendre à connaître les différentes instances sociales ( CHSCT, Comité d'Entreprise ...) et leurs fonctionnements.Vous verrez comment le rôle du manager et comment il interagit avec celles-ci. 

Déroulement du cours
 
Ce cours est composé de 8 chapitres.A la fin de chaque chapitre, les élèves doivent effectuer des exercices par écrit et les rendre au professeur.Le professeur ouvre alors le chapitre suivant.

Pour suivre ce cours, vous devez également assister à 4 cours en présentielle.Pour ma part, c'était le soir de 18h à 21h au Lycée benjamin Franklin d' Orleans. Durant ces séances, vous effectuerez des exercices pratiques en groupe ( gestion de conflits, conduite de réunion ... ) .

Les différents chapitres


Chap I L'entreprise et son organisation
Chap II L'ingénieur et le management humain
Chap III Les conditions du travail humain
Chap IV La fonction "Ressources Humaines"
Chap V Hygiène et sécurité dans le travail
Chap VI Les relations de travail
Chap VII Évaluation des compétences et besoin en formation
Chap VIII Conduite d'équipes et résolution de conflit

A noter :
  • Les 4 derniers chapitres sont les plus importants en terme de contenus ( 300 à 500 pages )
  • Il y a beaucoup de choses à apprendre.

Les points forts

  • Ce cours présente les différentes instances sociales, leur rôle.Cela donne une bonne vision du fonctionnement social de l'entreprise.J'aurais aimé avoir ce cours avant de commencer en entreprise.
  • Les ateliers lors des point de regroupement permettent de prendre conscience du rôle de manager et apportent des conseils utiles pour son application en entreprise.

L'examen

Voici quelques remarques : 
  • Ne négligez pas le dernier chapitre.
  • Des notes manuscrites étaient autorisées.
  • Vers la fin de la session, le professeur ouvre les annales.

 

En résumé, ce cours exige pas mal de travail. Il apporte des connaissances essentielles sur le fonctionnement des instances sociales en entreprises.Les regroupements en présentielles sont intéressant et vivant ( c'est important le soir après le travail ! ) .

 

vendredi 24 avril 2015

Grails et la création de pdf

Je réalise actuellement une application métier et dans ce cadre, j'ai eu besoin d'afficher des rapports au format pdf. Avant la version de Grails 2.5.0, j'utilisais le plugin export et il fonctionnait très bien.Par contre, avec la version Grails 2.5.0, j'ai eu des erreurs de compilation.J'ai aussi essayé le plugin rendering mais sans succès ( cf http://stackoverflow.com/questions/29694796/null-pointer-exception-with-grails-rendering-plugin ).
Par conséquent, j'ai décidé de le faire moi même avec une librairie :

org.apache.pdfbox

Dans le fichier BuildConfig.groovy, j'ai ajouté la dépendance :

   dependency {  
     ...  
     compile "org.apache.pdfbox:pdfbox:1.8.9"  
     ...  
   }  

Voici le code dans mon controlleur :

 class AppRetailController {  
   ...  
   def renderFormPDF(){  
     List<App> apps = new ArrayList<>()  
     String title = ""  
     String param = params.get("serverSelect")  
     ...  
     Fill the list apps  
     ...  
           title= "Liste de toutes les applications sur " + param  
           title += " (" + apps.size() + ")"  
           // Create all needed for Pdf document  
     PDDocument document = new PDDocument();  
     PDPage page = new PDPage();  
     PDPageContentStream contentStream;  
           // Here I want 30 rows by page  
     int pageNumber = apps.size()/30 + 1  
     log.info("Page number :" + pageNumber)  
     int countApp = 0  
           // for each page I draw table with datas  
     for (int i=1; i<=pageNumber; i++) {  
       log.info("countApp :" + countApp)  
       page = new PDPage();  
       contentStream = new PDPageContentStream(document, page);  
       int max = countApp + 30  
       if (max > apps.size()) {  
         max = apps.size() - 1  
       }  
       drawTable(page, contentStream, 700, 100, apps[countApp..max], title);  
       countApp = countApp + 30 + 1  
       contentStream.close();  
       document.addPage(page);  
     }  
     document.save("report.pdf");  
     document.close();  
     render( file:new File("report.pdf"), fileName: "report.pdf")  
   }  
   /**  
    * @param page  
    * @param contentStream  
    * @param y the y-coordinate of the first row  
    * @param margin the padding on left and right of table  
    * @param content a 2d array containing the table data  
    * @throws IOException  
    */  
   def drawTable(PDPage page, PDPageContentStream contentStream,  
                  float y, float margin,  
                  List<App> apps, String title) throws IOException {  
     final int rows = apps.size() + 1;  
     final int cols = 3;  
     final float rowHeight = 20f;  
     final float tableWidth = page.findMediaBox().getWidth()-(2*margin);  
     final float tableHeight = rowHeight * rows;  
     final float colWidth = tableWidth/(float)cols;  
     final float cellMargin=5f;  
     //draw the rows  
     float nexty = y ;  
     for (int i = 0; i <= rows; i++) {  
       contentStream.drawLine(margin,nexty,(float)(margin+tableWidth),nexty);  
       nexty-= rowHeight;  
     }  
     //draw the columns  
     float nextx = margin;  
     for (int i = 0; i <= cols; i++) {  
       contentStream.drawLine(nextx,y,nextx,(float)(y-tableHeight));  
       nextx += colWidth;  
     }  
     //now add the text  
     contentStream.setFont(PDType1Font.HELVETICA_BOLD,14);  
     contentStream.beginText();  
     contentStream.moveTextPositionByAmount((float)margin+cellMargin+10,(float)(y+20));  
     contentStream.drawString(title);  
     contentStream.endText();  
     contentStream.setFont(PDType1Font.HELVETICA_BOLD,12);  
     float textx = margin+cellMargin;  
     float texty = y-15;  
     //Define colunm title  
     contentStream.beginText();  
     contentStream.moveTextPositionByAmount(textx,texty);  
     contentStream.drawString("Nom");  
     contentStream.endText();  
     textx += colWidth;  
     contentStream.beginText();  
     contentStream.moveTextPositionByAmount(textx,texty);  
     contentStream.drawString("Description");  
     contentStream.endText();  
     textx += colWidth;  
     contentStream.beginText();  
     contentStream.moveTextPositionByAmount(textx,texty);  
     contentStream.drawString("Chemin dans ARENA");  
     contentStream.endText();  
     textx += colWidth;  
     texty-=rowHeight;  
     textx = margin+cellMargin;  
     contentStream.setFont(PDType1Font.HELVETICA,11);  
     apps.each {  
       contentStream.beginText();  
       contentStream.moveTextPositionByAmount(textx,texty);  
       contentStream.drawString(it.name);  
       contentStream.endText();  
       textx += colWidth;  
       contentStream.beginText();  
       contentStream.moveTextPositionByAmount(textx,texty);  
       String desc = it.description  
       if (desc.equals("EMPTY")) {  
         desc = ""  
       }  
       contentStream.drawString(desc);  
       contentStream.endText();  
       textx += colWidth;  
       contentStream.beginText();  
       contentStream.moveTextPositionByAmount(textx,texty);  
       String path = it.arenaPath  
       if (path == null) {  
         path = ""  
       }  
       contentStream.drawString(path);  
       contentStream.endText();  
       textx += colWidth;  
       texty-=rowHeight;  
       textx = margin+cellMargin;  
     }  
   }  
 }  


En conclusion, on peut dire que ce n'est pas la meilleur solution car il faut tout faire à la main et à mon avis il vaut mieux regarder des solutions telles que le plugin rendering.Par contre, ça fait le job et lorsque vous êtes pressé par le temps, cela fonctionne.
Un grand merci à ce blog pour l'utilisation de la librairie : http://fahdshariff.blogspot.fr/2010/10/creating-tables-with-pdfbox.html 

Hope this help,

Voir aussi : http://grails.github.io/grails-doc/2.5.x/ref/Controllers/render.html

mardi 31 mars 2015

Upgrade de Grails 2.4.4 vers la version 2.5.0


Voici un petit retour d'expérience pour ceux qui souhaiteraient mettre à jour leur version de Grails.
Cette mise à jour ne m'a posé aucun problème.Il suffit de bien suivre la Release Version ( https://github.com/grails/grails-core/releases/tag/v2.5.0 )

Pour résumé, j'ai seulement mis à jour les plugins suivants dans le fichier BuildConfig.groovy :
  • build ':tomcat:7.0.55.2'
  • compile ':cache:1.1.8'
  • compile ':scaffolding:2.1.2'
  • compile ':asset-pipeline:2.1.5'

J'ai eu une exception au démarrage de Grails car j'avais oublié de changer la valeur de region.factory_class dans le fichier Datasource.groovy ( cf Release Version ).
Voici l'exception que j'ai eu :

2015-03-31 16:28:39,590 [localhost-startStop-1] ERROR context.GrailsContextLoaderListener  - Error initializing the application: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'transactionManager_lookup' while setting constructor argument with key [1]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager_lookup': Cannot resolve reference to bean 'sessionFactory_lookup' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory_lookup': Invocation of init method failed; nested exception is org.hibernate.cache.CacheException: net.sf.ehcache.CacheException: Another unnamed CacheManager already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following:
1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
2. Shutdown the earlier cacheManager before creating new one with same name.
The source of the existing CacheManager is: DefaultConfigurationSource [ ehcache.xml or ehcache-failsafe.xml ]
...
Et la solution pour résoudre ce problème :
hibernate {
    ...
    cache.region.factory_class = 'org.hibernate.cache.SingletonEhCacheRegionFactory'
}

mardi 13 janvier 2015

Grails Mise à jour de Grails 2.3.11 vers Grails 2.4.4

J'ai réussi à mettre à jour à l'aide de https://grails.org/2.4.4+Release+Notes et http://grails.org/doc/latest/guide/upgradingFrom23.html . Ce n'est pas une mise à jour trivial et j'ai eu des exceptions au démarrage de mon appli web ainsi que pas mal de modification à faire pour que cela fonctionne à nouveau. (site assez important). Je vous recommande de bien suivre le lien de mise à jour
Voici quelques pistes pour vous aider :

Montée de version des plugins

Pour que cela fonctionne, j'ai du faire un upgrade des plugins suivants : cache, hibernate, jquery.
Si vous ne le faites pas, vous aurez des erreurs ...

Plugin asset-pipeline remplace le  plugin ressource

Cela implique de changer les répertoires de place et de les réorganiser dans le répertoire assets/.
Cela implique également la modification des includes dans vos pages GSP et aussi quelques surprises ( voir http://stackoverflow.com/questions/27906139/grails-assets-directory-management )

Plugin export:1.6

Ce plugin ne fonctionne plus.

Templates

J'ai effacé le répertoire templates puis relancer la commande grails install templates


Autre


Il faut noter l'ajout d'annotation @Validateable(nullable = true).
Cela implique la modification de quelques beans.

dimanche 14 décembre 2014

Grails, Maven and GSON : Could not find artifact


J'ai eu le problème suivant en voulant intégrer la librairie GSON à mon projet :

Error |
Resolve error obtaining dependencies: Could not find artifact com.google.code.gson:gson:zip:2.3.1 in grailsCentral (http://repo.grails.org/grails/plugins) (Use --stacktrace to see the full trace)


La solution est très simple.Il faut mettre la dépendance dans dependencies et non dans plugin :

dependencies {
        // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes e.g.
        runtime 'mysql:mysql-connector-java:5.1.24'
        compile 'com.google.code.gson:gson:2.3.1'
    }
Plus d'infos sur : http://stackoverflow.com/a/20974287/2473598

jeudi 30 octobre 2014

Comment exporter facilement ses données dans différents formats ( pdf, excel ...) avec Grails ?


Dans le site que je suis en train de réaliser, j'ai des tableaux de données et je veux pouvoir les exporter facilement dans le format désiré.Pour cela, il existe un plugin Grails : export
Avec ce plugin, vous allez pouvoir ajouter ceci dans vos page HTML :



Ce tutoriel va expliquer comment installer et configurer ce plugin ainsi que les petits problèmes que j'ai rencontré.

Installation du plugin


Pour installer le plugin, il vous faut ajouter dans BuildConfig.groovy :


repositories {
...
mavenRepo "http://repo.grails.org/grails/core"
...
}
plugins {
...

compile ":export:1.6"
...
}

Si vous ne spécifiez pas le repositories Maven ( ce n'est pas dans la documentation), vous allez avoir l'erreur ci-dessous :

Resolve error obtaining dependencies: Could not find artifact org.odftoolkit:odfdom-java:jar:0.8.5 in grailsCentral (http://repo.grails.org/grails/plugins) (Use --stacktrace to see the full trace)
Error |


Modification de la page GSP

 <head>
     ... 
     <r:require module="export"/>
     ... 
 </head>
 <body>
     <export:formats /> 
 </body>

Le tag d'export va permettre l'affichage de la barre des icons.

Remarques :
  • Vous pouvez mettre le tag export tag n'importe où dans la GSP
  • Vous  pouvez spécifier le format désiré :

<export:formats formats="['csv', 'excel', 'ods', 'pdf', 'rtf', 'xml']" /> 


Modification de votre controller

Voici mon controlleur ( avec seulement le code utile ) :


class ToolsController {

    // Export service provided by Export plugin

    def exportService

    def grailsApplication  //inject GrailsApplication

    def index() {

        if(!params.max) {

            params.max = 10

        }

        if ((params.extension != null)) {

            log.info(params.get('zest'))

            def format=params.extension

            if ("xls".equals(params.extension)) {

                format="excel"

            }

            if(format && format != "html"){

                response.contentType = grailsApplication.config.grails.mime.types[format]

                response.setHeader("Content-disposition", "attachment; filename=check.${params.extension}")

                List fields = ["machineName", "fileName", "confServerName"]

                Map labels = ["machineName": "Nom de machine", "fileName": "Nom de fichier",   "confServerName":"Valeur du ServerName"]

                Map formatters = new HashMap()

                Map parameters = new HashMap()

                exportService.export(format, response.outputStream,Check.list(params), fields, labels, formatters, parameters)

            }

        }

   }

}

Dans mon code, j'utilise une classe Domaine : Check avec 3 membres: machineName, fileName, confServerName.Ils sont spécifiés dans le code car c'est ce que je veux afficher dans le pdf.

Remarques :
  • J'ai rencontré quelques problèmes avec la valeur de params.format.Elle était toujours null et je ne sais pas pourquoi.Mon code est donc un peu différent de la documentation.
  • Il est aussi possible d'ajuster la taille des colonnes et de mettre le titre des colonnes en gras en utilisant formatters et parameters.Voir la documentation pour plus de détails : http://grails.org/plugin/export
Pour information, voici ma configuration  :
  • Grails 2.3.11
  • Plugin ; runtime ":resources:1.2.1"

mardi 16 septembre 2014

Grails : la gestion des bases de données dans différents environnements


Grails vous permet d'utiliser une base de données par environnements.Si vous changez d'environnements, Grails utilisera automatiquement la bonne base de données.
Cet article va vous montrer concrètement ce qu'il faut faire pour mettre en place trois environnements ( dev, test, production ).

Voici par exemple, les environnements que j'ai défini :

  • development: In memory database
  • test:               Mysql sur localhost
  • production :   Mysql sur une machine de production

Définir ses environnements dans DataSource.groovy

Voici le fichier qui contient les différents environnements cités ci-dessus :

hibernate {
    cache.use_second_level_cache = true
    cache.use_query_cache = false
    cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory' // Hibernate 3
//    cache.region.factory_class = 'org.hibernate.cache.ehcache.EhCacheRegionFactory' // Hibernate 4
}

// environment specific settings
environments {
    development {
        dataSource {
            dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', ''
            url = "jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE"
        }
        dataSource_lookup {
            pooled = true
            driverClassName = "org.h2.Driver"
            username = "sa"
            password = ""
        }
    }
    test {
        dataSource {
            pooled = true
            driverClassName = "com.mysql.jdbc.Driver"
            dialect = "org.hibernate.dialect.MySQL5InnoDBDialect"
            dbCreate = "create-drop"
            url = "jdbc:mysql://localhost/toolprod"
            username = "root"
            password = ""
        }

    }
    production {
        grails.config.locations = ["file:/opt/apache-tomcat-7.0.47/conf/ConfigToolprod.groovy"]
    }
}  


Production Environment



Comme vous pouvez le voir, la façon de définir l'environnement de production est différente.On a déplacé la configuration dans un fichier sur la machine.Il sera ainsi plus facile de changer de mot de passe et en plus, vous n'aurez pas besoin de reconstruire un war pour changer de mot de passe.

Dans l'exemple ci-dessous, il y a un exemple de datasource.Cet exemple contient beaucoup de paramétrage.Vous n'avez pas besoin de tous les définir.Par contre, il faut noter qu'avec cette configuration, Grails se reconnectera automatiquement à votre base Mysql.





ConfigToolprod.groovy


dataSource {
    pooled = true
    dbCreate = "update"
    url = "jdbc:mysql://localhost/toolprod"
    driverClassName = "com.mysql.jdbc.Driver"
    dialect = org.hibernate.dialect.MySQL5InnoDBDialect
    username = "LOGIN"
    password = "PASSWORD"
    properties {
       // Documentation for Tomcat JDBC Pool
       // http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#Common_Attributes
       // https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/tomcat/jdbc/pool/PoolConfiguration.html
       jmxEnabled = true
       initialSize = 5
       maxActive = 50
       minIdle = 5
       maxIdle = 25
       maxWait = 10000
       maxAge = 10 * 60000
       timeBetweenEvictionRunsMillis = 5000
       minEvictableIdleTimeMillis = 60000
       validationQuery = "SELECT 1"
       validationQueryTimeout = 3
       validationInterval = 15000
       testOnBorrow = true
       testWhileIdle = true
       testOnReturn = false
       ignoreExceptionOnPreLoad = true
       // http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#JDBC_interceptors
       jdbcInterceptors = "ConnectionState;StatementCache(max=200)"
       defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED // safe default
       // controls for leaked connections
       abandonWhenPercentageFull = 100 // settings are active only when pool is full
       removeAbandonedTimeout = 120
       removeAbandoned = true
       // use JMX console to change this setting at runtime
       logAbandoned = false // causes stacktrace recording overhead, use only for debugging
       // JDBC driver properties
       // Mysql as example
       dbProperties {
           // Mysql specific driver properties
           // http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
           // let Tomcat JDBC Pool handle reconnecting
           autoReconnect=false
           // truncation behaviour
           jdbcCompliantTruncation=false
           // mysql 0-date conversion
           zeroDateTimeBehavior='convertToNull'
           // Tomcat JDBC Pool's StatementCache is used instead, so disable mysql driver's cache
           cachePrepStmts=false
           cacheCallableStmts=false
           // Tomcat JDBC Pool's StatementFinalizer keeps track
           dontTrackOpenResources=true
           // performance optimization: reduce number of SQLExceptions thrown in mysql driver code
           holdResultsOpenOverStatementClose=true
           // enable MySQL query cache - using server prep stmts will disable query caching
           useServerPrepStmts=false
           useServerPrepStmts=false
           // metadata caching
           cacheServerConfiguration=true
           cacheResultSetMetadata=true
           metadataCacheSize=100
           // timeouts for TCP/IP
           connectTimeout=15000
           socketTimeout=120000
           // timer tuning (disable)
           maintainTimeStats=false
           enableQueryTimeouts=false
           // misc tuning
           noDatetimeStringSync=true
       }
    }
}