Grails RichUI - Incorrect international characters of the month names

I am working on a small project and I decided to use RichUI plugin do display a timeline.
The plugin is just great and working like a charm. If you want to try it, this tutorial is a very good one.

The english version works perfectly, but I have found a small bug in the czech localization. The czech characters were displayed incorrectly.
The whole page, including data of the timeline, was using utf-8 encoding (it was specified in the heading of the page), but the names of the months were in cp1250.

The problem lays in the source code of the RichUI plugin (I guess). A file with the czech names of the months was saved as cp1250 file, not as a utf-8 file.
So, the solution is simple. Change character set of the localization file

to utf-8 and save it.

Do not forget to delete

Update: The bug has been fixed in version 0.6. See Jira.

Web services in Grails

This article summarizes my experience with web services in Grails (and also Groovy). It will focus the on client side –
consuming web services. If you are looking for server size – providing services, you can use plugins like Metro or XFire.

Options

Once you want to create a web service client in pure groovy, you do not have much options. I have found just two libraries: Groovy SOAP and Groovy WS.

The first one is a deprecated module, so one have to use the Groovy WS.

Sisyphean challenge

Libraries

Making it running is a hard job. There are handy examples on the home page of the Groovy WS, but none of the examples was working. I spent significant amount of time to find out what is the problem. I was receiving this strange error message:

	Oct 26, 2008 9:48:19 PM org.apache.cxf.bus.spring.SpringBusFactory createBus
WARNING: Failed to create application context.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.apache.cxf.wsdl.WSDLManager' defined in class path resource [META-INF/cxf/cxf.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.apache.cxf.wsdl11.WSDLManagerImpl]: Constructor threw exception; nested exception is java.lang.ClassCastException: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:881)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:837)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:440)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
        at java.security.AccessController.doPrivileged(Native Method)
 
 
	blah blah blah

After investigation I did find that the problem is with libraries. The groovy WS library does not like xerces and xml-apis libraries.

SSL

The second difficulty was SSL. I do not remember details. It was somehow unable to download WSDL over SSL. It was necessary to download it and store into file system.

Compatibility

GroovyWS uses the Apache CXF libraries and they do not support RPC/Encoded web services.

java.lang.RuntimeException: Error compiling schema from WSDL at {https://my.url?wsdl}: undefined simple or complex type 'soapenc:Array' 
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory$InnerErrorListener.error(DynamicClientFactory.java:418)

Conclusion

I did not find the groovyWS to be a matured library. It is possible to use it for consuming web services, but only for the simplest ones. As soon as there is SSL, authentication… one have to use a “bigger hammer”. In my case, the hammer was Netbeans, that generated all the necessary classes.

Last, but not least. At the beginning I was not really sure what is the problem. I was suspecting the web services not to work correctly. So, I did use the soapUI testing tool to check that the web services are alive.

String similarity detection

I was looking for a simple string similarity detection algorithm and I did find the one on CatalySoft. Since I like it and I found it useful, I did create a groovy equivalent of it.

Here is the code:

public class LetterPairSimilarity {
 
  /** @return an array of adjacent letter pairs contained in the input string */
  private static def letterPairs(String str) {
    (0..str.size()-2).collect{str[it,it+1]} 
  }
 
  /** @return an ArrayList of 2-character Strings. */
  private static def wordLetterPairs(String str) {
    (str.split("\\s").collect{it} - [""]).collect{ letterPairs(it) }.flatten()
  }
 
  /** @return lexical similarity value in the range [0,1] */
  public static double compareStrings(String str1, String str2) {
    if (!str1 || !str2 || str1=="" || str2=="") {return 0.0}
    def p1=wordLetterPairs(str1.toUpperCase())
    def p2=wordLetterPairs(str2.toUpperCase())
 
    2*p1.intersect(p2).size() / (p1+p2).size
  }
}

Modalbox in Grails

There is a nice and handy javascript library for creating kind of a modal “window”, similar to the famous lightbox. Here are few lines of code to make it running in a Grails application

Installation

First of all, you have to download the library. The easiest way is to install a plugin modalbox

grails install-plugin modalbox

There was a slight problem in version 0.2. So, check your plugins/modalbox-0.2/grails-app/taglib/ModalboxTagLib.groovy. The version was not correct and the script tags were not correctly ended. Here is my tag library.

class ModalboxTagLib {
 
    static namespace = "modalbox"
 
    def createLink = { attrs,body ->
        // By default trigger onclick, but allow onmouseover etc
        def event = attrs.event ? attrs.event : 'onclick';
 
        // linkname only supported for backwards-compatibility. Default it to empty-string
        def linkname = attrs.linkname ? attrs.linkname : ""
 
        out << """
            <a href='${g.createLink(attrs)}' title='${attrs['title']}' ${event}='Modalbox.show(this.href, {title: this.title, width: ${attrs['width']}}); return false;'>${linkname}${body.call()}</a>
        """
    }
 
    def modalIncludes = {
        def jsFolder    = createLinkTo(dir:'plugins',file:'modalbox-0.2/js/modalbox')
        def cssFolder   = createLinkTo(dir:'plugins',file:'modalbox-0.2/css')
 
        out << """
            <script type='text/javascript' src='${jsFolder}/prototype.js' ></script>
    		<script type='text/javascript' src='${jsFolder}/scriptaculous.js?load=effects'></script>
    		<script type='text/javascript' src='${jsFolder}/modalbox.js' ></script>
    		<link rel='stylesheet' href='${cssFolder}/modalbox.css' />
        """
    }
}

“Parent” view

In the view that will call the Modalbox, use tag modalInclude like this one.

<modalbox:createLink controller="book" action="showDetails" params="[bookId:book.id]" title="Book details" width="500">book</modalbox:createLink>

Once clicked, it calls book/showDetails

“Modalbox” view

The view of book/showDetails is quite simple. You can create any static page and it will be displayed. If you want something more “spicy”, use AJAX.

Book details
 
<g:formRemote name="myForm" url="[controller:'book',action:'findSimilar']" update="[success:'similar']" onComplete="Modalbox.resizeToContent()">
	<input type="hidden" name="bookId" value="${book.id}" />
	<input id='search' name='search' />
	<input type="submit" value="Find similar" />
</g:formRemote >
 
<div id="similar">
</div>
 
<a href="#" title="Close window" onclick="Modalbox.hide(); return false;">Close</a>

Notice the resizeToContent() method. It assures, that the content that will come via AJAX will fit. Last, but not least; for comfortable close, there is the last line.

Enjoy it.

Grails: internationalization in the service

Today I spent some time by creation of localized messages in a service. Here is a small tutorial.

1. Create your service

grails create-service Local

2. Add a messageSource variable to your new service

class LocalService {
  def messageSource
}

3. Use it in a service method

// Initialize parameters
Object[] testArgs = {}
def msg = messageSource.resolveCode("message.code.to.translate", new java.util.Locale("EN")).format(testArgs)

4. Finally edit the grails-app/i18n/messages.properties

message.code.to.translate=It works!!!