Friday, April 22, 2011

Invoking a groovy script from a Java class

Here is a small script to send an email as \util\SendEmail.groovy
//Read properties
def emailHost = config['email.host']
def email = config['monitor.fromAddress']

//Sending an email notification
new AntBuilder().mail(mailhost:"${emailHost}", messagemimetype:'text/html',
            subject:"${sub}"){
          from(address:"${email}")
          to(address:"${email}")
          message("${content}")
      }

Now we need to invoke the script by injecting the properties into the script.
Here is the Java logic to invoke the script. There few other alternative way to invoke the script but this is one of them...



      /**
       *
       * @param message
       */
      private static void emailException(String message) {
            try {
                  GroovyScriptEngine gse = new GroovyScriptEngine(".\\util");
                  Binding binding = new Binding();
                  binding.setVariable("sub", "An exception notification - " + InetAddress.getLocalHost().getHostName());
                  binding.setVariable("content", message);
                  binding.setVariable("config", PropertyMgr.getInstance()); //this is illustrate injecting a Java object instance.
                  gse.run("SendEmail.groovy", binding);
           
            } catch (IOException e1) {
                  e1.printStackTrace();
                  logger.error(e1);
            } catch (ResourceException e1) {
                  e1.printStackTrace();
                  logger.error(e1);
            } catch (ScriptException e1) {
                  e1.printStackTrace();
                  logger.error(e1);
            }
      }

Share you comments!!

Friday, April 15, 2011

A quick groovy script to copy file from one folder to another

It quite interesting to use groovy script for simple task as this. Here is an example how can we copy the files from one folder to another...

def sourceDir = "C:\\Source"
def destinationDir = "C:\\Target"


//checking for source directory
def directory = new File("${sourceDir}")
if (!directory.isDirectory()) {
println "The provided directory name ${sourceDir} is NOT a directory."
}


//Clousre
def write = {data, lenth ->
output.write(data, 0, lenth)
}


//Closure
def fileCopyClosure = {
    if(it.canRead()) { //make sure whether you can read it
       def destFolder = new File("${destinationDir}")
          if(!destFolder.exists()) {
              println("Creating new destination directory  [${destFolder}]")
              destFolder.mkdir()
          }


          println "processing ${it.name} from ${it.canonicalPath}"


         def desti = new File("${destinationDir}\\${it.name}")


         //create output stream
         output = desti.newOutputStream()
         it.eachByte(1024, write)
         output.close()


         println "Copy completed${desti.name}"
     }
}
directory.eachFileRecurse(fileCopyClosure)

Invoking AJAX call from Grails

Usecase:
Need to populate second drop down values based on the selected first drop down value.
In this example let us discuss about populating the available applications on a selected server.

Implementation:
* In your main .gsp page, associate an id to the first select drop down(i.e. server drop down). The code snippet displays the list of server via domain class Server.groovy.

<g:select>
from="${Server.list()}"
id="serverSelect" noSelection="['':'-- Select Server --']"
name="selectedServer" value="${domainInstance?.selectedServer}"
optionKey="name" optionValue="name">
</g:select>


* Wrap the second select drop down (i.e. Application list) into a div tag.

<div id="appversion_select" >
<g:select from="${domainInstance?.applications}"
name="appVersion" value="${domainInstance?.selectedApplication}">
</g:select>
</div>

* Add the required javascript function invoke AJAX call to backed controller. Follow in line comments..

//This script listens to a change in the value of the select drop donw bearing an id as 'serverSelect'
document.observe('dom:loaded', function() {
$("serverSelect").observe("change", respondToServerSelect);
});

function respondToServerSelect(event)
{
//It inovkes the associated controller with selectedServer as parameter and updated the response in a
//bearing id as 'appversion_select'

new Ajax.Updater("appversion_select",

"/server/getAppsFromServer",

{method:'get', parameters: {

selectedServer : $F("selectedServer")
}
}
);
}


* Add a GSP matching the return view of the getAppFromServer method from the controller, default you can create getAppsFromServer.gsp with following code. This same as second dropdown code.

<g:select from="${domainInstance?.applications}"
name="appVersion" value="${domainInstance?.selectedApplication}">
</g:select>

* Controller code: Here is the closure required in the controller class

def getAppsFromServer = {
println ("Retrieve the application from the server")

def existingApps = new ArrayList()

// invoke the business service to get the applications.
domainInstance.appVersions = existingApps
return [domainInstance: domainInstance]
}


Once you cover all of them, now you should be able to populate the application list based on the selected server.

Appreciate your comments.....

Saturday, March 12, 2011

Integrating Grails application with LDAP for user authentication

Although there are many other sources where we can find information about the Grails and its plugins. I have gone through few difficulties while implementing the Grails LDAP plugin for user authentication.

So I would like to put all things in one place to cover the required aspects of "Integrating Grails application with your corporate Active Directory.

As LDAP plugin requires the spring security core plugin, we will begin with installing the security core plugin..

Step 1: Installing the spring security core plugin

Execute the command: grails install-plugin spring-security-core

Once the plugin is installed, we need to run the below script to create the necessary domain classes, controller objects.

While executing the command, we need to provide the domain class name for SecurityUser and SecurityRole

grails s2-quickstart com.adepu.security.SecuredUser com.adepu.security.SecuredRole


It creates the 3 domain classes and two controllers, addes the following line to Config.groovy configuration file

// Added by the Spring Security Core plugin:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'com.adepu.security.SecuredUser'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'com.adepu.security.SecuredUserSecuredRole'
grails.plugins.springsecurity.authority.className = 'com.adepu.security.SecuredRole'

For more information refer to http://www.grails.org/plugin/spring-security-core

Step 2: Installing the spring security LDAP plugin

Execute the commandgrails install-plugin spring-security-ldap

Once the command executed successfully, you need to add following configuration in Config.groovy.

grails.plugins.springsecurity.ldap.context.server = 'ldap://ds.main.adepu.com:389'
grails.plugins.springsecurity.ldap.context.managerDn = 'CN=_ADQuery,OU=Groups,DC=main,DC=adepu,DC=com'
grails.plugins.springsecurity.ldap.context.managerPassword = 'secret'
grails.plugins.springsecurity.ldap.authorities.groupSearchBase ='OU=Users_WM,DC=main,DC=adepu,DC=com'
grails.plugins.springsecurity.ldap.authorities.retrieveDatabaseRoles = false
grails.plugins.springsecurity.ldap.authorities.ignorePartialResultException= true
grails.plugins.springsecurity.ldap.search.base = 'OU=Users_WM,DC=main,DC=adepu,DC=com'
grails.plugins.springsecurity.ldap.search.filter = '(sAMAccountName={0})'
//grails.plugins.springsecurity.ldap.context.anonymousReadOnly = true
//grails.plugins.springsecurity.password.algorithm = 'SHA-256'

Some of them optional, you may need to use them based on your environment. For example, some AD implementation may allow anonymous read without specific credential.

For more information http://www.grails.org/plugin/spring-security-ldap


Troubleshooting and Debugging:
In case it is not working as expected, add the following logging configuration to see exactly what is going beyond the scenes. If there is any exception/error raised during user retrival from LDAP it may not throw an exception. By default it tries to read from the local database. This scenario leads you to believe that your LDAP configuration is not getting invoked at all (Atleast I felt so....)

debug 'org.codehaus.groovy.grails.plugins.springsecurity',
      'grails.plugins.springsecurity',
      'org.springframework.security'