Thursday, October 3, 2013

Grails Groovy dynamically invokeMethod with empty/single/multi parameters

You need to first get bean object of your service class.
Create a service like below and get your required service by calling:


serviceFinderService.getServiceByName("serviceName");

 If you have a service named "StudentService.groovy" then replace "serviceName" with "Student" or "student".


package com.pritom.services

import org.codehaus.groovy.grails.web.context.ServletContextHolder
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes

class ServiceFinderService {
    private static HashMap beanList = new HashMap();
    private def grailsApplication;
    private static def ctx;

    def serviceMethod() {

    }

    public def getServiceByName(String bean) throws Exception {
        if(!ctx) {
            ctx = ServletContextHolder.servletContext.getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT)
        }
        bean += "Service";
        bean = bean[0].toLowerCase() + bean.substring(1);
        if(beanList.containsKey(bean)) {
            return beanList.get(bean);
        }
        beanList.put(bean, ctx.getBean(bean));
        if(beanList.containsKey(bean)) {
            return beanList.get(bean);
        }
        throw new Exception("Invalid service");
    }
}


Now check and invoke the method if a specific method existing by such way:


def studentService = ServiceFinderService.getServiceByName("Student");

if(studentService.metaClass.respondsTo(studentService, "methodName", [Integer, String, Boolean] as Object[]) {
    def result = studentService.invokeMethod("methodName", [1, "Pritom K Mondal", true] as Object[]);
}

/* If your method is static then call it by: */
if(studentService.metaClass.respondsTo(studentService, "methodName", [Integer, String, Boolean] as Object[]) {
    def result = studentService.metaClass.getTheClass().invokeMethod("methodName", [1, "Pritom K Mondal", true] as Object[]);
}


Wednesday, October 2, 2013

Grails validate email address

you can use

import org.apache.commons.validator.EmailValidator
...
EmailValidator emailValidator = EmailValidator.getInstance()
if (emailValidator.isValid(valueToTest)) ....

the apache commons validators are included with Grails so you don't need to install another plugin.

Grails Hibernate - null id in entry (don't flush the Session after an exception occurs)

I ran into this issue today when trying to persist one of my objects.  The cause of the problem was interesting.  I was trying to save an object when a property/columns in the table had a unique constraint.  As a result, the object that I was trying to persist would not persist simply because the object's property it failed to meet the unique constraint.

As a result, a call to Save() on the object failed and the ID on the object I was trying to save was not set, but Grails Hibernate still processed the object and associated it with its persistence mechanism leaving it in a "semi-persistent" state with the Grails Hibernate persistence manager (ie: Grails Hibernate now knows about the object you tried to save and it SHOULD have fully evicted the object from its persistence manager because the save failed, but it didn't).

So, the solution that I implemented was to wrap the Save() in a try{} catch{} statement and handling exception.

Basically you need to do something like this:
Create a Filters in conf directory under grails project suppose named 'BaseFilters.groovy' with the following content:
 
import org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext
import org.codehaus.groovy.grails.web.context.ServletContextHolder
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes
import org.hibernate.FlushMode
import org.hibernate.Session
import org.hibernate.SessionFactory

class BaseFilters {
    private static GrailsWebApplicationContext ctx;

    def filters = {
        all(controller:'*', action:'*') {
            before = {
                Session session = getRequestSession();
                session.setFlushMode(FlushMode.MANUAL)
                request.requestSession = session;
            }
            after = { Map model ->
                try {
                    Session session = request.requestSession;
                    session.flush();
                } catch (Exception ex) {
                    ex.printStackTrace()
                }
            }
            afterView = { Exception e ->

            }
        }
    }

    private Session getRequestSession() {
        createCtx();
        SessionFactory sessionFactory = ctx.sessionFactory
        Session session = sessionFactory.currentSession
        return session;
    }

    private def createCtx() {
        if(!ctx) {
            ctx = ServletContextHolder.servletContext.getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT)
        }
    }
}

Originally session flush mode initially set to 'FlushMode.AUTO' which cause the error.
So I change the session flush mode to 'FlushMode' to 'MANUAL'.
And also make your service transaction false such: static transactional = false, add this line just below the class definition.

And in the after section, I just manually try to flush, which is not much needed, you can ignore it.
I just add this section to do some logic manually if need.

Tuesday, October 1, 2013

Grails domain class: unique constraint for multiple columns

Suppose a simple Grails domain class:


class Account {
    String countryId;

    String userName; 
 
    String areaId;
 
    String password;

    static constraints = {
        ...???...
    }
}


It is required that user names are unique for a particular countryId and areaId, thus there must be a unique contraint on three columns. And this is the constraints:

userName(unique: ['countryId', 'areaId'])
 
You can include as many other properties in the array that make up the 
other properties that must be considered in the "unique" constraint on 
the username. 

Grails pagination on a ArrayList

In my recent grails project, i needed to paginate on an array list, so I wrote a function and thought would share it with you all.

public List getFilteredList(int max, int offset) {
    max = Math.min(max ?: 25, 100)
    offset = (offset && offset > 0) ?: 0

    List names = getNames() //Loads the complete list
    int total = names.size()
    int upperLimit = findUpperIndex(offset, max, total)
    List filteredNames = names.getAt(offset..upperLimit)
    return filteredNames
}

private static int findUpperIndex(int offset, int max, int total) {
    max = offset + max - 1
    if (max >= total) {
        max -= max - total + 1
    }
    return max
}
So now if offset=20 and max=10, total = 28 so this will generate a list from 21st to 28th elements of the main list.

Grails: get class object by string/class name

grailsApplication.classLoader.loadClass("au.com.test.package.ClassName")

Monday, September 30, 2013

[Java/Grails] Class ConstrainedProperty

org.codehaus.groovy.grails.validation

[Java/Grails] Class ConstrainedProperty

java.lang.Object
  org.codehaus.groovy.grails.validation.ConstrainedProperty 
 


Method Summary
void addMetaConstraint(java.lang.String name, java.lang.Object value)
Obtains the value of the named meta constraint.
void applyConstraint(java.lang.String constraintName, java.lang.Object constrainingValue)
Applies a constraint for the specified name and consraint value.
Constraint getAppliedConstraint(java.lang.String name)
@param constraintName The name of the constraint to check
java.util.Collection getAppliedConstraints()
Obtains an applied constraint by name.
java.util.Map getAttributes()
java.lang.String getFormat()
java.util.List getInList()
@return Returns the inList.
java.lang.String getMatches()
@return Returns the matches.
java.lang.Comparable getMax()
java.lang.Integer getMaxSize()
java.lang.Object getMetaConstraintValue(java.lang.String name)
java.lang.Comparable getMin()
@return Returns the min.
java.lang.Integer getMinSize()
@return Returns the minSize.
java.lang.Object getNotEqual()
@return Returns the notEqual.
int getOrder()
@param order The order to set.
java.lang.String getPropertyName()
@return Returns the propertyName.
java.lang.Class getPropertyType()
@return Returns the max.
groovy.lang.Range getRange()
@return Returns the range.
java.lang.Integer getScale()
@return The scale, if defined for this property; null, otherwise
groovy.lang.Range getSize()
@param size The size to set.
java.lang.String getWidget()
boolean hasAppliedConstraint(java.lang.String constraintName)
@return Returns the propertyType.
static boolean hasRegisteredConstraint(java.lang.String constraintName)
@return Returns the appliedConstraints.
boolean isBlank()
@return the blank.
boolean isCreditCard()
boolean isDisplay()
@return Returns the display.
boolean isEditable()
@param editable The editable to set.
boolean isEmail()
@return Returns the email.
boolean isNullable()
@return Returns the nullable.
boolean isPassword()
boolean isUrl()
static void registerNewConstraint(java.lang.String name, java.lang.Class constraintClass)
static void registerNewConstraint(java.lang.String name, ConstraintFactory factory)
static void removeConstraint(java.lang.String name, java.lang.Class constraintClass)
static void removeConstraint(java.lang.String name)
void setAttributes(java.util.Map attributes)
void setBlank(boolean blank)
void setCreditCard(boolean creditCard)
void setDisplay(boolean display)
@return Returns the editable.
void setEditable(boolean editable)
@return Returns the order.
void setEmail(boolean email)
void setFormat(java.lang.String format)
void setInList(java.util.List inList)
void setMatches(java.lang.String regex)
void setMax(java.lang.Comparable max)
@param max The max to set.
void setMaxSize(java.lang.Integer maxSize)
@param maxSize The maxSize to set.
void setMessageSource(org.springframework.context.MessageSource source)
void setMin(java.lang.Comparable min)
@param min The min to set.
void setMinSize(java.lang.Integer minSize)
@param minSize The minLength to set.
void setNotEqual(java.lang.Object notEqual)
@param notEqual The notEqual to set.
void setNullable(boolean nullable)
void setOrder(int order)
void setPassword(boolean password)
void setPropertyName(java.lang.String propertyName)
@return Returns the url.
void setRange(groovy.lang.Range range)
void setSize(groovy.lang.Range size)
void setUrl(boolean url)
void setWidget(java.lang.String widget)
boolean supportsContraint(java.lang.String constraintName)
Checks with this ConstraintedProperty instance supports applying the specified constraint.
java.lang.String toString()
void validate(java.lang.Object target, java.lang.Object propertyValue, org.springframework.validation.Errors errors)