SlideShare a Scribd company logo
Fullstack Groovy developer
Iván López
@ilopmar
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 2
Hello!
@ilopmar
http://greachconf.com@madridgug
I'm Iván López
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 3
Thank you very much!
Q&A
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 4
Just kidding!
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 5
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 6
What's a fullstack developer?
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 7
Fullstack developer
Backend language
Javascript Mobile app
HTML
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 8
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 9
Polaromatic
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 10
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 11
1. Demo
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 12
2. Application flow
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 13
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 14
3. Backend
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 15
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 16
Polaromatic
● Spring Boot
● Core App
● Spring MVC
● Spring Integration Flow
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 17
Spring Integration Flow
<file:inbound-channel-adapter directory="work" channel="incommingFilesChannel"/>
<chain input-channel="incommingFilesChannel">
<service-activator ref="fileService" method="preprocessFile"/>
<service-activator ref="imageConverterService" method="applyEffect"/>
<service-activator ref="browserPushService" method="pushToBrowser"/>
<service-activator ref="metricsService" method="updateMetrics"/>
<service-activator ref="fileService" method="deleteTempFiles"/>
</chain>
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 18
Spring Integration Flow
File Service
<file:inbound-channel-adapter directory="work" channel="incommingFilesChannel"/>
<chain input-channel="incommingFilesChannel">
<service-activator ref="fileService" method="preprocessFile"/>
<service-activator ref="imageConverterService" method="applyEffect"/>
<service-activator ref="browserPushService" method="pushToBrowser"/>
<service-activator ref="metricsService" method="updateMetrics"/>
<service-activator ref="fileService" method="deleteTempFiles"/>
</chain>
Photo preprocessFile(File file) {
def pr = new PolaroidRequest(file)
this.preprocessFile(pr)
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 19
Spring Integration Flow
File Service
Photo preprocessFile(File file) {
def pr = new PolaroidRequest(file)
this.preprocessFile(pr)
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 20
Spring Integration Flow
File Service
Photo preprocessFile(File file) {
def pr = new PolaroidRequest(file)
this.preprocessFile(pr)
}
Photo preprocessFile(PolaroidRequest polaroidRequest) {
String outputFile = File.createTempFile("output", ".png").path
return new Photo(input: polaroidRequest.inputFile.absolutePath,
output: outputFile,
text: polaroidRequest.text)
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 21
Image converter
class ImageConverterService {
private static final String DEFAULT_CAPTION = "#LearningSpringBoot with Polaromaticn"
Random rnd = new Random()
Photo applyEffect(Photo photo) {
log.debug "Applying effect to file: ${photo.input}..."
def inputFile = photo.input
def outputFile = photo.output
double polaroidRotation = rnd.nextInt(6).toDouble()
String caption = photo.text ?: DEFAULT_CAPTION
def op = new IMOperation()
op.addImage(inputFile)
op.thumbnail(300, 300)
.set("caption", caption)
.gravity("center")
.pointsize(20)
.background("black")
.polaroid(rnd.nextBoolean() ? polaroidRotation : -polaroidRotation)
.addImage(outputFile)
def command = new ConvertCmd()
command.run(op)
photo
}
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 22
Metrics
class MetricsService {
static final String PHOTO_COUNTER_METRICS_FLICKR = "polaromatized.photos.flickr"
static final String PHOTO_COUNTER_METRICS_ANDROID = "polaromatized.photos.android"
@Autowired
CounterService counterService
Photo updateMetrics(Photo photo) {
if (photo.text) {
counterService.increment(PHOTO_COUNTER_METRICS_ANDROID)
} else {
counterService.increment(PHOTO_COUNTER_METRICS_FLICKR)
}
photo
}
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 23
Metrics
class MetricsService {
static final String PHOTO_COUNTER_METRICS_FLICKR = "polaromatized.photos.flickr"
static final String PHOTO_COUNTER_METRICS_ANDROID = "polaromatized.photos.android"
@Autowired
CounterService counterService
Photo updateMetrics(Photo photo) {
if (photo.text) {
counterService.increment(PHOTO_COUNTER_METRICS_ANDROID)
} else {
counterService.increment(PHOTO_COUNTER_METRICS_FLICKR)
}
photo
}
}
<chain input-channel="incommingFilesChannel">
<service-activator ref="fileService" method="preprocessFile"/>
<service-activator ref="imageConverterService" method="applyEffect"/>
<service-activator ref="browserPushService" method="pushToBrowser"/>
<service-activator ref="metricsService" method="updateMetrics"/>
<service-activator ref="fileService" method="deleteTempFiles"/>
</chain>
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 24
Metrics
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 25
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 26
FlickrDownloader
● Spring Boot CLI
● Download Flickr Interesting pictures
● Jsoup, GPars
● 55 lines of Groovy code (microservice?)
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 27
FlickrDownloader
@Slf4j
@EnableScheduling
@Grab('org.jsoup:jsoup:1.8.1')
@Grab('commons-io:commons-io:2.4')
@Grab('org.codehaus.gpars:gpars:1.2.1')
class FlickrDownloader {
static final String FLICKER_INTERESTING_URL =
"https://www.flickr.com/explore/interesting/7days"
static final String WORK_DIR = "./work"
final File workDir = new File(WORK_DIR)
@Scheduled(fixedRate = 30000L)
void downloadFlickrInteresting() {
def photos = extractPhotosFromFlickr()
withPool {
photos.eachParallel { photoUrl ->
log.info "Downloading photo ${photoUrl}"
def tempFile = download(photoUrl)
FileUtils.moveFileToDirectory(tempFile, workDir, true)
}
}
}
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 28
FlickrDownloader
@Slf4j
@EnableScheduling
@Grab('org.jsoup:jsoup:1.8.1')
@Grab('commons-io:commons-io:2.4')
@Grab('org.codehaus.gpars:gpars:1.2.1')
class FlickrDownloader {
static final String FLICKER_INTERESTING_URL =
"https://www.flickr.com/explore/interesting/7days"
static final String WORK_DIR = "./work"
final File workDir = new File(WORK_DIR)
@Scheduled(fixedRate = 30000L)
void downloadFlickrInteresting() {
def photos = extractPhotosFromFlickr()
withPool {
photos.eachParallel { photoUrl ->
log.info "Downloading photo ${photoUrl}"
def tempFile = download(photoUrl)
FileUtils.moveFileToDirectory(tempFile, workDir, true)
}
}
}
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 29
FlickrDownloader
@Slf4j
@EnableScheduling
@Grab('org.jsoup:jsoup:1.8.1')
@Grab('commons-io:commons-io:2.4')
@Grab('org.codehaus.gpars:gpars:1.2.1')
class FlickrDownloader {
static final String FLICKER_INTERESTING_URL =
"https://www.flickr.com/explore/interesting/7days"
static final String WORK_DIR = "./work"
final File workDir = new File(WORK_DIR)
@Scheduled(fixedRate = 30000L)
void downloadFlickrInteresting() {
def photos = extractPhotosFromFlickr()
withPool {
photos.eachParallel { photoUrl ->
log.info "Downloading photo ${photoUrl}"
def tempFile = download(photoUrl)
FileUtils.moveFileToDirectory(tempFile, workDir, true)
}
}
}
}
private List extractPhotosFromFlickr() {
Document doc = Jsoup.connect(FLICKER_INTERESTING_URL).get()
Elements images = doc.select("img.pc_img")
def photos = images
.listIterator()
.collect { it.attr('src').replace('_m.jpg', '_b.jpg') }
photos
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 30
FlickrDownloader
@Slf4j
@EnableScheduling
@Grab('org.jsoup:jsoup:1.8.1')
@Grab('commons-io:commons-io:2.4')
@Grab('org.codehaus.gpars:gpars:1.2.1')
class FlickrDownloader {
static final String FLICKER_INTERESTING_URL =
"https://www.flickr.com/explore/interesting/7days"
static final String WORK_DIR = "./work"
final File workDir = new File(WORK_DIR)
@Scheduled(fixedRate = 30000L)
void downloadFlickrInteresting() {
def photos = extractPhotosFromFlickr()
withPool {
photos.eachParallel { photoUrl ->
log.info "Downloading photo ${photoUrl}"
def tempFile = download(photoUrl)
FileUtils.moveFileToDirectory(tempFile, workDir, true)
}
}
}
}
private File download(String url) {
def tempFile = File.createTempFile('flickr_downloader', '')
tempFile << url.toURL().bytes
tempFile
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 31
FlickrDownloader
@Slf4j
@EnableScheduling
@Grab('org.jsoup:jsoup:1.8.1')
@Grab('commons-io:commons-io:2.4')
@Grab('org.codehaus.gpars:gpars:1.2.1')
class FlickrDownloader {
static final String FLICKER_INTERESTING_URL =
"https://www.flickr.com/explore/interesting/7days"
static final String WORK_DIR = "./work"
final File workDir = new File(WORK_DIR)
@Scheduled(fixedRate = 30000L)
void downloadFlickrInteresting() {
def photos = extractPhotosFromFlickr()
withPool {
photos.eachParallel { photoUrl ->
log.info "Downloading photo ${photoUrl}"
def tempFile = download(photoUrl)
FileUtils.moveFileToDirectory(tempFile, workDir, true)
}
}
}
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 32
FlickrDownloader
2015-08-31 21:56:11.139 INFO 16447 --- [111617-worker-1] polaromatic.FlickrDownloader
2015-08-31 21:56:11.139 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader
2015-08-31 21:56:11.139 INFO 16447 --- [111617-worker-3] polaromatic.FlickrDownloader
2015-08-31 21:56:11.354 INFO 16447 --- [111617-worker-1] polaromatic.FlickrDownloader
2015-08-31 21:56:11.375 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader
2015-08-31 21:56:11.527 INFO 16447 --- [111617-worker-3] polaromatic.FlickrDownloader
2015-08-31 21:56:11.537 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader
2015-08-31 21:56:11.612 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader
2015-08-31 21:56:11.693 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader
2015-08-31 22:02:17.019 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:19.451 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:21.661 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:22.079 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:22.877 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:23.392 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:23.749 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:24.250 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:24.695 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 33
FlickrDownloader
2015-08-31 21:56:11.139 INFO 16447 --- [111617-worker-1] polaromatic.FlickrDownloader
2015-08-31 21:56:11.139 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader
2015-08-31 21:56:11.139 INFO 16447 --- [111617-worker-3] polaromatic.FlickrDownloader
2015-08-31 21:56:11.354 INFO 16447 --- [111617-worker-1] polaromatic.FlickrDownloader
2015-08-31 21:56:11.375 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader
2015-08-31 21:56:11.527 INFO 16447 --- [111617-worker-3] polaromatic.FlickrDownloader
2015-08-31 21:56:11.537 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader
2015-08-31 21:56:11.612 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader
2015-08-31 21:56:11.693 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader
2015-08-31 22:02:17.019 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:19.451 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:21.661 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:22.079 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:22.877 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:23.392 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:23.749 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:24.250 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
2015-08-31 22:02:24.695 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 34
4. Frontend
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 35
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 36
Frontend
● MarkupTemplatEngine (HTML)
● Websockets
● Grooscript
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 37
HTML
yieldUnescaped '<!DOCTYPE html>'
html {
head {
title "Polaromatic"
link(rel: 'stylesheet', href: '/css/app.css')
link(rel: 'stylesheet', href: '/css/gh-fork-ribbon.css')
['webjars/sockjs-client/0.3.4-1/sockjs.min.js',
'webjars/stomp-websocket/2.3.1-1/stomp.min.js',
'webjars/jquery/2.1.3/jquery.min.js',
'webjars/handlebars/2.0.0-1/handlebars.min.js',
'js/Connection.js']
.each {
yieldUnescaped "<script src='$it'></script>"
}
}
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 38
HTML
body {
...
div(id: 'header') {
div(class: 'center') {
a(href: 'https://github.com/lmivan/contest', target: 'blank') {
img(src: 'images/polaromatic-logo.png')
}
p('Polaromatic')
span('Powered by Spring Boot')
}
}
div(id: 'timeline', class: 'center')
}
script(id: 'photo-template', type: 'text/x-handlebars-template') {
div(class: 'photo-cover') {
div(class: 'photo', style: 'visibility:hidden; height:0') {
img(src: '{{image}}')
}
}
}
yieldUnescaped "<script>Connection().start()</script>"
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 39
Websockets
@Configuration
@EnableWebSocketMessageBroker
class WebsocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker '/notifications'
}
@Override
void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint('/polaromatic').withSockJS()
}
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 40
Websockets
class BrowserPushService {
@Autowired
SimpMessagingTemplate template
Photo pushToBrowser(Photo photo) {
log.debug "Pushing file to browser: ${photo.output}"
String imageB64 = new File(photo.output).bytes.encodeBase64().toString()
template.convertAndSend "/notifications/photo", imageB64
return photo
}
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 41
Websockets
class BrowserPushService {
@Autowired
SimpMessagingTemplate template
Photo pushToBrowser(Photo photo) {
log.debug "Pushing file to browser: ${photo.output}"
String imageB64 = new File(photo.output).bytes.encodeBase64().toString()
template.convertAndSend "/notifications/photo", imageB64
return photo
}
}
<chain input-channel="incommingFilesChannel">
<service-activator ref="fileService" method="preprocessFile"/>
<service-activator ref="imageConverterService" method="applyEffect"/>
<service-activator ref="browserPushService" method="pushToBrowser"/>
<service-activator ref="metricsService" method="updateMetrics"/>
<service-activator ref="fileService" method="deleteTempFiles"/>
</chain>
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 42
Websockets
class Connection {
@GsNative
def initOn(source, path) {/*
var socket = new SockJS(path);
return [Handlebars.compile(source), Stomp.over(socket)];
*/}
def start() {
def source = $("#photo-template").html()
def (template, client) = initOn(source, '/polaromatic')
client.debug = null
client.connect(gs.toJavascript([:])) { ->
client.subscribe('/notifications/photo') { message ->
def context = [image: 'data:image/png;base64,' + message.body]
def html = template(context)
$("#timeline").prepend(html)
$("#timeline .photo:first-child img").on("load") {
$(this).parent().css(gs.toJavascript(display: 'none', visibility: 'visible', height: 'auto'))
$(this).parent().slideDown()
}
}
}
}
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 43
5. Android
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 44
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 45
Android App
● Disclaimer: I'm not an Android developer
● Lazybones template (@marioggar)
● Traits, @CompileStatic, AST Transformations,…
● SwissKnife
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 46
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 47
Android
trait Toastable {
@OnUIThread
void showToastMessage(String message) {
Toast toast = Toast.makeText(applicationContext, message, Toast.LENGTH_SHORT)
toast.show()
}
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 48
Android
trait Toastable {
@OnUIThread
void showToastMessage(String message) {
Toast toast = Toast.makeText(applicationContext, message, Toast.LENGTH_SHORT)
toast.show()
}
}
@CompileStatic
public class ShareActivity extends Activity implements Toastable {
...
showToastMessage(getString(R.string.share_ok_msg))
...
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 49
6. Tests
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 50
Tests
● Spock Framework
● 0.7 for more than 3 years
● Now 1.0
● JUnit compatible (but way better)
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 51
Spock
class BrowserPushServiceSpec extends Specification {
void 'should push a converted photo to the browser'() {
given: 'a photo'
def output = File.createTempFile("output", "")
def photo = new Photo(output: output.path)
and: 'a mocked SimpMessagingTemplate'
def mockSimpMessagingTemplate = Mock(SimpMessagingTemplate)
and: 'the push service'
def browserPushService = new BrowserPushService(template: mockSimpMessagingTemplate)
when: 'pushing the photo to the browser'
browserPushService.pushToBrowser(photo)
then: 'the photo is pushed'
1 * mockSimpMessagingTemplate.convertAndSend('/notifications/photo', "")
}
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 52
7. Build tool
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 53
Build tool
● Gradle
● Multiproject to build backend, documentation and android
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 54
Gradle
subprojects {
buildscript {
repositories {
jcenter()
}
}
repositories {
jcenter()
}
}
task wrapper(type: Wrapper) {
gradleVersion = '2.2.1'
}
build.gradle settings.gradle
include 'polaromatic-back'
include 'polaromatic-groid'
include 'polaromatic-docs'
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 55
8. Documentation
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 56
Documentation
● Asciidoctor (FTW!)
● Gradle plugin
● Backends: html, epub, pdf,...
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 57
Asciidoctor
buildscript {
dependencies {
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.2'
}
}
apply plugin: 'org.asciidoctor.convert'
asciidoctor {
sourceDir 'src/docs'
outputDir "${buildDir}/docs"
attributes 'source-highlighter': 'coderay',
toc : 'left',
icons : 'font'
}
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 58
Asciidoctor
[source,xml,indent=0]
.src/main/resources/resources.xml
----
include::{polaromaticBackResources}/resources.xml[tags=appFlow]
----
<1> Define the integration with the file system
<2> Preprocess the file received
<3> Apply the Polaroid effect
<4> Send the new photo to the browser using Websockets
<5> Update the metrics
<6> Delete all temporary files
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 59
Asciidoctor
[source,xml,indent=0]
.src/main/resources/resources.xml
----
include::{polaromaticBackResources}/resources.xml[tags=appFlow]
----
<1> Define the integration with the file system
<2> Preprocess the file received
<3> Apply the Polaroid effect
<4> Send the new photo to the browser using Websockets
<5> Update the metrics
<6> Delete all temporary files
<!-- tag::appFlow[] -->
<file:inbound-channel-adapter directory="work" channel="incommingFilesChannel"/> <!--1-->
<chain input-channel="incommingFilesChannel">
<service-activator ref="fileService" method="preprocessFile"/> <!--2-->
<service-activator ref="imageConverterService" method="applyEffect"/> <!--3-->
<service-activator ref="browserPushService" method="pushToBrowser"/> <!--4-->
<service-activator ref="metricsService" method="updateMetrics"/> <!--5-->
<service-activator ref="fileService" method="deleteTempFiles"/> <!--6-->
</chain>
<!-- end::appFlow[]-->
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 60
Asciidoctor
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 61
9. Summary
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 62
“Groovy, groovy everywhere...”
Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 63
@ilopmar
lopez.ivan@gmail.com
https://github.com/lmivan
Iván López
http://bit.ly/feedback-groovy
Thanks!
Any questions?

More Related Content

What's hot

Grooscript in Action SpringOne2gx 2015
Grooscript in Action SpringOne2gx 2015Grooscript in Action SpringOne2gx 2015
Grooscript in Action SpringOne2gx 2015
Jorge Franco Leza
 
Develop Android app using Golang
Develop Android app using GolangDevelop Android app using Golang
Develop Android app using Golang
SeongJae Park
 
Android build process (1)
Android build process (1)Android build process (1)
Android build process (1)Shubham Goyal
 
An introduction to_golang.avi
An introduction to_golang.aviAn introduction to_golang.avi
An introduction to_golang.avi
SeongJae Park
 
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
Iván López Martín
 
Go for Mobile Games
Go for Mobile GamesGo for Mobile Games
Go for Mobile Games
Takuya Ueda
 
(Live) build and run golang web server on android.avi
(Live) build and run golang web server on android.avi(Live) build and run golang web server on android.avi
(Live) build and run golang web server on android.avi
SeongJae Park
 
Groovy & Grails
Groovy & GrailsGroovy & Grails
Groovy & Grails
Michael Yan
 
Golang start and tips
Golang start and tipsGolang start and tips
Golang start and tips
Aaron King
 
Android is going to Go! Android and Golang
Android is going to Go! Android and GolangAndroid is going to Go! Android and Golang
Android is going to Go! Android and Golang
Almog Baku
 
GradleのREPLプラグイン紹介 #jggug
GradleのREPLプラグイン紹介 #jggugGradleのREPLプラグイン紹介 #jggug
GradleのREPLプラグイン紹介 #jggug
kyon mm
 
Pavimentando el camino con Jakarta EE 9 y Apache TomEE
Pavimentando el camino con Jakarta EE 9 y Apache TomEE Pavimentando el camino con Jakarta EE 9 y Apache TomEE
Pavimentando el camino con Jakarta EE 9 y Apache TomEE
César Hernández
 
Let the contribution begin
Let the contribution beginLet the contribution begin
Let the contribution begin
SeongJae Park
 
Serving Pull Requests with Jenkins
Serving Pull Requests with JenkinsServing Pull Requests with Jenkins
Serving Pull Requests with Jenkins
Seth Goings
 
Understanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for Modules
Understanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for ModulesUnderstanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for Modules
Understanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for Modules
Mitali Bisht
 
Golang for PHP programmers: A practical introduction
Golang for PHP programmers: A practical introductionGolang for PHP programmers: A practical introduction
Golang for PHP programmers: A practical introduction
Richard Tuin
 
Gopenflow demo v1 (english)
Gopenflow demo v1 (english)Gopenflow demo v1 (english)
Gopenflow demo v1 (english)Hiroaki Kawai
 
Paving the road with Jakarta EE and Apache TomEE - JCON 2021
Paving the road with Jakarta EE  and Apache TomEE - JCON 2021Paving the road with Jakarta EE  and Apache TomEE - JCON 2021
Paving the road with Jakarta EE and Apache TomEE - JCON 2021
César Hernández
 
Use Groovy&Grails in your spring boot projects
Use Groovy&Grails in your spring boot projectsUse Groovy&Grails in your spring boot projects
Use Groovy&Grails in your spring boot projects
Paradigma Digital
 
2008-12-21 Rubinius
2008-12-21 Rubinius2008-12-21 Rubinius
2008-12-21 RubiniusLin Jen-Shin
 

What's hot (20)

Grooscript in Action SpringOne2gx 2015
Grooscript in Action SpringOne2gx 2015Grooscript in Action SpringOne2gx 2015
Grooscript in Action SpringOne2gx 2015
 
Develop Android app using Golang
Develop Android app using GolangDevelop Android app using Golang
Develop Android app using Golang
 
Android build process (1)
Android build process (1)Android build process (1)
Android build process (1)
 
An introduction to_golang.avi
An introduction to_golang.aviAn introduction to_golang.avi
An introduction to_golang.avi
 
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
 
Go for Mobile Games
Go for Mobile GamesGo for Mobile Games
Go for Mobile Games
 
(Live) build and run golang web server on android.avi
(Live) build and run golang web server on android.avi(Live) build and run golang web server on android.avi
(Live) build and run golang web server on android.avi
 
Groovy & Grails
Groovy & GrailsGroovy & Grails
Groovy & Grails
 
Golang start and tips
Golang start and tipsGolang start and tips
Golang start and tips
 
Android is going to Go! Android and Golang
Android is going to Go! Android and GolangAndroid is going to Go! Android and Golang
Android is going to Go! Android and Golang
 
GradleのREPLプラグイン紹介 #jggug
GradleのREPLプラグイン紹介 #jggugGradleのREPLプラグイン紹介 #jggug
GradleのREPLプラグイン紹介 #jggug
 
Pavimentando el camino con Jakarta EE 9 y Apache TomEE
Pavimentando el camino con Jakarta EE 9 y Apache TomEE Pavimentando el camino con Jakarta EE 9 y Apache TomEE
Pavimentando el camino con Jakarta EE 9 y Apache TomEE
 
Let the contribution begin
Let the contribution beginLet the contribution begin
Let the contribution begin
 
Serving Pull Requests with Jenkins
Serving Pull Requests with JenkinsServing Pull Requests with Jenkins
Serving Pull Requests with Jenkins
 
Understanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for Modules
Understanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for ModulesUnderstanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for Modules
Understanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for Modules
 
Golang for PHP programmers: A practical introduction
Golang for PHP programmers: A practical introductionGolang for PHP programmers: A practical introduction
Golang for PHP programmers: A practical introduction
 
Gopenflow demo v1 (english)
Gopenflow demo v1 (english)Gopenflow demo v1 (english)
Gopenflow demo v1 (english)
 
Paving the road with Jakarta EE and Apache TomEE - JCON 2021
Paving the road with Jakarta EE  and Apache TomEE - JCON 2021Paving the road with Jakarta EE  and Apache TomEE - JCON 2021
Paving the road with Jakarta EE and Apache TomEE - JCON 2021
 
Use Groovy&Grails in your spring boot projects
Use Groovy&Grails in your spring boot projectsUse Groovy&Grails in your spring boot projects
Use Groovy&Grails in your spring boot projects
 
2008-12-21 Rubinius
2008-12-21 Rubinius2008-12-21 Rubinius
2008-12-21 Rubinius
 

Viewers also liked

Groovy scripts with Groovy
Groovy scripts with GroovyGroovy scripts with Groovy
Groovy scripts with Groovy
Andrés Viedma Peláez
 
Macro macro, burrito burrit
Macro macro, burrito burritMacro macro, burrito burrit
Macro macro, burrito burrit
Mario García
 
Groovy no es java sin punto y coma v3
Groovy no es java sin punto y coma v3Groovy no es java sin punto y coma v3
Groovy no es java sin punto y coma v3
Pablo Alba
 
Groovy android
Groovy androidGroovy android
Groovy android
Mario García
 
Geb+spock: let your functional tests live long and prosper
Geb+spock: let your functional tests live long and prosperGeb+spock: let your functional tests live long and prosper
Geb+spock: let your functional tests live long and prosper
Esther Lozano
 
GriffDnie (Griffon Demo)
GriffDnie (Griffon Demo)GriffDnie (Griffon Demo)
GriffDnie (Griffon Demo)
Jorge Aguilera
 
Gorm for cassandra
Gorm for cassandraGorm for cassandra
Gorm for cassandra
Rafael Bermúdez Míguez
 
Rajeev digital marketing resume
Rajeev digital marketing resumeRajeev digital marketing resume
Rajeev digital marketing resume
Rajeev Rajanala
 
Introduccion al Desarrollo web - slides
Introduccion al Desarrollo web - slidesIntroduccion al Desarrollo web - slides
Introduccion al Desarrollo web - slides
Gonzalo Palavecino
 
Lectoraatsboek. Vreemdetalendidactiek in een veranderende leeromgeving
Lectoraatsboek. Vreemdetalendidactiek in een veranderende leeromgevingLectoraatsboek. Vreemdetalendidactiek in een veranderende leeromgeving
Lectoraatsboek. Vreemdetalendidactiek in een veranderende leeromgeving
Kristi Jauregi Ondarra
 
Oficina Kas 09 E 10 De Fevereiro Rio De Janeiro
Oficina Kas   09 E 10 De Fevereiro   Rio De JaneiroOficina Kas   09 E 10 De Fevereiro   Rio De Janeiro
Oficina Kas 09 E 10 De Fevereiro Rio De JaneiroAureo Ricardo Salles
 
Lectorale rede kristi jauregi ondarra
Lectorale rede kristi jauregi ondarraLectorale rede kristi jauregi ondarra
Lectorale rede kristi jauregi ondarra
Kristi Jauregi Ondarra
 
Conviértete en un desarrollador web front-end
Conviértete en un desarrollador web front-endConviértete en un desarrollador web front-end
Conviértete en un desarrollador web front-end
video2brain_mx
 
Tutorial gliffy
Tutorial gliffyTutorial gliffy
Tutorial gliffy
Ana Torres
 
teaching methods
teaching methods teaching methods
teaching methods
estefycoronel
 

Viewers also liked (16)

Groovy scripts with Groovy
Groovy scripts with GroovyGroovy scripts with Groovy
Groovy scripts with Groovy
 
Macro macro, burrito burrit
Macro macro, burrito burritMacro macro, burrito burrit
Macro macro, burrito burrit
 
Groovy no es java sin punto y coma v3
Groovy no es java sin punto y coma v3Groovy no es java sin punto y coma v3
Groovy no es java sin punto y coma v3
 
Groovy android
Groovy androidGroovy android
Groovy android
 
Geb+spock: let your functional tests live long and prosper
Geb+spock: let your functional tests live long and prosperGeb+spock: let your functional tests live long and prosper
Geb+spock: let your functional tests live long and prosper
 
GriffDnie (Griffon Demo)
GriffDnie (Griffon Demo)GriffDnie (Griffon Demo)
GriffDnie (Griffon Demo)
 
Gorm for cassandra
Gorm for cassandraGorm for cassandra
Gorm for cassandra
 
Rajeev digital marketing resume
Rajeev digital marketing resumeRajeev digital marketing resume
Rajeev digital marketing resume
 
Introduccion al Desarrollo web - slides
Introduccion al Desarrollo web - slidesIntroduccion al Desarrollo web - slides
Introduccion al Desarrollo web - slides
 
Lectoraatsboek. Vreemdetalendidactiek in een veranderende leeromgeving
Lectoraatsboek. Vreemdetalendidactiek in een veranderende leeromgevingLectoraatsboek. Vreemdetalendidactiek in een veranderende leeromgeving
Lectoraatsboek. Vreemdetalendidactiek in een veranderende leeromgeving
 
Experiencia práctica 1
Experiencia práctica 1Experiencia práctica 1
Experiencia práctica 1
 
Oficina Kas 09 E 10 De Fevereiro Rio De Janeiro
Oficina Kas   09 E 10 De Fevereiro   Rio De JaneiroOficina Kas   09 E 10 De Fevereiro   Rio De Janeiro
Oficina Kas 09 E 10 De Fevereiro Rio De Janeiro
 
Lectorale rede kristi jauregi ondarra
Lectorale rede kristi jauregi ondarraLectorale rede kristi jauregi ondarra
Lectorale rede kristi jauregi ondarra
 
Conviértete en un desarrollador web front-end
Conviértete en un desarrollador web front-endConviértete en un desarrollador web front-end
Conviértete en un desarrollador web front-end
 
Tutorial gliffy
Tutorial gliffyTutorial gliffy
Tutorial gliffy
 
teaching methods
teaching methods teaching methods
teaching methods
 

Similar to SpringOne 2GX 2015 - Fullstack Groovy developer

12 Factor, or Cloud Native Apps – What EXACTLY Does that Mean for Spring Deve...
12 Factor, or Cloud Native Apps – What EXACTLY Does that Mean for Spring Deve...12 Factor, or Cloud Native Apps – What EXACTLY Does that Mean for Spring Deve...
12 Factor, or Cloud Native Apps – What EXACTLY Does that Mean for Spring Deve...
cornelia davis
 
Implementing microservices tracing with spring cloud and zipkin (spring one)
Implementing microservices tracing with spring cloud and zipkin (spring one)Implementing microservices tracing with spring cloud and zipkin (spring one)
Implementing microservices tracing with spring cloud and zipkin (spring one)
Reshmi Krishna
 
What's new in Reactor Californium
What's new in Reactor CaliforniumWhat's new in Reactor Californium
What's new in Reactor Californium
Stéphane Maldini
 
State of Securing Restful APIs s12gx2015
State of Securing Restful APIs s12gx2015State of Securing Restful APIs s12gx2015
State of Securing Restful APIs s12gx2015
robwinch
 
Simplifying Apache Geode with Spring Data
Simplifying Apache Geode with Spring DataSimplifying Apache Geode with Spring Data
Simplifying Apache Geode with Spring Data
VMware Tanzu
 
Building a Secure App with Google Polymer and Java / Spring
Building a Secure App with Google Polymer and Java / SpringBuilding a Secure App with Google Polymer and Java / Spring
Building a Secure App with Google Polymer and Java / Spring
sdeeg
 
riffing on Knative - Scott Andrews
riffing on Knative - Scott Andrewsriffing on Knative - Scott Andrews
riffing on Knative - Scott Andrews
VMware Tanzu
 
Under the Hood of Reactive Data Access (1/2)
Under the Hood of Reactive Data Access (1/2)Under the Hood of Reactive Data Access (1/2)
Under the Hood of Reactive Data Access (1/2)
VMware Tanzu
 
Reactive frontends with RxJS and Angular
Reactive frontends with RxJS and AngularReactive frontends with RxJS and Angular
Reactive frontends with RxJS and Angular
VMware Tanzu
 
Spring Cloud Gateway - Stéphane Maldini
Spring Cloud Gateway - Stéphane MaldiniSpring Cloud Gateway - Stéphane Maldini
Spring Cloud Gateway - Stéphane Maldini
VMware Tanzu
 
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
VMware Tanzu
 
Spring Cloud Gateway
Spring Cloud GatewaySpring Cloud Gateway
Spring Cloud Gateway
Stéphane Maldini
 
In the workshop with GCP, Home Depot & Cloud Foundry
In the workshop with GCP, Home Depot & Cloud FoundryIn the workshop with GCP, Home Depot & Cloud Foundry
In the workshop with GCP, Home Depot & Cloud Foundry
Christopher Grant
 
SpringOnePlatform2017 recap
SpringOnePlatform2017 recapSpringOnePlatform2017 recap
SpringOnePlatform2017 recap
minseok kim
 
SpringOne2GX 2014 Splunk Presentation
SpringOne2GX 2014 Splunk PresentationSpringOne2GX 2014 Splunk Presentation
SpringOne2GX 2014 Splunk Presentation
Damien Dallimore
 
Reactor 3.0, a reactive foundation for java 8 and Spring
Reactor 3.0, a reactive foundation for java 8 and SpringReactor 3.0, a reactive foundation for java 8 and Spring
Reactor 3.0, a reactive foundation for java 8 and Spring
Stéphane Maldini
 
Cloud Native Java with Spring Cloud Services
Cloud Native Java with Spring Cloud ServicesCloud Native Java with Spring Cloud Services
Cloud Native Java with Spring Cloud Services
VMware Tanzu
 
Policy Enforcement on Kubernetes with Open Policy Agent
Policy Enforcement on Kubernetes with Open Policy AgentPolicy Enforcement on Kubernetes with Open Policy Agent
Policy Enforcement on Kubernetes with Open Policy Agent
VMware Tanzu
 
Zuul @ Netflix SpringOne Platform
Zuul @ Netflix SpringOne PlatformZuul @ Netflix SpringOne Platform
Zuul @ Netflix SpringOne Platform
Mikey Cohen - Hiring Amazing Engineers
 
Reactive Data Access with Spring Data
Reactive Data Access with Spring DataReactive Data Access with Spring Data
Reactive Data Access with Spring Data
VMware Tanzu
 

Similar to SpringOne 2GX 2015 - Fullstack Groovy developer (20)

12 Factor, or Cloud Native Apps – What EXACTLY Does that Mean for Spring Deve...
12 Factor, or Cloud Native Apps – What EXACTLY Does that Mean for Spring Deve...12 Factor, or Cloud Native Apps – What EXACTLY Does that Mean for Spring Deve...
12 Factor, or Cloud Native Apps – What EXACTLY Does that Mean for Spring Deve...
 
Implementing microservices tracing with spring cloud and zipkin (spring one)
Implementing microservices tracing with spring cloud and zipkin (spring one)Implementing microservices tracing with spring cloud and zipkin (spring one)
Implementing microservices tracing with spring cloud and zipkin (spring one)
 
What's new in Reactor Californium
What's new in Reactor CaliforniumWhat's new in Reactor Californium
What's new in Reactor Californium
 
State of Securing Restful APIs s12gx2015
State of Securing Restful APIs s12gx2015State of Securing Restful APIs s12gx2015
State of Securing Restful APIs s12gx2015
 
Simplifying Apache Geode with Spring Data
Simplifying Apache Geode with Spring DataSimplifying Apache Geode with Spring Data
Simplifying Apache Geode with Spring Data
 
Building a Secure App with Google Polymer and Java / Spring
Building a Secure App with Google Polymer and Java / SpringBuilding a Secure App with Google Polymer and Java / Spring
Building a Secure App with Google Polymer and Java / Spring
 
riffing on Knative - Scott Andrews
riffing on Knative - Scott Andrewsriffing on Knative - Scott Andrews
riffing on Knative - Scott Andrews
 
Under the Hood of Reactive Data Access (1/2)
Under the Hood of Reactive Data Access (1/2)Under the Hood of Reactive Data Access (1/2)
Under the Hood of Reactive Data Access (1/2)
 
Reactive frontends with RxJS and Angular
Reactive frontends with RxJS and AngularReactive frontends with RxJS and Angular
Reactive frontends with RxJS and Angular
 
Spring Cloud Gateway - Stéphane Maldini
Spring Cloud Gateway - Stéphane MaldiniSpring Cloud Gateway - Stéphane Maldini
Spring Cloud Gateway - Stéphane Maldini
 
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
 
Spring Cloud Gateway
Spring Cloud GatewaySpring Cloud Gateway
Spring Cloud Gateway
 
In the workshop with GCP, Home Depot & Cloud Foundry
In the workshop with GCP, Home Depot & Cloud FoundryIn the workshop with GCP, Home Depot & Cloud Foundry
In the workshop with GCP, Home Depot & Cloud Foundry
 
SpringOnePlatform2017 recap
SpringOnePlatform2017 recapSpringOnePlatform2017 recap
SpringOnePlatform2017 recap
 
SpringOne2GX 2014 Splunk Presentation
SpringOne2GX 2014 Splunk PresentationSpringOne2GX 2014 Splunk Presentation
SpringOne2GX 2014 Splunk Presentation
 
Reactor 3.0, a reactive foundation for java 8 and Spring
Reactor 3.0, a reactive foundation for java 8 and SpringReactor 3.0, a reactive foundation for java 8 and Spring
Reactor 3.0, a reactive foundation for java 8 and Spring
 
Cloud Native Java with Spring Cloud Services
Cloud Native Java with Spring Cloud ServicesCloud Native Java with Spring Cloud Services
Cloud Native Java with Spring Cloud Services
 
Policy Enforcement on Kubernetes with Open Policy Agent
Policy Enforcement on Kubernetes with Open Policy AgentPolicy Enforcement on Kubernetes with Open Policy Agent
Policy Enforcement on Kubernetes with Open Policy Agent
 
Zuul @ Netflix SpringOne Platform
Zuul @ Netflix SpringOne PlatformZuul @ Netflix SpringOne Platform
Zuul @ Netflix SpringOne Platform
 
Reactive Data Access with Spring Data
Reactive Data Access with Spring DataReactive Data Access with Spring Data
Reactive Data Access with Spring Data
 

More from Iván López Martín

SalmorejoTech 2024 - Spring Boot <3 Testcontainers
SalmorejoTech 2024 - Spring Boot <3 TestcontainersSalmorejoTech 2024 - Spring Boot <3 Testcontainers
SalmorejoTech 2024 - Spring Boot <3 Testcontainers
Iván López Martín
 
CommitConf 2024 - Spring Boot <3 Testcontainers
CommitConf 2024 - Spring Boot <3 TestcontainersCommitConf 2024 - Spring Boot <3 Testcontainers
CommitConf 2024 - Spring Boot <3 Testcontainers
Iván López Martín
 
Voxxed Days CERN 2024 - Spring Boot <3 Testcontainers.pdf
Voxxed Days CERN 2024 - Spring Boot <3 Testcontainers.pdfVoxxed Days CERN 2024 - Spring Boot <3 Testcontainers.pdf
Voxxed Days CERN 2024 - Spring Boot <3 Testcontainers.pdf
Iván López Martín
 
VMware - Testcontainers y Spring Boot
VMware - Testcontainers y Spring BootVMware - Testcontainers y Spring Boot
VMware - Testcontainers y Spring Boot
Iván López Martín
 
Spring IO 2023 - Dynamic OpenAPIs with Spring Cloud Gateway
Spring IO 2023 - Dynamic OpenAPIs with Spring Cloud GatewaySpring IO 2023 - Dynamic OpenAPIs with Spring Cloud Gateway
Spring IO 2023 - Dynamic OpenAPIs with Spring Cloud Gateway
Iván López Martín
 
Codemotion Madrid 2023 - Testcontainers y Spring Boot
Codemotion Madrid 2023 - Testcontainers y Spring BootCodemotion Madrid 2023 - Testcontainers y Spring Boot
Codemotion Madrid 2023 - Testcontainers y Spring Boot
Iván López Martín
 
CommitConf 2023 - Spring Framework 6 y Spring Boot 3
CommitConf 2023 - Spring Framework 6 y Spring Boot 3CommitConf 2023 - Spring Framework 6 y Spring Boot 3
CommitConf 2023 - Spring Framework 6 y Spring Boot 3
Iván López Martín
 
Construyendo un API REST con Spring Boot y GraalVM
Construyendo un API REST con Spring Boot y GraalVMConstruyendo un API REST con Spring Boot y GraalVM
Construyendo un API REST con Spring Boot y GraalVM
Iván López Martín
 
jLove 2020 - Micronaut and graalvm: The power of AoT
jLove 2020 - Micronaut and graalvm: The power of AoTjLove 2020 - Micronaut and graalvm: The power of AoT
jLove 2020 - Micronaut and graalvm: The power of AoT
Iván López Martín
 
Codemotion Madrid 2020 - Serverless con Micronaut
Codemotion Madrid 2020 - Serverless con MicronautCodemotion Madrid 2020 - Serverless con Micronaut
Codemotion Madrid 2020 - Serverless con Micronaut
Iván López Martín
 
JConf Perú 2020 - ¡Micronaut en acción!
JConf Perú 2020 - ¡Micronaut en acción!JConf Perú 2020 - ¡Micronaut en acción!
JConf Perú 2020 - ¡Micronaut en acción!
Iván López Martín
 
JConf Perú 2020 - Micronaut + GraalVM = <3
JConf Perú 2020 - Micronaut + GraalVM = <3JConf Perú 2020 - Micronaut + GraalVM = <3
JConf Perú 2020 - Micronaut + GraalVM = <3
Iván López Martín
 
JConf México 2020 - Micronaut + GraalVM = <3
JConf México 2020 - Micronaut + GraalVM = <3JConf México 2020 - Micronaut + GraalVM = <3
JConf México 2020 - Micronaut + GraalVM = <3
Iván López Martín
 
Developing Micronaut Applications With IntelliJ IDEA
Developing Micronaut Applications With IntelliJ IDEADeveloping Micronaut Applications With IntelliJ IDEA
Developing Micronaut Applications With IntelliJ IDEA
Iván López Martín
 
CommitConf 2019 - Micronaut y GraalVm: La combinación perfecta
CommitConf 2019 - Micronaut y GraalVm: La combinación perfectaCommitConf 2019 - Micronaut y GraalVm: La combinación perfecta
CommitConf 2019 - Micronaut y GraalVm: La combinación perfecta
Iván López Martín
 
Codemotion Madrid 2019 - ¡GraalVM y Micronaut: compañeros perfectos!
Codemotion Madrid 2019 - ¡GraalVM y Micronaut: compañeros perfectos!Codemotion Madrid 2019 - ¡GraalVM y Micronaut: compañeros perfectos!
Codemotion Madrid 2019 - ¡GraalVM y Micronaut: compañeros perfectos!
Iván López Martín
 
Greach 2019 - Creating Micronaut Configurations
Greach 2019 - Creating Micronaut ConfigurationsGreach 2019 - Creating Micronaut Configurations
Greach 2019 - Creating Micronaut Configurations
Iván López Martín
 
VoxxedDays Bucharest 2019 - Alexa, nice to meet you
VoxxedDays Bucharest 2019 - Alexa, nice to meet youVoxxedDays Bucharest 2019 - Alexa, nice to meet you
VoxxedDays Bucharest 2019 - Alexa, nice to meet you
Iván López Martín
 
JavaDay Lviv 2019 - Micronaut in action!
JavaDay Lviv 2019 - Micronaut in action!JavaDay Lviv 2019 - Micronaut in action!
JavaDay Lviv 2019 - Micronaut in action!
Iván López Martín
 
CrossDvlup Madrid 2019 - Alexa, encantado de conocerte
CrossDvlup Madrid 2019 - Alexa, encantado de conocerteCrossDvlup Madrid 2019 - Alexa, encantado de conocerte
CrossDvlup Madrid 2019 - Alexa, encantado de conocerte
Iván López Martín
 

More from Iván López Martín (20)

SalmorejoTech 2024 - Spring Boot <3 Testcontainers
SalmorejoTech 2024 - Spring Boot <3 TestcontainersSalmorejoTech 2024 - Spring Boot <3 Testcontainers
SalmorejoTech 2024 - Spring Boot <3 Testcontainers
 
CommitConf 2024 - Spring Boot <3 Testcontainers
CommitConf 2024 - Spring Boot <3 TestcontainersCommitConf 2024 - Spring Boot <3 Testcontainers
CommitConf 2024 - Spring Boot <3 Testcontainers
 
Voxxed Days CERN 2024 - Spring Boot <3 Testcontainers.pdf
Voxxed Days CERN 2024 - Spring Boot <3 Testcontainers.pdfVoxxed Days CERN 2024 - Spring Boot <3 Testcontainers.pdf
Voxxed Days CERN 2024 - Spring Boot <3 Testcontainers.pdf
 
VMware - Testcontainers y Spring Boot
VMware - Testcontainers y Spring BootVMware - Testcontainers y Spring Boot
VMware - Testcontainers y Spring Boot
 
Spring IO 2023 - Dynamic OpenAPIs with Spring Cloud Gateway
Spring IO 2023 - Dynamic OpenAPIs with Spring Cloud GatewaySpring IO 2023 - Dynamic OpenAPIs with Spring Cloud Gateway
Spring IO 2023 - Dynamic OpenAPIs with Spring Cloud Gateway
 
Codemotion Madrid 2023 - Testcontainers y Spring Boot
Codemotion Madrid 2023 - Testcontainers y Spring BootCodemotion Madrid 2023 - Testcontainers y Spring Boot
Codemotion Madrid 2023 - Testcontainers y Spring Boot
 
CommitConf 2023 - Spring Framework 6 y Spring Boot 3
CommitConf 2023 - Spring Framework 6 y Spring Boot 3CommitConf 2023 - Spring Framework 6 y Spring Boot 3
CommitConf 2023 - Spring Framework 6 y Spring Boot 3
 
Construyendo un API REST con Spring Boot y GraalVM
Construyendo un API REST con Spring Boot y GraalVMConstruyendo un API REST con Spring Boot y GraalVM
Construyendo un API REST con Spring Boot y GraalVM
 
jLove 2020 - Micronaut and graalvm: The power of AoT
jLove 2020 - Micronaut and graalvm: The power of AoTjLove 2020 - Micronaut and graalvm: The power of AoT
jLove 2020 - Micronaut and graalvm: The power of AoT
 
Codemotion Madrid 2020 - Serverless con Micronaut
Codemotion Madrid 2020 - Serverless con MicronautCodemotion Madrid 2020 - Serverless con Micronaut
Codemotion Madrid 2020 - Serverless con Micronaut
 
JConf Perú 2020 - ¡Micronaut en acción!
JConf Perú 2020 - ¡Micronaut en acción!JConf Perú 2020 - ¡Micronaut en acción!
JConf Perú 2020 - ¡Micronaut en acción!
 
JConf Perú 2020 - Micronaut + GraalVM = <3
JConf Perú 2020 - Micronaut + GraalVM = <3JConf Perú 2020 - Micronaut + GraalVM = <3
JConf Perú 2020 - Micronaut + GraalVM = <3
 
JConf México 2020 - Micronaut + GraalVM = <3
JConf México 2020 - Micronaut + GraalVM = <3JConf México 2020 - Micronaut + GraalVM = <3
JConf México 2020 - Micronaut + GraalVM = <3
 
Developing Micronaut Applications With IntelliJ IDEA
Developing Micronaut Applications With IntelliJ IDEADeveloping Micronaut Applications With IntelliJ IDEA
Developing Micronaut Applications With IntelliJ IDEA
 
CommitConf 2019 - Micronaut y GraalVm: La combinación perfecta
CommitConf 2019 - Micronaut y GraalVm: La combinación perfectaCommitConf 2019 - Micronaut y GraalVm: La combinación perfecta
CommitConf 2019 - Micronaut y GraalVm: La combinación perfecta
 
Codemotion Madrid 2019 - ¡GraalVM y Micronaut: compañeros perfectos!
Codemotion Madrid 2019 - ¡GraalVM y Micronaut: compañeros perfectos!Codemotion Madrid 2019 - ¡GraalVM y Micronaut: compañeros perfectos!
Codemotion Madrid 2019 - ¡GraalVM y Micronaut: compañeros perfectos!
 
Greach 2019 - Creating Micronaut Configurations
Greach 2019 - Creating Micronaut ConfigurationsGreach 2019 - Creating Micronaut Configurations
Greach 2019 - Creating Micronaut Configurations
 
VoxxedDays Bucharest 2019 - Alexa, nice to meet you
VoxxedDays Bucharest 2019 - Alexa, nice to meet youVoxxedDays Bucharest 2019 - Alexa, nice to meet you
VoxxedDays Bucharest 2019 - Alexa, nice to meet you
 
JavaDay Lviv 2019 - Micronaut in action!
JavaDay Lviv 2019 - Micronaut in action!JavaDay Lviv 2019 - Micronaut in action!
JavaDay Lviv 2019 - Micronaut in action!
 
CrossDvlup Madrid 2019 - Alexa, encantado de conocerte
CrossDvlup Madrid 2019 - Alexa, encantado de conocerteCrossDvlup Madrid 2019 - Alexa, encantado de conocerte
CrossDvlup Madrid 2019 - Alexa, encantado de conocerte
 

Recently uploaded

Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
DianaGray10
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
Dorra BARTAGUIZ
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Jeffrey Haguewood
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Product School
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
Frank van Harmelen
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
DanBrown980551
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Tobias Schneck
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
Elena Simperl
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
Product School
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 

Recently uploaded (20)

Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 

SpringOne 2GX 2015 - Fullstack Groovy developer

  • 2. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 2 Hello! @ilopmar http://greachconf.com@madridgug I'm Iván López
  • 3. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 3 Thank you very much! Q&A
  • 4. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 4 Just kidding!
  • 5. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 5
  • 6. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 6 What's a fullstack developer?
  • 7. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 7 Fullstack developer Backend language Javascript Mobile app HTML
  • 8. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 8
  • 9. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 9 Polaromatic
  • 10. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 10
  • 11. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 11 1. Demo
  • 12. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 12 2. Application flow
  • 13. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 13
  • 14. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 14 3. Backend
  • 15. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 15
  • 16. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 16 Polaromatic ● Spring Boot ● Core App ● Spring MVC ● Spring Integration Flow
  • 17. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 17 Spring Integration Flow <file:inbound-channel-adapter directory="work" channel="incommingFilesChannel"/> <chain input-channel="incommingFilesChannel"> <service-activator ref="fileService" method="preprocessFile"/> <service-activator ref="imageConverterService" method="applyEffect"/> <service-activator ref="browserPushService" method="pushToBrowser"/> <service-activator ref="metricsService" method="updateMetrics"/> <service-activator ref="fileService" method="deleteTempFiles"/> </chain>
  • 18. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 18 Spring Integration Flow File Service <file:inbound-channel-adapter directory="work" channel="incommingFilesChannel"/> <chain input-channel="incommingFilesChannel"> <service-activator ref="fileService" method="preprocessFile"/> <service-activator ref="imageConverterService" method="applyEffect"/> <service-activator ref="browserPushService" method="pushToBrowser"/> <service-activator ref="metricsService" method="updateMetrics"/> <service-activator ref="fileService" method="deleteTempFiles"/> </chain> Photo preprocessFile(File file) { def pr = new PolaroidRequest(file) this.preprocessFile(pr) }
  • 19. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 19 Spring Integration Flow File Service Photo preprocessFile(File file) { def pr = new PolaroidRequest(file) this.preprocessFile(pr) }
  • 20. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 20 Spring Integration Flow File Service Photo preprocessFile(File file) { def pr = new PolaroidRequest(file) this.preprocessFile(pr) } Photo preprocessFile(PolaroidRequest polaroidRequest) { String outputFile = File.createTempFile("output", ".png").path return new Photo(input: polaroidRequest.inputFile.absolutePath, output: outputFile, text: polaroidRequest.text) }
  • 21. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 21 Image converter class ImageConverterService { private static final String DEFAULT_CAPTION = "#LearningSpringBoot with Polaromaticn" Random rnd = new Random() Photo applyEffect(Photo photo) { log.debug "Applying effect to file: ${photo.input}..." def inputFile = photo.input def outputFile = photo.output double polaroidRotation = rnd.nextInt(6).toDouble() String caption = photo.text ?: DEFAULT_CAPTION def op = new IMOperation() op.addImage(inputFile) op.thumbnail(300, 300) .set("caption", caption) .gravity("center") .pointsize(20) .background("black") .polaroid(rnd.nextBoolean() ? polaroidRotation : -polaroidRotation) .addImage(outputFile) def command = new ConvertCmd() command.run(op) photo } }
  • 22. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 22 Metrics class MetricsService { static final String PHOTO_COUNTER_METRICS_FLICKR = "polaromatized.photos.flickr" static final String PHOTO_COUNTER_METRICS_ANDROID = "polaromatized.photos.android" @Autowired CounterService counterService Photo updateMetrics(Photo photo) { if (photo.text) { counterService.increment(PHOTO_COUNTER_METRICS_ANDROID) } else { counterService.increment(PHOTO_COUNTER_METRICS_FLICKR) } photo } }
  • 23. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 23 Metrics class MetricsService { static final String PHOTO_COUNTER_METRICS_FLICKR = "polaromatized.photos.flickr" static final String PHOTO_COUNTER_METRICS_ANDROID = "polaromatized.photos.android" @Autowired CounterService counterService Photo updateMetrics(Photo photo) { if (photo.text) { counterService.increment(PHOTO_COUNTER_METRICS_ANDROID) } else { counterService.increment(PHOTO_COUNTER_METRICS_FLICKR) } photo } } <chain input-channel="incommingFilesChannel"> <service-activator ref="fileService" method="preprocessFile"/> <service-activator ref="imageConverterService" method="applyEffect"/> <service-activator ref="browserPushService" method="pushToBrowser"/> <service-activator ref="metricsService" method="updateMetrics"/> <service-activator ref="fileService" method="deleteTempFiles"/> </chain>
  • 24. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 24 Metrics
  • 25. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 25
  • 26. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 26 FlickrDownloader ● Spring Boot CLI ● Download Flickr Interesting pictures ● Jsoup, GPars ● 55 lines of Groovy code (microservice?)
  • 27. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 27 FlickrDownloader @Slf4j @EnableScheduling @Grab('org.jsoup:jsoup:1.8.1') @Grab('commons-io:commons-io:2.4') @Grab('org.codehaus.gpars:gpars:1.2.1') class FlickrDownloader { static final String FLICKER_INTERESTING_URL = "https://www.flickr.com/explore/interesting/7days" static final String WORK_DIR = "./work" final File workDir = new File(WORK_DIR) @Scheduled(fixedRate = 30000L) void downloadFlickrInteresting() { def photos = extractPhotosFromFlickr() withPool { photos.eachParallel { photoUrl -> log.info "Downloading photo ${photoUrl}" def tempFile = download(photoUrl) FileUtils.moveFileToDirectory(tempFile, workDir, true) } } } }
  • 28. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 28 FlickrDownloader @Slf4j @EnableScheduling @Grab('org.jsoup:jsoup:1.8.1') @Grab('commons-io:commons-io:2.4') @Grab('org.codehaus.gpars:gpars:1.2.1') class FlickrDownloader { static final String FLICKER_INTERESTING_URL = "https://www.flickr.com/explore/interesting/7days" static final String WORK_DIR = "./work" final File workDir = new File(WORK_DIR) @Scheduled(fixedRate = 30000L) void downloadFlickrInteresting() { def photos = extractPhotosFromFlickr() withPool { photos.eachParallel { photoUrl -> log.info "Downloading photo ${photoUrl}" def tempFile = download(photoUrl) FileUtils.moveFileToDirectory(tempFile, workDir, true) } } } }
  • 29. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 29 FlickrDownloader @Slf4j @EnableScheduling @Grab('org.jsoup:jsoup:1.8.1') @Grab('commons-io:commons-io:2.4') @Grab('org.codehaus.gpars:gpars:1.2.1') class FlickrDownloader { static final String FLICKER_INTERESTING_URL = "https://www.flickr.com/explore/interesting/7days" static final String WORK_DIR = "./work" final File workDir = new File(WORK_DIR) @Scheduled(fixedRate = 30000L) void downloadFlickrInteresting() { def photos = extractPhotosFromFlickr() withPool { photos.eachParallel { photoUrl -> log.info "Downloading photo ${photoUrl}" def tempFile = download(photoUrl) FileUtils.moveFileToDirectory(tempFile, workDir, true) } } } } private List extractPhotosFromFlickr() { Document doc = Jsoup.connect(FLICKER_INTERESTING_URL).get() Elements images = doc.select("img.pc_img") def photos = images .listIterator() .collect { it.attr('src').replace('_m.jpg', '_b.jpg') } photos }
  • 30. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 30 FlickrDownloader @Slf4j @EnableScheduling @Grab('org.jsoup:jsoup:1.8.1') @Grab('commons-io:commons-io:2.4') @Grab('org.codehaus.gpars:gpars:1.2.1') class FlickrDownloader { static final String FLICKER_INTERESTING_URL = "https://www.flickr.com/explore/interesting/7days" static final String WORK_DIR = "./work" final File workDir = new File(WORK_DIR) @Scheduled(fixedRate = 30000L) void downloadFlickrInteresting() { def photos = extractPhotosFromFlickr() withPool { photos.eachParallel { photoUrl -> log.info "Downloading photo ${photoUrl}" def tempFile = download(photoUrl) FileUtils.moveFileToDirectory(tempFile, workDir, true) } } } } private File download(String url) { def tempFile = File.createTempFile('flickr_downloader', '') tempFile << url.toURL().bytes tempFile }
  • 31. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 31 FlickrDownloader @Slf4j @EnableScheduling @Grab('org.jsoup:jsoup:1.8.1') @Grab('commons-io:commons-io:2.4') @Grab('org.codehaus.gpars:gpars:1.2.1') class FlickrDownloader { static final String FLICKER_INTERESTING_URL = "https://www.flickr.com/explore/interesting/7days" static final String WORK_DIR = "./work" final File workDir = new File(WORK_DIR) @Scheduled(fixedRate = 30000L) void downloadFlickrInteresting() { def photos = extractPhotosFromFlickr() withPool { photos.eachParallel { photoUrl -> log.info "Downloading photo ${photoUrl}" def tempFile = download(photoUrl) FileUtils.moveFileToDirectory(tempFile, workDir, true) } } } }
  • 32. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 32 FlickrDownloader 2015-08-31 21:56:11.139 INFO 16447 --- [111617-worker-1] polaromatic.FlickrDownloader 2015-08-31 21:56:11.139 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader 2015-08-31 21:56:11.139 INFO 16447 --- [111617-worker-3] polaromatic.FlickrDownloader 2015-08-31 21:56:11.354 INFO 16447 --- [111617-worker-1] polaromatic.FlickrDownloader 2015-08-31 21:56:11.375 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader 2015-08-31 21:56:11.527 INFO 16447 --- [111617-worker-3] polaromatic.FlickrDownloader 2015-08-31 21:56:11.537 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader 2015-08-31 21:56:11.612 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader 2015-08-31 21:56:11.693 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader 2015-08-31 22:02:17.019 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:19.451 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:21.661 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:22.079 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:22.877 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:23.392 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:23.749 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:24.250 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:24.695 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
  • 33. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 33 FlickrDownloader 2015-08-31 21:56:11.139 INFO 16447 --- [111617-worker-1] polaromatic.FlickrDownloader 2015-08-31 21:56:11.139 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader 2015-08-31 21:56:11.139 INFO 16447 --- [111617-worker-3] polaromatic.FlickrDownloader 2015-08-31 21:56:11.354 INFO 16447 --- [111617-worker-1] polaromatic.FlickrDownloader 2015-08-31 21:56:11.375 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader 2015-08-31 21:56:11.527 INFO 16447 --- [111617-worker-3] polaromatic.FlickrDownloader 2015-08-31 21:56:11.537 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader 2015-08-31 21:56:11.612 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader 2015-08-31 21:56:11.693 INFO 16447 --- [111617-worker-2] polaromatic.FlickrDownloader 2015-08-31 22:02:17.019 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:19.451 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:21.661 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:22.079 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:22.877 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:23.392 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:23.749 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:24.250 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader 2015-08-31 22:02:24.695 INFO 9872 --- [pool-1-thread-1] polaromatic.FlickrDownloader
  • 34. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 34 4. Frontend
  • 35. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 35
  • 36. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 36 Frontend ● MarkupTemplatEngine (HTML) ● Websockets ● Grooscript
  • 37. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 37 HTML yieldUnescaped '<!DOCTYPE html>' html { head { title "Polaromatic" link(rel: 'stylesheet', href: '/css/app.css') link(rel: 'stylesheet', href: '/css/gh-fork-ribbon.css') ['webjars/sockjs-client/0.3.4-1/sockjs.min.js', 'webjars/stomp-websocket/2.3.1-1/stomp.min.js', 'webjars/jquery/2.1.3/jquery.min.js', 'webjars/handlebars/2.0.0-1/handlebars.min.js', 'js/Connection.js'] .each { yieldUnescaped "<script src='$it'></script>" } } }
  • 38. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 38 HTML body { ... div(id: 'header') { div(class: 'center') { a(href: 'https://github.com/lmivan/contest', target: 'blank') { img(src: 'images/polaromatic-logo.png') } p('Polaromatic') span('Powered by Spring Boot') } } div(id: 'timeline', class: 'center') } script(id: 'photo-template', type: 'text/x-handlebars-template') { div(class: 'photo-cover') { div(class: 'photo', style: 'visibility:hidden; height:0') { img(src: '{{image}}') } } } yieldUnescaped "<script>Connection().start()</script>" }
  • 39. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 39 Websockets @Configuration @EnableWebSocketMessageBroker class WebsocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker '/notifications' } @Override void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint('/polaromatic').withSockJS() } }
  • 40. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 40 Websockets class BrowserPushService { @Autowired SimpMessagingTemplate template Photo pushToBrowser(Photo photo) { log.debug "Pushing file to browser: ${photo.output}" String imageB64 = new File(photo.output).bytes.encodeBase64().toString() template.convertAndSend "/notifications/photo", imageB64 return photo } }
  • 41. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 41 Websockets class BrowserPushService { @Autowired SimpMessagingTemplate template Photo pushToBrowser(Photo photo) { log.debug "Pushing file to browser: ${photo.output}" String imageB64 = new File(photo.output).bytes.encodeBase64().toString() template.convertAndSend "/notifications/photo", imageB64 return photo } } <chain input-channel="incommingFilesChannel"> <service-activator ref="fileService" method="preprocessFile"/> <service-activator ref="imageConverterService" method="applyEffect"/> <service-activator ref="browserPushService" method="pushToBrowser"/> <service-activator ref="metricsService" method="updateMetrics"/> <service-activator ref="fileService" method="deleteTempFiles"/> </chain>
  • 42. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 42 Websockets class Connection { @GsNative def initOn(source, path) {/* var socket = new SockJS(path); return [Handlebars.compile(source), Stomp.over(socket)]; */} def start() { def source = $("#photo-template").html() def (template, client) = initOn(source, '/polaromatic') client.debug = null client.connect(gs.toJavascript([:])) { -> client.subscribe('/notifications/photo') { message -> def context = [image: 'data:image/png;base64,' + message.body] def html = template(context) $("#timeline").prepend(html) $("#timeline .photo:first-child img").on("load") { $(this).parent().css(gs.toJavascript(display: 'none', visibility: 'visible', height: 'auto')) $(this).parent().slideDown() } } } } }
  • 43. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 43 5. Android
  • 44. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 44
  • 45. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 45 Android App ● Disclaimer: I'm not an Android developer ● Lazybones template (@marioggar) ● Traits, @CompileStatic, AST Transformations,… ● SwissKnife
  • 46. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 46
  • 47. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 47 Android trait Toastable { @OnUIThread void showToastMessage(String message) { Toast toast = Toast.makeText(applicationContext, message, Toast.LENGTH_SHORT) toast.show() } }
  • 48. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 48 Android trait Toastable { @OnUIThread void showToastMessage(String message) { Toast toast = Toast.makeText(applicationContext, message, Toast.LENGTH_SHORT) toast.show() } } @CompileStatic public class ShareActivity extends Activity implements Toastable { ... showToastMessage(getString(R.string.share_ok_msg)) ... }
  • 49. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 49 6. Tests
  • 50. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 50 Tests ● Spock Framework ● 0.7 for more than 3 years ● Now 1.0 ● JUnit compatible (but way better)
  • 51. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 51 Spock class BrowserPushServiceSpec extends Specification { void 'should push a converted photo to the browser'() { given: 'a photo' def output = File.createTempFile("output", "") def photo = new Photo(output: output.path) and: 'a mocked SimpMessagingTemplate' def mockSimpMessagingTemplate = Mock(SimpMessagingTemplate) and: 'the push service' def browserPushService = new BrowserPushService(template: mockSimpMessagingTemplate) when: 'pushing the photo to the browser' browserPushService.pushToBrowser(photo) then: 'the photo is pushed' 1 * mockSimpMessagingTemplate.convertAndSend('/notifications/photo', "") } }
  • 52. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 52 7. Build tool
  • 53. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 53 Build tool ● Gradle ● Multiproject to build backend, documentation and android
  • 54. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 54 Gradle subprojects { buildscript { repositories { jcenter() } } repositories { jcenter() } } task wrapper(type: Wrapper) { gradleVersion = '2.2.1' } build.gradle settings.gradle include 'polaromatic-back' include 'polaromatic-groid' include 'polaromatic-docs'
  • 55. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 55 8. Documentation
  • 56. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 56 Documentation ● Asciidoctor (FTW!) ● Gradle plugin ● Backends: html, epub, pdf,...
  • 57. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 57 Asciidoctor buildscript { dependencies { classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.2' } } apply plugin: 'org.asciidoctor.convert' asciidoctor { sourceDir 'src/docs' outputDir "${buildDir}/docs" attributes 'source-highlighter': 'coderay', toc : 'left', icons : 'font' }
  • 58. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 58 Asciidoctor [source,xml,indent=0] .src/main/resources/resources.xml ---- include::{polaromaticBackResources}/resources.xml[tags=appFlow] ---- <1> Define the integration with the file system <2> Preprocess the file received <3> Apply the Polaroid effect <4> Send the new photo to the browser using Websockets <5> Update the metrics <6> Delete all temporary files
  • 59. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 59 Asciidoctor [source,xml,indent=0] .src/main/resources/resources.xml ---- include::{polaromaticBackResources}/resources.xml[tags=appFlow] ---- <1> Define the integration with the file system <2> Preprocess the file received <3> Apply the Polaroid effect <4> Send the new photo to the browser using Websockets <5> Update the metrics <6> Delete all temporary files <!-- tag::appFlow[] --> <file:inbound-channel-adapter directory="work" channel="incommingFilesChannel"/> <!--1--> <chain input-channel="incommingFilesChannel"> <service-activator ref="fileService" method="preprocessFile"/> <!--2--> <service-activator ref="imageConverterService" method="applyEffect"/> <!--3--> <service-activator ref="browserPushService" method="pushToBrowser"/> <!--4--> <service-activator ref="metricsService" method="updateMetrics"/> <!--5--> <service-activator ref="fileService" method="deleteTempFiles"/> <!--6--> </chain> <!-- end::appFlow[]-->
  • 60. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 60 Asciidoctor
  • 61. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 61 9. Summary
  • 62. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 62 “Groovy, groovy everywhere...”
  • 63. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 63 @ilopmar lopez.ivan@gmail.com https://github.com/lmivan Iván López http://bit.ly/feedback-groovy Thanks! Any questions?