Boost your productivity.
Grails yourself!
Manuel Ángel Quindimil
@quindimildev
https://goo.gl/gzOHZb
Who I am?
- Senior web developer at Salenda
- Working with Grails since 2011
- Scrum Master Certified
- Discovering Angular 2
https://goo.gl/gzOHZb
What is Grails?
- Powerful web framework
- Java platform
- Based on Convention over Configuration
- Integrates with JVM
- Immediately productive
- Integrated ORM
https://goo.gl/gzOHZb
Resolving the web development puzzle
- Groovy as language
- Built on Spring Boot
- Gradle build system
- Object Relational Mapping (ORM) layer built on Hibernate
- A controller layer built on Spring MVC
https://goo.gl/gzOHZb
Resolving the web development puzzle
- Embedded Tomcat container with fly reloading
- Dependency injection. Spring container
- Internationalization (i18n) built on Spring's core MessageSource concept
https://goo.gl/gzOHZb
Start!
Creating a new project
Creating a new project
$ grails create-app my-app
project name
https://goo.gl/gzOHZb
Running our new project
$ grails run-app
or using the gradle wrapper
$ ./gradlew bootRun
https://goo.gl/gzOHZb
GORM
Grails Object Relational Mapping
What is GORM?
- Data access toolkit
- Allow access for relational and non-relational data such as:
- SQL
- MondoDB
- Cassandra
- Neo4j
- Redis
https://goo.gl/gzOHZb
Creating a domain
Domain class could be also created directly into the domain folder
$ grails create-domain-class es.example.Book
package es.example
class Book {
String title
String isbn
String description
}
https://goo.gl/gzOHZb
Creating a domain
Domain class could be also created directly into the domain folder
$ grails create-domain-class es.example.Author
package es.example
class Author {
String name
String email
}
https://goo.gl/gzOHZb
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
}
}
https://goo.gl/gzOHZb
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"
}
}
https://goo.gl/gzOHZb
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
}
}
https://goo.gl/gzOHZb
Database connection
Setting a MySQL connection
Include the JDBC driver
dependencies {
// ...
runtime "mysql:mysql-connector-java:5.1.36"
// ...
}
build.gradle
https://goo.gl/gzOHZb
Setting a MySQL connection
Setting DB configuration
application.yml
#..
dataSource:
pooled: true
jmxExport: true
driverClassName: com.mysql.jdbc.Driver
username: example
password: example
environments:
development:
dataSource:
dbCreate: create-drop
url: jdbc:mysql://localhost:3306/example
#..
https://goo.gl/gzOHZb
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 ->
Book book = new Book(title: "Book${authorIndex}-${bookIndex}",
description: "description ${authorIndex}-${bookIndex}")
author.addToBooks(book)
}
author.save()
}
}
//to de when app is destroyed
def destroy = {
}
}
BootStrap.groovy
https://goo.gl/gzOHZb
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
https://goo.gl/gzOHZb
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
https://goo.gl/gzOHZb
Plugins
Plugins
We can add functionality installing plugins or create our own
https://goo.gl/gzOHZb
Securing our app
Installing Spring Security Core plugin
https://goo.gl/gzOHZb
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.example User Role
https://goo.gl/gzOHZb
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'))
}
//..
https://goo.gl/gzOHZb
Securing controllers/actions
AuthorController.groovy
package es.example
import grails.plugin.springsecurity.annotation.Secured
@Secured(['ROLE_ADMIN', 'ROLE_USER'])
class AuthorController {
//..
@Secured('ROLE_ADMIN')
def delete() { }
//..
}
https://goo.gl/gzOHZb
Custom config
AuthorController.groovy
//..
grails.plugin.springsecurity.logout.postOnly = false
//..
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
https://goo.gl/gzOHZb
Rest API
Grails profiles
Running "create-app" the web profile is used by default
A profile encapsulates an application structure, set of commands, plugins and capabilities
https://goo.gl/gzOHZb
Grails profiles
-
Some of them are:
- Angular profile
- Rest-api
How to use:
$ grails create-app my-rest-app --profile=rest-api
https://goo.gl/gzOHZb
JSON Views
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.plugins.views-json"
//..
dependencies {
//..
compile 'org.grails.plugins:views-json'
//..
}
build.gradle
https://goo.gl/gzOHZb
JSON Views
package es.example
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.example.AuthorService
https://goo.gl/gzOHZb
JSON Views
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
https://goo.gl/gzOHZb
JSON Views
import es.example.Author
model{
Iterable<Author> authors
}
json tmpl.author(authors)
search.gson
Creating JSON Views with a template
import es.example.Author
model{
Author author
}
json{
name author.name
numBooks author.books.size()
}
_author.gson
https://goo.gl/gzOHZb
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
https://goo.gl/gzOHZb
Deploying
$ java -jar my-app-0.1.war
Runnable WAR
https://goo.gl/gzOHZb
We are hiring!
hello@salenda.es
Thanks!
Boost your productivity. Grails yourself!
By Manuel Ángel Quindimil López
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.
- 1,402