Skip to content
This repository was archived by the owner on Jun 7, 2024. It is now read-only.

Adding plug in modules

mlist edited this page May 7, 2014 · 8 revisions

OLF can be extended with new functionality in a modular fashion. This could be anything, from a data analyis module for next-gen sequencing data to a cookbook for your favourite lab cake. OLF modules are more or less identical to grails plug-ins. The only difference is that developers implementing an OLF module are aware of the concepts for extending OLF's menu, adding tabs or adding operations to existing data objects, as well as for creating new add-ins.

This being said, we want to go step by step through the creation of a new very simplistic OLF module for lab stock management.

##Creating a grails plug-in The creation of a grails plug-in is very well described in the [grails user documentation] (http://grails.org/doc/latest/guide/plugins.html#creatingAndInstallingPlugins). We will assume that you have configured grails correctly.

grails create-plugin modules/OpenLabStocks

A new folder OpenLabStocks will appear that contains all you need to get started except of a few things.

You need to manually create a folder for the content modules OLF will need later under modules/your-plug-in/grails-app/

creating a folder for modules

OpenLabFramework will automatically load all plug-ins found in the modules folder. Therefore you can control which plug-ins to add to your installation by removing folders you don't want to use. You should, however, keep at least OpenLabBackend, since it provides the essential base functionality.

##Adding new functionality Our new module needs to get a data entity of its own to keep track of the different chemicals etc. we want to manage. We therefore switch back to the OpenLabStock folder where we introduce a new domain class called StockItem:

grails create-domain-class org.openlab.stock.StockItem

StockItem is a typical domain object and needs a little work:

package org.openlab.stock

import org.openlab.main.DataObject

class StockItem extends DataObject{

    String name
    String alternativeName
    String description
    boolean orderSoon

    String toString(){
        name
    }

    static mapping = {
        table 'olfStockItem'
    }

    static constraints = {
    }
}

It should be noted that mapping a table name explicitly is necessary in OLF in contrast to ordinary grails applications. The reason for this lies in the hierarchical class structure of OLF, which is based on inheritance. Now we should also a controller class. Instead of adding controller with generate-controller (the way it's normally done), we just create one from hand. Add a new class StockItemController.groovy to grails-app/controllers:

package org.openlab.stock

class StockItemController {  
    def scaffold = true
}

That's all? Yes, that's all. You are welcome to use generate-controller anyway to have the typical CRUD methods in here, but this comes at some disadavantages: You'll add redundancy, you'll loose clarity, and you'll have to propagate any changes in the scaffolding code to all classes that have their customized CRUD methods. What you should do however, is adding further methods to the controller, for instance:

package org.openlab.stock

class StockItemController {

    def scaffold = true

    def listStockItemsToOrder(){
        def stockItemsToOrder = StockItem.findAllByOrderSoon(true)
        
        render view: "list", model: [stockItemInstanceList: stockItemsToOrder, stockItemInstanceTotal: stockItemsToOrder.size()]
    }
}

We just added an additional action to the method that lists only stock items that need to be ordered. We don't even have to create a new view since we can just re-use the existing list view with a custom model.

##Add OpenLabStock to the menu OpenLabStock is already fully functional. However, no-one can use it unless it can be reached via the menu. We therefore add a MenuModule. Place this file under grails-app/modules

package org.openlab.module.menu

import groovy.xml.MarkupBuilder
import org.openlab.module.MenuModule

class StockMenuModule implements MenuModule{

    def getPriority()
    {
        6
    }

    def getMenu()
    {
        def writer = new StringWriter()
        def xml = new MarkupBuilder(writer)
        def controller = "stockItem"

        xml.root
                {
                    submenu(label: 'Lab Stocks')
                            {
                                menuitem(controller: controller, action: 'create', label: 'Create new Lab Stock')
                                menuitem(controller: controller, action: 'list', label: 'List Lab Stocks')
                                menuitem(controller: controller, action: 'listStockItemsToOrder', label: 'List Lab Stocks that need ordering')
                            }
                }

        return writer.toString()
    }
}

##First Results Let's look at the result of our hard work and start the web application. Switch to the OpenLabFrontend folder and execute

grails run-app

OpenLabStocks example

The beauty of grails and OLF is that scaffolding code handles both the database interaction and CRUD interactions without any additional work. Of course you'll have to invest a little more in order to get more complicated things done. However, all is possible since the hidden complexity of the underlying frameworks is at your finger tips.

Clone this wiki locally