Search This Blog

Friday, December 24, 2010

Grails template driven emailing with mail plugin


In this post I will walk through how to configure email using mail plugin.
1. Install mail plugin in your project.
grails install-plugin mail
2.
Add activation and mail jars to lib directory.
I use these jars
activation:1.1.1
mail-1.4.3
3.
To resources.groovy add mailSender definition and configure it
    mailSender(org.springframework.mail.javamail.JavaMailSenderImpl) {
        host = 'smtp.gmail.com'
        port = 465
        username = 'xxx@gmail.com'
        password = 'xxx'
        javaMailProperties = ['mail.smtp.auth': 'true',
                'mail.smtp.socketFactory.port': '465',
                'mail.smtp.socketFactory.class': 'javax.net.ssl.SSLSocketFactory',
                'mail.smtp.socketFactory.fallback': 'false']
    }
    
    
4. Add a email template(if needed)
Create a directory grails-app\views\emailtemplates
Add a email.gsp with code you want -sample below
<%@ page contentType="text/html" %>
<html>
<head><title>${mytitle}</title></head>
<body><h1>${mymail}</h1></body>
</html>
ContentType of the gsp should be changed based on your need.
5. In your controller add the emailing code
           mailService.sendMail{
        to    "xxx@yahoo.com"
                from  "xxx@gmail.com"
                subject  "Email test"
            body  (
                view: "/emailtemplates/email",
                model: [mytitle: "My title", mymail: "Test Email"]
            )
            }
            
     If you dont need a template to render from just supply the body of the email.

Tuesday, December 21, 2010

Grails and JSON:Consuming JSON data via multi-part form upload

JSON is a concise format that is extremely popular for data exchange.
Most webservices these days consume JSON as input for processing instead of XML as it is lightweight(depenedent on domain)

Here is an example of consuming a json file uploaded via a web form in you web application using grails.

Grails as usual provides fantastic support for JSON parsing.
Parsing a JSON input and creating domain objects out this is very easy with grails.

I have a domain object like this
class Message {
String name
String content
    static constraints = {
    name(nullable:false)
    content(nullable:false)
    }
}

Here is a sample JSON input file that can be used for creating multiple domain objects

File:Messages.json
[
{"name":"ann","content":"What a Wonderful World"},
{"name":"nandhu","content":"Wonderful World"},
]

Note that JSON representation is very simple.
Key,Value pairs separated by ":" for each property and enclosed in {} constitute one object.
Objects can be separated by comma and enclosed with [] to constitute an array of like objects.

In order to upload the JSON file we would need a multipart form upload gsp as shown below

//form multipart upload code
        <div>
        <g:form method="post" action="postRest" enctype="multipart/form-data">
    <input type="file" name="file"/>
    <input type="submit"/>
</g:form>
        </div>

This form does a post to action called "postRest" on the same controller.
A different controller can be used by using controller="name" property in addition

Now finally you need to add the controller action.
There you have to get the JSON representation first.
Then you create a domain object and fill data into it from JSON representation.
Finally you save this object.
Make sure you check the newly saved object to ensure there arent any errors.

    def postRest = {
     println request.getFile("file").inputStream.text
    
     def jsonArray = JSON.parse(request.getFile("file").getInputStream(),"UTF-8")
     println "jsonArray=${jsonArray}"
     jsonArray.each{
     println it
     Message m = new Message()
     bindData(m, it)
     m.save(flush:true)
     if(m.errors) {
m.errors.each{println it}    
     }
     }
    }

In the next post I will blog on how to expose this as a webservice.

Monday, December 20, 2010

Grails testing support enhanced:full emulation of GORM

Grails testing support enhanced to provide a full emulation of GORM.
Peter LedBrook(author of Grails in Action) has written a post how to get this in your project.
Pretty easy config and powerful features added.
Grails Rocks!

Config changes needed in short are


1.Add to repositories:
mavenRepo "http://maven.springframework.org/milestone" 
mavenRepo "http://snapshots.repository.codehaus.org" 


2. 
test( "org.grails:grails-datastore-gorm-test:1.0.0.M1") {
     excludes "persistence-api", "sl4j-simple", "commons-logging"

}

3. Add to test
 @Mixin(DatastoreUnitTestMixin) and 
add a call to disconnect() in your tearDown()


Wednesday, December 8, 2010

Grails and multi tenancy - Multi tenancy setup with grails




I was playing with multi tenancy setup with grails.
While there were some examples I found most them were old and werent updated for recent grails versions.
Ran into a bunch of errors when I tried to use multitenancy plugin with spring security.
Had to try out a few things before i was able to correct all the errors and get this working.
I try here to give a step by step guide to setting up multitenancy for grails based apps.

Create a simple domain class
grails create-domain-class com.helloworld.Message

install spring security plugin
>grails install-plugin spring-security-core

Create the user and roles
grails s2-quickstart org.racetrack User Role

Install multitenant plugin
grails install-plugin multi-tenant

install Multi-Tenant Spring Security Integration
grails install-plugin multi-tenant-spring-security

Add to config.groovy
tenant {
mode = "multiTenant" // "singleTenant" OR "multiTenant"
datasourceResolver.type = "db"
resolver {
type = "request"
resolver.request.dns.type = "db"
request.dns.type = "db"
}
}


Annotate domain classes that are to be shared after importing Multitenat annotation
import com.infusion.tenant.groovy.compiler.MultiTenant;

@MultiTenant

Add to the User Class
/** for multi-tenant-acegi plugin **/
Integer userTenantId
Add the following constraints 
// Existing constraints
userTenantId(min: 0)
Create a dns map table
grails create-dns-map
Now with all the setup in place you should be able to run your app with multitenancy setup.


Grails and Jasper Reports - Issue with Utf-8 when designing reports with iReport


Jasper reports works perfectly well with grails. However I ran into some issues designing the report layout with iReport, the default designer for Jasper Reports and trying to integrate it with my grails based application. Here is the issue and solution in the hope that it is useful to others who run into this.

Please leave a note if you find this post useful or if you would like me to write something specific about grails or spring.


Jasperreports complains with utf-8 issue when it tries to render the report.

Problem can be solved adding parameter -Dfile.encoding=UTF-8 to the VM.

To add parameter edit etc/ireport.conf,
Modify 'default_options' parameter it should look like this:
   default_options="-J-Dfile.encoding=UTF-8 -J-Xms256M -J-Xmx512M"

Now the reports render perfectly - Enjoy!

Grails : Scheduling jobs with Quartz


Had taken the time and integrated quartz with grails.
Thought I will share it.
In this post I will discuss how to Install and configure quartz with jobs persistent in a database( mysql)
1.
Get quartz distribution.
Unzip to a directory.
Run the table-creation SQL scripts in the "docs/dbTables" directory of the Quartz distribution
2.Install quartz plugin
grails install-plugin quartz

3.
Create a file, QuartzConfig.groovy in grails-app\conf
Specify quartz startup and storage options here like this:
quartz {
    autoStartup = true
    jdbcStore = true
    waitForJobsToCompleteOnShutdown = true
}
environments {
    test {
        quartz {
            autoStartup = true
        }
    }
}

4.
Create a file, quartz.properties in grails-app\conf 
Configure your db name in URL as well as user name and password
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 3
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass =
org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.dataSource = prodDataSource
org.quartz.jobStore.isClustered = false
org.quartz.dataSource.prodDataSource.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.prodDataSource.URL = "jdbc:mysql://localhost:3306/xxx?autoreconnect=true">org.quartz.dataSource.prodDataSource.user=grails
org.quartz.dataSource.prodDataSource.password ="server"
5.
In resources.groovy in grails-app\conf\spring
add the imports:
import org.springframework.scheduling.quartz.SchedulerFactoryBean 
import org.codehaus.groovy.grails.jobs.*
import org.codehaus.groovy.grails.plugins.quartz.listeners.*
add this to spring beans dsl:
quartzScheduler(SchedulerFactoryBean) {
autoStartup = false
dataSource = ref('dataSource')
transactionManager = ref('transactionManager')
configLocation = 'classpath:quartz.properties'
jobFactory = ref('quartzJobFactory')
jobListeners = [ref("${SessionBinderJobListener.NAME}")]
globalJobListeners = [ref("${ExceptionPrinterJobListener.NAME}")]
}   
6.
Create a service class(or where you would prefer to do this) with grails create-service
Enable the service class to be injeced with a scheduler by declaring like this
    def quartzScheduler
    
define a method which will do the scheduling for you.
In this eg I put in a domain object for later retrieval during job execution.
   def schedule(my.Motd m) {
       // execute task
    def jobDetail = new JobDetail(m?.message, group, MotdJob.class);
    jobDetail.getJobDataMap().put("job", m)
    SimpleDateFormat formatter  = new SimpleDateFormat ("yyyy.MM.dd hh:mm:ss");
    Date myDate = formatter.parse("2010.07.02 15:13:56");
    def myTrigger = new SimpleTrigger("myTrigger" + new Random().nextInt().toString(), "mygroup" + new Random().nextInt().toString(),  myDate,null,0,0)
    quartzScheduler.scheduleJob(jobDetail, myTrigger);
    }

7.
Create a quartz job using 
grails create-job fully-qualified-job-name
In this class define a execute method and implement your business logic
    void execute(JobExecutionContext context) {
         String instName = context.getJobDetail().getName();
         println "I have been triggered to run instGroup"
         String instGroup = context.getJobDetail().getGroup();
    
        JobDataMap dataMap = context.getJobDetail().getJobDataMap();
        def mo =dataMap.get("job")
        if(mo) {
            Motd m = (Motd)mo
        }
        else 
        println "null job"
        
        return
    }

8.
If you job uses a domain class (like in example above) you need to create a jar with all the domain class used by quartz and add this to your lib directory
NOTE: This is at best a hack solution. Better option is doing this through classloader. But I wont go into it.
Thats it.
Enjoy and email me at trbala attherateof yahoo.com if you need an exmaple source or if you can offer me a good paying job in siliconvalley!!!