alexgorbatchev

Tuesday, July 11, 2017

Gorm - Sorting by calculated or derived field

Recently, while trying to work with a legacy database I needed to create a default sort on a String field that sometimes held a number. One cannot simply sort on the String field because it will produce incorrect results, such as [1, 10, 11,..., 2, 20, ...]. A simple method for correcting this is to pad the field with 0's, so that it produces the results [00001, 00002, 00010, ...]). In order to accomplish this by default in the domain class, in the domain's mapping closure simply add a formula to a sort field.

To create a default sort on a calculated or derived field

class Book {
String name
String bookOrder //<-- String data type for the purposes of the example
String sortField //<-- Calculated/Derived field
static mapping = {
// Note the use of the database field name 'book_order', not the object's property name bookOrder
sortField formula: 'lpad(book_order, 5, \'0\')' // <-- SQL formula used to generate the sortField value in GORM
sort sortField: 'asc'
}
String toString() {
bookOrder
}
}
view raw Book.groovy hosted with ❤ by GitHub

After loading a series of 20 books into GORM (GORM Book loading code below), retrieving them using Book.list() should produce [1, 2, ..., 10, 11, ..., 20]

(20..1).each {
new Book(name: "Book $it", bookOrder: it.toString()).save()
}

References

Tuesday, November 8, 2016

Add custom Nexus Repository OSS to your Grails 3 Gradle build

After creating Grails 3 plugins and publishing them to your private/public Nexus Repository OSS server, you will want to use them in your projects. To use your custom Grails 3 plugins just add the following closure block to the repositories closure in build.gradle:

repositories {
...
maven {
credentials {
username NEXUS_USERNAME
password NEXUS_PASSWORD
}
url 'https://[my.nexus.repo]/repository/releases/'
}
}
view raw build.gradle hosted with ❤ by GitHub

As with previous examples, NEXUS_USERNAME and NEXUS_PASSWORD are project parameters that you can store in gradle.properties file or pass on the command line.

Publishing Grails 3 plugins to Nexus Repository OSS using Gradle

To publish a Grails 3 plugin to Nexus Repository OSS is extremely simple because the necessary Gradle plugin is already included in the build.gradle file by default. Just add a publishing closure to the build.gradle file and you are ready to push to your private Nexus Repository OSS server.

publishing {
repositories {
maven {
credentials {
username NEXUS_USERNAME
password NEXUS_PASSWORD
}
url "http://[my.nexus.repo]/repository/releases/"
}
}
}
view raw build.gradle hosted with ❤ by GitHub
As in the Grails application publishing example, the NEXUS_USERNAME and NEXUS_PASSWORD keywords are parameters that you store in gradle.properties and can overwrite with command line parameters, such as
./gradlew -PNEXUS_USERNAME=[your_username] -PNEXUS_PASSWORD=[your_password] publish-plugin
view raw command line hosted with ❤ by GitHub

** Edit **

Per Amad's comments, the grailsPublish closure may be required. I modified the attributes in the closure supplied by the create-plugin script as follows:

// dependencies
grailsPublish {
user = 'dspies'
key = 'key'
githubSlug = 'foo/bar'
license {
name = 'Apache-2.0'
}
title = 'My Plugin Name'
desc = 'My Plugin Description'
developers = [dspies:'David Spies']
portalUser = ''
portalPassword = ''
}
// rest of build.gradle

Publishing Grails 3 applications to Nexus Repository OSS using Gradle

To publish a Grails 3 application to Nexus Repository OSS you just need to make a few tweaks to the build.gradle file.  Just add the Gradle maven-publish plugin and a publishing closure to the build.gradle file and you are ready to push to your private Nexus Repository OSS server.

apply plugin:"maven-publish"
// Other closure blocks
publishing {
publications {
maven(MavenPublication) {
from components.java
}
}
repositories {
maven {
credentials {
username NEXUS_USERNAME
password NEXUS_PASSWORD
}
url "https://[my.nexus.repo]/repository/releases/"
}
}
}
view raw build.gradle hosted with ❤ by GitHub

Above, the NEXUS_USERNAME and NEXUS_PASSWORD are parameters that you store in gradle.properties and can overwrite with command line parameters, such as

./gradlew -PNEXUS_USERNAME=[your_username] -PNEXUS_PASSWORD=[your_password] publish
view raw command line hosted with ❤ by GitHub

Tuesday, June 21, 2016

Angular 2 Exceptions: TypeError: Cannot read property 'annotations' of undefined

After playing with the newest incarnation of the Angular 2 Router (version 3.0.0-alpha.7) on a seperate test branch, I came back to my mainline branch and cleared my node_modules, build, tmp, and typings directories just to be safe. After reinstalling my npm modules (npm install), I received this gem, "TypeError: Cannot read property 'annotations' of undefined". Knowing that it was working prior to creating my test branch, and after some frustration examined the error a bit closer and saw that the html template causing the issue was related to the the routerLink directive, or more generally the Angular Router package. Digging into it a bit more I discovered that my npm semver for @angular/router-deprecated was "^2.0.0-rc.1" instead of "2.0.0-rc.1" and therefore was installing the Angular 2 RC-2 version of the deprecated router and was causing the error. After correcting the package, more specifcially the semver, for router-deprecated to 2.0.0-rc.1 and re-running npm install, all was well with the world.

The full exception is:


Friday, June 17, 2016

Angular 2 Exceptions: TypeError: (msg || "").replace is not a function

While performing tdd using the Angular CLI, I have come across this exception a few times. In most cases this is caused by a missing import.  The Angular CLI kicks off a test before an import has been added to the component (or service, etc).  If you have the benefit of an IDE, check that it has not highlighted a problem with one of your imports.

The full exception is:

17 06 2016 08:46:39.287:WARN [web-server]: 404: /base/dist/traceur
Missing error handler on `socket`.
TypeError: (msg || "").replace is not a function
at /home/dspies/projects/sms/node_modules/karma/lib/reporter.js:45:23
at onBrowserError (/home/dspies/projects/sms/node_modules/karma/lib/reporters/base.js:58:60)
at null.<anonymous> (/home/dspies/projects/sms/node_modules/karma/lib/events.js:13:22)
at emitTwo (events.js:100:13)
at emit (events.js:185:7)
at onKarmaError (/home/dspies/projects/sms/node_modules/karma/lib/browser.js:95:13)
at Socket.<anonymous> (/home/dspies/projects/sms/node_modules/karma/lib/events.js:13:22)
at emitOne (events.js:95:20)
at Socket.emit (events.js:182:7)
at Socket.onevent (/home/dspies/projects/sms/node_modules/socket.io/lib/socket.js:335:8)
at Socket.onpacket (/home/dspies/projects/sms/node_modules/socket.io/lib/socket.js:295:12)
at Client.ondecoded (/home/dspies/projects/sms/node_modules/socket.io/lib/client.js:193:14)
at Decoder.Emitter.emit (/home/dspies/projects/sms/node_modules/component-emitter/index.js:134:20)
at Decoder.add (/home/dspies/projects/sms/node_modules/socket.io-parser/index.js:247:12)
at Client.ondata (/home/dspies/projects/sms/node_modules/socket.io/lib/client.js:175:18)
at emitOne (events.js:90:13)
at Socket.emit (events.js:182:7)
at Socket.onPacket (/home/dspies/projects/sms/node_modules/engine.io/lib/socket.js:101:14)
at emitOne (events.js:90:13)
at WebSocket.emit (events.js:182:7)
at WebSocket.Transport.onPacket (/home/dspies/projects/sms/node_modules/engine.io/lib/transport.js:104:8)
at WebSocket.Transport.onData (/home/dspies/projects/sms/node_modules/engine.io/lib/transport.js:115:8)
view raw BadImport.log hosted with ❤ by GitHub

Tuesday, April 5, 2016

Grails 3 war file naming issues in Jenkins

Correcting the war file/artifact/package name in grails package

By default my Jenkins build server puts its projects into a directory called 'workspace' so when I run grails package it creates a war/jar called workspace-0.1.war/jar.  In order to generate the correct jar/war file name, you can create a file called settings.gradle in the root of the project with a single property rootProject.name and specify the name you would like:

rootProject.name = 'my-project'
view raw settings.gradle hosted with ❤ by GitHub
and when you run grails package it will create the appropriate my-project-0.1.jar/war

Resources:

  • http://stackoverflow.com/questions/32976039/how-do-you-change-the-application-name-in-grails-3