Showing posts with label Grails. Show all posts
Showing posts with label Grails. Show all posts

Points To Remember


  • You need to inject the SessionFactory object in the service or the controller, where you want to use it.
  • Get the current session from the session factory and execute the query in this session using sessionFactory.getCurrentSession().
  • You can also execute the query in a new session by using sessionFactory.openSession().

Executing SQL query in grails

Person.groovy
package com.ekiras.grails;

class Person{

String username
String email
String password

static mapping = {

}

static constraints = {
username nullable: true
password nullable: false, blank: false
email nullable: false, blank: false
}



}
PersonService.groovy
package com.ekiras.grails;

import org.hibernate.SessionFactory;
import grails.transaction.Transactional

import com.ekiras.grails.Person;

@Transactional
class PersonService{

SessionFactory sessionFactory;

def listPersons(){
String query = "select distinct username from person";
def personList = sessionFactory.getCurrentSession().createSQLQuery(query).list();
return personList;
}

boolean deletePerson(Person person){
String query = "delete from person where username=${person.username}";
Integer rowsEffected = sessionFactory.getCurrentSession().createSQLQuery(query).executeUpdate();
if(rowsEffected == 1);
return true;
else
return false;
}

Person updatePerson(Person person){
String query = "update person set username=${person.username} where id={person.id}";
Integer rowsEffected = sessionFactory.getCurrentSession().createSQLQuery(query).executeUpdate();
if(rowsEffected == 1);
return person;
else
// throw new Exception();
}


}

This is how you can execute the simple SQL queries in Grails using hibernate sessionFactory.

Points To Remember


  • Add the plugin Csv Grails plugin .
  • You can do it manually without the plugin if the you have a uniform structure of the csv file.

Upload a Csv 

You need to add the dependency for the csv file reader in BUildConfig.groovy as shown below
BuildConfig.groovy
compile ":csv:0.3.1"
And you have a csv file like the following.

upload.jsp
<g:uploadForm action="upload">
<input type="file" name="file">
<g:submitButton name="file" value="Upload"/>
</g:uploadForm>
When the above form is submitted then the request will be handled by the controller action as shown below

UploadController.groovy
def upload() {
MultipartFile file = request.getFile( 'file' )
file.inputStream.eachCsvLine { row ->
String name = row[1] ?: "NA";
String email = row[2] ?: "NA";

// Business Logic here
}
}
Now you can do your business logic in the space provided.

Points To Remember


  • Versioning  of Controllers can be done in grails with the help of UrlMappings and Namespaces.
  • We can have two or more controllers with the same name as long as they are in different packages and different namespaces.
  • You can map these controllers in UrlMappings like /$namespace/$controller/$action

Versioning of Grails Controllers 

The easiest way of versioning the grails controllers is to do it with the help of namespaces. So in this example we will try to do versioning of the controllers on the basis of namespaces.
Test.groovy
package com.ekiras.versioning.v1

class TestController {

static namespace = "v1"

def index() {
render "Hi, This is version 1"
}
}

Test.groovy
package com.ekiras.versioning.v2

class TestController {

static namespace = "v2"

def index() {
render "Hi, This is version 2"
}
}

UrlMappings
class UrlMappings {

static mappings = {

"/$namespace/$controller/$action?/$id?(.$format)?"{
constraints {
// apply constraints here
}
}


"/$controller/$action?/$id?(.$format)?"{
constraints {
// apply constraints here
}
}

"/"(view:"/index")
"500"(view:'/error')
// Other Mappings
}
}

So now we can call the two different controllers with the same name but different namespaces.
For example, if we run our app at root context at port 8080, then we can access these like following

http://localhost:8080/v1/test
http://localhost:8080/v2/test

Points To Remember


  1. You must have a project created in Developers console to use Youtube data api and other api's.
  2. You should save the youtube refresh token in a database or file where you can save it for a long time and use it.
  3. Youtube refresh token is generated only once, so if you want to regenerate it go to google accounts page and revoke access to your project and then re authenticate.
  4. To revoke access, go to Connected Apps and Sites in the above mentioned url and click on your project and then click revoke access to revoke access to the app.

Steps to Use Youtube Data Api v3

  1. You need to create a new Project in your at Developers Console.
  2. After creating a project you need to go to Project -> Api & auth -> Credentials , and then create a new Client ID.
  3. Go to Project -> Api & auth ->APIs and enable Youtube Analytics API and YouTube Data API v3. This will enable your project to use consume these api's.
  4. For using these api's in your application you need to setup the callback url. Go to Project -> Api & auth ->API -> Credentials
  5. You are all ready to use the youtube data api.
 In this tutorial we will see how to use the youtube data api in Grails. See how to use Youtube data api in Java example.

Add Rest Plugin to your project

BuildConfig.groovy
Add the following dependency to your project BuildConfig to enable rest calls using HttpBuilder.
compile ":rest:0.8"


Config.groovy
Save your data in the Config and use it in database, config used in this example is given below.
youtube{

clientId="your_client_id"
clientSecret="your_client_secret"
scope ="https://gdata.youtube.com"
responseType ="code"
accessType="offline"
redirectUrl = "http://localhost:8085/youtube/callBack"

url{
auth = "https://accounts.google.com/o/oauth2/auth"
token = "https://accounts.google.com/o/oauth2/token"
userInfo = "https://www.googleapis.com/oauth2/v2/userinfo"
dataApi = "https://www.googleapis.com/youtube/v3"
}

}

Use Youtube Data Api v3

YoutubeController.groovy
Use this controller to authenticate the user from the google account and use youtube api. You should implement the logic to save the response data i.e. refresh token in database.
class YoutubeController {


YoutubeAuthService youtubeAuthService


def auth(){
response.sendRedirect(youtubeAuthService.createAuthorizeRequest());
}

def callBack(String code){
// User did not rejected authorization of your project
if(!code)
redirect(action: 'Error Action')
def object = youtubeAuthService.getAccessToken(code)

// Save your Youtube Tokens to DB
// or hit data api to get User info using access token and then save
 
// chain the request to your success handler.
chain(controller: 'controller', action: 'action')
}
}

YoutubeAuthService.groovy
Use this service to get the access token and refresh tokens
package com.ekiras.youtube

import groovyx.net.http.HTTPBuilder
import groovyx.net.http.Method

import static groovyx.net.http.ContentType.URLENC

class YoutubeAuthService {

def grailsApplication


String createAuthorizeRequest() {
String clientId = grailsApplication.config.youtube.clientId;
String authUrl = grailsApplication.config.youtube.url.auth;
String redirectUrl = grailsApplication.config.youtube.redirectUrl;
String scope = grailsApplication.config.youtube.scope;
String responseType = grailsApplication.config.youtube.responseType;
String accessType = grailsApplication.config.youtube.accessType;

String authRequest = authUrl + "?client_id=" + clientId + "&redirect_uri=" + redirectUrl + "&scope=" + scope + "&response_type=" + responseType + "&access_type=" + accessType
return authRequest;
}

def getAccessToken(String code){

String clientId = grailsApplication.config.youtube.clientId;
String clientSecret = grailsApplication.config.youtube.clientSecret;
String tokenRequestUrl = grailsApplication.config.youtube.url.token;
String redirectUrl = grailsApplication.config.youtube.redirectUrl;
String grantType = "authorization_code";

Map data = ['client_id':clientId,'client_secret':clientSecret,'code':code ,'redirect_uri':redirectUrl,'grant_type':grantType]
HTTPBuilder httpBuilder = new HTTPBuilder(tokenRequestUrl);

httpBuilder.request(Method.POST){
requestContentType = URLENC
body = data;
response.success = {resp, reader ->
// reader contains a access_token,token_type and expires_in
return reader
}
response.failure = {response, reader ->
return null
}
}
}

}

Points To Remember

You need to change the UserDetailsService, User Object of the spring security to achieve this.

Add Custom User Details to Spring Security Authentication Object

First of all we nee to create a new User Object that will override the User class of the spring security in package org.springframework.security.core.userdetails.User After this, you need to tell  UserDetailsService to use this object as the principal for the authentication token. For this you will have to override the UserDetailsService of the spring security.

You can have the custom User object like.
Custom User Class -> MyUser.groovy
package com.ekiras

import org.springframework.security.core.GrantedAuthority

/**
* Created by ekansh on 24/1/15.
*/
class MyUser extends org.springframework.security.core.userdetails.User {

// Declare all custom attributes here
private final Object id;
private String name;

public MyUser(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<GrantedAuthority> authorities, Object id, String name) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired,
accountNonLocked, authorities);

// Initialize all the custom attributes here like the following.
this.id = id;
this.name = name;
}

/**
* Get the id.
* @return the id
*/
public Object getId() {
return id;
}
}

So now our User object will also contain a field name that is the concatenation of first name and last name.
Custom UserDertailService -> MyUserDetailsService.groovy
package com.ekiras

import grails.plugin.springsecurity.SpringSecurityUtils
import grails.plugin.springsecurity.userdetails.NoStackUsernameNotFoundException
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.core.userdetails.UsernameNotFoundException

/**
* Created by ekansh on 23/1/15.
*/
class MyUserDetailsService implements UserDetailsService {

static final GrantedAuthority NO_ROLE = new SimpleGrantedAuthority(SpringSecurityUtils.NO_ROLE)

@Override
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

User user = User.findByUsername(username)
if(!user)
throw new NoStackUsernameNotFoundException();

Collection<GrantedAuthority> authorities;

user.authorities.each {authority->
authorities.collect(new SimpleGrantedAuthority(authority))
}

authorities = authorities ?: [NO_ROLE]

// Return the Custom User object
return new MyUser(username, user.password, user.enabled, !user.accountExpired, !user.passwordExpired,!user.accountLocked, authorities, user.id, user.firstName+ user.lastName);
}
}

So now we have a custom UserDetailsService that will load our MyUser  object in spring security authentication principal, instead of conventional GromUser object. You need to do one last thing to make things work. You need to override the UserDetailsService and tell spring security to use your custom UserDetailsService and you can do it like the following.
Add this in resources.groovy
userDetailsService(MyUserDetailsService)

Thats it, now you have can add any number of custom attributes of the User object to spring security authentication.

Points To Remember

You may need to create an AuthenticatioFilter when you want to create a custom logic for handling the authentication filter. You may also want to create your own Authentication Provider, Entry Point, Authentication Token etc to customize the authentication process to a new level.

Step 1 : Create a Filter

Let us first create a class named MyAuthenticationFilter and then register it as a bean in resources.groovy. After we have created the class and registered the it as a bean, we can use this class as a filter for our custom spring security authentication.

Class : MyAuthenticationFilter.groovy
package com.ekiras

import org.springframework.context.ApplicationEventPublisher
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent
import org.springframework.security.core.Authentication
import org.springframework.security.core.AuthenticationException
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter
import org.springframework.security.web.authentication.AuthenticationFailureHandler
import org.springframework.security.web.authentication.AuthenticationSuccessHandler

import javax.servlet.FilterChain
import javax.servlet.ServletException
import javax.servlet.ServletRequest
import javax.servlet.ServletResponse
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

/**
* Created by ekansh on 19/1/15.
*/
class MyAuthenticationFilter extends AbstractAuthenticationProcessingFilter{

public static final String USERNAME = 'j_username';
public static final String PASSWORD = 'j_password';


AuthenticationSuccessHandler authenticationSuccessHandler
AuthenticationFailureHandler authenticationFailureHandler
ApplicationEventPublisher applicationEventPublisher



protected MyAuthenticationFilter() {
super('/mylogin') // Register the url that will be intercepted by this filter.
}

@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req
HttpServletResponse response = (HttpServletResponse) resp
  //Check if the url contains the filterProcessUrl and required authentication is false, if not then pass the request to the next filter.
if (!request.getRequestURI().contains(filterProcessesUrl) && !requiresAuthentication(request, response)) {
chain.doFilter(request, response)
return
}

// Create an authentication token that will be returned.
Authentication authentication;
try{ // If the credentials to not match then an AuthenticationException is thrown.
authentication = attemptAuthentication(request, response)
// If successfully authenticated then pass the request to the success handler
if(authentication.authenticated)
successfulAuthentication(request,response,authentication)
}
catch(AuthenticationException exception){
// Pass the request to authentication failure handler.
unsuccessfulAuthentication(request,response,exception)
return
}
}

@Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
return true;
}


@Override
Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {

String username = getUsername(httpServletRequest);
String password = getPassword(httpServletRequest);

Authentication authentication = new UsernamePasswordAuthenticationToken(username, password);

return this.authenticationManager.authenticate(authentication);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException{
SecurityContextHolder.getContext().setAuthentication(authentication)
applicationEventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authentication, this.class))
authenticationSuccessHandler.onAuthenticationSuccess(request,response,authentication)
}

@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException{
authenticationFailureHandler.onAuthenticationFailure(request,response, exception)
}

// Get the username from the request object
String getUsername(HttpServletRequest request){
return request.getParameter(USERNAME);
}

// get the password from the request object
String getPassword(HttpServletRequest request){
return request.getParameter(PASSWORD);
}
}

Now we register the class as a spring bean in resources.groovy like this.
    myAuthenticationFilter(MyAuthenticationFilter){
authenticationManager = ref('authenticationManager')
sessionAuthenticationStrategy = ref('sessionAuthenticationStrategy')
authenticationSuccessHandler = ref('authenticationSuccessHandler')
authenticationFailureHandler = ref('authenticationFailureHandler')
rememberMeServices = ref('rememberMeServices')
authenticationDetailsSource = ref('authenticationDetailsSource')
filterProcessesUrl = '/mylogin'
}

Now you need to register this filter in the deployment descriptor so that the these effects take place. There are two ways of doing this

  1. You can declare your filter using a filter chain in Config.groovy. See the documentation how to do this.
  2.  You can declare the filter in bootsrap as following
    SpringSecurityUtils.clientRegisterFilter('myAuthenticationFilter', SecurityFilterPosition.SECURITY_CONTEXT_FILTER.order + 10)

Points To Remember

Go to the Grails Spring Security Plugin and add the dependency in the BuildConfig.

Integrate Spring Security in Grails

Add the latest grails spring security plugin in the build config of the project. This will add spring security jars and classes that will be used to configure spring security in the project.
http://grails.org/plugin/spring-security-core
Now run the following command from the terminal.
grails s2-quickstart com.ekiras User Role
Here the syntax of the above command is
grails s2-quickstart {package} {user domain} {authority domain}
The above command will create three Domains in the project User, Role and UserRole. user domain will contain the user info, role domain will contain Authorities and UserRole will contain the user authority mappings.
It will also add the following settings to the Config.groovy

// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.ekiras.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.ekiras.UserRole'
grails.plugin.springsecurity.authority.className = 'com.ekiras.Role'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
'/': ['permitAll'],
'/index': ['permitAll'],
'/index.gsp': ['permitAll'],
'/assets/**': ['permitAll'],
'/**/js/**': ['permitAll'],
'/**/css/**': ['permitAll'],
'/**/images/**': ['permitAll'],
'/**/favicon.ico': ['permitAll']
]
It tells that the userDomain class authority class and user-authority join class. For other settings of the Spring security you can open the file DefaultSecurityConfig.groovy .

See the Default Password Encoders and Custom Password Encoders in Grails Spring Security.

Points To Remember

  • You need to add the @Validateable annotation to the command class.
  • Use importFrom in the constraints block with the domain name to import the constraints from domain.

How to add Constraints to the Command Object.

Lets us look at the example below. We have created a Domain by name User and a Command object by name UserCommand. We have created the constraints for email, password, first name and last name in User domain. We will import these constraints from domain to the command object and add some more constraints like verify password( if password and confirm password match).

User.groovy
package com.ekiras.domain

class User {

String email
String password
String firstName
String lastName

static constraints = {
email(nullable: false, blank: false, unique: true, email:true)
password(nullable: false, blank: false)
firstName(nullable: false, blank: false)
lastName(nullable: false, blank: false)
}

}

UserCommand.groovy
package com.ekiras.co

import com.ekiras.domain.User
import grails.validation.Validateable


@Validateable
class UserCommand {

String email
String password
String firstName
String lastName
String confirmPassword
static constraints = {
// Imports the constraints of the User domain in UserCommand
importFrom User
password minSize: 8, validator: {password, obj ->
obj.confirmPassword == password ? true : 'Passwords do not match'
}
}

You can now call the validate method over the UserCommand like userCommand.validate() and you can get the errors by calling userCommand.hasErrors() . This is how you can add constraints of the domain to the command objects or any other class.

Points To Remember
  • By default, in grails all the html code and script code is escaped.
  • You can render your html string as html in three ways, change in config, change at page level and change at field level. 
Rendering HTML String in a GSP in Grails.
Suppose we have a String like the following and we want it to get rendered as HTML in our gsp. By default out code will get rendered like this.
Hi < br />My name is Ekansh Rastogi < br />I want this in three lines.
But we wanted out output as
Hi 
My name is Ekansh Rastogi
I want this in three lines.

So, following are the ways in which you can render your HTML String as HTML.
  1. Render the Html String you want to encode as HTML.
    ${raw(htmlString)}
    This will encode the string and make it render like html. This will encode only the string on which it is called upon.
  2. Render the all HTML Strings in a page to encode as HTML.
    <%@page expressionCodec="none" %>
    This will render all the html strings in the page as HTML. In this case we may not want to encode each string separately to HTML, just one directive will do our work for the whole page.
  3. Render the all HTML Strings in the Web project to encode as HTML.
    grails {

        views {

            gsp {

                encoding = 'UTF-8'

                htmlcodec = 'xml' // use xml escaping instead of HTML4 escaping

                codecs {

                    expression = 'none' // escapes values inside ${}

                    scriptlet = 'html' // escapes output from scriptlets in GSPs

                    taglib = 'none' // escapes output from taglibs

                    staticparts = 'none' // escapes output from static template parts

                }

            }

            // escapes all not-encoded output at final stage of outputting

            // filteringCodecForContentType.'text/html' = 'html'

        }

    }
    This will render all the html strings in the whole web application. In this case we may not need to encode each string field as HTML nor do we need to add the page directives on each page.
Please note that, making all the html strings to encode as HTML will make your site vulnerable to attacks like Cross Site Scripting.  So it is advised to make use of this very judiciously. 
First things that comes in mind
  • Respond was introduced in Grails v2.3.
  • Render is used by Grails to render different forms of responses from simple text response, to views to templates.
  • Respond automatically attempts to return the most appropriate type for the requested content type.
  • Respond is a better version of render, and can do everything render does.
Example
In case you want to send data to the view in "xml" or in "json" format then you will have to do the following
  • render : // renders text for a specified content-type/encoding
    render(text: "some xml", contentType: "text/xml", encoding: "UTF-8"
    render(text: "some json", contentType: "text/json", encoding: "UTF-8"
  • respond :  by using respond, it will automatically select the correct return type
  • respond( text: "some text in json or xml" [formats : ['xml' , 'json']]) it will automatically send the required respond depending upon the type of request.