Skip to content

Instantly share code, notes, and snippets.

@arkadijs
Last active January 4, 2016 09:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arkadijs/8603056 to your computer and use it in GitHub Desktop.
Save arkadijs/8603056 to your computer and use it in GitHub Desktop.
Groovy Grails life

The Origin

I'm here not to teach you - see me as a guiding friend, a facilitator. We'll go together through a journey of getting better at some particular, non-hype, well understood yet sometimes problematic, still modern technology for developing web- and service-oriented applications. Hopefully it will give you a new perspective on how such things could be built.

It's up to you to choose what it'll be for you - an epic or a walk in the park. Most of the value will be to stay till the end, though.

To do the homework I expect about 5 hours of commitment per week -- similar to Coursera. Some colleagues already demonstrated that it could be done. But, compared to consuming nicely prepared material, we're on raw side this time -- you'll be setting your own tactical learning plan and digging for materials instead.

Last but not least, my opinion and judgments are always subjective.

The technology

The foundation to understand Grails lays on Groovy.

You can write Groovy as you write Java -- almost any Java is valid Groovy, but Groovy-lads will choke on your code and you won't get an invite to team's dinner. Even quite uncommon-looking code can be deconstructed using not-so-many simple rules. In this respect, Groovy is much safer place -- language limitations prevents madness occurred to some Scala folks, who took great idea too far into the realm of disconnected gibberish.

Understanding the basics saves time in retrospective and prevents, for example, constant milking of StackOverflow for yet-another-piece-of-code to workaround another-piece-of-code your great colleague stole for the project year ago from the aforementioned site.

I believe, we should touch following topics:

  1. Groovy
  2. Grails core: classic Web layer, Validation, REST, Testing
  3. GORM
  4. Grails Async programming
  5. GPars -- Groovy foundation for concurrent programming
  6. Gradle
  7. Scripting and Grape
  8. JRebel
  9. Twitter Bootstrap and/or Skeleton
  10. Glisten on AWS deployed via CloudBees

Not necessary in that order.

What's not in on the curriculum

We won't cover (ill-inspired) Spring Roo. Spring Boot is from different world fighting theirs own battle. While Vert.x is cool project by itself; also being a better (polyglot) alternative to much overrated Node.js -- it is still a niche product. Trending JavaScript web frameworks are the universe on their own. Plain jQuery will be enough to grasp the basics. Let UI developers deal with boilerplate. They love to polish modern html foundation for IE8.

In case you are here to learn hype-thingie -- just stop reading. Still there? Redirecting you to the Immutant primer.

What to do this week?

Task and demo

A field of N x M squares is represented by N lines of exactly M characters each. The character '*' represents a mine and the character '.' represents no-mine. Example input (a 3 x 4 mine-field of 12 squares, 2 of which are mines):

*...
..*.
....

Your task is to write a program to accept this input and produce as output a hint-field of identical dimensions where each square is a * for a mine or the number of adjacent mine-squares if the square does not contain a mine. Example output (for the above input):

*211
12*1
0111

Recommended setup:

  1. Use tests to develop and verify the code.
  2. Use Gradle to build and test the project.

In a 11-Feb meeting, everyone will show the demo of the assignment. We'll discuss whats great and problematic with your code and why. Most essential attributes of good code are:

  1. completeness of the solution
  2. clarity
  3. reduced boilerplate without clarity sacrifice
  4. testability
  5. performance

4-Feb meeting notes

First, some facts:

  • 5 people show up out of 11 subscribed
  • 3 had a working code to demo
  • 1 person sent initial code via email.

As we collectively decided, due to a slow start we slip the schedule by one week. Why?

  • to polish the code
  • get more fluent with Groovy
  • catch up with the team, for those who need it
  • those who're fine with Week 1, are moving to Week 2.

You know what to do.

My observation about the demo in general:

  • Stay with the task! The rules are simple yet precise.
  • Write tests! The purpose of our activity is to get various aspects of software development right. We're not hammering out the product that should be out yesterday.
  • Writing tests inherently helps functional decomposition.
  • IDE or command-line is no substitution for Gradle.
  • Don't be too clever - the language features are here to help, not to obscure the intent.
  • Cut&paste code won't fly: 2+ repetitions - extract common piece.
  • Avoid instance variables as a vehicle of passing parameters between methods - use function arguments and return values (say no to limited visibility, no safety, unclear concurrency, tedious refactoring).
  • Avoid reusing variables (for unrelated purposes), think in terms of data transformation between immutable input -> output data structures. Groovy is relatively well suited for that. More on that below.

You asked for Groovy examples, here are some:

Rant

Rich Hickey, creator of Clojure, described object systems as overly simplistic models of the real world. He emphasized the inability of OOP to model time properly, which is getting increasingly problematic as software systems become more concurrent.

If you have time, watch the presentation or just transcript with slides or check a pdf.

In my opinion, the OOP is a hammer and every problem looks like a nail then. Overwhelming majority of C++ or Java practices promote binding of code and data into single unit - class - as a method of problem decomposition. Only supplementing it with namespaces (packages) to improve modularity and introducing static modifier to help hold pieces together (otherwise it won't).

As a trivial example, the aforementioned approach results in code that allocate new object just to get current time (hello, new Date()) or blatant impedance mismatches when real problem hits the fan.

There are other options.

Clojure

Not that we must go and write Clojure tomorrow, no. Looking around and borrowing ideas is a must, though.

The lesson: don't get Kyle mad.

Check it out as a mind-blowing exercise.

Kyle Kingsbury is a dev behind Riemann, who wrote Knossos as an argument for extensive battle of great minds.

11-Feb meeting notes

Due to a noticeable progress (hurray!), we're moving to Week 2 task of developing a simple Grails application. Please see Week 2 below.

Ok, practical things:

About the meeting:

  1. I expect you to do the demo first. I'm the customer, I want pretty things that works. We discuss implementation details after that. I've much better attitude if I'm impressed. (too many I-s, I know)
  2. Tests, tests, test helps ...
  3. ... functional decomposition and program modularity.
  4. Many things in Groovy that resemble a collection are iterable. String is a collection of characters, thus iterable. Use for() /For-Statements or each()/collect()/findAll()/any()/etc., forget about direct use of iterators.
  5. World is moving toward programming practices that encourage use of immutable data structures, transformations, avoiding shared state. The result is better software: testable, thread-safe, concurrent, readable. The software we can reason about. Such software can be composed without unexpected side-effects (software that do poke at random memory around - surely cannot).
  6. An explanation how groovy-wslite request parameters works: RESTClient -> ContentBuilder

Week 2

As usual, dedicate at least 5 hours to deal with the topic and do the demo.

Task

Your task is to write a web application that provides an UI to manage system users. There is no authentication, no internationalization, and just two screens:

  1. User List screen - a table with three columns: (login) username, name, surname.
  2. A New User form with three fields: name, surname, username, and a Create button.
  3. The username input field could be derived from name and/or surname, but must not change after first edit.
  4. There must be a functionality on User List screen to delete user.
  5. Supposedly, the best user experience while deleting the user would be to send DELETE HTTP request to the server (in background) and delete the (HTML) row via DOM on success, thus not refreshing the page. A jQuery will be simple and fast tool to implement this.
  6. There should be a message presented confirming the action.
  7. Pretty UI is cheap these days: use Twitter Bootstrap in the form of Grails plugin / howto. Or plug Skeleton into the project yourself.
  8. Don't feel too bad if you cannot instantly grasp (default) Grails testing framework - Spock. Those given: when: then: are just Groovy labels and a compile-time AST transformation supplied by Spock plugin. Having plain old JUnit tests is much better than having no fancy tests.

Everything else is up to you.

In a 18-Feb meeting, everyone will show the demo of the assignment. We'll discuss whats great and problematic with your code and why. Whats important this week?

  1. User experience
  2. Pretty UI
  3. DRY
  4. Tests would be nice

25-Feb meeting notes

Not many people attended. Moving to Week 3. I'll post the task Wednesday evening.

  1. It's good to dive into details to understand how things work.
  2. But, on practical side: use whats already there (plugins): Kickstart, Bootstrap, Foundation. Use generate-* to scaffold the boilerplate and then patch the output.
  3. Use install-templates to copy default Grails scaffolding templates to src/templates/scaffolding/ and patch them before generation.
  4. Web assets are managed by Resources plugin / more that will do it right out-of-the-box.

Week 3

A simpler task this week, yet it exercise corroboration between Grails application and external service.

Yes, templates are boring.

Task

Your task is to implement OAuth 2.0 (pseudo-)authentication for the application written during Week 2.

  1. At first, a user visiting the application is presented with an explanation and an option (a) to stop or (b) to sign-in using fixed external OAuth provider.
  2. After sign-in, Week 2 application kicks-in and everything works like before, but user has an option to sign-out.
  3. Which OAuth provider? It's your choice, probably pick one of the existing: G+ / Google, Facebook, GitHub, whatever - thats not important. Or roll your own service.
  4. While you may use (client) libraries tailored specifically to OAuth and probably to specific provider (like Facebook has an offer), I really wish you do the interaction manually on HTTP request-response level. I recommend groovy-wslite for that.
  5. Depending on provider, it may be feasible to exchange access token to long-lived access token, but that is not mandated for the demo.
  6. Async requests and/or background processing is not necessary, just do all the stuff in simple and synchronous way on client (page requester) thread.
  7. Please note, that OAuth is not OpenID. But you may choose to implement OpenID instead.
  8. Optional: if you really have time, implement sign-up using external provider. After identity and basic data are retrieved, the user's account is saved into the USER database table. So users can also login via account that is already present in the table.

4-Mar meeting notes

Even less people attended. I like the dedication very much.

  1. Don't use complex authn&authz plugins, like Spring Security or Apache Shiro. Use Grails filters with create-filters.
  2. Skip overblown Google Java API client libraries. They are API centered in a sense that OAuth phase is minor addition to the whole story of consuming the rest of Google services.
  3. Use plain HTTP together with Google's OAuth 2.0 Playground.
  4. Alternatively, try GitHub OAuth - it's documentation is significantly cleaner than the Google one.
  5. Get nice buttons.
  6. If you get 400 Bad Request { "error" : "redirect_uri_mismatch" } from Google, then try redirect_uri: 'postmessage' in HTTP request and set data-redirecturi="postmessage" on button. (not sure the last thing is necessary)

There will be no new task this week. Please finish current one.

Week 4

Lets go back to MVC thing and rearrange the user(-s) views to include user photo / avatar.

Task

Your task is to add photo upload, thumbnailing, and photo rendering functionality to the application developed through Weeks 2 and 3.

  1. The list of users is now a responsive grid with each user having an avatar thumbnail displayed in the cell together with the name, etc.
  2. On User Create form (or whatever you have to create user) there is a possibility to upload a picture file.
  3. The picture could be saved to the database or to the file, your choice.
  4. The real problem is - the picture could be arbitrary large, while a small thumbnail is required to render user grid-list reliably.
  5. Async programming come to rescue to save the situation.
  6. Use task {} primitive to resize the picture in background emitting Promise to the view.

21-Mar meeting notes

  1. First, let finish with the Grails async topic, those who didn't :)
  2. Bonus points: try Java VisualVM (jvisualvm command) on Grails JVM process. Put Thread.sleep() in controller and task{}. Check how - on what thread the work is performed.
  3. Then take a quick overview of GPars facilities. On next meeting we'll discuss Actor framework principles, concurrency primitives, and briefly STM.

1-Apr meeting notes

Not much to update. Keep going! Dedicate your attention to parallel collections and async invocation in GPars - Chapter 3, Agents - Chapter 7, Actors - Chapter 5. It is really too much to grok in one or several attempts. Choose one topic and do something simple, reaffirming your knowledge with practical exercise.

Here is the link explaining hardware Transactional Synchronization Extensions. So, basically, only IBM and now Intel has something in hardware for STM.

Week 5

This week task is a sidetrack from Grails activities into the realm of concurrency.

Task

Your task is to create an utility that produces image thumbnails from a directory that contains a large number of large photos.

  1. The input for the utility is a directory name.
  2. The directory probably has other sub-directories and the nesting level is arbitrary deep.
  3. Scan directory recursively and for every .jpg file found, create a new file .thumb.jpg in the same directory that holds the original file.
  4. Given a typical workstation has 2 to 8 threads of execution available, the (CPU intensive) thumbnails generation process should be parallelized to complete utility invocation as fast as possible.
  5. Use GPars. Do not retreat to plain Java threads.
  6. You may opt-in to use Actors, a simpler combination of groovyx.gpars.GParsPool.withPool with Closure.callAsync(), or maybe something else.

Week 6

The Cloud technologies are all around us - an essential topic that gives competitive advantage. Let deploy our Grails application in the cloud!

Task

Your task is to leverage free CloudBees CI service.

  1. Create an account with CloudBees.
  2. Install bees tools.
  3. Follow the tutorial.
  4. Configure application to be built, tested, and deployed on Git push.
  5. Optionally, use Nitrous.IO web-based development environment. They don't have Java-specific boxes, but any box (presumably) has Java and Git installed.

Alternatively, try OpenShift Online, or Jelastic, or Heroku.

Inspirational samples could be found at Bitbucket.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment