Search

Dark theme | Light theme
Showing posts with label JDriven. Show all posts
Showing posts with label JDriven. Show all posts

March 5, 2013

Grails Seminar at JDriven

On March 26th we are organizing a Grails seminar at JDriven, the company I work for. During the seminar we will look at how and why you can be very productive with Grails. Some of the subjects we will cover are:

  • Business issues while developing web applications
  • Grails and Groovy - how do they fit in your Java architecture
  • Differences between Java/JEE
  • What is in it for you
  • How to migrate
  • Advantages

For more details (in Dutch) visit JDriven website.

September 27, 2012

New: JDriven Company Blog

I work for a company called JDriven in the Netherlands. We focus on technologies that simplify and improve development of enterprise applications. Since last week we started our own blog. Here you can find copies of the Groovy related blog posts from my own blog Messages from mrhaki. My colleagues also write blog posts about subjects like agile, Scrum, Spring technologies and much more.

You can check it out at blog.jdriven.com

April 9, 2012

Groovy Goodness: Collate a List into Sub-lists

I totally missed the new collate() method for List objects available since Groovy 1.8.6. With this method we can divide a list into sub-lists of a specified size. We can include a boolean parameter to indicate if we want to include remainders that don't fit in the specified size of the collated sub-lists. Finally we can use a parameter to define how many steps we go through the list before dividing the list into sub-lists.

def letters = 'a'..'g'

assert letters.collate(3) == [['a', 'b', 'c'], ['d', 'e', 'f'], ['g']]

// Step through original list with 
// 2 steps and collate.
assert letters.collate(3, 2) == [['a', 'b', 'c'], ['c', 'd', 'e'], ['e', 'f', 'g'], ['g']]

// Don't include remainder in result.
// Default a remainder is included in the result.
boolean remainder = false
assert letters.collate(3, remainder) == [['a', 'b', 'c'], ['d', 'e', 'f']]
assert letters.collate(3, 2, remainder) == [['a', 'b', 'c'], ['c', 'd', 'e'], ['e', 'f', 'g']]

March 8, 2012

Grails Goodness: Shortcut to Open Test Reports in Interactive Console

We can use the open command in the interactive console in Grails to open files. For example to edit the default layout view we can typ in the console:

grails> open grails-app/views/layouts/main.gsp

The application associated with GSP files starts and opens the file main.gsp.

So normally we have to pass actual filename with the complete path to the open command to open them. But Grails provides two shortcuts: test-report and dep-report. To see the output of our tests we can simply type open test-report:

grails> test-app
| Compiling 38 source files

| Tests PASSED - view reports in target/test-reports
grails> open test-report

Grails now opens the file target/test-reports/html/index.html.

The dep-report shortcut open the dependency report after we have run the dependency-report command:

grails> dependency-report
| Dependency report output to [/Users/mrhaki/samples/iconsole/target/dependency-report/index.html]
grails> open dep-report

March 5, 2012

Grails Goodness: Render GSP Views And Templates Outside Controllers

In a Grails application we use Groovy Server Pages (GSP) views and templates to create content we want to display in the web browser. Since Grails 2 we can use the groovyPageRenderer instance to render GSP views and templates outside a controller. For example we can render content in a service or other classes outside the scope of a web request.

The groovyPageRenderer instance is of type grails.gsp.PageRenderer and has a render() method like we use in a controller. We can pass a view or template name together with a model of data to be used in the GSP. The result is a String value.
The class also contains a renderTo() method that can be used to generate output to a Writer object. For example we can generate files with the output of the GSP rendering by passing a FileWriter instance to this method.

In the following sample we create a GSP view confirm.gsp and a GSP template _welcome.gsp. We also create a Grails service with two methods to use the GSP view and template.

%{-- File: grails-app/views/email/_welcome.gsp --}%
Hi, ${username}
%{-- File: grails-app/views/email/confirm.gsp --}%
<!doctype html>
<head>
    <title>Confirmation</title>
</head>

<body>

<h2><g:render template="/email/welcome" model="[username: username]"/></h2>

<p>
    Thank you for your registration.
</p>

</body>
</html>
// File: grails-app/services/page/renderer/RenderService.groovy
package page.renderer

import grails.gsp.PageRenderer

class RenderService {

    /**
     * Use the variable name groovyPageRenderer to enable
     * automatic Spring bean binding. Notice the variable
     * starts with groovy..., could be cause of confusing because
     * the type is PageRenderer without prefix Groovy....
     */
    PageRenderer groovyPageRenderer

    String createConfirmMessage() {
        groovyPageRenderer.render view: '/email/confirm', model: [username: findUsername()]
    }

    String createWelcomeMessage() {
        groovyPageRenderer.render template: '/email/welcome', model: [username: findUsername()]
    }

    private String findUsername() {
        // Lookup username, for this example we return a
        // simple String value.
        'mrhaki'
    }
}

Next we create a integration test to see if our content is rendered correctly:

// File: test/integration/page/renderer/RenderOutputTests.groovy
package page.renderer

import org.junit.Assert
import org.junit.Test

class RenderOutputTests {

    RenderService renderService

    @Test
    void welcomeMessage() {
        Assert.assertEquals 'Hi, mrhaki', renderService.createWelcomeMessage().trim()
    }

    @Test
    void confirmMessage() {
        final String expectedOutput = '''
        <!doctype html>
        <head>
            <title>Confirmation</title>
        </head>

        <body>

        <h2>
        Hi, mrhaki</h2>

        <p>
            Thank you for your registration.
        </p>

        </body>
        </html>'''

        Assert.assertEquals expectedOutput.stripIndent(), renderService.createConfirmMessage()
    }
}

We can run our test and everything is okay:

$ grails test-app RenderOutputTests
| Completed 2 integration tests, 0 failed in 1051ms
| Tests PASSED - view reports in target/test-reports

We can use tags from tag libraries in our GSP views and templates. The Sitemesh layouts cannot be used. The PageRenderer works outside of the request scope, which is necessary for the Sitemesh layouts. Because we are outside of the web request scope we cannot generate absolute links in the GSP view directly. If we change the confirm GSP view and add a tag to create an absolute link we get an UnsupportedOperationExeption with the message You cannot read the server port in non-request rendering operations.

%{-- File: grails-app/views/email/confirm.gsp --}%
<!doctype html>
<head>
    <title>Confirmation</title>
</head>

<body>

<h2><g:render template="/email/welcome" model="[username: username]"/></h2>

<p>
    Thank you for your registration.
</p>

<p>
    To use the application can you directly go to the
    <g:link absolute="true" controller="index">home page</g:link>.
</p>

</body>
</html>

But we can simply workaround this issue. Remember that since Grails 2 we can use the grailsLinkGenerator to generate links in for example a service. So we create our absolute link with the grailsLinkGenerator and pass it as a model attribute to our GPS view.

package page.renderer

import grails.gsp.PageRenderer
import org.codehaus.groovy.grails.web.mapping.LinkGenerator

class RenderService {

    PageRenderer groovyPageRenderer

    LinkGenerator grailsLinkGenerator

    String createConfirmMessage() {
        final String homePageLink = grailsLinkGenerator.link(controller: 'index', absolute: true)
        groovyPageRenderer.render(view: '/email/confirm', model: [link: homePageLink, username: findUsername()])
    }

    String createWelcomeMessage() {
        groovyPageRenderer.render template: '/email/welcome', model: [username: findUsername()]
    }

    private String findUsername() {
        // Lookup username, for this example we return a
        // simple String value.
        'mrhaki'
    }
}
%{-- File: grails-app/views/email/confirm.gsp --}%
<!doctype html>
<head>
    <title>Confirmation</title>
</head>

<body>

<h2><g:render template="/email/welcome" model="[username: username]"/></h2>

<p>
    Thank you for your registration.
</p>

<p>
    To use the application can you directly go to the
    <a href="${link}">home page</a>.
</p>

</body>
</html>

January 23, 2012

Groovy Goodness: Solve Naming Conflicts with Builders

With Groovy we can use for example the MarkupBuilder or JSONBuilder to create XML or JSON content. The builders are a very elegant way to create the content. Most builders in Groovy use the invokeMethod and getProperty and setProperty methods to dynamically build the contents. But this also means that if we have builder node names that are the same as method or property names in the local context of our code running the builder, that we have a naming conflict. Let's see this with a simple sample:

import groovy.xml.*

def body = []

def writer = new StringWriter()
def builder = new MarkupBuilder(writer)
builder.message {
    body(contentType: 'plain') {
        text 'Simple message'
    }
}

def contents = writer.toString()
println contents

When we run this code we get an error message:

groovy.lang.MissingMethodException: No signature of method: java.util.ArrayList.call() is applicable for argument types: (java.util.LinkedHashMap, xmlmessage$_run_closure1_closure2) values: [[contentType:plain], xmlmessage$_run_closure1_closure2@50502819]
Possible solutions: tail(), wait(), last(), any(), max(), clear()
 at xmlmessage$_run_closure1.doCall(xmlmessage.groovy:7)
 at xmlmessage$_run_closure1.doCall(xmlmessage.groovy)
 at xmlmessage.run(xmlmessage.groovy:6)

Groovy tries to use the ArrayList class of our books variable to execute a call method with two parameters of type LinkedHashMap and closure. So our local variable is found by the builder and the builder tries to use this variable, which results in the shown error.

The following sample shows what happens if we have a local method with the same name as a node in the builder:

import groovy.xml.*

def body(value) {
    println "body contents is $value"
}

def writer = new StringWriter()
def builder = new MarkupBuilder(writer)
builder.message {
    body {
        text 'Simple message'
    }
}

def contents = writer.toString()
println contents

We get the following output if we run this script:

body contents is 
<message>
  <text>Simple message</text>
</message>

Our method with the name body has the same signature and name as the body node in the builder. Our local method is invoked and we see the output of the println statement.

To solve this naming conflict we can change the name of our local variable or method. But this is not always possible or desired. Imagine the method or variable is dynamically added to our class than we cannot change the name. But we can also change our builder syntax slightly to get what we want.

To force our builder to use the builder's code to create the contents we can prepend the node name with delegate. Delegate is the closure context of our builder. This way our builder will not use any already defined variable or method names to create the content.

import groovy.xml.*

def body = []

def writer = new StringWriter()
def builder = new MarkupBuilder(writer)
builder.message {
    delegate.body(contentType: 'plain') {
        text 'Simple message'
    }
}

def contents = writer.toString()
println contents

When we run the script we get the following output:

<message>
  <body contentType='plain'>
    <text>Simple message</text>
  </body>
</message>

And that is the output we want.

If we are using Grails and use the render method to create XML or JSON we must be aware that methods are also dynamically available in a controller. For example the message method from the Grails tag libraries is a method in a controller:

package builder.naming

class SampleController {

    def index() {
        render(contenType: 'text/xml') {
            message {
                content 'Contents'
            }
        }
    }
}

If we invoke this controller we get the following XML output:

<content>Contents</content>

But if we change the code to:

package builder.naming

class SampleController {

    def index() {
        render(contenType: 'text/xml') {
            delegate.message {
                content 'Contents'
            }
        }
    }
}

We get the following output:

<message><content>Contents</content></message>