Affichage des articles dont le libellé est Grails. Afficher tous les articles
Affichage des articles dont le libellé est Grails. Afficher tous les articles

samedi 12 mars 2016

Grails 3 : ORM Mapping Invalid: Specified config option


J'avais l'erreur suivante au démarrage de mon application GRAILS 3.1.1 :

ERROR org.grails.orm.hibernate.cfg.HibernateMappingBuilder - ORM Mapping Invalid: Specified config option [name] does not exist for class [toolprod.Machine]!

A cause de cette erreur, il n'y avait pas de création de table

Voici la classe domaine qui posait problème :

 class Machine {  
   /**  
    * Name of the web server.  
    */  
   String name  
   /**  
    * IP address.  
    */  
   String ipAddress  
   /**  
    * Application list in this machine.  
    */  
   Set<App> apps = []  
   /**  
    * Servers list.  
    */  
   Set<Server> servers = []  
   static hasMany = [apps : App, servers : Server]  
   static mapping = {  
     sort "name"  
   }  
   static constraints = {  
     name()  
     ipAddress(nullable: true)  
   }  


   
Pour résoudre ce problème, j'ai ajouté un attribut par défaut à name   :

   static constraints = {  
     name(nullable: false)  
     ipAddress(nullable: true)  
   }  

samedi 5 mars 2016

Netbeans changement du répertoire .gradle

Pour résoudre ce problème, j'ai initialisé la variable système GRADLE_USER_HOME avec le nouveau répertoire ( paramètre puis paneau de configuration ... ) :

    variable name : GRADLE_USER_HOME
    value of variable : E:\repos\gradle

Cela a ensuite fonctionné dans Netbeans  ( il vous faudra probablement faire quelques refresh, ouverture/fermeture de projets ...)

Hope this help !

samedi 3 octobre 2015

Grails 3 : ajouter le plugin bootstrap


Voici un petit tutoriel pour ajouter le plugin bootstrap à un projet  Grails 3.Il y a quelques différences avec Grails 2.x mais pas tant que cela.
La première chose à faire est de chercher son plugin.Ils sont maintenant localisés sur  Bintray.
J'ai récupéré le plugin Bootstrap sur le lien suivant : https://bintray.com/kensiprell/gradle-plugins/bootstrap-framework/view#read


Ajout des dépendances : build.gradle


Les dépendances sont maintenant gérées dans le fichier build.gradle :

buildscript {
    ext {
         //bootstrapFramework = [
         //    version             : "3.3.5",
         //    cssPath             : "grails-app/assets/stylesheets",
         //    jsPath              : "grails-app/assets/javascripts",
         //    useIndividualJs     : false,
         //    useLess             : false,
         //    invalidVersionFails : false,
         //    fontAwesome : [
         //       install             : false
         //       version             : "4.3.0",
         //       useLess             : false
         //       invalidVersionFails : false
         //    ]
         //]
    }
    repositories {
        jcenter()
    }
    dependencies {
        classpath "com.siprell.plugins:bootstrap-framework:1.0.3"
    }
}


apply plugin: "com.siprell.plugins.bootstrap-framework"


Utilisation dans une page GSP


Ensuite, une fois la configuration du build.gradle effectuée, il suffit de faire une GSP et d'inclure les dépendances jquery, bootstrap dans votre GSP.
Voici un exemple classique de navbar :


<html lang="en" class="no-js">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title><g:layoutTitle default="Grails"/></title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <asset:javascript src="jquery-2.1.3.js"/>
        <asset:javascript src="bootstrap-all.js"/>
        <asset:stylesheet src="bootstrap-all.css"/>
        <asset:stylesheet src="font-awesome-all.css"/>
        <g:layoutHead/>
    </head>
    <body>
    <nav class="navbar navbar-default">
                <div class="container-fluid">
                  <!-- Brand and toggle get grouped for better mobile display -->
                  <div class="navbar-header">
                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                      <span class="sr-only">Toggle navigation</span>
                      <span class="icon-bar"></span>
                      <span class="icon-bar"></span>
                      <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="#">Brand</a>
                  </div>

                  <!-- Collect the nav links, forms, and other content for toggling -->
                  <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                    <ul class="nav navbar-nav">
                      <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                      <li><a href="#">Link</a></li>
                      <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                          <li><a href="#">Action</a></li>
                          <li><a href="#">Another action</a></li>
                          <li><a href="#">Something else here</a></li>
                          <li role="separator" class="divider"></li>
                          <li><a href="#">Separated link</a></li>
                          <li role="separator" class="divider"></li>
                          <li><a href="#">One more separated link</a></li>
                        </ul>
                      </li>
                    </ul>
                    <form class="navbar-form navbar-left" role="search">
                      <div class="form-group">
                        <input type="text" class="form-control" placeholder="Search">
                      </div>
                      <button type="submit" class="btn btn-default">Submit</button>
                    </form>
                    <ul class="nav navbar-nav navbar-right">
                      <li><a href="#">Link</a></li>
                      <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                          <li><a href="#">Action</a></li>
                          <li><a href="#">Another action</a></li>
                          <li><a href="#">Something else here</a></li>
                          <li role="separator" class="divider"></li>
                          <li><a href="#">Separated link</a></li>
                        </ul>
                      </li>
                    </ul>
                  </div><!-- /.navbar-collapse -->
                </div><!-- /.container-fluid -->
            </nav>
        <g:layoutBody/>
    </body>

   

Running Gradle task

Pour télécharger et installer le plugin, j'ai exécuté les task Gradle suivante : clean et assemble.
Pour cela, dans Netbeans, il faut faire clic droit sur le projet et sélectionner Task puis clean ou Assemble.Ensuite, il faut redémarrer votre application.


   
   
   
   

Grails 3 and Netbeans 8.0.2 : warning sur la compatibilité avec Gradle 2.3

J'avais un warning qui apparaissait dans Netbeans IDE 8.0.2 à propos de la compatibilité Gradle 2.3.
Pour résoudre ce petit problème, j'ai juste suivi les étapes suivantes.Dans l'onglet files, j'ai fait un click droit sur mon projet.J'ai sélectionné properties et Gradle project dans les Categories.
Puis j'ai changé  la Gradle home à un répertoire Gradle sur mon poste de travail ( Gradle 2.7 ) :






Et le warning a disparu !

dimanche 20 septembre 2015

Grails 3 et les IDE


Cela fait quelques temps que je cherche un IDE qui offre le support de Grails 3.
Pour le moment, voici l'état des lieux :
  • Eclipse : aucun support, le plugin n'est plus disponible sous STS.
  • Intellij : apparemment c'est supporté mais il faut payer la licence ...
  • Netbeans : début de support
Le point posistif, c'est que Netebans 8.0.2 reconnait les projets Grails 3.Ainsi, j'ai pu créer et importer un projet Grails 3.Vous pourrez également démarrer votre projet et il y a une coloration syntaxique pour les GSP.il faut avouer cependant que ce n'est pas encore complet mais au moins on peut commencer à se faire un peu la main dessus.

https://stackoverflow.com/questions/29441503/grails-3-0-support-in-netbeans/32425071#32425071

Une dernière chose, sous Eclipse, vous pouvez importer un projet Grails 3 en tant que projet Gradle comme l'indique la documentation mais ce n'est pas terrible.Je n'ai pas réussi à avoir la coloration syntaxique.A suivre donc ...

vendredi 18 septembre 2015

Mise à jour de Grails 2.5.0 vers 2.5.1

J'ai fait cette mise à jour sans problème.Il suffit juste de mettre à jour les plugins qui sont listés dans la ReleaseNote.

Le seul petit détail qui est un peu perturbant, c'est que vous avez un warning : Script 'Upgrade' not found.
Pour résoudre ce problème, vous devez sélectionner 3 (SetGrailsVersion) dans le menu ci-dessous :

|Running pre-compiled script
|Script 'Upgrade' not found, did you mean:
   1) MigrateDocs
   2) IntegrateWith
   3) SetGrailsVersion
   4) InstallDependency
   5) DependencyReport
Please make a selection or enter Q to quit: 3


A noter également, j'ai résolu le problème suivant en upgradant ma version de Grails : http://stackoverflow.com/questions/32562678/grails-plugin-error-class-path-resource-cannot-be-resolved

mercredi 16 septembre 2015

Comment importer des fichiers avec GRAILS ?

Dans les sites métiers, nous avons souvent besoin d'importer des fichiers de configuration.
Il y a plusieurs méthodes pour le faire.Je vais vous en présenter deux : avec un  formulaire ou avec une url.Dans cet article, je n'aborderai pas la question sur les batchs car ,dans mon cas, cela ne fonctionne pas avec la version GRAILS 2.5.



Une IHM pour importer des fichiers


Si vous avez seulement quelques fichiers à importer manuellement, le plus simple est de réaliser un formulaire.

Exemple de formulaire form.gsp


Dans ce formulaire, on appelle l'action init du controlleur admin.La balise input file avec le paramêtre multiple va permettre d'uploader plusieurs fichiers.


<g:uploadForm action="init" controller="admin">
    <form role="form">
        <div class="form-group">
            <label for="files">Choix du fichier à parser</label>
            <input type="file" id="files" name="files[]" multiple>
            <p class="help-block">Vous devez choisir un fichier httpd.conf</p>
        </div>
        <div class="form-group">
            <label for="machinename">Nom de la machine</label>
            <input type="text" class="form-control" id="machinename" name="machinename" placeholder="....ac-limoges.fr" value="">
        </div>
        <button type="submit" class="btn btn-info">Submit</button>
    </form>
</g:uploadForm>


Controller


Le tableau files[] va contenir tous les fichiers à Importer.Attention au type de file, il s'agit de org.springframework.web.multipart.MultiPartFile et non de java.io.File.Donc par exemple, vous pouvez traiter les fichiers de la manière suivante :
      
class AdminController {
  
   def init() {
        if (request instanceof MultipartHttpServletRequest) {
            ...
            request.getFiles("files[]").each { file ->
                log.info("init() file to parse:" + file.originalFilename)
                       InputStream inputStream = file.inpustream
                       BufferedReader = new BufferedReader(new InputStreamReader(inputStream))

                        try {
                            String ldapUser = EMPTY
                            String ldapPwd = EMPTY
                            String ldapHost = EMPTY
                            String ldapPort = EMPTY

                            while ((line = br.readLine()) != null) {
                            ...
                            }
                        }
            }
            ...
        }
    }
...


Import de fichier de manière automatique


Une autre façon de faire est d'utiliser une méthode du controlleur.Cela permet d'importer des fichiers automatiquement :

class AdminController {
    def reloadData() {
        def path = "E:\\projet\\toolprod\\import\\"

        log.info("reloadData() Initializing application from httpd.conf files in machine directory ...")
        new File(path).listFiles().findAll{
            if (it.isDirectory()) {
                log.info("reloadData() Machine name ( Directory name ) :" + it.name)
                String machineName = it.name
                log.debug("reloadData() files list:" + it.listFiles())
                for (File f : it.listFiles()) {
                ...

            }

        }
...



Ensuite, il vous suffit d'accéder à l'url : http://localhost:8080/appli/admin/reloadData
Après cela, il est facile de faire un curl et de le mettre dans une crontab.


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"

dimanche 31 août 2014

Mettre à jour Grails 2.3.6

J'ai décidé de mettre à jour Grails car ma version de Grails commence à dater un peu ( Grails 2.3.6)...
Dans un premier temps,j'ai voulu tester le jdk1.8 pour voir ce que cela donner puis finalement j'ai fait un test avec Grails 2.4.3 et le jdk 1.7.
Finalement, le choix de la raison sera de passer à Grails 2.3.11 ...


Petite remarque : j'utilise le plugin Grails d'IntelliJ qui a une option "Change Grails SDK". Cela me permet de passer à une autre version de Grails très facilement et surtout de revenir en arrière facilement

Grails 2.3.6 with JDK 1.8_05

Cette mise à jour à échouer et d'après ce que j'ai lu ici et là, c'est normal.
Grails 2.3.6 ne fonctionne pas avec le jdk 1.8


J'ai eu le message d'erreur suivant au démarrage de mon site Grails : Java HotSpot(TM) Server VM warning: ignoring option PermSize=256m; support was removed in 8.0 

opt/drieu/jdk1.8.0_05/bin/java -Dgrails.home=/opt/drieu/grails-2.3.6 -Dbase.dir=/home/drieu/workspaces/toolprod -Dtools.jar=/opt/drieu/jdk1.8.0_05/lib/tools.jar -Dgroovy.starter.conf=/opt/drieu/grails-2.3.6/conf/groovy-starter.conf -Xmx768M -Xms768M -XX:MaxPermSize=256m -XX:PermSize=256m -javaagent:/opt/drieu/grails-2.3.6/lib/org.springsource.springloaded/springloaded-core/jars/springloaded-core-1.1.4.jar -noverify -Dspringloaded=profile=grails -Didea.launcher.port=7532 -Didea.launcher.bin.path=/opt/drieu/intellij/idea-IU-12.1.6/bin -Dfile.encoding=UTF-8 -classpath /opt/drieu/grails-2.3.6/lib/org.codehaus.groovy/groovy-all/jars/groovy-all-2.1.9.jar:/opt/drieu/grails-2.3.6/dist/grails-bootstrap-2.3.6.jar:/opt/drieu/intellij/idea-IU-12.1.6/lib/idea_rt.jar com.intellij.rt.execution.application.AppMain org.codehaus.groovy.grails.cli.support.GrailsStarter --main org.codehaus.groovy.grails.cli.GrailsScriptRunner --conf /opt/drieu/grails-2.3.6/conf/groovy-starter.conf run-app
Java HotSpot(TM) Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
Java HotSpot(TM) Server VM warning: ignoring option PermSize=256m; support was removed in 8.0
| Loading Grails 2.3.6
| Configuring classpath
| Configuring classpath.
| Environment set to development
| Environment set to development.
| Environment set to development..
| Environment set to development...
| Environment set to development....
| Environment set to development.....
| Packaging Grails application
| Packaging Grails application.
| Packaging Grails application..
| Packaging Grails application...
| Packaging Grails application....
| Packaging Grails application.....
| Running Grails application
Java HotSpot(TM) Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[ERROR] 2014-08-30 19:29:07,296 ScaffoldingGrailsPlugin - Error configuration scaffolding: startup failed:
script1409426946353650946897.groovy: -1: Repetitive method name/signature for method 'java.lang.Object withFormat(groovy.lang.Closure)' in class 'toolprod.ServerController'.
 @ line -1, column -1.
script1409426946353650946897.groovy: -1: Repetitive method name/signature for method 'java.lang.Object withFormat(groovy.lang.Closure)' in class 'toolprod.ServerController'.
 @ line -1, column -1.
2 errors
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
script1409426946353650946897.groovy: -1: Repetitive method name/signature for method 'java.lang.Object withFormat(groovy.lang.Closure)' in class 'toolprod.ServerController'.
 @ line -1, column -1.
script1409426946353650946897.groovy: -1: Repetitive method name/signature for method 'java.lang.Object withFormat(groovy.lang.Closure)' in class 'toolprod.ServerController'.
 @ line -1, column -1.
2 errors
    at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:309)
    at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1065)
    at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:572)
    at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:550)
    at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:527)
    at ScaffoldingGrailsPlugin.createScaffoldedInstance(ScaffoldingGrailsPlugin.groovy:183)
    at ScaffoldingGrailsPlugin.configureScaffoldingController(ScaffoldingGrailsPlugin.groovy:138)
    at ScaffoldingGrailsPlugin.configureScaffolding(ScaffoldingGrailsPlugin.groovy:113)
    at ScaffoldingGrailsPlugin$_closure2.doCall(ScaffoldingGrailsPlugin.groovy:88)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
[INFO ] 2014-08-30 19:29:07,523 conf.BootStrap - ENVIRONNEMENT : DEVELOPMENT
[INFO ] 2014-08-30 19:29:07,523 conf.BootStrap - Nothing to load at startup ...
| Server running. Browse to http://localhost:8080/toolprod


Grails 2.3.6 à 2.4.3


J'ai aussi tester ce cas de figure.Avec un jdk1.7, j'ai tenté de faire une mise à jour vers Grails 2.4.3 mais sans succès.
J'ai eu une erreur de compilation :


Grails 2.4.3 with jdk7

me/drieu/workspaces/toolprod/target/work/plugins/scaffolding-2.0.1/src/java/org/codehaus/groovy/grails/scaffolding/view/ScaffoldingViewResolver.java:42: error: no interface expected here
public class ScaffoldingViewResolver extends GrailsViewResolver {
                                             ^
/home/drieu/workspaces/toolprod/target/work/plugins/scaffolding-2.0.1/src/java/org/codehaus/groovy/grails/scaffolding/view/ScaffoldedGroovyPageView.java:87: error: method createResponseWriter in class GroovyPageView cannot be applied to given types;
            out = createResponseWriter(response);
                  ^
  required: GrailsWebRequest,HttpServletResponse
  found: HttpServletResponse
  reason: actual and formal argument lists differ in length
/home/drieu/workspaces/toolprod/target/work/plugins/scaffolding-2.0.1/src/java/org/codehaus/groovy/grails/scaffolding/view/ScaffoldedGroovyPageView.java:75: error: method does not override or implement a method from a supertype
    @Override
    ^
/home/drieu/workspaces/toolprod/target/work/plugins/scaffolding-2.0.1/src/java/org/codehaus/groovy/grails/scaffolding/view/ScaffoldingViewResolver.java:88: error: cannot find symbol
        return super.createFallbackView(viewName);
               ^
  symbol:   variable super
  location: class ScaffoldingViewResolver
/home/drieu/workspaces/toolprod/target/work/plugins/scaffolding-2.0.1/src/java/org/codehaus/groovy/grails/scaffolding/view/ScaffoldingViewResolver.java:58: error: method does not override or implement a method from a supertype
    @Override
    ^
/home/drieu/workspaces/toolprod/target/work/plugins/scaffolding-2.0.1/src/java/org/codehaus/groovy/grails/scaffolding/view/ScaffoldingViewResolver.java:97: error: cannot find symbol
        view.setApplicationContext(getApplicationContext());
                                   ^
  symbol:   method getApplicationContext()
  location: class ScaffoldingViewResolver
/home/drieu/workspaces/toolprod/target/work/plugins/scaffolding-2.0.1/src/java/org/codehaus/groovy/grails/scaffolding/view/ScaffoldingViewResolver.java:98: error: cannot find symbol
        view.setServletContext(getServletContext());
                               ^
  symbol:   method getServletContext()
  location: class ScaffoldingViewResolver
/home/drieu/workspaces/toolprod/target/work/plugins/scaffolding-2.0.1/src/java/org/codehaus/groovy/grails/scaffolding/view/ScaffoldingViewResolver.java:99: error: cannot find symbol
        view.setTemplateEngine(templateEngine);
                               ^
  symbol:   variable templateEngine
  location: class ScaffoldingViewResolver
8 errors


1 error

Process finished with exit code 1


Le meilleur choix

Ce n'est pas vraiment une surprise mais Il semble que le meilleur choix soit pour le moment de passer à Grails 2.3.11 ;-)
J'ai mis à jour sans problème et sans régression cette version de Grails.



vendredi 30 mai 2014

Déployer son site web Grails sur le cloud OpenShift




J'ai utilisé le cloud d'OpenShift pour déployer un site web faits en Grails. Cet article va présenter un résumé des étapes nécessaires ainsi que quelques conseils et retours d'expériences.


  Quel est la meilleur méthode pour déployer son site Grails sur OpenShift ?


La meilleur méthode que j'ai trouvé pour déployer son site Grails est de construire un war puis de le copier sur le cloud.

Par défaut, Grails a une option pour générer un war : grails war

Pour plus de détails : http://grails.org/doc/2.2.1/ref/Command%20Line/war.html


Remarque :

  • Vous pouvez utiliser le plugin Tomcat de Grails Tomcat plugin pour faire de Tomcat le servlet container utilisé par défaut lors du développement.
  • Vous pouvez effacer les fichiers non nécessaire dans votre war en ajoutant des configurations dans le fichier Config.groovy :
    1:  grails.war.resources = {  
    2:     stagingDir -> delete(dir: "$stagingDir/selenium")   
    3:  }   
    


Installation et configuration du client ssh


Il vous faut tout d'abord créer un compte sur OpenShift. Ensuite, vous pourrez configurer votre accès ssh. Il suffit simplement d'installer le package rubygems et git. Par exemple sur Gentoo, il suffit de faire ;

 emerge dev-ruby/rubygems  
 emerge git   


Si vous n'avez pas Gentoo, vous pouvez aller voir sur le site d'OpenShift  : https://www.openshift.com/get-started#cli


 gem install rhc  
 su - user  
 rhc-setup   

Voici un exemple de output de la commande rhc-setup :
#rhc setup
OpenShift Client Tools (RHC) Setup Wizard

This wizard will help you upload your SSH keys, set your application namespace, and check that other programs like Git are properly installed.

Using XXXX to login to openshift.redhat.com
Password: ******

OpenShift can create and store a token on disk which allows to you to access the server without using your password. The key is stored in your home directory and should be kept secret.  You can delete the key at any time by running 'rhc
logout'.
Generate a token now? (yes|no) yes
Generating an authorization token for this client ... lasts about 1 month

Saving configuration to /home/USER/.openshift/express.conf ... done
Checking for git ... found git version 1.8.5.5
Checking common problems .. done
Checking for a domain ... MYDOMAIN
Checking for applications ... found 1
  opendoowap http://opendoowap-totalprog.rhcloud.com/

  You are using 1 of 3 total gears
  The following gear sizes are available to you: small

Your client tools are now configured.



Déployer votre application sur le cloud

Une fois l'accès ssh configuré et que vous avez builder le war, il vous suffit de le copier sur le cloud. OpenShift utilise Git pour déployer automatiquement les applications.Si vous voulez que cela fonctionne avec un war, il y a une petite astuce : http://totalprog.blogspot.fr/2013/12/probleme-avec-le-deploiement-de-rootwar.html

Accès à votre application

 

Comment se connecter avec ssh ?

  • Logguer vous sur le site d'OpenShift.
  • Clic sur l'onglet Application.
  • Clic sur votre application.










  • A droite de l'écran, clic sur le lien : "Want to log in your application 
  • Copie la ligne sur votre console.

Par exemple :

#ssh 529e2274e0b???b@myapp.rhcloud.com


Commandes utiles :

help
tail_all
ctl_app stop
ctl_app start

Voici quelques liens utiles pour plus de détails :

  • https://www.openshift.com/developers/remote-access#keys
  • https://www.openshift.com/get-started#cli


Visitez votre site web

Le lien pour accéder à votre site web est dans la partie Application details sur le site d'OpenShift.

Temps de réponse très long

J'ai rencontré un problème lors de l' accès au  site. Le temps de chargement était vraiment très long. J'ai trouvé la solution à ce problème sur StackOverFlow :

 openshift : my local gears often timeout and go down which cause response time very long

If you do not access your application for 24 hours, it will get idled (if this is a free acount), and depending on how large your application is, it could take awhile to spin back up when you do access it again.

En fait, pour les comptes "gratuits", ils sont automatiquement  mis à "idled" si il n'y a pas d'accès pendant 24 heures.


Conclusion

Déployer un site fait avec Grails n'est pas très difficile.Si vous souhaitez voir un projet example, j'ai mis un projet sur GitHub https://github.com/drieu/fjLearning et j'ai mis en ligne le site à cette adresse :  opendoowap-totalprog.rhcloud.com