Eren Avşaroğulları is highly motivated open source developer and enthusiast on Java and related open source technologies. He has over 8 years of professional software design and development experiences in different domains such as telecommunication, finance and control & automation. His areas of interest are Web Frameworks, Distributed and Paralel Computing, High-Performance Systems, High Availability and Scalability. His current focus is Large-Scaled & High Available Enterprise Applications and GSM Network Platform & Service Design and Developments. He writes on the open source technologies. He hold a B.Sc. degree in Electrical & Electronics Engineering and a M.Sc. degree in Control & Automation Engineering. Eren is a DZone MVB and is not an employee of DZone and has posted 9 posts at DZone. You can read more from them at their website. View Full User Profile

Spring Dynamic Language Support with Groovy

01.09.2013
| 7979 views |
  • submit to reddit

Groovy is a dynamic and object-oriented programming language running on JVM. It uses a syntax like Java, can be embedded in Java and is compiled to byte-code. Java code can be called from Groovy, and vice versa. Some of Groovy features are Meta and Functional programming, Dynamic typing (with the def keyword), Closures, GroovyBeans, Groovlets, integration with Bean Scripting Framework(BSF), Generics, Anotation and Collection Support.

This article explains fundamental Spring Dynamic Language Support for Groovy via the following ways :

1) By using Java syntax and Spring Stereotype,
2) By using Groovy syntax and Spring Stereotype,
3) By using inline-script feature,
4) By using Spring Groovy language support(lang:groovy).

Used Technologies :

JDK 1.7.0_09
Spring 3.2.0
Groovy 2.0.4
Maven 3.0.4

STEP 1 : CREATE MAVEN PROJECT

A maven project is created as below. (It can be created by using Maven or IDE Plug-in).

STEP 2 : LIBRARIES

Firstly, dependencies are added to Maven’ s pom.xml.

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>3.2.0.RELEASE</spring.version>
</properties>
 
<!-- Spring 3 dependencies -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
</dependency>
 
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
</dependency>
 
<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-all</artifactId>
    <version>2.0.4</version>
</dependency>

maven-compiler-plugin(Maven Plugin) is used to compile the project with JDK 1.7

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
        <compilerId>groovy-eclipse-compiler</compilerId>
        <verbose>true</verbose>
        <source>1.7</source>
        <target>1.7</target>
        <encoding>${project.build.sourceEncoding}</encoding>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-eclipse-compiler</artifactId>
            <version>2.6.0-01</version>
        </dependency>
    </dependencies>
</plugin>

maven-shade-plugin(Maven Plugin) can be used to create runnable-jar

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>2.0</version>
 
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
                <transformers>
                    <transformer
                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <mainClass>com.onlinetechvision.exe.Application</mainClass>
                    </transformer>
                    <transformer
                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.handlers</resource>
                    </transformer>
                    <transformer
                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.schemas</resource>
                    </transformer>
                </transformers>
            </configuration>
        </execution>
    </executions>
</plugin>

STEP 3 : CREATE Employee CLASS

Employee Bean is created.

package com.onlinetechvision.employee;
 
/**
 * Employee Bean
 *
 * @author onlinetechvision.com
 * @since 24 Dec 2012
 * @version 1.0.0
 *
 */
public class Employee {
 
    private String id;
    private String name;
    private String surname;
 
    public Employee(String id, String name, String surname) {
        this.id = id;
        this.name = name;
        this.surname = surname;
    }
 
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getSurname() {
        return surname;
    }
 
    public void setSurname(String surname) {
        this.surname = surname;
    }  
 
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + ((surname == null) ? 0 : surname.hashCode());
        return result;
    }
 
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Employee other = (Employee) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (surname == null) {
            if (other.surname != null)
                return false;
        } else if (!surname.equals(other.surname))
            return false;
        return true;
    }
 
    @Override
    public String toString() {
        return "Employee [id=" + id
                            + ", name=" + name
                            + ", surname=" + surname + "]";
    }  
 
}

METHOD 1 : USING JAVA SYNTAX

STEP 4 : CREATE IGroovyEmployeeCacheService INTERFACE

IGroovyEmployeeCacheService Interface is created to expose Groovy Cache functionality.

package com.onlinetechvision.groovy.srv
 
import com.onlinetechvision.employee.Employee
 
/**
 * IGroovyEmployeeCacheService Interface exposes cache functionality.
 *
 * @author onlinetechvision.com
 * @since 24 Dec 2012
 * @version 1.0.0
 *
 */
interface IGroovyEmployeeCacheService {
 
    /**
     * Adds employee entry to cache
     *
     * @param Employee employee
     *
     */
    void addToEmployeeCache(Employee employee);
 
    /**
     * Gets employee entry from cache
     *
     * @param String id
     * @return Employee employee
     */
    Employee getFromEmployeeCache(String id);
 
    /**
     * Removes employee entry from cache
     *
     * @param Employee employee
     *
     */
    void removeFromEmployeeCache(Employee employee);
 
}

STEP 5 : CREATE GroovyEmployeeCacheService IMPL

GroovyEmployeeCacheService Class is created by implementing IGroovyEmployeeCacheService Interface.

package com.onlinetechvision.groovy.srv
 
import com.onlinetechvision.employee.Employee;
import org.springframework.stereotype.Service;
 
/**
 * GroovyEmployeeCacheService Class is implementation of IGroovyEmployeeCacheService Interface.
 *
 * @author onlinetechvision.com
 * @since 24 Dec 2012
 * @version 1.0.0
 *
 */
@Service
class GroovyEmployeeCacheService implements IGroovyEmployeeCacheService  {
 
    private Map<String, Employee> cache = new HashMap();
 
    /**
     * Adds employee entry to cache
     *
     * @param Employee employee
     *
     */
    public void addToEmployeeCache(Employee employee) {
        getCache().put(employee.getId(), employee);
        println print(employee, "added to cache...");
    }
 
    /**
     * Gets employee entry from cache
     *
     * @param String id
     * @return Employee employee
     */
    public Employee getFromEmployeeCache(String id) {
        Employee employee = getCache().get(id);
        println print(employee, "gotten from cache...");
        return employee;
    }
 
    /**
     * Removes employee entry from cache
     *
     * @param Employee employee
     *
     */
    public void removeFromEmployeeCache(Employee employee) {
        getCache().remove(employee.getId());
        println print(employee, "removed from cache...");
        println "Groovy Cache Entries :" + getCache();
    }
 
    public Map<String, Employee> getCache() {
        return cache;
    }
 
    public void setCache(Map<String, Employee> map) {
        cache = map;
    }
 
    /**
     * Prints operation information
     *
     * @param Employee employee
     * @param String description
     *
     */
    private String print(Employee employee, String desc) {
        StringBuilder strBldr = new StringBuilder();
        strBldr.append(employee)
        strBldr.append(" ");
        strBldr.append(desc);
 
        return strBldr.toString();
    }
}

STEP 6 : CREATE IEmployeeService INTERFACE

IUserService Interface is created for Spring service layer and shows how to integrate Spring and Groovy Service layers.

package com.onlinetechvision.spring.srv;
 
import com.onlinetechvision.employee.Employee;
 
/**
 * IEmployeeService Interface is created to represent Spring Service layer.
 *
 * @author onlinetechvision.com
 * @since 24 Dec 2012
 * @version 1.0.0
 *
 */
public interface IEmployeeService {
 
    /**
     * Adds Employee entry to cache
     *
     * @param Employee employee
     *
     */
    void addToGroovyEmployeeCache(Employee employee);
 
    /**
     * Gets Employee entry from cache
     *
     * @param String id
     * @return Employee employee
     */
    Employee getFromGroovyEmployeeCache(String id);
 
    /**
     * Removes Employee entry from cache
     *
     * @param Employee employee
     *
     */
    void removeFromGroovyEmployeeCache(Employee employee); 
 
}

STEP 7 : CREATE EmployeeService IMPL

EmployeeService Class is created by implementing IUserService Interface.

package com.onlinetechvision.spring.srv;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import com.onlinetechvision.employee.Employee;
import com.onlinetechvision.groovy.srv.IGroovyEmployeeCacheService;
 
/**
 * EmployeeService Class is implementation of IEmployeeService interface.
 *
 * @author onlinetechvision.com
 * @since 24 Dec 2012
 * @version 1.0.0
 *
 */
@Service
public class EmployeeService implements IEmployeeService {
 
    @Autowired
    private IGroovyEmployeeCacheService groovyEmployeeCacheService ;
 
    /**
     * Adds Employee entry to cache
     *
     * @param Employee employee
     *
     */
    public void addToGroovyEmployeeCache(Employee employee) {
        getGroovyEmployeeCacheService().addToEmployeeCache(employee);
    }
 
    /**
     * Gets Employee entry from cache
     *
     * @param String id
     * @return Employee employee
     */
    public Employee getFromGroovyEmployeeCache(String id) {
        return getGroovyEmployeeCacheService().getFromEmployeeCache(id);
    }  
 
    /**
     * Removes Employee entry from cache
     *
     * @param Employee employee
     *
     */
    public void removeFromGroovyEmployeeCache(Employee employee) {
        getGroovyEmployeeCacheService().removeFromEmployeeCache(employee);
    }
 
    public IGroovyEmployeeCacheService getGroovyEmployeeCacheService() {
        return groovyEmployeeCacheService;
    }
 
    public void setGroovyEmployeeCacheService(IGroovyEmployeeCacheService groovyEmployeeCacheService) {
        this.groovyEmployeeCacheService = groovyEmployeeCacheService;
    }  
 
}

STEP 8 : CREATE applicationContext.xml

Spring Configuration file, applicationContext.xml, is created.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 
http://www.springframework.org/schema/context
 
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 
    <context:component-scan base-package="com.onlinetechvision.spring.srv, com.onlinetechvision.groovy.srv"/>
 
</beans>

STEP 9 : CREATE Application CLASS

Application Class is created to run the application.

package com.onlinetechvision.exe;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.onlinetechvision.spring.srv.EmployeeService;
import com.onlinetechvision.spring.srv.IEmployeeService;
import com.onlinetechvision.employee.Employee;
 
/**
 * Application Class starts the application
 *
 * @author onlinetechvision.com
 * @since 24 Dec 2012
 * @version 1.0.0
 *
 */
public class Application
{
    /**
     * Starts the application
     *
     * @param  String[] args
     *
     */
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
 
        IEmployeeService employeeService = (IEmployeeService) context.getBean(EmployeeService.class);
 
        Employee firstEmployee = new Employee("1", "Jake", "Gyllenhaal");
        Employee secondEmployee = new Employee("2", "Woody", "Harrelson");
 
        employeeService.addToGroovyEmployeeCache(firstEmployee);
        employeeService.getFromGroovyEmployeeCache(firstEmployee.getId());
        employeeService.removeFromGroovyEmployeeCache(firstEmployee);
 
        employeeService.addToGroovyEmployeeCache(secondEmployee);
        employeeService.getFromGroovyEmployeeCache(secondEmployee.getId());
    }
 
}

STEP 10 : BUILD PROJECT

After OTV_Spring_Groovy Project is build, OTV_Spring_Groovy-0.0.1-SNAPSHOT.jar is created.

STEP 11 : RUN PROJECT

After created OTV_Spring_Groovy-0.0.1-SNAPSHOT.jar file is run, output logs are shown as the following :

Employee [id=1, name=Jake, surname=Gyllenhaal] added to cache...
Employee [id=1, name=Jake, surname=Gyllenhaal] gotten from cache...
Employee [id=1, name=Jake, surname=Gyllenhaal] removed from cache...
Groovy Cache Entries :[:]
 
Employee [id=2, name=Woody, surname=Harrelson] added to cache...
Employee [id=2, name=Woody, surname=Harrelson] gotten from cache...

So far, first way has been explained. Let us take a look to the other ways :

METHOD 2 : USING GROOVY SYNTAX

IGroovyEmployeeCacheService Interface and GroovyEmployeeCacheService Impl can be also designed by using Groovy syntax as the following :

STEP 12.1 : CREATE IGroovyEmployeeCacheService INTERFACE

IGroovyEmployeeCacheService Interface is created by using Groovy syntax.

package com.onlinetechvision.groovy.srv
 
import com.onlinetechvision.employee.Employee
 
/**
 * IGroovyEmployeeCacheService Interface exposes cache functionality.
 *
 * @author onlinetechvision.com
 * @since 24 Dec 2012
 * @version 1.0.0
 *
 */
interface IGroovyEmployeeCacheService {
 
    /**
     * Adds employee entry to cache
     *
     * @param Employee employee
     *
     */
    def addToEmployeeCache(Employee employee);
 
    /**
     * Gets employee entry from cache
     *
     * @param String id
     * @return Employee employee
     */
    def getFromEmployeeCache(String id);
 
    /**
     * Removes employee entry from cache
     *
     * @param Employee employee
     *
     */
    def removeFromEmployeeCache(Employee employee);
 
}

STEP 12.2 : CREATE GroovyEmployeeCacheService IMPL

GroovyEmployeeCacheService Class is created by using Groovy syntax.

package com.onlinetechvision.groovy.srv
 
import com.onlinetechvision.employee.Employee;
import org.springframework.stereotype.Service;
 
/**
 * GroovyEmployeeCacheService Class is implementation of IGroovyEmployeeCacheService Interface.
 *
 * @author onlinetechvision.com
 * @since 24 Dec 2012
 * @version 1.0.0
 *
 */
@Service
class GroovyEmployeeCacheService implements IGroovyEmployeeCacheService  {
 
    def cache = new HashMap();
 
    /**
     * Adds employee entry to cache
     *
     * @param Employee employee
     *
     */
    def addToEmployeeCache(Employee employee) {
        getCache().put(employee.getId(), employee);
        println print(employee, "added to cache...");
    }
 
    /**
     * Gets employee entry from cache
     *
     * @param String id
     * @return Employee employee
     */
    def getFromEmployeeCache(String id) {
        Employee employee = getCache().get(id);
        println print(employee, "gotten from cache...");
        return employee;
    }
 
    /**
     * Removes employee entry from cache
     *
     * @param Employee employee
     *
     */
    def removeFromEmployeeCache(Employee employee) {
        getCache().remove(employee.getId());
        println print(employee, "removed from cache...");
        println "Groovy Cache Entries :" + getCache();
    }
 
    def getCache() {
        return cache;
    }
 
    def setCache(Map<String, Employee> map) {
        cache = map;
    }
 
    /**
     * Prints operation information
     *
     * @param Employee employee
     * @param String description
     *
     */
    def print(Employee employee, String desc) {
        StringBuilder strBldr = new StringBuilder();
        strBldr.append(employee)
        strBldr.append(" ");
        strBldr.append(desc);
    }
}

METHOD 3 : USING INLINE-SCRIPT FEATURE

GroovyEmployeeCacheService Impl can be also defined by using inline-script feature as the following :

STEP 13.1 : DEFINE GroovyEmployeeCacheService IMPL via applicationContext.xml

GroovyEmployeeCacheService Impl Class can be defined in applicationContext.xml.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 
http://www.springframework.org/schema/context
 
http://www.springframework.org/schema/context/spring-context-3.0.xsd
 
http://www.springframework.org/schema/lang
 
http://www.springframework.org/schema/lang/spring-lang-3.0.xsd">
 
    <context:component-scan base-package="com.onlinetechvision.spring.srv"/>
 
    <lang:groovy id="groovyEmployeeCacheService">
        <lang:inline-script>
            package com.onlinetechvision.groovy.srv
 
            import com.onlinetechvision.employee.Employee;
            import org.springframework.stereotype.Service;
 
            class GroovyEmployeeCacheService implements IGroovyEmployeeCacheService {
 
                def cache = new HashMap();
 
                def addToEmployeeCache(Employee employee) {
                    getCache().put(employee.getId(), employee);
                    println print(employee, "added to cache...");
                }
 
                def getFromEmployeeCache(String id) {
                    Employee employee = getCache().get(id);
                    println print(employee, "gotten from cache...");
                    return employee;
                }
 
                def removeFromEmployeeCache(Employee employee) {
                    getCache().remove(employee.getId());
                    println print(employee, "removed from cache...");
                    println "Groovy Cache Entities :" + getCache();
                }
 
                def getCache() {
                    return cache;
                }
 
                def setCache(Map map) {
                    cache = map;
                }
 
                def print(Employee employee, String desc) {
                    StringBuilder strBldr = new StringBuilder();
                    strBldr.append(employee)
                    strBldr.append(" ");
                    strBldr.append(desc);
                }
            }
        </lang:inline-script>
    </lang:groovy>
 
</beans>

METHOD 4 : USING SPRING GROOVY LANGUAGE SUPPORT

GroovyEmployeeCacheService Impl can be also defined to Spring application-context without using stereotype(@Service) as the following :

STEP 14.1 : DEFINE GroovyEmployeeCacheService IMPL via applicationContext.xml

GroovyEmployeeCacheService Impl Class can be defined in applicationContext.xml.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 
http://www.springframework.org/schema/context
 
http://www.springframework.org/schema/context/spring-context-3.0.xsd
 
http://www.springframework.org/schema/lang
 
http://www.springframework.org/schema/lang/spring-lang-3.0.xsd">
 
    <context:component-scan base-package="com.onlinetechvision.spring.srv"/>
 
    <lang:groovy id="groovyEmployeeCacheService" script-source="classpath:com/onlinetechvision/groovy/srv/GroovyEmployeeCacheService.groovy"/>
 
</beans>

STEP 15 : DOWNLOAD

https://github.com/erenavsarogullari/OTV_Spring_Groovy

REFERENCES :

Groovy User Guide
Spring Dynamic Language Support




 

Published at DZone with permission of Eren Avşaroğulları, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)