Grails: print QRCodes with qrcode 0.3 plugin nested into rendering 0.4.3 plugin

The output app side all ways forever scared me: since building a printer output “bit by bit” with escape codes into a MS-DOS app, to make a complex print form helped by tools like Cristal reports, It’s evident for me the output is a boooring task.

But all has changed when I had discovered any of the output plugins set of grails environment: export, rendering and the fantastic qrcode. With those tools the making of a output is a easily and quickly thing.

Following the dependence injection of the Grails paradigm, We have only declare the  instance plugin into our controller and Springs make it the rest. (qrcode and rendering only have it to make the plugin installation into the project context)

But stop us the theory and go to the cake: the render of a QRCode is whatever a simply question: only we need the well installed plugins, one action which will be called from the view:

   def printFragmentosQrCode = {
             def entradaInstance = Entradas.get(params.id)         
             renderPdf(template: "/printTest",model:[Objects2QRList:entradaInstance.fragmentos,entradaInstance:entradaInstance],filename: "fragsQRCodes.pdf")
        }

and a GSP template wich has the rendering responsibility:

<%@ page contentType="text/html;charset=UTF-8" %>

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <title>Sample title</title>
    </head>
    <body>
        <g:each in="${Objects2QRList}" var="o" >
            <qrcode:image width='o?.size' text="${o?.encodeAsHTML()}" />
        </g:each>
    </body>
</html>

If we analyze the code, It looks simple; the action take a objects collection (entradaInstance.fragmentos) and send it to the template with a name of output pdf file (also may be a png). Into template, It generate the plugin call by the insert of the specific tags, the <qrcode> tag;

<qrcode:image width="90" text="${o?.referencia.encodeAsHTML()},${o?.tipoFragmento.nombreProcesado}" />

The rendering plugin have to create a xml file and finally transform it in a pdf with a serie of png 2D codes. Unfortunately, the nesting plugins generate a xml ‘not well formed’ error with s entity:

"The reference to entity “s” must end with the ';' delimiter exception"

Googling I could see the xml error was a problem relates with the bad resolving by xml parser of the ‘&’ special character. Anyway, my problem don’t was a self code problem but was a plugin code ‘bug’ (at least a not well formed XML disfunction)

The advantage of free software let me to see the source code of qrcode plugin files. A plugin has a similar structure that whichever grails project: controller(s), view(s),  tag library(s) an more…It was easy to find the origin of my problem:

It was a ‘bug’ in the building of qrcode image url. The ‘s’ entity it’s really the size property of the image (and the size attribute of  <qrcode> tag) as I could see in the ‘QRCodeTagLib.groovy’ file:

  def image = { attrs ->
    def size = attrs.height?:attrs.width
    String text = attrs.text
    String src = createLink(controller:'qrcode',action:'text',params:[text:text,s:size])
    out << """ <img class="qrcode" src="${src}" alt="${text}" />"""
}

The src attribute of the <img> tag was valued by $src variable, wich was generated into the own closure by a call to ‘text’ action of controller (with the createLink() groovy function). Then, there was the problem.

I suppose the bug could be a bad generation of url image string, more exactly with the ‘&’ characters of the concatenation of the GET params request. Then, the solution was  replace those with the appropiate equivalence ‘&amp;’.

For this, I used the replaceAll() groovy function and the result was:

def image = { attrs ->
    def size = attrs.height?:attrs.width
    String text = attrs.text
    String src = createLink(controller:'qrcode',action:'text',params:[text:text,s:size])
     String src2=src.replaceAll(/&/,'&')
    out << """ <img class="qrcode" src="${src2}" alt="${text}" />"""
    }

Yeah! I did!

Don’t remember to modificate the others tags into tagLib plugin.

Regards squids.

Advertisements

A little bug in Grails Searchable plugin

I’m going to develop -really, I’m in analysis of requirements phase, but we need a set of web tools for managing the legacy data infrastructure- a management scientific collections project and, after try a lot of web technologies, I select Grails. Grails offer, under my point of view, multiple advantages wich promote their election:

  • A solid and maintainable infrastructure for MVC web based projects
  • A dynamic and easily learn-to language: Groovy
  • A framework IoC based
  • A natural connection and integration with legacy Java systems and Java libraries
  • A integration with ORM persistence (here, hibernate)
  • Finally, a facility for add multiple (GNU) plugins.

This last facility has been which has permitted to integrate easily a search service based of lucene engine. Lucene is a strong search engine for multiple search types: by generic match, or by substrings…over all the data or over a specific column…searching with wildcards and concatenation operators… and all over a only textbox.

The grails plugin is the searchable plugin. Once has been  installed in our grails project, the declaration in a domain groovy class makes the container inyect the Searchable class and then It can be utilized by the controller class for generate a search method.

Searchable has two first methods applied how static domain class methods (ClassSearchable.search() and ClassSearchable.searcEvery()), search and searchEvery, wich deliver a resultSearch object but at two distinct faces:

  • A paginate object
  • A full list hits object

If You wants to show a paginate list, the search first method is the ideal candidate. Else if You was thinking at a persistent memory object -like a file, the second search method is the best.

In my project, It was possible a search without a knowledge of the exact term. There, the use of wildcards  are necessary. Moreover, was intended than If the result of search It was a empty list, another suggested query could be indicated.

But I had seen that anything was not well. No suggests occurred when the find pattern contained a wildcard. The debug process indicates a null resultSearch…I don’t understander.

I tried to eliminate the suggested query indication…argg..else It ran! I googled and then I seen that It’s a plugin bug…and I think is not yet parched 😦 .

The solution is not fine: I find a null searchResult for activate the suggest query option. This is the code:

    def search = {
        try {
            def query=params.q?:flash.queryString
            params.q=flash.queryString
            if (!query) {
                flash.message="No hay parámetros. Reconstruya la consulta..."
                redirect(action:"index")
                return [:]
            }
            params.max = Math.min(params.max ? params.int('max') : 17, 100)
            //ojo a suggestQuery (param) y suggestedQuery (property)

            def searchResult = Catalogo.search(query,params)
            flash.queryString = query
            //OJO: Hasta que no se obtenga la búsqueda, no se puede generar la consulta
            //con sugerencia, porque si no peta si q lleva wildCards -es un bug del plugin-
            if(searchResult.total==0){
                params.suggestQuery = true
                searchResult = Catalogo.search(query,params)
                def sugerida = searchResult.suggestedQuery
                flash.message = sugerida
            }
            return [searchResult: searchResult, params:params]
        }
        catch (e) {
            return [searchError: true]
        }
    }

I’d like you to be useful. Regards squids!