Sunday, October 28, 2012

Posting XML request using Groovy's HttpBuilder


       

Here I would like discuss few points on how to use HttpBuilder to post xml request message onto service url.

       /**
        * Creates a User based on params.
        *
        * @param params
        * @return
        */
       def submitMessage(Map params) {
             
              def http =  HttpBuilder();
              http.post(buildRequestMap(params, buildRequestXML), processScccess);
       }
      
      
       /**
        * Method to create properties map to post over the HTTP.
        * @param reqParams
        * @param reqCreatorClosure
        * @return
        */
       Map buildRequestMap(Map reqParams, Closure reqCreatorClosure) {

              Map options = [:];
              Map h = [:];

              h.'Content-Type' = 'text/xml';
              options.'headers' = h;
              options.'uri' = "http://localhost/test/processServlet";
             
              if(null != reqCreatorClosure) {
                     Object returnVal = reqCreatorClosure.call(reqParams);
                     options.put("body", returnVal);
              }
              return options;
       }

      
       /**
        * Closure to create a request xml based on params
        */
       def buildRequestXML = { Map params ->
             
              def writer = new StringWriter()
              def xml = new MarkupBuilder(writer)
              xml.request() {
                     message(messageId: "test123") {
                        "Test Message"
                     }
              }
              return writer.toString();
       }
      
       /**
        * Closure the process a successful response.
        */
       def processScccess = { resp, xml ->
              println "My response handler got response: ${resp.statusLine}"
              println "Response = ${xml}" // print response reader
       }

Thank you..

Send an email in Groovy using AntBuilder

Purpose: How to send an email with Groovy script.
The following example shows how can we send an email using Groovy script. You can create other type email content by setting the appropriate mime type.

In this example, we are trying to send an email notification with table of available topic from the repository.

Using groovy xml markup builder, you can most of the html tags, as shown below to create such paragraphs, hyperlinks etc..

Using AntBuilder, it allows us to attach documents as an email attachments as well.
  

//preparing an email notification
def repositoryDir = "http://prolificworks.blogspot.com"
def emailHost = mailserver_host
def fromEmail = youremail
def toEmail = receipts_email

def writer = new StringWriter()
new groovy.xml.MarkupBuilder(writer).html {
    head {
        style(type:"text/css", ''' 
        .headerRow { 
        margin: 10px; 
        padding: 1px; 
        background-color: #AAAAAA
        } 
        .lineItemRow { 
        margin: 10px; 
        padding: 1px; 
        background-color: #CCCCCC
        } 
    ''') 
    }
    body {
    h3("A Sample notification email from ProlificWorks.)
        table {
            tr('class':'headerRow') {
                th('S.No'); th('Topic Name'); th('Date')
            }
            counter = 1
            fileList.findAll {
                def temp = it
                tr('class':'lineItemRow') {
                    td("${counter}")
                    td(temp.Name)
                    td(temp.CreatedTime)
                }
                counter++
            }
       }
       a(href:"${repositoryDir}", "Repository Location:")
       p("Report Generated: ${new Date()}")
       p("For more information, you can contact us.")
    }
}

//Sending an email notification
if(fileList.size() > 0) {
    def ant = new AntBuilder()
    ant.mail(mailhost:"${emailHost}", messagemimetype:'text/html',
             subject:"A Sample notification email from ProlificWorks."){
        from(address:"${fromEmail}")
        to(address:"${toEmail}")
        message(writer)
        attachments(){
           fileset(dir:"${repoDirPath}"){
             include(name:"<>")
        }
    }
    }   
}

I hoe this post helps you, you can post comment/question for more information. Thank you for reading the post. Let us explore more Groovy together.

Monday, May 14, 2012

Whats in Groovy

Get today's date in your desired format.


def today = Calendar.getInstance()
def todayFormatted = String.format('%tm/%<td/%<tY', today)
println todayFormatted


Run the Groovy Console, you will see the date as 05/15/2012 (of course if would be current date)
















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'

Friday, December 31, 2010

Developing custom MBeans for JMX monitoring

Developing custom MBeans for JMX monitoring

In many cases, it might be useful to monitor the metrics of a Software Component. Some cases, we may not find suitable tools to get the required statistics and data. Those situations demand to you write own custom implementing to collect the metrics / statistics. So wrapping the custom implementation as an MBean, is simplest possible way to get the job done. Because any standard JMX based monitoring tool can monitor an MBean running the JVM. Let us examine the required steps to develop a custom MBean to accomplish the below use case.

Use case:
A business component, A Service Manager is responsible to process all the service requests generated in the application. This component invokes the external system's service call as part of business computation. As it is a critical component in the application, we need to monitor the performance statistics of the component described below.
• Number of total requests served.
• Number of failed requests.
• Percentage of success rate.
• Average Response Time
• Maximum Response Time
• Minimum Response Time

Implementation steps:
1. Define a monitor bean interface
2. Implement the monitor bean interface
3. Register the MBean with JVM's MBean Server
4. Expose methods for business component (to feed the data in)

Define a monitor bean interface:
• This interface exposes the MBean implementation to JVM's MBean Server.
• It lists the available methods, can be invoked by the MBean Server. Create AServiceMBean.java as below.
• If any of the attributes are allowed to be set by the monitoring tool, we need to provide the setter method.
• If we want to maintain them as read only values only getter would help, no setters.

package com.sample.mbean;

public interface AServiceMBean {

// read only methods..
public int getTotalServcieCalls();
public long getAverageResponseTime();
public long getMaxResponseTime();
public long getMinResponseTime();
public int getFailedServiceCalls();
public int getSuccessServiceCalls();

// a read-write attribute
public String getName();
public String setName(String name);

}

Implement the monitor bean interface:
• It is a class, implements the the MBean interface.
• This class implements the logic to compute the required statistics on raw data (fed by business component) and makes the computed metrics available for JMX server.
• This class should extends one of the MBean class (StandarMBean, StandardEmitterMBean) to convert the class as an eligible MBean.
• You can even implement DynamicMBean, MBeanRegistration interfaces to override the default behavior (for a specific behavior) of a standard MBean. - will discuss further as we progress....

package com.sample.mbean;

import java.lang.management.ManagementFactory;

import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.StandardMBean;

public class AServiceMBeanImpl extends StandardMBean implements
AServiceMBean {

private static int totalCalls;
private static long totalResponseTime;
private static int totalFailedCalls;
private static long maxResponseTime;
private static long minResponseTime;
private static long avgResponseTime;

public AServiceMBeanImpl() {
super(AServiceMBean.class, true);
}

public AServiceMBeanImpl(Class mbeanInterface)
throws NotCompliantMBeanException {
super(mbeanInterface);
}

public AServiceMBeanImpl(Class mbeanInterface, boolean isMXBean) {
super(mbeanInterface, isMXBean);
}

public AServiceMBeanImpl(T implementation, Class mbeanInterface,
boolean isMXBean) {
super(implementation, mbeanInterface, isMXBean);
}

public AServiceMBeanImpl(T implementation, Class mbeanInterface)
throws NotCompliantMBeanException {
super(implementation, mbeanInterface);
}

@Override
public int getFailedServiceCalls() {
return totalFailedCalls;
}

@Override
public long getMaxResponseTime() {
return maxResponseTime;
}

@Override
public long getMinResponseTime() {
return minResponseTime;
}

@Override
public String getName() {
return "AService-Component";
}


@Override
public String setName(String name) {
//name = name;
}
@Override
public int getSuccessServiceCalls() {
return totalCalls - totalFailedCalls;
}

@Override
public int getTotalServcieCalls() {
return totalCalls;
}

@Override
public long getAverageResponseTime() {
// return totalResponseTime/(totalCalls-totalFailedCalls);
return avgResponseTime;
}

/**
* methods exposed to business component, via which they can feed the data to MBean.
*
**/
public static void addAServiceCall(boolean result, long responseTime) {
totalCalls ++;

if(result) {

if(responseTime < minResponseTime) minResponseTime = responseTime; if(responseTime > maxResponseTime) maxResponseTime = responseTime;

totalResponseTime = ++ responseTime;

} else {
totalFailedCalls++;
}
}


public static void setMaxTime(long maxResultTimeMilli) {
maxResponseTime = maxResultTimeMilli;

}

public static void setAvgTime(long averageResultTimeMilli) {
avgResponseTime = averageResultTimeMilli;

}

public static void setTotalCount(int thread_count) {
totalCalls = thread_count;

}

public static void setMinTime(long minResultTimeMilli) {
minResponseTime = minResultTimeMilli;

}
}

Register the MBean with JVM's MBean Server
Once an MBean is implemented, it needs to be registered with platform MBean, so the MBean is visible to the internal MBean Server. For simplicity you can have the registering the logic as part of the custom MBean implementation. But I would prefer to isolate the registration logic from business computation logic, into another class solely responsible to register and retrieve the custom MBeans.
• Get instance of MBeanServer using ManagementFactory.getPlatformMBeanServer()
• Create an instance of custom MBean with a name
• Register with the MBeanServer
try {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

AServiceMBeanImpl mbean = new AServiceMBeanImpl();
ObjectName name = new ObjectName(
"com.sample.mbean:type=AServiceMBean");
mbs.registerMBean(mbean, name);

} catch (MalformedObjectNameException e) {
e.printStackTrace();
System.exit(0);
} catch (InstanceAlreadyExistsException e) {
e.printStackTrace();
System.exit(0);
} catch (MBeanRegistrationException e) {
e.printStackTrace();
System.exit(0);
} catch (NotCompliantMBeanException e) {
e.printStackTrace();
}
Expose methods for business component
It is a method exposed to business component. A business component invokes this method and feeds the component's raw data in. It the custom bean applies the logic on and prepares the metrics ready
public static void addAServiceCall(boolean result, long responseTime) {
totalCalls ++;

if(result) {

if(responseTime < minResponseTime) minResponseTime = responseTime; if(responseTime > maxResponseTime) maxResponseTime = responseTime;

totalResponseTime = ++ responseTime;

} else {
totalFailedCalls++;
}
}

Executing the MBean
Once all the above steps are complete, make sure invoke the register method during application star up. It can be invoked however you want but need to make sure the MBean registered once before trying to access from the JMX monitoring tool.
As and when the business component wants feed the data, invoke the exposed method as below.* It can use any of the exposed to methods.
//Feed the MBean...
AServiceMBeanImpl. addAServiceCall(true, timeinmilli);
AServiceMBeanImpl.setMaxTime(maxResultTimeMilli);
AServiceMBeanImpl.setMinTime(minResultTimeMilli);
AServiceMBeanImpl.setAvgTime(averageResultTimeMilli);
AServiceMBeanImpl.setTotalCount(THREAD_COUNT);

Monitoring the MBean
Using the regular approach connect any JMX based monitoring tool (eg. Visual VM), navigate to MBean section, the custom AServiceMBean Service will be shown with the available data.

Friday, November 19, 2010

Enabling remote JMX monitoring for a Java application

In this, I would like to go through the required configuration to enable an application form remote JMX monitoring. So that it can be monitored using profiling tools like jconsole, Visual VM etc..

To enable a JVM for remote JMX monitoring, we need to provide following JAVA_OPTIONS to while starting the JVM.

Simple Configuration - No authentication
-Dcom.sun.management.jmxremote.port=6969
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

The above parameters enable the JVM to accept the JMX connectivity at port 6969. You can use an unused port number for this.

If an application is using Java Wrapper Service to start the JVM, the JAVA OPTIONS should be added to wrapper.conf file as below,

wrapper.java.additional.XX=-Dcom.sun.management.jmxremote.port=6969
wrapper.java.additional.XX=-Dcom.sun.management.jmxremote.ssl=false
wrapper.java.additional.XX=-Dcom.sun.management.jmxremote.authenticate=false

where XX indicates the sequence of java options in wrapper.conf. They might vary, need to be adjusted.

Configuration with Authentication
Remote JMX connectivity can be configured to enforce the security credentials. Here the credential information is accessed from access and password files for authentication and authorization.

-Dcom.sun.management.jmxremote.authenticate=*true*
-Dcom.sun.management.jmxremote.access.file=jmxremote.access
-Dcom.sun.management.jmxremote.password.file=jmxremote.password 

The default location for these files is JRE_HOME/lib/management. You can keep the files based on your application configuration. I would prefer to under /conf directory.

*jmxremote.access contains*
########## jmxremote.access ######################
normalUser readonly
superUser readwrite

*jmxremote.password contains*
########## jmxremote.password ######################
# The "normalUser " role has password "passwOrd".
normalUser passwOrd
superUser passwOrd

Here the very important note is the jmxremote.password file should be owned and accessible by Owner only. Otherwise you would receive an error message File must be restricted to read access (wording may change).





Security authentication can be implemented using JAAS Callback mechanism, where we need to provide implementation for javax.security.auth.callback.NameCallback, javax.security.auth.callback.PasswordCallback

-Dcom.sun.management.jmxremote.login.config=login.config

Using this option, you can even authentication against a third party tool like LDAP etc..

Configuration with SSL encryption
Provide the following JAVA OPTIONS
-Dcom.sun.management.jmxremote.ssl=true
-Djavax.net.ssl.keyStore=     <>
-Djavax.net.ssl.trustStore=    <>
-Djavax.net.ssl.keyStoreType=     <>
-Djavax.net.ssl.keyStorePassword=     <>
-Djavax.net.ssl.trustStoreType=     <>
-Djavax.net.ssl.trustStorePassword=     <>

It covers the quick and basic configuration required to enable a Java application for remote JMX monitoring. I hope it helps you as well..