Boost your productivity.
Grails yourself!
Manuel Ángel Quindimil
@quindimildev
http://goo.gl/KpIYUo
Who is Manuel Quindimil?
- Senior web developer at Salenda
- Scrum Master Certified
- Has worked with Grails since 2011
http://goo.gl/KpIYUo
What is Grails?
- Powerful web framework
- Java platform
- Based on Convention over Configuration
- Integrates with JVM
- Immediately productive
- Integrated ORM
http://goo.gl/KpIYUo
Resolving the web development puzzle
http://goo.gl/KpIYUo
Resolving the web development puzzle
- Embedded Tomcat container with fly reloading
- Dependency injection. Spring container
- Internationalization (i18n) built on Spring's core MessageSource concept
http://goo.gl/KpIYUo
Start!
Creating a new project
Creating a new project
$ grails create-app my-app
project name
http://goo.gl/KpIYUo
Running our new project
$ grails run-app
or using the gradle wrapper
$ ./gradlew bootRun
http://goo.gl/KpIYUo
GORM
Grails Object Relational Model
What is GORM?
- Data access toolkit
- Allow access for relational and non-relational data such as:
- SQL (Hibernate)
- MondoDB
- Cassandra
- Neo4j
- Redis
http://goo.gl/KpIYUo
Creating a domain
Domain class could be also created directly into the domain folder
$ grails create-domain-class es.jbcnconf.Book
package es.jbcnconf
class Book {
String title
String isbn
String description
}
http://goo.gl/KpIYUo
Creating a domain
Domain class could be also created directly into the domain folder
$ grails create-domain-class es.jbcnconf.Author
package es.jbcnconf
class Author {
String name
String email
}
http://goo.gl/KpIYUo
Constraints
Defining validation rules, schema generation
class Book {
String title
String isbn
String description
static constraints = {
isbn nullable: true
}
}
class Author {
String name
String email
static constraints = {
email email: true, nullable: true
}
}
http://goo.gl/KpIYUo
Database mapping
Defining the way a domain is mapped to the DB
class Book {
String title
String isbn
String description
static constraints = {
isbn nullable: true
}
static mapping = {
table "books"
description type: "text"
}
}
http://goo.gl/KpIYUo
One-to-many association
Creating a 1:n relation between two classes
class Book {
String title
String isbn
String description
static belongsTo = [author: Author]
static constraints = {
isbn nullable: true
}
static mapping = {
table "books"
description type: "text"
}
}
class Author {
String name
String email
static hasMany = [books: Book]
static constraints = {
email email: true, nullable: true
}
}
http://goo.gl/KpIYUo
Database connection
Setting a MySQL connection
Include the JODB driver
dependencies {
// ...
runtime "mysql:mysql-connector-java:5.1.36"
// ...
}
build.gradle
http://goo.gl/KpIYUo
Setting a MySQL connection
Setting DB configuration
application.yml
#..
dataSource:
pooled: true
jmxExport: true
driverClassName: com.mysql.jdbc.Driver
username: jbcnconf
password: jbcnconfpass
environments:
development:
dataSource:
dbCreate: create-drop
url: jdbc:mysql://localhost:3306/jbcndb
#..
http://goo.gl/KpIYUo
Programmatic start-up configuration
Bootstrap class
Programmatic start-up configuration can be added
class BootStrap {
//to do when app is launched
def init = { servletContext ->
50.times{ authorIndex ->
Author author = new Author(name: "Author ${authorIndex}",
email: "email${authorIndex}@salenda.es")
3.times{ bookIndex ->
author.addToBooks(title: "Book${authorIndex}-${bookIndex}",
description: "description ${authorIndex}-${bookIndex}")
}
author.save()
}
}
//to de when app is destroyed
def destroy = {
}
}
BootStrap.groovy
http://goo.gl/KpIYUo
Scaffolding
Scaffolding
Generates some basic CRUD interfaces for a domain class
$ grails generate-all *
-
Generates:
- The necessary views (GSPs)
- Controller actions for:
- Create, Edit, Show & Delete an instance
http://goo.gl/KpIYUo
Scaffolding
If we do not want to use it....
dependencies {
// ...
//remove this
compile "org.grails.plugins:scaffolding"
// ...
}
build.gradle
Do not remove it if you have used cause includes some required dependencies
http://goo.gl/KpIYUo
Plugins
Plugins
We can add functionality installing plugins or create our own
http://goo.gl/KpIYUo
Securing our app
Installing Spring Security Core plugin
http://goo.gl/KpIYUo
Installing Spring Security Core pluging
dependencies {
// ...
compile 'org.grails.plugins:spring-security-core:3.1.1'
// ...
}
build.gradle
Setting the user and role classes
$ grails s2-quickstart es.jbcnconf User Role
http://goo.gl/KpIYUo
Creating a user with a certaing role
BootStrap.groovy
//..
if(!Role.count){
['ROLE_ADMIN', 'ROLE_USER'].each{ roleName ->
new Role(authority: roleName).save(flush:true)
}
}
if(!User.count){
User admin = new User(username: 'admin', password: 'admin')
admin.save(flush: true, failOnError: true)
UserRole.create(admin, Role.findByAuthority('ROLE_ADMIN'))
User user = new User(username: 'user', password: 'user')
user.save(flush: true, failOnError: true)
UserRole.create(user, Role.findByAuthority('ROLE_USER'))
}
//..
http://goo.gl/KpIYUo
Securing controllers/actions
AuthorController.groovy
package es.jbcnconf
import grails.plugin.springsecurity.annotation.Secured
@Secured(['ROLE_ADMIN', 'ROLE_USER'])
class AuthorController {
//..
@Secured('ROLE_ADMIN')
def delete() { }
//..
}
http://goo.gl/KpIYUo
Custom config
AuthorController.groovy
//..
grails.plugin.springsecurity.logout.postOnly = false
//..
http://goo.gl/KpIYUo
Logout is only allow by default but can be set
//..
//We haven't created this 'email' property yet!
grails.plugin.springsecurity.userLookup.usernamePropertyName = 'email'
//..
Changing login by username for other user property instead
application.groovy
application.groovy
Rest API
Grails profiles
http://goo.gl/8s89PA
Running "create-app" the web profile is used by default
A profile encapsulates an application structure, set of commands, plugins and capabilities
Grails profiles
http://goo.gl/8s89PA
-
Some of them are:
- Angular profile (1.x) - 2.x soon
- Rest-api
How to use:
$ grails create-app my-rest-app --profile=rest-api
JSON Views
http://goo.gl/8s89PA
Comes by default with the rest-api profile
but we can use them on our app with web profile
buildscript {
//..
dependencies {
//..
classpath "org.grails.plugins:views-gradle:1.0.12"
}
}
//Insert after Grails core gradle plugins
apply plugin: "org.grails.grails-web"
apply plugin: "org.grails.plugins.views-json"
//..
dependencies {
//..
compile 'org.grails.plugins:views-json'
//..
}
build.gradle
JSON Views
http://goo.gl/8s89PA
package es.jbcnconf
import grails.transaction.Transactional
@Transactional
class AuthorService {
def search(String name, String email) {
// Dynamic finders are the easiest way for retrieving data from DB
// Author.findAllByNameLike("%${name}%")
// Criterias have better performance, and do more complex queries
Author.withCriteria{
like("name", "%${name}%")
if(email){
like("email", "%${email}%")
}
}
}
}
AuthorService.groovy
Creating a service for searching Authors
$ grails create-service es.jbcnconf.AuthorService
JSON Views
http://goo.gl/8s89PA
Injecting the service bean in the controller
//@Secured(['ROLE_ADMIN', 'ROLE_USER'])
@Secured('permitAll')
class AuthorController {
AuthorService authorService
//..
def search(){
[authors: authorService.search(params.name, params.email)]
}
AuthorController.groovy
Allowing free access to the controller
Invokes the service method
The request parameters map
Creating an action
JSON Views
http://goo.gl/8s89PA
import es.jbcnconf.Author
model{
Iterable<Author> authors
}
json tmpl.author(authors)
search.gson
Creating JSON Views
import es.jbcnconf.Author
model{
Author author
}
json{
name author.name
numBooks author.books.size()
}
_author.gson
Deploying the app
WAR building
..
version "0.1"
..
build.gradle
Specifying the app version
Building a runnable war
$ grails dev package
$ ./gradlew assemble -Dgrails.env=dev
or using the gradle wrapper
http://goo.gl/KpIYUo
Deploying
$ java -jar my-app-0.1.war
Runnable WAR
http://goo.gl/KpIYUo
Thanks!
JBCNConf - Boost your productivity. Grails yourself!
By Manuel Ángel Quindimil López
JBCNConf - Boost your productivity. Grails yourself!
We are going to learn how to create a web-app with Grails 3. Also applying some security plugins and others, to learn how to start developing with the most productivity Java framework, from the beginning to deploying a war into Tomcat.
- 2,638