Showing posts with label grails. Show all posts
Showing posts with label grails. Show all posts

Wednesday, August 11, 2010

short reminder for stupid me

If the tag does not work, it is most probably because I forgot to add the braces to the variable:

 
never works!

 
usually does work!

Tuesday, August 10, 2010

grails and SVN

I added my grails projects to a SVN repository, in order to be able to work someplace else. When I tried to check my projects out however, they did not run.

I included .project and .classpath files as I already learned that they are needed for eclipse to recognize them as grails projects.

Problem: When I ran run-app I got error messages complaining that plugins could not be resolved (locally). Also the plugin manager in STS did not list any plugins. Nothing worked.

What I missed however was that you have to run grails upgrade to reinstantiate other missing files. Afterwards plugins are resolved correctly and downloaded from the internet. This solution was found here.

Tuesday, July 20, 2010

making export plugin work with filterpane

The export plugin and the filterpane plugin for themselves work like a charm. If you try to export your filtered list however, you run into problems. The root of this problem has been recognized during an earlier discussion on the mailing list.

The problem: You have to extend the filter action to deal with the export. Therefore you have to apply the filterService.filter method with the same filter params as when you applied the actual filter.

The workaround (not a perfect solution): To solve this problem I save the filter params in the session. When export is applied on the filter action the filter params are retrieved from the session. That works well although I'm not very happy with storing so much information in the session permanently.

The Code:

Here I have modified the example from the plugin page. The export-part of the list action is extracted and gets its own export closure, which can then be used by the filter action as well. I also do not explicitly name the parameters as I am using this code in a scaffolded controller. Therefore a list is fetched of all properties, excluded those that are not really representative.

def export = {attrs ->
  
  def response = attrs.response
  println attrs.exportList
  
  def excluded = grails.persistence.Event.allEvents.toList() + ["mapping", "lastModifierId", "hasMany", "class", "belongsTo", "constraints", "searchable", "attached", "errors", "metaClass", "log", "object", "version", "beforeInsert", "beforeUpdate", "mappedBy", "springSecurityService", "type", "typeLabel"]
  List fields = ${className}.newInstance().properties.keySet().toList().findAll { !excluded.contains(it) && !isId(it)}

  response.contentType = org.codehaus.groovy.grails.commons.ConfigurationHolder.config.grails.mime.types[attrs.format]
  response.setHeader("Content-disposition", "attachment; filename=${className}.\${attrs.extension}")
  
  exportService.export(attrs.format, response.outputStream, attrs.exportList, fields, [:], [:], [:])
 }
 
 def isId(def label)
 {
  label.reverse().startsWith("dI")
 }

 def filter = {  
  if(!params.max) params.max = 10
  println "out:" +params
  if(params?.format && params.format != "html" && session.filterParams)
  {
   def exportList = filterService.filter( session.filterParams, ${className} )
   println "list:" + exportList
   export(response: response, extension: params.extension, format: params.format, exportList: exportList)
  }
  
  session.filterParams = params
  
  render( view:'list',
   model:[ ${propertyName}List: filterService.filter( params, ${className} ),
   ${propertyName}Total: filterService.count( params, ${className} ),
   filterParams: com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params),
   params:params ] )
 }

EDIT: Steve made me aware that it is easy to extract the necessary parameters with a helper method. One should therefore rather modify the export taglib to pass the correct parameters to the filter action. Also see Steve's comment below.

EDIT: Please forget about most of the crazy stuff I have done here :-) You can pass the filterParams with the export tag like this:


Thursday, July 15, 2010

just some notes about working with scaffolding code

When I modify scaffolding templates I always wonder how to obtain different properties like e.g. the class name or the id of the current instance. A general remark: What confused me most in the beginning was notation like \${${...}}. What you have to know is that \$ is escaped and is therefore what you can normally achieve in GSPs with a $. The unescaped $ within that clause is for the template. When actual code is generated from the template those $ are resolved immediately. You can therefore only use properties that are kown at this stage. Here are a few examples.

\${${className}}
This resolves the long version of the current class name

You often see that properties of an instance are iterated. The variable name of a property is then 'p':

${p.name}
This is the name of the property as it is used in the current instance. You need this value if you want to access that property in a controller (similar to this: domainClassInstance."${params.propertyName}").

${p.referencedDomainClass?.propertyName}
This one gives you the propertyName of the referenced domain class, thus the domain class of the property p. The propertyName is equal to the controller name if you stick to the convention.

${p.referencedDomainClass?.fullName}
Sometimes you need to have the full class name with the whole package notation. This can be useful for domain class instantiation (see my last post).

${p.referencedDomainClass?.shortName}
This is the actual class name omitting the package notation.

how to get a domain class instance from a class string (e.g. via params)

I had the problem that I could pass the class name from my gsp to my controller, but I didn't know how to work with that being a String. Luckily I stumpled about the solution in a code example somewhere on the web:

def grailsApplication
grailsApplication.getDomainClass(params.className).newInstance()

Wednesday, July 7, 2010

creating custom grails artefacts

I wanted to create my own kind of artefacts, in order to make easy extension of my application easier. I already had an interface called "Module" that has been implemented by classes that add new content to my sites. There were two problems that artefacts could solve for me:
  1. Dynamic reloading on code change won't work in non-artefact classes :-(
  2. Whenever I introduce a new module, I have to manually register it with a service handler.
As an artefact a module is automagically added and corresponding classes are hot-swapped if changed. I followed the great instructions on this page to get started.

The only thing I have done differently was in the last step, when I access the modules like this:

def grailsApplication

def modules = grailsApplication.getModuleClasses().collect { 
 it.referenceInstance
}

The thing is, getModuleClasses() returns 'GrailsClasses' and not java.lang.classes. At first I took the wrong road from there, trying to use it.class, which is then the DefaultModuleClass that you had to define with no abilities. I wondered how to obtain the underlying 'real' module class. Looking into the properties of the GrailsClass I found out that you can get the class of the module by accessing 'class'. But you can do even better: A instance is already attached and can be accessed by it.referenceInstance.

Happy artefacting!

Tuesday, June 29, 2010

Parsing XML: two stumbling blocks and a problem with params

Today I wanted to parse some XML content from NCBI into my grails application. I followed the instructions on:

http://www.ibm.com/developerworks/java/library/j-grails05208/index.html

Although the connection did not seem to have any problems, the parsing from a XMLSlurper object to a map did. There were in fact two problems I had to face and luckily I found the solution for both of them here:

http://stackoverflow.com/questions/1849547/groovy-xmlslurper-not-parse-my-xml-file

The first problem was that you cannot have a dash in your XML node unless you embrace it with hyphens like this:
ncbiXML.GBSeq.'GBSeq_accession-version' as String

I guess dashes are otherwise interpreted like dots (separators). I imagined something like that when I encountered the error "no property like that".

After fixing this the code ran through. The tests however still failed as only empty values were returned. The solution was to ignore the top node of the XML input. Starting one node below everything worked fine.

Now, equiped with a nice map I wanted to create domain objects following the helpful steps at the end of this article:

http://thediscoblog.com/2009/02/19/restful-grails-services-in-3-steps/

To make the properties editable before submission, I added a new action to a controller that redirects to "create" and hands over the xml parsed map from XMLSlurper as params.

That would probably have worked if it hadn't been for one property that was not a string, but an object. I thought no problem, all I have to do is use a dynamic finder to get my object with the string. This produces errors as grails interpreted this parameter as String and threw conversion exceptions when trying to parse a string to my object:

Cannot convert value of type [java.lang.String] to required type

I have googled for hours and tried everything, but finally I found the very simple solution. You have to put it like this to convince grails that it has to look up for a domain object itself via id:

ncbiMap.'organism.id' = organism.id

Again, the hyphens are very important. In the beginning I tried different things without them and then grails tries to resolve the dot instead of letting the parameter go.

Now everything works fine and I hope someone can use this to get started real fast on this (not like me :-)

Wednesday, June 23, 2010

add drag and drop functionality to GRAILS-UI datatable editors

In my application I have added a GRAILS-UI datatable with in-line cell editing functionality at the bottom of my page. Problem was that the date picker element, which is a big fat, didn't fit onto the page and was unusable though. I asked the mailing list for help about that and Matthew Taylor adviced me to try and manipulate the position via CSS. That did not work for me as I figured out that the position was hard-coded in the style property of the div tag.


When I googled for a solution I found a post where it is explained how drag and drop functionality can be added to a YUI calendar widget. I adapted the solution here. Unfortunately I found no better way as to manipulate GRAILS-UI's source code. I edited DataTableTagLib.groovy around line 215 like this:

case 'date':
 editorConstruction += """
  var ${editorName} = 
  new YAHOO.widget.DateCellEditor();\n
  ${editorName}.subscribe('showEvent', function()
  {var dd = new YAHOO.util.DD(
  ${editorName}.getContainerEl());});\n"""
break;

With this, the date picker has become draggable and can be of use for my users again.

Wednesday, June 16, 2010

javascript event mechanism for my application

The more and more I ajaxify my grails application,the harder it gets to keep all information on a site up-to-date. In my worst-case scenario there are dozens of dependencies and it is impossible to think of all of them. So the time for a event mechanism has finally come. Why haven't you done that a long time ago, you might ask. Well, I am not really familiar with javascript and as there is no in-editor correction like in my early Java days on Eclipse, I have had a hard time finding bugs in my code.

Lucky me: the cool guys from the YUI project have already taken the worst complexity of the problem of my shoulders. This means that I have used the YUI2 event utility. There are benefits I can not even imagine as a newbie, but features like automatic scope correction, object pass-throughs, etc. sound very cool and benefitial to me. Here is how I have set the whole thing up:

I have modified the main.gsp to introduce an event handler object. Putting it here makes sure that it will be available on every page:


I have not imported any js files as the necessary files have already been included by other grails plugins (mainly grails-ui). Read the doc if you have to.

One a page where I want to have event functionality I first declare an event (in this case it was within a taglib):


Now, whenever necessary I declare a callback function and register it with the event handler as listener:


The callback functions then usually make use of ${remoteFunction} to update a specific part of the page. I would not have guessed it, but if you got rid of spelling mistakes it works like a charm!

Tuesday, June 15, 2010

externalize datasource settings

Although common practice, it is not so easy to find out how to externalize your settings in a good way. I found the solution in combination of two posts:

How the property file has to look like:
http://stackoverflow.com/questions/970133/externalizing-grails-datasource-configuration

How it should be included by grails:
http://phatness.com/2010/03/how-to-externalize-your-grails-configuration/comment-page-1/#comment-1484

Wednesday, June 9, 2010

take care when using it in groovy each loop

One mistake I am making over and over is the following situation:

 def someCollection = [...]
 someCollection.each{
   println it // it works here
   doSomethingWithClauses{
     println it // it cannot be resolved here
   }
 }

As soon as you use the it in encapsulated code {}, it cannot be resolved anymore. It took me ages to find that mistake in the first place, but unfortunately I produce something like that quite often and then I wonder what the hell is wrong.

What you have to do to make it right is giving the iteration variable another name:

 def someCollection = [...]
 someCollection.each{ someItem ->
   println someItem // it works here
   doSomethingWithClauses{
     println someItem // hey cool it works here too
   }
 }

Tuesday, June 8, 2010

How to get rid of compiler errors

Today I stumbled about a page that gives a pretty cool introduction in how to setup grails 1.1 in eclipse:

http://www.objectpartners.com/2009/05/27/eclipse-setup-for-grails-11-development/

The author also explains how to get rid of compiler errors that are due to the acegi plugin. This helped to erase almost all of them, for the rest I think I should check whether the grails path is set correctly.

including javascript in gsp

Today I have tried out at least a hundred different ways for including js files into my main.gsp by hand. My approach looked like that:



I tried ${resource} first, but then I found this in grails Q&A:

Q: Why won't XXX Javascript Library Display Properly?

A: Sometimes third party javascript libraries depend upon other resources loaded directly from the javascript files themselves like stylesheets. Examples of libraries that do this would be the Yahoo UI libraries and niftycube. When the javascript attempts to load the URL Grails changes the URL so that the resource is not found. Try adding a link using the createLinkTo tag for the particular resource.

So it tried ${createLink}, but in the end nothing worked. I finally succeeded when I discovered that there was an extra taglib to do the trick with YUI JS files, which I was interested in:



The solution can be found in the most obvious place: http://www.grails.org/YUI+Plugin

Really wish I had looked there sooner :-)

Now I wonder if the problem was YUI specific and if my approach would work on other files. Maybe I'm going to find out some day...

Wednesday, June 2, 2010

Querying simple collections in grails

Imagine a domain class has a collection of simple types like e.g.

class Domain
{
static hasMany[strings: String]
}

What would you do if you wanted to have a set of all instances of Domain that have a string called "blabla". Well my first guess was to use the dynamic method findBy, but this does not work. The same goes for using Domain.withCriteria{}. I found the solution in a jira where you can find a feature request about that. Meanwhile you have to do the querying yourself. I have included a static method within my Domain class to avoid DRYness:

static def match(String matchThis)
{
Domain.executeQuery('from DBUser where :name in elements(strings)', [name: matchThis])
}

Problem solved...

Tuesday, June 1, 2010

datasources plugin for grails

In my current project I wanted to have content and security information separated from application specific settings. I therefore wanted to store the information into separate databases. This was far easier than expected with the datasources plugin from grails. I only had to install the plugin and add the file datasources.groovy to /grails-app/conf/

datasources = { 
 datasource(name: 'ds2'){
  domainClasses([org.openlab.settings.GlobalSetting, org.openlab.settings.UserSetting, org.openlab.security.Requestmap])
  pooled(true)
  driverClassName('org.hsqldb.jdbcDriver')
  url('jdbc:hsqldb:mem:devDB')
  username('sa')
  password('')
  dbCreate('create-drop')
  hibernate {
   cache {
    use_second_level_cache(false)
    use_query_cache(false)
   }
  }  
 } 
}

The usual datasource configuration remains intact and is the core or default database. In datasources.groovy you can define as many additional databases as you like. You only have to follow this pattern where the hibernate information is included as well as the definition of domain classes you wish to store in the new database.

The clear distribution of domain classes to datasources makes this approach easy and the only thing you have to consider are foreign key relations when separating the wrong domain classes.

Thursday, May 27, 2010

Microsoft SQL Server 2005 with GRAILS

Today I found a blog that helped me setting up MS SQL 2005 Express with Grails in a few minutes.

http://lsonline.de/blog/2009/11/grails-with-microsoft-sql-2005/

Friday, May 14, 2010

RichUI TreeView onLabelClick does not work with current YUI

Running into this problem again and again, I decided to finally write down what one has to change in order to make the onLabelClick work again:

The root of the problem is that in the current YUI the name of the action has changed. This is why you have to open the TreeViewRenderer.groovy in the src folder of the RichUI Plugin.

There you have to look for line 36 and switch "labelClick" with "clickEvent". VoilĂ .

Just a remark: If you want to access the id of the node late - please don't ask why - access node.node.additionalId in contrary to node.id or node.additionalId. Further change that line 37 accordingly.

Thursday, May 6, 2010

YUI layout manager



Yesterday I discovered the YUI layout manager. It is a javascript solutions dividing your browser viewport into up to 5 parts (top, bottom, left, right and center). If you ask, why should I use that thing and not rely on div/css. Here are some advantages I can immediately see here:
  1. It is super easy to produce the basic layout you like in <>
  2. You get cool js effects like resizing, toggling, etc.
  3. You can be sure that the layout works in every browser (YUI is reliable in this).
  4. It looks super cool and is skinnable via CSS.
Here is what you have to do:

Include the following resources:
<script type="text/javascript" src="http://yui.yahooapis.com/combo?2.8.0r4/build/utilities/utilities.js&2.8.0r4/build/container/container-min.js&2.8.0r4/build/resize/resize-min.js&2.8.0r4/build/layout/layout-min.js&2.8.0r4/build/menu/menu-min.js"/>
Include the following script:
<script type="text/javascript">
YAHOO.util.Event.onDOMReady(function() {
var layout = new YAHOO.widget.Layout({
units: [
{ position: 'top', height: 28, body: 'top1' },
{ position: 'right', header: 'Right', width: 300, resize: false, collapse: true, scroll: true, body: 'right1', animate: true, gutter: '5' },
{ position: 'bottom', height: 28, body: 'bottom1' },
{ position: 'left', header: 'Left', width: 200, body: 'left1', gutter: '5', resize: true, scroll: true, animate:true, collapse:true},
{ position: 'center', body: 'center1', gutter: '5 0', scroll: true }
]
});

layout.render();
});
</script>
The options are self-explaining and make the whole thing easy to configure. You can even nest layouts like in the attached screenshot.

Wednesday, May 5, 2010

access templates belonging to plugins - file not found exception

My current web project is split up into several parts. The best way to achieve this was utilizing the plugin mechanism of grails. Unfortunately grails (1.2 SNAPSHOT) is not able to find templates that are part of a plugin. I am quite sure I installed the plugins properly, as controllers, etc. are found.

Apparently, this is a known bug and lucky for me there is also a work-around presented:

render(template:"/bla/foo", plugin:"name-of-plugin", ...) and for gsp <g:render template="/bla/foo" plugin="name-of-plugin" ... />


Works perfectly as soon as you find out what the correct sPelLinG of your plugin is. In the end I used "grails list-plugins" to answer that question.

Tuesday, May 4, 2010

passing javascript parameters with remoteFunction

There have been a lot of examples where I needed to pass javascript variables through a remoteFunction in order to Ajax-Update a part of my web application.

I had almost given up when I found the solution in a blog entry. I wasn't able to guess the correct escaping of ' signs on my own, but this solution obviously got it right:

${remoteFunction(controller:'myController',
action:'someAction',update:'targetDiv',
params:'\'oneParameter=\'+jsOneParameter+\'&anotherParameter=\'+jsSecondParameter')};