Friday, November 30, 2012

STS 3.1.0 and Grails 2.1.1 Exception jline_.dll already loaded in another classloade​r

I set up a new Grails project in STS 3.1.0 and I always got the below exception when I tried to edit a file. Sometimes it works (after I closed STS and restart) sometimes not.

I never found the displayed folder! C:\Users\hhb\AppData\Local\Temp\jline_.dll already loaded in another classloader.

Before, I converted 2 projects to STS 3.1.0 and Grails 2.1.1 from earliers releases and I had no issues with this projects.

The cause of this exception was, that I copied outside of STS from the file system some Groovy classes to the new project which had no or wrong package names. This needed to be fixed outside of STS.

java.lang.UnsatisfiedLinkError: Native Library C:\Users\hhb\AppData\Local\Temp\jline_.dll already loaded in another classloader at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1768) at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1699) at java.lang.Runtime.load0(Runtime.java:770) at java.lang.System.load(System.java:1003) at jline.WindowsTerminal.loadLibrary(WindowsTerminal.java:322) at jline.WindowsTerminal.initializeTerminal(WindowsTerminal.java:240) at jline.Terminal.setupTerminal(Terminal.java:75) at jline.Terminal.getTerminal(Terminal.java:26) at jline.ConsoleReader.(ConsoleReader.java:174) at jline.ConsoleReader.(ConsoleReader.java:169) at grails.build.logging.GrailsConsole.createConsoleReader(GrailsConsole.java:169) at grails.build.logging.GrailsConsole.(GrailsConsole.java:133) at grails.build.logging.GrailsConsole.createInstance(GrailsConsole.java:268) at grails.build.logging.GrailsConsole.getInstance(GrailsConsole.java:245) at org.codehaus.groovy.grails.cli.logging.GrailsConsoleErrorPrintStream.println(GrailsConsoleErrorPrintStream.java:59) at org.codehaus.jdt.groovy.internal.compiler.ast.GroovyErrorCollectorForJDT.addErrorAndContinue(GroovyErrorCollectorForJDT.java:34) at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:107) at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:126) at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:135) at org.codehaus.groovy.control.SourceUnit.addError(SourceUnit.java:392) at org.codehaus.groovy.antlr.ErrorRecoveredCSTParserPlugin.reportCST(ErrorRecoveredCSTParserPlugin.java:156) at org.codehaus.groovy.antlr.ErrorRecoveredCSTParserPlugin.transformCSTIntoAST(ErrorRecoveredCSTParserPlugin.java:128) at org.codehaus.groovy.antlr.AntlrParserPlugin.parseCST(AntlrParserPlugin.java:115) at org.codehaus.groovy.control.SourceUnit.parse(SourceUnit.java:264) at org.codehaus.groovy.control.CompilationUnit$8.call(CompilationUnit.java:186) at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:940) at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:612) at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:588) at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:565) at org.codehaus.jdt.groovy.internal.compiler.ast.GroovyCompilationUnitDeclaration.processToPhase(GroovyCompilationUnitDeclaration.java:171) at org.codehaus.jdt.groovy.internal.compiler.ast.GroovyParser.dietParse(GroovyParser.java:455) at org.codehaus.jdt.groovy.integration.internal.MultiplexingSourceElementRequestorParser.parseCompilationUnit(MultiplexingSourceElementRequestorParser.java:73) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process_aroundBody0(CompilationUnitProblemFinder.java:200) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process_aroundBody1$advice(CompilationUnitProblemFinder.java:244) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java:1) at org.codehaus.jdt.groovy.model.GroovyCompilationUnit.buildStructure(GroovyCompilationUnit.java:319) at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:258) at org.eclipse.jdt.internal.core.JavaElement.openWhenClosed(JavaElement.java:526) at org.eclipse.jdt.internal.core.BecomeWorkingCopyOperation.executeOperation(BecomeWorkingCopyOperation.java:38) at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:728) at org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:788) at org.eclipse.jdt.internal.core.CompilationUnit.becomeWorkingCopy(CompilationUnit.java:102) at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitDocumentProvider.createFileInfo(CompilationUnitDocumentProvider.java:999) at org.eclipse.ui.editors.text.TextFileDocumentProvider.connect(TextFileDocumentProvider.java:478) at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitDocumentProvider.connect(CompilationUnitDocumentProvider.java:1242) at org.eclipse.ui.texteditor.AbstractTextEditor.doSetInput(AbstractTextEditor.java:4222) at org.eclipse.ui.texteditor.StatusTextEditor.doSetInput(StatusTextEditor.java:237) at org.eclipse.ui.texteditor.AbstractDecoratedTextEditor.doSetInput(AbstractDecoratedTextEditor.java:1480) at org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.internalDoSetInput(JavaEditor.java:2584) at org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.doSetInput(JavaEditor.java:2557) at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor.doSetInput(CompilationUnitEditor.java:1395) at org.codehaus.groovy.eclipse.editor.GroovyEditor.doSetInput(GroovyEditor.java:1019) at org.eclipse.ui.texteditor.AbstractTextEditor$19.run(AbstractTextEditor.java:3209) at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464) at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372) at org.eclipse.ui.internal.WorkbenchWindow$13.run(WorkbenchWindow.java:1675) at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:1672) at org.eclipse.ui.texteditor.AbstractTextEditor.internalInit(AbstractTextEditor.java:3227) at org.eclipse.ui.texteditor.AbstractTextEditor.init(AbstractTextEditor.java:3254) at org.eclipse.ui.internal.EditorReference.initialize(EditorReference.java:324) at org.eclipse.ui.internal.e4.compatibility.CompatibilityPart.create(CompatibilityPart.java:288) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:56) at org.eclipse.e4.core.internal.di.InjectorImpl.processAnnotated(InjectorImpl.java:859) at org.eclipse.e4.core.internal.di.InjectorImpl.processAnnotated(InjectorImpl.java:839) at org.eclipse.e4.core.internal.di.InjectorImpl.inject(InjectorImpl.java:111) at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:319) at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:240) at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:161) at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:102) at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:71) at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:53) at org.eclipse.e4.ui.workbench.renderers.swt.ContributedPartRenderer.createWidget(ContributedPartRenderer.java:141) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createWidget(PartRenderingEngine.java:896) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:630) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:732) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:703) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:697) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:682) at org.eclipse.e4.ui.workbench.renderers.swt.StackRenderer.showTab(StackRenderer.java:1114) at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer$1.handleEvent(LazyStackRenderer.java:67) at org.eclipse.e4.ui.services.internal.events.UIEventHandler$1.run(UIEventHandler.java:41) at org.eclipse.swt.widgets.Synchronizer.syncExec(Synchronizer.java:180) at org.eclipse.ui.internal.UISynchronizer.syncExec(UISynchronizer.java:150) at org.eclipse.swt.widgets.Display.syncExec(Display.java:4687) at org.eclipse.e4.ui.internal.workbench.swt.E4Application$1.syncExec(E4Application.java:187) at org.eclipse.e4.ui.services.internal.events.UIEventHandler.handleEvent(UIEventHandler.java:38) at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:197) at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:197) at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1) at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230) at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148) at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:135) at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:78) at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:39) at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:81) at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:58) at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:374) at org.eclipse.e4.ui.model.application.ui.impl.ElementContainerImpl.setSelectedElement(ElementContainerImpl.java:171) at org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.showElementInWindow(ModelServiceImpl.java:418) at org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.bringToTop(ModelServiceImpl.java:385) at org.eclipse.e4.ui.internal.workbench.PartServiceImpl.delegateBringToTop(PartServiceImpl.java:579) at org.eclipse.e4.ui.internal.workbench.PartServiceImpl.bringToTop(PartServiceImpl.java:315) at org.eclipse.e4.ui.internal.workbench.PartServiceImpl.showPart(PartServiceImpl.java:985) at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:3079) at org.eclipse.ui.internal.WorkbenchPage.access$22(WorkbenchPage.java:3003) at org.eclipse.ui.internal.WorkbenchPage$8.run(WorkbenchPage.java:2985) at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2981) at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2940) at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2931) at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:373) at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:179) at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:249) at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:228) at org.eclipse.jdt.ui.actions.SelectionDispatchAction.dispatchRun(SelectionDispatchAction.java:275) at org.eclipse.jdt.ui.actions.SelectionDispatchAction.run(SelectionDispatchAction.java:251) at org.eclipse.jdt.internal.ui.navigator.OpenAndExpand.run(OpenAndExpand.java:50) at org.eclipse.ui.actions.RetargetAction.run(RetargetAction.java:221) at org.eclipse.ui.navigator.CommonNavigatorManager$3.open(CommonNavigatorManager.java:185) at org.eclipse.ui.OpenAndLinkWithEditorHelper$InternalListener.open(OpenAndLinkWithEditorHelper.java:48) at org.eclipse.jface.viewers.StructuredViewer$2.run(StructuredViewer.java:866) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49) at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175) at org.eclipse.jface.viewers.StructuredViewer.fireOpen(StructuredViewer.java:864) at org.eclipse.jface.viewers.StructuredViewer.handleOpen(StructuredViewer.java:1152) at org.eclipse.ui.navigator.CommonViewer.handleOpen(CommonViewer.java:462) at org.eclipse.jface.viewers.StructuredViewer$6.handleOpen(StructuredViewer.java:1256) at org.eclipse.jface.util.OpenStrategy.fireOpenEvent(OpenStrategy.java:275) at org.eclipse.jface.util.OpenStrategy.access$2(OpenStrategy.java:269) at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:309) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4169) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3758) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1029) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:923) at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:86) at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:588) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:543) at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:124) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584) at org.eclipse.equinox.launcher.Main.run(Main.java:1438)

Tuesday, November 23, 2010

GrailsExceptionResolver null pointer exception

This is the message I got after I hit a button in the gsp with an action="waiver".

23.11.10 09:36:35.054] ERROR errors.GrailsExceptionResolver - null
java.lang.NullPointerException
at java.lang.Thread.run(Thread.java:619)

I had a hard time to figure out this problem. The associated controller had an action:

def waiver = {
}

and the waver.gsp exists.

Now why did the exception happen? The reason was, because the controller has a method called getWaiver().

Friday, November 19, 2010

Log4J problem after deployment to Tomcat

The problem not happens on STS with Jetty.

By mistype a log statement, instead of:
log.debug("....")
typed
Log.debug("...."), oops that's wrong!!
this was the cause for an exception on the tomcat server:

org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.NoClassDefFoundError: org.mortbay.log.Log
org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet.doDispatch(GrailsDispatcherServlet.java:318)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:70)
org.codehaus.groovy.grails.web.util.WebUtils.forwardRequestForUrlMappingInfo(WebUtils.java:293)
org.codehaus.groovy.grails.web.util.WebUtils.forwardRequestForUrlMappingInfo(WebUtils.java:269)
org.codehaus.groovy.grails.web.util.WebUtils.forwardRequestForUrlMappingInfo(WebUtils.java:261)
org.codehaus.groovy.grails.web.mapping.filter.UrlMappingsFilter.doFilterInternal(UrlMappingsFilter.java:181)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.codehaus.groovy.grails.web.sitemesh.GrailsPageFilter.obtainContent(GrailsPageFilter.java:171)
org.codehaus.groovy.grails.web.sitemesh.GrailsPageFilter.doFilter(GrailsPageFilter.java:110)
org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:65)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
root cause
java.lang.NoClassDefFoundError: org.mortbay.log.Log
SocService$_save_closure1.class$(SocService.groovy)
SocService$_save_closure1.$get$$class$org$mortbay$log$Log(SocService.groovy)
SocService$_save_closure1.doCall(SocService.groovy:86)
SocService.save(SocService.groovy:44)
SocService$$FastClassByCGLIB$$830c874e.invoke()
net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
SocService$$EnhancerByCGLIB$$277a9fbf.save()
SocService$save.call(Unknown Source)
DocumentEditController$_closure2_closure33_closure117.doCall(DocumentEditController.groovy:997)


Config.groovy entries:
// log4j configuration
log4j = {
appenders {
console name: 'stdout', layout: pattern(conversionPattern:'%d{[dd.MM.yy HH:mm:ss.SSS]} %-5p %c{2} %x - %m%n')
rollingFile name: 'file', layout: pattern(conversionPattern:'%d{[dd.MM.yy HH:mm:ss.SSS]} %-5p %c{2} %x - %m%n'), file: 'fab.log'
}
root {
error()
additivity = true
}

error 'org.codehaus.groovy.grails.web.servlet', // controllers
'org.codehaus.groovy.grails.web.pages', // GSP
'org.codehaus.groovy.grails.web.sitemesh', // layouts
'org.codehaus.groovy.grails."web.mapping.filter', // URL mapping
'org.codehaus.groovy.grails."web.mapping', // URL mapping
'org.codehaus.groovy.grails.commons', // core / classloading
'org.codehaus.groovy.grails.plugins', // plugins
'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration
'org.springframework',
'org.hibernate'

debug file:['grails.app']
'org.hibernate'
//stdout:'grails.app'

warn 'org.mortbay.log'

}

Saturday, January 30, 2010

GrailsUI.datePicker versus RichUI.dateChooser

The issue is, to work with and control the tab key from the keyboard and get a reference to the id param in the tag richui:dateChooser or gui:datePicker.

e.g:
< onfocus="document.getElementById('filingDate').focus();" tabindex="1">
< id="filingDate" name="filingDate" formatstring="MM/dd/yyyy">
< /td >

In both plugins the id is documented, but only GrailsUI works. RichUI generates an artifical id and no reference is possible. The work with tab key in GrailsUI is more predictable than in RichUI.

Another difference between RichUI and GrailsUI is, how the params are delievered to a command object:
In RichUI: filingDate = "struct"
filingDate_month = "01"
filingDate_day = "30"
filingDate_year = "2010"

In GrailsUI: filingDate = "01/30/2010"

Additional tip:
RichUI don't modifies the page layout.
GrailsUI does. To prevent this following modifications can be made:

1. In main.gsp - move "g:layoutHead" before link to the css
< rel="stylesheet" href="${createLinkTo(dir:'css',file:'main.css')}" >

2. In the app gsp, put this line
gui:resources components="['datePicker']"
as first line after the head tag

3. Overwrite GailsUI grails-ui.css in own css file:
.datefield {
position:relative;
top:0px;
left:0px;
white-space:nowrap;
width:25em;
padding:0px 10px 0px 0px;
}

.datefield input {
width:75px;
}

Saturday, January 3, 2009

Transient properties in a domain class

It is always a common problem to create display values for a view from persistent data. Database amounts don’t have a $ sign and are not formatted, or phone numbers, dates etc. This format conversion can be done in the view with specific tags like g:formatDate or g:formatNumber, or by an own developed tag.

But if there is a specific logic to create a display value this could be done directly in the domain class with a transient variable and the related method.

class Address implements Serializable {

String acctAddr1
String acctAddr2
String acctAddr3

ZipCode zipCode

static transients = ['cityState']

static constraints = {
acctAddr1(nullable:true, blank:true, maxSize:30)
acctAddr2(nullable:true, blank:true, maxSize:30)
acctAddr3(nullable:true, blank:true, maxSize:30)
zipCode(nullable:true)
}

String getCityState() {
if ( zipCode ) {
return zipCode.city + "," + zipCode.state + " " + zipCode.zipCode
else
return ""
}
}
}

class ZipCode implements Serializable {

String zipCode
String state
String city

static constraints = {
zipCode(nullable:false, maxSize:10)
state(nullable:false, maxSize:2)
city(nullable:false, maxSize:30)
}
}

Thursday, January 1, 2009

View event (request) handling and controller design

The default Grails CRUD application consists of one controller (responsible for requests) and four pages (views). These are list, create, edit, show pages. A new controller instance is created for each request. The request can handle in different ways:

  • Call a view (page)
  • Interaction with a domain, service, get data for passing it to a view or from a view (page)
  • Writing directly to the response writer
  • Redirecting to another action in the same controller or to another controller

If no action is specified by calling a controller (e.g. URI) the controller handles a default action.

  • If the controller defines only one action, it becomes the default action.
  • A action called index, becomes the default action.def index = { redirect(action:list) }
  • A value of a defined string property called defaultAction.def defaultAction = ‘list’

A CRUD controller has the actions: index (default action), list (show list of entries), create (render create view from list), save (save new domain from create view), edit (render edit view from list), update (update existing domain from edit view), delete (delete domain from list view), show (render show view from list).

Beyond CRUD applications the page flow (views) and event (request) handling becomes more complex and complicated. Even for CRUD applications, I am wondering why we need 3 views for create, edit and show.

Controller design considerations:

Assuming a number of views in a flow to collect data where at the end follows an action (for e.g. save).

  1. One controller for one view.
  2. One controller for all views with action, redirect etc.
  3. One controller for all views with a web flow http://grails.org/WebFlow.

I suggest the third solution, even if I have good experience with solution 1. The advantage I see is the maintenance, that all requests are covered in one controller which belongs to this view flow. The grails web flow has 5 different scope you can utilize:

  • request - Stores an object for the scope of the current request
  • flash - Stores the object for the current and next request only
  • flow - Stores objects for the scope of the flow, removing them when the flow reaches an end state
  • conversation - Stores objects for the scope of the conversation including the root flow and nested subflows
  • session - Stores objects inside the users session

See example on the Web Page http://www.hbbaeuerle.com/html/controller.html

Saturday, October 18, 2008

Usage of Regular Expression for validation

To use the Regular Expression facility will save a lot of coding. It works perfect together with Grails validation in Domain or Command classes. You should use it!

For more information see: http://www.hbbaeuerle.com/html/regular_expression.html

http://www.hbbaeuerle.com/