84
2007 JavaOne SM Conference | Session BOF-9843 | BOF-9843 Grails, Trails, and Sails: Rails Through a Coffee Filter Matt Hughes David Esterkin Chariot Solutions http://chariotsolutions.com

Grails, Trails, and Sails: Rails Through a Coffee Filter

Embed Size (px)

Citation preview

Page 1: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

BOF-9843

Grails, Trails, and Sails:Rails Through a Coffee Filter

Matt HughesDavid Esterkin

Chariot Solutions http://chariotsolutions.com

Page 2: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 2

Agenda

Brief History of Web DevelopmentRuby On RailsSails TrailsGrailsThe Future of *ails

Page 3: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 3

Agenda

Brief History of Web DevelopmentRuby On RailsSails TrailsGrailsThe Future of *ails

Page 4: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

A Brief History of Web Application Development

In the beginning there was pain

4

then came Ruby on Rails

. . .

Page 5: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 5

Agenda

Brief History of Web DevelopmentRuby On RailsSails TrailsGrailsThe Future of *ails

Page 6: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Rails Screencast

6

rails blog_app

Page 7: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Gives You...

7

A functional CRUD app in 15 minutes

Page 8: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Ruby on Rails

8

Convention over

Configuration

Opinionated Software

Don’t Repeat Yourself

Get Real

80/20 RuleTest Driven

Development

MVC

Agile

Page 9: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Rails Dissected

9

ActiveRecord Model

ActionController Controller

ERB ViewRuby

Page 10: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 10

State of Java Web Development

• Coincides with• Disillusioned with EJB 2.x• Code, compile, deploy, restart server cycle• Popularity of dynamic languages on the JVM• Realization that Enterpriseyness != Self-Worth

Page 11: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 11

Page 12: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

The Contenders

12

Trail Domain Driven Design

Sail Controller-centric

Grail DDD / Full stack

Page 13: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 13

Agenda

Brief History of Web DevelopmentRuby On RailsSailsTrailsGrailsThe Future of *ails

Page 14: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

• Started in 2005• Brings the flavor of Rails development to

Java• Viento: custom template engine• Rigging: custom dependency injection library

14

Page 15: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Similar to *ails

• Generates nice URLs• Promotes easy testing

• Templates are closest to Rails of the 3 Java frameworks

15

Page 16: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Differs from *ails

• Does not provide utilities to generate scaffolding• No functionality to facilitate Hibernate persistence

layer

16

Page 17: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Components

• Model: Hibernate• Developers don’t think ActiveRecord can be duplicated

in Java• Already comfortable with Hibernate

• View: Viento• Custom template engine• Supports partials and caching• Mixins

• Controller: Rigging• Custom dependency injection library• Provides convention over configuration defaults

17

Page 18: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Convention over Configuration

• Controllers all go in a specific package• Action URL contains the controller name, action

name, and action parameters• ‘widget/list’ => WidgetController.list()

• Views all go under the /views webapp directory• View names match the controller/action names

• /views/widget/list.vto

• Template engine extensions follow similar pattern• View tools are in org.opensails.examples.tools• Mixins are in org.opensails.examples.mixins

18

Page 19: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Generate Sample Application

• Download zip file from opensails.org• Create Eclipse project

• Import Existing Projects into Workspace• Select Archive file (downloaded zip file)

• Configure Server• Run as Java Application• Main Class org.opensails.example.JettyBoot

19

Page 20: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Add New Controllerpublic class PostController extends BaseController {public void list() { expose("posts", postService.getAllPosts());}public void view(int postId) { expose("post", postService.getPost(postId);}public void add() { exposeModel(“post”, new Post());}public void save(Post post) { // persist post}

20

Extends BaseController

Maps to /post/* urls

Maps to /post/listExposes ‘posts’ to view

Maps to /post/view/#idExposes ‘post’ to view

Exposes the Post model for a form to use

Post is loaded from the form

Page 21: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

List Posts View (list.vto)<body> ... <table> <tr> <th>Date</th> <th>Title</th> </tr> $posts.each(cur_post) [[ <tr> <td>$cur_post.dateString</td> <td> <a href="/app/post/view/$cur_post.id">$cur_post.title</a> </td> </tr> ]] </table> <a href="/app/post/add">New Post</a> ...</body>

21

Ruby like each construct

Bean style attribute access

Page 22: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Add Post view (/post/add.vto)<html> <head><title>Add Post</title></head> <body> $form.start $form.text('post.title').label("Title")<br /> $form.textarea('post.body').label("Body")<br /> $form.submit("Post Entry").action(save, [$post]) $form.end </body></html>

22

Maps to PostController.save(post)

Page 23: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Viento: Top Level MixinsIn Java: public class Mixin { public boolean isEven (int i) { return (i % 2 == 0); } } ... binding.mixin(new Mixin());

In Viento: $isEven($row_num)

23

Page 24: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Viento: Type Mixins

In Java: public class EvenMixin { public boolean isEven (int i) { return (i % 2 == 0); } } ... binding.mixin(int.class, new EventMixin());

In Viento: $row_num.isEven

24

Page 25: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Viento: Method MissingIn Java: public class TagTool implements MethodMissing { public String methodMissing(String methodName, Object[] args) { return “<” + methodName + “>”; } } ... binding.put(“tag”, new TagTool());

In Viento: $tag.div

25

Page 26: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Viento: Custom Method Names

In Java: public class Tool { @Name(“?”) public String question(String arg) { return “do something interesting”; }

In Viento: $tool.?(“my string”)

26

Page 27: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Roadmap

• Project is dormant• Development team is now using Rails!

• Lead developer was very helpful, and would like to see Sails continue

27

Page 28: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 28

Agenda

Brief History of Web DevelopmentRuby On RailsSails TrailsGrailsThe Future of *ails

Page 29: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

• Started in mid 2005• Currently at 1.0-SNAPSHOT

• Influences• Ruby on Rails • Naked Objects pattern

29

Page 30: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Rails Influence

• Rapid web application development• Scaffolding generation

• Convention over configuration

30

Page 31: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Naked Objects Influence

• http://nakedobjects.org• Domain Driven Design

• Domain objects are behaviorally complete• Domain objects have single point of definition

31

Page 32: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Components

• Tapestry• Spring

• Hibernate• Maven

32

Page 33: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Getting Started

• Requirements• Java 1.5• Maven 2

• trails-archetype• 1.0-SNAPSHOT: build locally• Release will be in maven repository

33

Page 34: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Creating the Application

mvn -U archetype:create \ -DarchetypeGroupId=org.trailsframework \ -DarchetypeArtifactId=trails-archetype \ -DremoteRepositories= \http://snapshots.repository.codehaus.org/ \ -DarchetypeVersion=1.0-SNAPSHOT \ -DgroupId=com.chariotsolutions.trailsdemo \ -DartifactId=trailsdemo

34

Page 35: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 35

Source structure created, and includes base domain object

JUnit application test

Hibernate configuration(set for HSQL)

What this generates

Page 36: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Running the Application

mvn tomcat:run or mvn jetty:run

• Create process generates a base domain object

• Initially uses an in-memory HSQL database

36

Page 37: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

IDE Support

• Because Trails is built on popular Java libraries, there is already pretty good support in the popular IDEs• mvn eclipse• mvn idea• Netbeans mevenide?

37

Page 38: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Create Company domain class@Entity@ValidateUniqueness(property="name")public class Company { private int id; private String name; private String website;

@Id @GeneratedValue(strategy = GenerationType.AUTO) public int getId() ...

@PropertyDescriptor(index=0) public getName() ...

@PropertyDescriptor(index=1) public String getWebsite() ...

// omitted setters}

38

Define as an entityForce name to be unique

Define Primary Keyand generation method

Set screen display order

Page 39: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Create Speaker domain class@Entitypublic class Speaker { private int id; private String name; private Date presentationDate; private Company employer;

@ManyToOne @JoinColumn(name="company_id") @PropertyDescriptor(index=3) public Company getEmployer() ...

}

39

Define many to one relationship betweenspeaker and company

Page 40: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Ready to Go!

mvn tomcat:run or mvn jetty:run

40

Page 41: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Home page

41

Page 42: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

List Companies

42

Page 43: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Search Company

43

Page 44: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Add/Edit/Delete Company

44

Page 45: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

List Speakers

45

Page 46: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Search Speaker

46

Page 47: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Add/Edit/Delete Speaker

47

Page 48: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Customizing View

• Copy the default view to view specific to the controller.• cp DefaultEdit SpeakerEdit

• Modify like any other Tapestry template

48

Page 49: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Roadmap

• Release version 1.0

• Search refactoring and Lucene integration

• equals() Aspect

49

Page 50: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 50

Agenda

Brief History of Web DevelopmentRuby On RailsSails TrailsGrailsThe Future of *ails

Page 51: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 51

• Open-source web framework started in early 2006• Most heavily influenced by Rails

• Built with top of Groovy• Dynamic language• Can compile down to Java bytecode• Interoperability with Java key goal• 1.0 released early 2007

Page 52: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 52

First Cousin of Rails

• Takes the most inspiration from Rails• Design really driven by language

• Ruby drives Rails• Groovy drives Grails

Page 53: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 53

...But not the Weird Cousin

• All the libraries you already know• Hibernate 3.2• Spring• SiteMesh• Quartz

• And access to anything else in the Java world

• Calls into Java natural

Page 54: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 54

What’s the Same?

• Project quickstart / artifact generation• MVC• Convention over Configuration• Dynamic finder methods• Interactive console• Support for development/production mode

Page 55: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 55

What’s Different Philosophically?

• Domain Driven Development• No class to inherit from• Class properties drive DB, not the other way around

• Embrace Legacy• Support for more complex relationships with Hibernate• Middlegen support in the works

• Go Beyond Crud• Grails Services

• Half in Groovy, Half in Java

Page 56: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 56

What’s Different Technically?

• Performance• Uses native threads• Runs on JVM

• Deployment• Deploys as a war, hence any servlet

container including app servers• These are arguably the motivations behind

JRuby

Page 57: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 57

Up and Running

grails create-app glogger

Page 58: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 58

Gives you...Built-in support for internationalization

Support for transactional services

Promotes TDD

Go under the coverswhen you need to

Your J2EE webapp

Page 59: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 59

What Else Can It Do?

create-controllercreate-domain-classcreate-jobcreate-plugincreate-scriptcreate-servicecreate-tag-libcreate-test-suite

create-webtestgenerate-allgenerate-controllergenerate-viewsgenerate-webtestinstall-plugininstall-templatesrun-apprun-webtestshell

Page 60: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 60

Dissecting the Domain

grails create-domain-class Post

grogger\grails-app\domain\Post.groovygrogger\grails-tests\PostTests.groovy

Page 61: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 61

Further Dissecting the Domainclass Post {   String title  String body  String author  String tags  Date datePosted

  static hasMany = [comments:Comment]  static constraints = {    title(unique:true, length:0..150)    body(blank:false, maxSize:5000)    datePosted(nullable:false)  }}      

No super class!

Simple properties automatically mapped

Easy definition of relationships

Powerful constraints

Page 62: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 62

Generating the Rest

grails generate-all Post

grails-app\controllers\PostController.groovygrails-app\views\post\list.gsp......................show.gsp......................edit.gsp......................create.gsp

Page 63: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 63

Groovy Views (GSP)• Groovy Server Pages• Creation of custom tags couldn’t be easier

• No TLDs• Changes are seen instantly

• Discourages scripting• Ships with large and growing tag library

• Includes tags for AJAX

Page 64: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 64

Controllers - Generatedclass PostController { def index = { redirect(action:list,params:params) }

def allowedMethods = [delete:'POST', save:'POST', update:'POST'] def list = { ... } def show = { ... } def delete = { ... } ... ...

def edit = { ... } def update = { ... }

def create = { ... }

def save = { ... }}

Page 65: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 65

Controllers - Dynamic

class PostController { def scaffold = true}

Page 66: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 66

Controllers - Dynamic Override

class PostController { def scaffold = true def list = { if(!params.max)params.max = 10 [ postList: Post.list( params ).reverse() ] } }

Implement methods to override the default

Page 67: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 67

Let’s See the App

Page 68: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Glogger Homepage

68

Page 69: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Create Post

69

Page 70: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

List Posts

70

Page 71: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

View Post

71

Page 72: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 72

Edit Post

Page 73: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 73

Dynamic Methods and Properties

Post.findByAuthor("Matt")Post.findByTitleAndAuthor("Grails", "Matt")Post.findAll()Post.listOrderTitle()Post.hasErrors()Post.save()

Page 74: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 74

Services

• Keeping business logic in the right place class PostService { boolean transactional = false }

• Dependency Inject by Convention (Autowiring) class PostService { CommentService commentService }

Page 75: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 75

Builders - Query Criteria

def c = Post.createCriteria() def results = c { like("title", "%grails%") and { eq("author", "Matt") } maxResults(10) order("title", "desc") }

Page 76: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 76

Builders - Configuration

def bb = new grails.spring.BeanBuilder() bb.beans { dataSource(BasicDataSource) { driverClassName = "org.hsqldb.jdbcDriver" url = "jdbc:hsqldb:mem:grailsDB" username = "sa" password = "" } sessionFactory(ConfigurableLocalSessionFactoryBean) { dataSource = dataSource } }

Page 77: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 77

Builders - XML Generation

import groovy.xml.MarkupBuilderdef xmlDoc= new MarkupBuilder()xmlDoc.blog { post(title:"Grails Rocks") { body("Grails has some real potential") comment("Yeah right", author:"anonymous")) } }

<blog> <post title="Grails Rocks" author="Matt"> <body> Grails has some real potential </body> <comment author="anonymous"> Yeah right. </comment> </post></blog>

Page 78: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 78

Grails Roadmap• 1.0 now targeted for autumn 2007• Performance and stability are key• Middlegen support• JPA support• JavaScript templates

Page 79: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 79

Agenda

Brief History of Web DevelopmentRuby On RailsSails TrailsGrailsThe Future of *ails

Page 80: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 80

Popularity

Page 81: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 81

Jobs

Page 82: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 | 82

But...

Room for Growth

Page 83: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session BOF-9843 |

Why Aren’t *ails More Popular?

• Haven’t reached critical 1.0 milestone• Do Trails/Sails solve enough pain points?

• JRuby• Are Java developers holding out for JRuby on Rails?

• Inertia?• Rails already has huge community, documentation,

training, etc

83

Page 84: Grails, Trails, and Sails: Rails Through a Coffee Filter

2007 JavaOneSM Conference | Session XXXX | 84

Q&A