Showing posts with label Grails. Show all posts
Showing posts with label Grails. Show all posts

Saturday, March 12, 2016

Grails 3 : ORM Mapping Invalid: Specified config option


I have the following error at startup of my GRAILS 3.1.1 application :

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

The consequence was that it can't create the table Machine.

Here is my domain class which had the error :

 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)  
   }  


   
To solve this issue, I set a default value for name    :

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

Saturday, March 5, 2016

Netbeans change the .gradle directory

To solve this problem, I set the system environment variable GRADLE_USER_HOME to an other directory like the following :

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

Then in Netbeans It works ( perhaps you have to make some clean, close and open project to refresh it )

Hope this help !

Saturday, October 3, 2015

Grails 3 and Netbeans 8.0.2 : warning about Gradle 2.3 compatibility


I had a warning in Netbeans IDE 8.0.2 about Gradle 2.3 compatibility.I followed the following steps to clear this warning. In files tab, I did a right clik on my project.I choose properties and Gradle project Categories.Then I changed the Gradle home to my Gradle 2.7 directory like the following :






And the annoying warning disappeared !

Sunday, September 20, 2015

Grails 3 and IDE support


I'm looking at support of grails 3 by the IDE.
To now, here is an overview :
  • Eclipse : none support, plug-in disappeared from STS.
  • Intellij : appears to be support but you to pay licensing ...
  • Netbeans : begins of support
The good point is Netbeans 8.0.2 recognizes Grails 3 project.So, i was able to create a new Grails 3 project.You can launch you application and there is also syntax highlights in GSP.
However, it's just the beginning and it needs some works.But, you can begin to practice with Grails 3.

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

One comment, under Eclipse, you can import Grails project as a Gradle project like said in documentation.But, I didn't find how to have syntax highlights in GSP.

Friday, September 18, 2015

Upgrade Grails 2.5.0 to 2.5.1

I successfully upgrade Grails to the version 2.5.1It's quite simple.You only have to follow the release note about plugins update.
I met only one problem.I had this warning : Script 'Upgrade' not found.

To solve that issue, you have to select 3 (SetGrailsVersion) ant it will make the update.

|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


With this update, I solved the following error : http://stackoverflow.com/questions/32562678/grails-plugin-error-class-path-resource-cannot-be-resolved

Wednesday, September 16, 2015

How to import files in GRAILS ?

In business web site, we often used to import config files.There are many way to achieve this in GRAILS.In this paper, we will talk about two possibilities but not about batch because it doesn't work for me in GRAILS 2.5.0.

An IHM to import file

You can import files with a classical html form like the following :








A form example : form.gsp

Below, here is an example of Grails upload form by using g:uploadForm tags.This form, when submit, calls the init action from the admin controller.It passed files in parameter with Input tag.The input file with the parameter multiple will permit to upload severeal files.

<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


For example, to parse a file, you could do the following :
      
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) {
                            ...
                            }
                        }
            }
            ...
        }
    }

...

The arry files[] will contain all import files.You have to notice that file is type of org.springframework.web.multipart.MultiPartFile and not java.io.File


Import files automaticaly


An other way, is to import files automaticaly. You just have to do a method in the controller like the following :

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()) {
                ...

            }

        }

...

Then you need to access at the following url : http://localhost:8080/appli/admin/reloadData
After that, it's easy to make a crontab with a curl to make automatisation ...

Friday, April 24, 2015

Grails and Pdf creation

In my businness application, I needed to print report in a pdf file.Before Grails 2.5.0, I used export-plugin with success.I tried to use with Grails 2.5.0 but I obtained compilation errors.That's why I looked for other solutions.
I found rendering plugin but I had an error when rendering ( see http://stackoverflow.com/questions/29694796/null-pointer-exception-with-grails-rendering-plugin ).
Finaly, I decided to do it myself with apache pdfbox

In my BuildConfig.groovy, I added the dependency :

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

And here is the code in my controller :

 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;  
     }  
   }  
 }  


So, this is not the best solution.I would have preferred something like rendering plugin but it's works and I needed it immediately.A big thanks to this blog for the use of pdf library : http://fahdshariff.blogspot.fr/2010/10/creating-tables-with-pdfbox.html 

Hope this help,

See also : http://grails.github.io/grails-doc/2.5.x/ref/Controllers/render.html

Friday, April 3, 2015

Grails : an example of remoteFunction with two parameters


In my businness web application, I wanted to use a selectbox which call a controller method to check mail address stores in ldap. On change of selectbox, it will automaticaly check if the mail exists in ldap.In this paper, we will talk about the use of remoteFunction with 2 parameters.I wrote it because I had difficulties with this ( especially the syntax ) and I hope it could help someone !

The gsp


In my gsp, I had an input text and a select box.The remoteFunction calls the action of the controller ajaxCheckMailInLDAP. Parameters are passed in params. ( Be carefull at the syntax ).Once achieved, the javascript method checkLdapMail(data) called.

example

// Show the result
 <div id="create_status_ok" class="alert alert-success" role="alert" style="display: none">
        <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
        <span class="sr-only">Info:</span>
        Vérification dans le LDAP OK ! vous pouvez créer cette adresse.
 </div> 
 ...
 
// form that use remoteFunction 
<form>
   <input type="text" class="form-control" id="rne" name="rne" placeholder="....087XXX" value="">  
   ...  
   <g:select noSelection="['0':'Choisir un type de boîte']" optionKey="id" optionValue="fullNameType" name="shortNameType" id="selecttype" from="${toolprod.MailType.list()}"
    onchange="
    cleanMsg();
    ${remoteFunction(
       controller:'tools',
       action:'ajaxCheckMailInLDAP',
       params:'\'id=\' + this.value + \'&rne=\' + document.getElementById(\'rne\').value',
       onSuccess:'checkLdapMail(data)')}"
    ></g:select> 
 </form>  


The controller's action


Here is my controller wich render an array as JSON.Note that the name of data variable is important !

 class ToolsController {  
 ...  
   def ajaxCheckMailInLDAP = {  
        log.info("ajaxCheckMailInLDAP()")
 
       String mail = params.rne + "@.."

        // Init JSON data
        def data = [:]
        data.put("id", "1")
        if (checkMail(mail)) {// just return a boolean
            data.put("text", "KO")
        } else {
            data.put("text", "OK")
        } 
        data.put("mail", mail)
        log.info("ajaxCheckMailInLDAP() END" + mail)
        render data as JSON 
   }  
 ....  
 }  

To finish, below is the javascript method :

    /**
     * Show result stored in data on html page
     * @param data JSON data send by ajaxCheckMailInLDAP in controller.
     */
    function checkLdapMail(data) {
        console.log("checkLdapMail()");

        document.getElementById('selecttype').value=0;
        document.getElementById('create_status_ko').style.display='none';
        document.getElementById('create_status_ok').style.display='none';
        document.getElementById('create_status_info').style.display='block';

        if (data.text == "KO") {
            document.getElementById('create_status_info').style.display='none';
            document.getElementById('create_status_ko').style.display='block';
            document.getElementById('create_status_ko').textContent= data.mail.toString() + " existe deja dans le LDAP !";
        }
        if (data.text == "OK") {
            document.getElementById('create_status_info').style.display='none';
            document.getElementById('create_status_ok').style.display='block';
            document.getElementById('btnSubmit').disabled = false;
        }

        if (data.text == "EMPTY") {
            document.getElementById('create_status_info').style.display='none';
            document.getElementById('create_status_ko').style.display='block';
            document.getElementById('create_status_ko').textContent= "le rne est vide !";

        }
        console.log("checkLdapMail() : end");
    }

To make it works, I use the parameter name data.An other important things, I used Grails 2.4.4 to make this example.
I hope it will help you in your developpement.



Tuesday, March 31, 2015

Upgrade Grails 2.4.4 to 2.5.0

I successfully upgraded Grails 2.4.4 to 2.5.0 by following the Release Version text files ( https://github.com/grails/grails-core/releases/tag/v2.5.0 ).

I only upgraded plugins version in BuildConfig.groovy:

  • build ':tomcat:7.0.55.2'
  • compile ':cache:1.1.8'
  • compile ':scaffolding:2.1.2'
  • compile ':asset-pipeline:2.1.5'

I also met an exception because I forget to change cache.region.factory_class in Datasource.groovy ( cf Release Version ).
Here is the exception :

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 ]
...

To solves it, I only have to do the following change in Datasource.groovy :

hibernate {
    ...
    cache.region.factory_class = 'org.hibernate.cache.SingletonEhCacheRegionFactory'
}

Tuesday, January 13, 2015

Grails update successfully from 2.3.11 to 2.4.4

I successfully update Grails from 2.3.11 to 2.4.4 by following https://grails.org/2.4.4+Release+Notes and http://grails.org/doc/latest/guide/upgradingFrom23.html. It was not a simple update due to a substancial existing web site.I had error at startup and many things to do to make it works.
So, here are some advices to help to complete this task :

Upgrade plugins

Be carefull, if you don't upgrade plugins like cache, hibernate, jquery, you will have stranges errors.

Plugin asset-pipeline replace resource plugin

You will have to move directory and organize them in assets directory and also change all include in GSP.Possibles surprises will perhaps appear : see http://stackoverflow.com/questions/27906139/grails-assets-directory-management

Plugin export:1.6

To now, it doesn't work for me

Templates

I delete templates directory end recreate it by command : grails install templates.
It fixes some errors.

Other 

There is a new annotation : @Validateable(nullable = true)

Sunday, December 14, 2014

Grails and GSON : Could not find artifact


I had the following problem by adding GSON at my project :

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)


Solution was simple.To solve this problem, put GSOn in dependencies section and not in plugin section :

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'
    }
More details on : http://stackoverflow.com/a/20974287/2473598

Thursday, October 30, 2014

How to export your datas easily in different format with Grails ( pdf, excel ... )


In my business web site, I have array with datas and I want a way to publish it in severeal format.
To achieve this, it exists the Grails export plugin.Here is what you will have under your array :



This tutorial will explain how to quickly use the export plugin and problems I met.

Plugin install


To install, the plugin I added in BuildConfig.groovy :


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

compile ":export:1.6"
...
}


If you don't add, the Maven Repositories, you will have this error :

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 |


Modify your GSP

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

The export tag will display icons and the require will had required css.
If you clic on pdf button,

Notes :
  • You can put the export tag where you want in the GSP
  • You can specify format you want :

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


Modify your controller

Here is my controller :


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)

            }

        }

   }

}

I had a Check domain class with 3 fields : machineName, fileName, confServerName.These fields will be display in the pdf


Notes :
  • I had some problem with params.format values.In my case, it was always null and I don't know why.That's why my code is not exactly the same of the documentation
  • You can also format text and adjust column size with formatters and parameters.See documentation for more details.

If you want more details about plugin installation, you could see the documentation : http://grails.org/plugin/export
Here is my Grails configuration :
  • Grails 2.3.11
  • Plugin ; runtime ":resources:1.2.1"

Tuesday, September 16, 2014

Grails : database management in multiple environments


With Grails, you can use a database for a specific environments.If you change environments, Grails will use the database you define.

For example, you can define the following environments :

  • development: In memory database
  • test:               Mysql on localhost
  • production :   Mysql on production machine

Define your environments in DataSource.groovy



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


As you can see, the way you define production environment is quite different.You define a path where are stored datasource.
With this sort of configuration, you doesn't have to build your Grails project an other time if you want to change the login and password.Moreover, authentication is only in one place.I find it much better.

Below, there is an example of my ConfigToolprod.groovy file. An important thing, this configuration will permit Mysql database to reconnect automaticaly.

Comment : File contains a lot parameter because they had a bug in a old version of Grails.You certainly doesn't need all parameters.



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
       }
    }
}




Sunday, August 31, 2014

Upgrading Grails 2.3.6

Today, I decided to upgrade my Grails web site.
Now, I use Grails 2.3.6 and I decided to test severeal solution to upgrade my web site.
One note about how I upgrade my Grails version.I used "Change Grails SDK" feature of Grails plugin in IntelliJ.It simple and you can go back easily !

Grails 2.3.6 with JDK 1.8_05


This upgrade wasn't successful.Grails 2.3.6 doesn't work with JDK 1.8.
I rode forum and it seems normal.

I had the following message : 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 to 2.4.3


I also test the following use case.I upgraded to 2.4.3 my web site.
However,  I had compilation error :


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


The right choice


It isn't a suprise but the right choice is to update Grails 2.3.6 to 2.3.11.
It 's easy and it works ;-)

Friday, May 30, 2014

Deploy your Tomcat Grails website on OpenShift






Deploy your Grails web site on OpenShift

I use OpenShift cloud to deploy my web site made with Grails. This article will give you a summary of what you have to do if you want to deploy a web site on OpenShift cloud. It will also give some advice and feedback.

 

 Which way to deploy your Grails application on OpenShift ?

The best way I found to deploy my Grails application is to build a war and then deploy it on Openshift.

By default, Grails has the war command available : grails war

See also the Grails web site for more details about it : http://grails.org/doc/2.2.1/ref/Command%20Line/war.html


Note :

  • You can use Tomcat plugin to makes Tomcat the default servlet container for Grails at development time.
  •  You can delete unwanted files in your war by adding some configuration in Config.groovy :
    1:  grails.war.resources = {  
    2:     stagingDir -> delete(dir: "$stagingDir/selenium")   
    3:  }   
    


Install and configure Openshift client


First of all you have to create an account on Openshift then you will be able to install and configure openshift tools. You only have to install rubygems and git package. For example, on Gentoo, type the following commands :

 emerge dev-ruby/rubygems  
 emerge git   


If you don't have Gentoo, you can see on the openshift website : https://www.openshift.com/get-started#cli
Then, you only have to execute following command :

 gem install rhc  
 su - user  
 rhc-setup   


Here is an example :

#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.



Deploy your application on the cloud

Once, you can access with ssh and you have a war application, you only have to copy it on your account.OpenShift uses Git to push your application on the cloud : https://www.openshift.com/developers/deploying-and-building-applications

In our case, you had to make some change if you want it works. See my tips : http://totalprogus.blogspot.fr/2013/12/problem-while-deploying-rootwar-on.html

Access in your application

 

How to connect with ssh ?

  • Go and Log in openshift website.
  • Clic on Application tab
  • Clic on your application









  • At the right of the screen, clic on the link : "Want to log in your application 
  • Copy the line in your console.

For example :

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


Usefull commands

help
tail_all
ctl_app stop
ctl_app start

If you want more details, here is usefull links :

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


Visit your website

 The access link for your web site is in the openshift website ( Clic on your Application in the Application detail ).

Response time very long

I had a problem with very long time to first access to my web site.I found solution on 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.



To conclude


Deploy a web site on OpenShift cloud was not really diffcult.Just keep in mind that whit free account you have to access every 24 hours to your web site. Some people has also difficulties with proxy configuration ...
If you wan to see an example of source code, you can look at my GitHub project example : https://github.com/drieu/fjLearning.You can also visit the project on the web at opendoowap-totalprog.rhcloud.com