Grails... microservices...
you must be crazy man!
20 years Java
10+ years Spring
6+ years Groovy/Grails
PowerBuilder
C/C++
FORTRAN
1st career in aviation/aerospace
twitter: @jackfrosch linkedin: ../in/jackfrosch
email: jackfrosch@gmail.com grails.slack.com: @jackfrosch
{ "about-me" :
{ "experience" : [ "20 years Java",
"6+ years Groovy/Grails",
"PowerBuilder, C/C++, FORTRAN"
"Aviation/Aerospace before Software Development"],
"community" : [ "Gateway JUG founder and leader",
"Past DFW GGUG Co-leader",
"Always cookin' up something ..."],
"contacts" : [ {"twitter" : "@jackfrosch"},
{"linkedin" : "../in/jackfrosch"},
{"email" : "jackfrosch@gmail.com"},
{"grails.slack.com":"@jackfrosch"}]
}
}
Microservices are small, autonomous services that work together.
Sam Newman Building Microservices, O'Reilly Media
http://www.whattofix.com/images/ComplexERDExample.gif
Probably not small functional scope...
Everything should be made as simple as possible, but not simpler*
* though attributed to Einstein, this simple quote is actually from
Roger Sessions paraphrasing (and simplifying!) a statement by Albert Einstein
A system that is hard to understand is hard to change.
— Eric Evans, Domain-Driven Design
http://www.memes.com/meme/498049
http://bit.ly/thoughtworks-consumer-driven-contracts
http://famouswonders.com/wp-content/gallery/pyramids-of-egypt/pyramid-of-khafre.jpg
http://martinfowler.com/articles/microservices.html
http://www.openmakesoftware.com/images/ReleaseEngineer/CI-CD.png
https://media.licdn.com/mpr/mpr/p/8/005/083/1a8/257d716.jpg
http://kennysilva.net/wp-content/uploads/2010/12/orchestra-conductor.jpg
class Passenger {
String accountNo
String firstName
String lastName
Address billingAddress
Payment paymentPreference
List<Payment> paymentHistory
Phone home
Phone mobile
Phone work
BloodType bloodType
...
}
// For Trip Management
class Passenger {
String accountNo
String firstName
String lastName
Phone mobile
...
}
// For Billing
class Passenger {
String accountNo
String firstName
String lastName
Address billingAddress
List<Payment> paymentHistory
Phone home
Phone work
...
}
The evils of too much coupling between services are far worse than the problems caused by code duplication.
- Sam Newman, Building Microservices
an organization that is made by loosely joining together smaller organizations
http://www.merriam-webster.com/dictionary/federation
the formation of a political unity, with a central government, by a number of separate states, each of which retains control of its own internal affairs.
http://dictionary.reference.com/browse/federation
In our terms: The formation of an application, with central governance of common infrastructure concerns, by a number of separate microservices, each of which retains control of its own internal design and implementation.
The advancement and diffusion of knowledge is the only guardian of true liberty.
- James Madison, father of the US Constitution
Knowledge is power
"ELK Stack"
"They're inside the room!"
"Yikes!"
"Mmm, you look tasty."
Perimeter security reminds me of the movie, Aliens
Spring Boot & Spring Cloud to the rescue!
There are many metrics out of the box, but you can create your own.
http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html
http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html
http://bit.ly/vignette2_wikia_nocookie_net_ghostbusters
http://martinfowler.com/bliki/CircuitBreaker.html
http://martinfowler.com/bliki/images/microservicePrerequisites/sketch.png
Full stack != monolith
Web UI, SQL / NOSQL Database Support, Spring, Hibernate, Security, REST, Java, Groovy...
$grails create-app HelloWorld
grails> create-controller demo.Hello
package demo
class HelloController {
def index() {
render 'Hello SpringOne2GX 2015!'
}
}
Full stack CRUD apps are about as easy...
1. Create controller
2. Make it do something
3. See it to believe it!
package demo
class Person {
String firstName
String lastName
String email
String twitterHandle
static constraints = {
firstName blank:false, maxSize: 32
lastName blank: false, maxSize: 64
email blank: false, maxSize: 128, email:true
twitterHandle nullable:true, maxSize:64
}
}
grails> run-app
$ curl -i -X GET http://localhost:8080/persons
[jfrosch@localhost demo]$ HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Application-Context: application:development
Content-Type: text/xml;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 07 Sep 2015 21:26:16 GMT
<?xml version="1.0" encoding="UTF-8"?><list />
$
Hmm... 200 OK good ... XML bad.
package demo
import grails.rest.Resource
@Resource(uri='/persons')
class Person {
String firstName
String lastName
String email
String twitterHandle
static constraints = {
firstName blank:false, maxSize: 32
lastName blank: false, maxSize: 64
email blank: false, maxSize: 128, email:true
twitterHandle nullable:true, maxSize:64
}
}
grails create-app RestfulCrud
$ curl -i -X GET http://localhost:8080/persons.json
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Application-Context: application:development
Content-Type: text/xml;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 07 Sep 2015 21:26:16 GMT
[]
$
200 OK good ... JSON good.
$ curl -i -X GET --header "Accept:application/json" http://localhost:8080/persons
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Application-Context: application:development
Content-Type: text/xml;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 07 Sep 2015 21:26:16 GMT
[]
$
200 OK good ... JSON good.
package demo
import grails.rest.Resource
@Resource(uri='/persons', formats=['json', 'xml'])
class Person {
String firstName
String lastName
String email
String twitterHandle
static constraints = {
firstName blank:false, maxSize: 32
lastName blank: false, maxSize: 64
email blank: false, maxSize: 128, email:true
twitterHandle nullable:true, maxSize:64
}
}
$ curl -i -X GET http://localhost:8080/persons
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Application-Context: application:development
Content-Type: text/xml;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 07 Sep 2015 21:26:16 GMT
[]
$
200 OK good ... JSON good.
$ curl -i -X GET http://localhost:8080/persons.xml
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Application-Context: application:development
Content-Type: text/xml;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 07 Sep 2015 21:26:16 GMT
<?xml version="1.0" encoding="UTF-8"?><list />
$
200 OK good ... XML weird, but you wanted weird
package demo
import grails.rest.RestfulController
class PersonController extends RestfulController<Person> {
static responseFormats =['json', 'xml']
PersonController() {
super(Person)
}
def findPersonsWithLastNameLike(String likeness) {
respond Person.findByLastNameLike("${likeness}%")
}
}
class UrlMappings {
static mappings = {
"/persons"(resources:'person')
"/persons/search/withLastNameLike/$likeness"(controller: 'person',
action: 'findPersonsWithLastNameLike')
}
}
/catalog acts as the root of the uri
This is the default after error in recommendation engine
... After killing recommendation engine ...
You'd be crazy to adopt a microservice architecture using Grails...
unless your application needs to be ...
(even if your company isn't ready for the cloud yet)