SlideShare a Scribd company logo
JAVA LIBRARIES
YOU CAN’T
AFFORD TO MISS
ANDRES ALMIRAY
@AALMIRAY
DISCLAIMER
THE CHALLENGE
Write an application that consumes a REST
API.
Components must be small and reusable.
Say no to boilerplate code.
Behavior should be easy to test.
THE LIBRARIES
PRODUCTION
Guice | Spring
OkHttp
Retrofit
JDeferred
RxJava
MBassador
Lombok
Slf4j | Log4j2
TEST
JUnitParams
Mockito
Jukito
Awaitility
Spock
WireMock
GITHUB API
Well documented REST API
Latest version located at
https://developer.github.com/v3/
We’re interested in the repositories
operation for now
QUERYING REPOSITORIES
API described at
https://developer.github.com/v3/repos/#list-
organization-repositories
Given a query of the form
GET /orgs/${organization}/repos
QUERY RESULT
[
{
"id": 1296269,
"owner": { /* omitted for brevity */ },
"name": "Hello-World",
"full_name": "octocat/Hello-World",
"description": "This your first repo!",
"html_url": "https://github.com/octocat/Hello-World",
/* many other properties follow */
},
/* additional repositories if they exist */
]
WHAT WE’LL NEED
Dependency Injection
HTTP client & REST behavior
JSON mapping
Boilerplate buster
Handle concurrency
GET THE CODE
https://github.com/aalmiray/javatrove/
DEPENDENCY
INJECTION
public interface Github {
Promise<Collection<Repository>> repositories(String name);
}
public class AppController {
@Inject private AppModel model;
@Inject private Github github;
public void loadRepositories() {
model.setState(RUNNING);
github.repositories(model.getOrganization())
.done(model.getRepositories()::addAll)
.fail(this::handleException)
.always((state, resolved, rejected) -> model.setState(READY));
}
}
Guice - https://github.com/google/guice
Injector injector = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(Github.class)
.to(GithubImpl.class)
.in(Singleton.class);
bind(AppModel.class)
.in(Singleton.class);
bind(GithubAPI.class)
.toProvider(GithubAPIProvider.class)
.in(Singleton.class);
// additional bindings …
}
});
Guice - https://github.com/google/guice
• Reference implementation for JSR-330.
• Can bind types, instances, constant values.
• Can provide lazily evaluated instances, i.e, providers.
• Extensible lifecycle.
BONUS
Guava - https://github.com/google/guava
• New Collections:
• MultiSet
• BiMap
• MultiMap
• Table
• Utility classes for Collections
• Utility classes for String
• Caches
• Reflection
• I/O
• Functional programming support (JDK6+)
Spring - http://projects.spring.io/spring-
framework
• More than just dependency injection
• Supports JSR-330
• Assertions
• MessageSource + MessageFormat
• Serialization
• JDBC, JPA
• JMX
• Validation
• Scheduling
• Testing
REDUCING
BOILERPLATE
CODE
Lombok - https://projectlombok.org
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder;
import lombok.Data;
import lombok.Setter;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class Repository implements Comparable<Repository> {
private String name;
private String description;
@Setter(onMethod = @__({@JsonProperty("full_name")}))
private String fullName;
@Setter(onMethod = @__({@JsonProperty("html_url")}))
private String htmlUrl;
// continued
Lombok - https://projectlombok.org
// continued
@Builder
public static Repository build(String name, String fullName, String
description, String htmlUrl) {
Repository repository = new Repository();
repository.name = name;
repository.fullName = fullName;
repository.description = description;
repository.htmlUrl = htmlUrl;
return repository;
}
}
Lombok - https://projectlombok.org
public class ApplicationEvent {
}
@lombok.Data
@lombok.EqualsAndHashCode(callSuper = true)
@lombok.ToString(callSuper = true)
public class NewInstanceEvent extends ApplicationEvent {
@javax.annotation.Nonnull
private final Object instance;
}
Lombok - https://projectlombok.org
• Reduce boilerplate source code by generating bytecode.
• Relies on APT (Annotation Processing Tool).
• Extensible but not for the faint of heart.
• Common usages already covered, i.e, POJOs, builders.
• Don’t forget to enable annotation processing in your IDE!
BEHAVIOR
SLF4J - http://www.slf4j.org
• Wraps all other logging frameworks:
• java.util.logging
• Apache Commons Logging
• Apache Log4j
• Provides varargs methods
HTTP
How many options are out there to build an
HTTP client?
How many ways are there to build a REST
client?
OkHttp - http://square.github.io/okhttp
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
OkHttp - http://square.github.io/okhttp
• Basic HTTP/HTTP2 Client API.
• Configuration is extensible via factory classes.
• HTTP lifecycle can be decorated via interceptors.
ADDING JAVA ON TOP OF HTTP
What steps do we must ensure in order to
build an HTTP/REST client?
How should HTTP error codes be handled?
How to handle connection errors?
Parsing results in format X or Y.
Retrofit - http://square.github.io/retrofit
public interface GithubAPI {
@GET("/orgs/{name}/repos")
Call<List<Repository>> repositories(@Path("name") String name);
@GET
Call<List<Repository>>> repositoriesPaginate(@Url String url);
}
Retrofit - http://square.github.io/retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(
JacksonConverterFactory.create(objectMapper))
.build();
return retrofit.create(GithubAPI.class);
githubApi.repositories("foo");
Retrofit - http://square.github.io/retrofit
• Wraps REST calls with Java interfaces.
• Extensible via factories.
• Relies on OkHttp.
MULTI-THREADED CODE
The golden rule of UI programming:
- Everything related to UI must be
executed inside the UI thread (read/write
UI properties, paint/repaint, etc).
- Everything else must be executed
outside of the UI thread.
JDeferred - http://jdeferred.org
public interface Github {
Promise<Collection<Repository>, Throwable, Void> repositories(String name);
}
JDeferred - http://jdeferred.org
public class GithubImpl implements Github {
@Inject private GithubAPI api;
@Inject private DeferredManager deferredManager;
@Override
public Promise<Collection<Repository>, Throwable, Void> repositories(final
String name) {
return deferredManager.when(() -> {
Response<List<Repository>> response = api.repositories(name).execute();
if (response.isSuccess()) { return response.body(); }
throw new IllegalStateException(response.message());
});
}
}
JDeferred - http://jdeferred.org
model.setState(RUNNING);
int limit = model.getLimit();
limit = limit > 0 ? limit : Integer.MAX_VALUE;
Promise<Collection<Repository>, Throwable, Repository> promise =
github.repositories(model.getOrganization(), limit);
promise.progress(model.getRepositories()::add)
.fail(Throwable::printStackTrace)
.always((state, resolved, rejected) -> model.setState(READY));
JDeferred - http://jdeferred.org
• Delivers the concept of Promises
• Promises can be chained
• Java8 friendly, i.e, lambda expressions can be used
• One shot execution.
REACTIVE PROGRAMMING
It’s time to embrace a new paradigm.
Reactive programming is a new name for
old and well-known concepts:
events and streams
RxJava - http://reactivex.io
Observable<Repository> observable =
github.repositories(model.getOrganization());
if (model.getLimit() > 0) {
observable = observable.take(model.getLimit());
}
Subscription subscription = observable
.timeout(10, TimeUnit.SECONDS)
.doOnSubscribe(() -> model.setState(RUNNING))
.doOnTerminate(() -> model.setState(READY))
.subscribeOn(Schedulers.io())
.subscribe(
model.getRepositories()::add,
Throwable::printStackTrace);
model.setSubscription(subscription);
Retrofit + RxJava
public interface GithubAPI {
@GET("/orgs/{name}/repos")
Observable<Response<List<Repository>>> repositories(@Path("name") String
name);
@GET
Observable<Response<List<Repository>>> repositoriesPaginate(@Url String url);
}
Retrofit + RxJava
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(JacksonConverterFactory.create(objectMapper))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
return retrofit.create(GithubAPI.class);
Retrofit + RxJava
// concatenating multiple results into a single Observable
public Observable<Repository> repositories(String organization) {
requireNonNull(organization, "Argument 'organization' must not be blank");
return paginatedObservable(
() -> {
LOG.info("Querying /orgs/{}/repos", organization);
return api.repositories(organization);
},
(Links links) -> {
String next = links.next();
LOG.info("Querying {}", next);
return api.repositoriesPaginate(next);
});
}
Retrofit + RxJava
// concatenating multiple results into a single Observable
private static <T> Observable<T> paginatedObservable(FirstPageSupplier<T>
firstPage, NextPageSupplier<T> nextPage) {
return processPage(nextPage, firstPage.get());
}
private static <T> Observable<T> processPage(NextPageSupplier<T> supplier,
Observable<Response<List<T>>> items) {
return items.flatMap(response -> {
Links links = Links.of(response.headers().get("Link"));
Observable<T> currentPage = Observable.from(response.body());
if (links.hasNext()) {
return currentPage.concatWith(processPage(supplier,
supplier.get(links)));
}
return currentPage;
});
}
RxJava - http://reactivex.io
• Implements the Observable pattern.
• Delivers dozens of operations out of the box, e.g. zip, reduce,
concat.
• Supports backpressure, i.e, when the data producer is faster than
the data consumer.
COMPONENT COMMUNICATION
How do you keep two unrelated
components communicated with one
another?
How do you push data down the stream
without forcing publishers to wait for
consumers?
MBassador -
https://github.com/bennidi/mbassador
// event publishing
@Inject private ApplicationEventBus eventBus;
model.setSubscription(observable
.timeout(10, TimeUnit.SECONDS)
.doOnSubscribe(() -> model.setState(RUNNING))
.doOnTerminate(() -> model.setState(READY))
.doOnError(throwable -> eventBus.publishAsync(new ThrowableEvent(throwable)))
.subscribeOn(Schedulers.io())
.subscribe(model.getRepositories()::add));
MBassador -
https://github.com/bennidi/mbassador
// event consuming
import net.engio.mbassy.listener.Handler;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
public class ApplicationEventHandler {
@Inject private ApplicationEventBus eventBus;
@PostConstruct private void init() { eventBus.subscribe(this); }
@PreDestroy private void destroy() { eventBus.unsubscribe(this); }
@Handler
public void handleThrowable(ThrowableEvent event) {
// handle event here !!
}
}
MBassador -
https://github.com/bennidi/mbassador
• Configurable event bus based on annotations.
• Faster implementation than Guava’s event bus.
• https://github.com/bennidi/eventbus-performance
• NOTE: project is no longer actively maintained, fixes and features will
be slow to come.
TESTING
JUnitParams -
https://github.com/Pragmatists/JUnitParams
@RunWith(JUnitParamsRunner.class)
public class SampleServiceTest {
@Test
@Parameters({",Howdy stranger!",
"Test, Hello Test"})
public void sayHello(String input, String output) {
// given:
SampleService service = new SampleService();
// expect:
assertThat(service.sayHello(input), equalTo(output));
}
}
JUnitParams -
https://github.com/Pragmatists/JUnitParams
• Parameterize multiple methods with different argument
cardinality.
• Different data provider strategies.
Mockito - http://mockito.org
@Test @Parameters({",Howdy stranger!", "Test, Hello Test"})
public void sayHelloAction(String input, String output) {
// given:
SampleController controller = new SampleController();
controller.setModel(new SampleModel());
controller.setService(mock(SampleService.class));
// expectations
when(controller.getService().sayHello(input)).thenReturn(output);
// when:
controller.getModel().setInput(input);
controller.sayHello();
// then:
assertThat(controller.getModel().getOutput(), equalTo(output));
verify(controller.getService(), only()).sayHello(input);
}
Mockito - http://mockito.org
• Fluid DSL based on static methods.
• Provides support for Stubs, Mocks, and Spies.
• Mock interfaces, abstract classes, and concrete classes.
Jukito - https://github.com/ArcBees/Jukito
@RunWith(JukitoRunner.class)
public class SampleControllerJukitoTest {
@Inject private SampleController controller;
@Before
public void setupMocks(SampleService sampleService) {
when(sampleService.sayHello("Test")).thenReturn("Hello Test");
}
@Test
public void sayHelloAction() {
controller.setModel(new SampleModel());
controller.getModel().setInput("Test");
controller.sayHello();
assertThat(controller.getModel().getOutput(),
equalTo("Hello Test"));
verify(controller.getService(), only()).sayHello("Test");
}
}
Jukito - https://github.com/ArcBees/Jukito
• Combines JUnit, Guice, and Mockito
• Bind multiple values to the same source type.
• Can be used to parameterize test methods.
Spock- http://spockframework.org
@spock.lang.Unroll
class SampleControllerSpec extends spock.lang.Specification {
def "Invoke say hello with #input results in #output"() {
given:
SampleController controller = new SampleController()
controller.model = new SampleModel()
controller.service = Mock(SampleService) {
sayHello(input) >> output
}
when:
controller.model.input = input
controller.sayHello()
then:
controller.model.output == output
where:
input << ['', 'Test']
output << ['Howdy, stranger!', 'Hello Test']
}
}
Spock- http://spockframework.org
• Groovy based DSL.
• Parameterize multiple methods with different argument
cardinality.
• Parameterize test method names.
• JUnit friendly (can use extensions and rules).
Awaitility -
https://github.com/awaitility/awaitility
@Test
public void happyPath(Github github) {
// given:
Collection<Repository> repositories = createSampleRepositories();
when(github.repositories(ORGANIZATION))
.thenReturn(Observable.from(repositories));
// when:
model.setOrganization(ORGANIZATION);
controller.load();
await().timeout(2, SECONDS).until(model::getState, equalTo(State.READY));
// then:
assertThat(model.getRepositories(), hasSize(10));
assertThat(model.getRepositories(), equalTo(repositories));
verify(github, only()).repositories(ORGANIZATION);
}
Awaitility -
https://github.com/awaitility/awaitility
• DSL for testing multi-threaded code.
• Extensions available for Java8, Groovy, and Scala.
• Conditions can be customized with Hamcrest matchers.
WireMock- http://wiremock.org/
import static com.github.tomakehurst.wiremock.client.WireMock.*;
String nextUrl = "/organizations/1/repos?page=2";
List<Repository> repositories = createSampleRepositories();
stubFor(get(urlEqualTo("/orgs/" + ORGANIZATION + "/repos"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "text/json")
.withHeader("Link", "<http://localhost:8080" + nextUrl + ">; rel="next"")
.withBody(repositoriesAsJSON(repositories.subList(0, 5), objectMapper))));
stubFor(get(urlEqualTo(nextUrl ))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "text/json")
.withBody(repositoriesAsJSON(repositories.subList(5, 10), objectMapper))));
WireMock- http://wiremock.org/
• Supply custom HTTP response payloads.
• DSL for matching HTTP requests.
• Supports record and playback.
THANK YOU!
ANDRES ALMIRAY
@AALMIRAY

More Related Content

What's hot

Spring & Hibernate
Spring & HibernateSpring & Hibernate
Spring & Hibernate
Jiayun Zhou
 
Spring Boot
Spring BootSpring Boot
Spring Boot
Jiayun Zhou
 
Java(ee) mongo db applications in the cloud
Java(ee) mongo db applications in the cloud Java(ee) mongo db applications in the cloud
Java(ee) mongo db applications in the cloud Shekhar Gulati
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
Joshua Long
 
Java EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSFJava EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSFJiayun Zhou
 
Contract-driven development with OpenAPI 3 and Vert.x | DevNation Tech Talk
Contract-driven development with OpenAPI 3 and Vert.x | DevNation Tech TalkContract-driven development with OpenAPI 3 and Vert.x | DevNation Tech Talk
Contract-driven development with OpenAPI 3 and Vert.x | DevNation Tech Talk
Red Hat Developers
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End Development
All Things Open
 
Retrofit
RetrofitRetrofit
Retrofit
bresiu
 
Android Libs - Retrofit
Android Libs - RetrofitAndroid Libs - Retrofit
Android Libs - Retrofit
Daniel Costa Gimenes
 
SymfonyCon Berlin 2016 Jenkins Deployment Pipelines
SymfonyCon Berlin 2016 Jenkins Deployment PipelinesSymfonyCon Berlin 2016 Jenkins Deployment Pipelines
SymfonyCon Berlin 2016 Jenkins Deployment Pipelines
cpsitgmbh
 
iOS Behavior-Driven Development
iOS Behavior-Driven DevelopmentiOS Behavior-Driven Development
iOS Behavior-Driven Development
Brian Gesiak
 
Building domain-specific testing tools : lessons learned from the Apache Slin...
Building domain-specific testing tools : lessons learned from the Apache Slin...Building domain-specific testing tools : lessons learned from the Apache Slin...
Building domain-specific testing tools : lessons learned from the Apache Slin...
Robert Munteanu
 
Retrofit
RetrofitRetrofit
Retrofit
Amin Cheloh
 
Arquillian Constellation
Arquillian ConstellationArquillian Constellation
Arquillian Constellation
Alex Soto
 
Springを用いた社内ライブラリ開発
Springを用いた社内ライブラリ開発Springを用いた社内ライブラリ開発
Springを用いた社内ライブラリ開発
Recruit Lifestyle Co., Ltd.
 
JVM Dive for mere mortals
JVM Dive for mere mortalsJVM Dive for mere mortals
JVM Dive for mere mortals
Jakub Kubrynski
 
The world of gradle - an introduction for developers
The world of gradle  - an introduction for developersThe world of gradle  - an introduction for developers
The world of gradle - an introduction for developers
Tricode (part of Dept)
 
Using the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM DevelopmentUsing the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM Development
Schalk Cronjé
 
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers VersionCool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Schalk Cronjé
 

What's hot (20)

Spring & Hibernate
Spring & HibernateSpring & Hibernate
Spring & Hibernate
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Java(ee) mongo db applications in the cloud
Java(ee) mongo db applications in the cloud Java(ee) mongo db applications in the cloud
Java(ee) mongo db applications in the cloud
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
 
Java EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSFJava EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSF
 
Contract-driven development with OpenAPI 3 and Vert.x | DevNation Tech Talk
Contract-driven development with OpenAPI 3 and Vert.x | DevNation Tech TalkContract-driven development with OpenAPI 3 and Vert.x | DevNation Tech Talk
Contract-driven development with OpenAPI 3 and Vert.x | DevNation Tech Talk
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End Development
 
Retrofit
RetrofitRetrofit
Retrofit
 
Android Libs - Retrofit
Android Libs - RetrofitAndroid Libs - Retrofit
Android Libs - Retrofit
 
SymfonyCon Berlin 2016 Jenkins Deployment Pipelines
SymfonyCon Berlin 2016 Jenkins Deployment PipelinesSymfonyCon Berlin 2016 Jenkins Deployment Pipelines
SymfonyCon Berlin 2016 Jenkins Deployment Pipelines
 
iOS Behavior-Driven Development
iOS Behavior-Driven DevelopmentiOS Behavior-Driven Development
iOS Behavior-Driven Development
 
Building domain-specific testing tools : lessons learned from the Apache Slin...
Building domain-specific testing tools : lessons learned from the Apache Slin...Building domain-specific testing tools : lessons learned from the Apache Slin...
Building domain-specific testing tools : lessons learned from the Apache Slin...
 
Retrofit
RetrofitRetrofit
Retrofit
 
Gradle Introduction
Gradle IntroductionGradle Introduction
Gradle Introduction
 
Arquillian Constellation
Arquillian ConstellationArquillian Constellation
Arquillian Constellation
 
Springを用いた社内ライブラリ開発
Springを用いた社内ライブラリ開発Springを用いた社内ライブラリ開発
Springを用いた社内ライブラリ開発
 
JVM Dive for mere mortals
JVM Dive for mere mortalsJVM Dive for mere mortals
JVM Dive for mere mortals
 
The world of gradle - an introduction for developers
The world of gradle  - an introduction for developersThe world of gradle  - an introduction for developers
The world of gradle - an introduction for developers
 
Using the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM DevelopmentUsing the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM Development
 
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers VersionCool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
 

Viewers also liked

vJUG - The JavaFX Ecosystem
vJUG - The JavaFX EcosystemvJUG - The JavaFX Ecosystem
vJUG - The JavaFX Ecosystem
Andres Almiray
 
Java libraries you can't afford to miss
Java libraries you can't afford to missJava libraries you can't afford to miss
Java libraries you can't afford to miss
Andres Almiray
 
Desktop|Embedded Application API JSR
Desktop|Embedded Application API JSRDesktop|Embedded Application API JSR
Desktop|Embedded Application API JSR
Andres Almiray
 
Greach - The Groovy Ecosystem
Greach - The Groovy EcosystemGreach - The Groovy Ecosystem
Greach - The Groovy Ecosystem
Andres Almiray
 
Real World Event Sourcing and CQRS
Real World Event Sourcing and CQRSReal World Event Sourcing and CQRS
Real World Event Sourcing and CQRS
Matthew Hawkins
 
55 New Features in JDK 9
55 New Features in JDK 955 New Features in JDK 9
55 New Features in JDK 9
Simon Ritter
 
Gradle Glam: Plugis Galore
Gradle Glam: Plugis GaloreGradle Glam: Plugis Galore
Gradle Glam: Plugis Galore
Andres Almiray
 
Griffon: what's new and what's coming
Griffon: what's new and what's comingGriffon: what's new and what's coming
Griffon: what's new and what's coming
Andres Almiray
 
Gradle Glam: Plugis Strike Back
Gradle Glam: Plugis Strike BackGradle Glam: Plugis Strike Back
Gradle Glam: Plugis Strike Back
Andres Almiray
 
Gr8conf - The Groovy Ecosystem Revisited
Gr8conf - The Groovy Ecosystem RevisitedGr8conf - The Groovy Ecosystem Revisited
Gr8conf - The Groovy Ecosystem RevisitedAndres Almiray
 
Asciidoctor, because documentation does not have to suck
Asciidoctor, because documentation does not have to suckAsciidoctor, because documentation does not have to suck
Asciidoctor, because documentation does not have to suck
Andres Almiray
 
Machine Learning for Developers
Machine Learning for DevelopersMachine Learning for Developers
Machine Learning for Developers
Danilo Poccia
 
Get Value from Your Data
Get Value from Your DataGet Value from Your Data
Get Value from Your Data
Danilo Poccia
 
Writing your CV & preparing for interview - Information for tax professionals
Writing your CV & preparing for interview - Information for tax professionalsWriting your CV & preparing for interview - Information for tax professionals
Writing your CV & preparing for interview - Information for tax professionals
The SR Group
 
Data i 3D-modeller for helhetlig planlegging
Data i 3D-modeller for helhetlig planleggingData i 3D-modeller for helhetlig planlegging
Data i 3D-modeller for helhetlig planlegging
Johan Granlund
 
Beyond the Bubble: Conservative Party Conference 2014
Beyond the Bubble: Conservative Party Conference 2014Beyond the Bubble: Conservative Party Conference 2014
Beyond the Bubble: Conservative Party Conference 2014
Ipsos UK
 
Food safety 101 reduced size
Food safety 101 reduced sizeFood safety 101 reduced size
Food safety 101 reduced sizepatesb0048
 
Challenges for Post-PhD Career Development - Dr Ian Lyne
Challenges for Post-PhD Career Development - Dr Ian LyneChallenges for Post-PhD Career Development - Dr Ian Lyne
Challenges for Post-PhD Career Development - Dr Ian Lyne
Arts and Humanities Research Council (AHRC)
 
Andrew Sentence: The "New Normal" for the global economy
Andrew Sentence: The "New Normal" for the global economyAndrew Sentence: The "New Normal" for the global economy
Andrew Sentence: The "New Normal" for the global economyNuffield Trust
 
Pengaruh prosesing thd antioksidan
Pengaruh prosesing thd antioksidanPengaruh prosesing thd antioksidan
Pengaruh prosesing thd antioksidan
Yohanes Kristianto
 

Viewers also liked (20)

vJUG - The JavaFX Ecosystem
vJUG - The JavaFX EcosystemvJUG - The JavaFX Ecosystem
vJUG - The JavaFX Ecosystem
 
Java libraries you can't afford to miss
Java libraries you can't afford to missJava libraries you can't afford to miss
Java libraries you can't afford to miss
 
Desktop|Embedded Application API JSR
Desktop|Embedded Application API JSRDesktop|Embedded Application API JSR
Desktop|Embedded Application API JSR
 
Greach - The Groovy Ecosystem
Greach - The Groovy EcosystemGreach - The Groovy Ecosystem
Greach - The Groovy Ecosystem
 
Real World Event Sourcing and CQRS
Real World Event Sourcing and CQRSReal World Event Sourcing and CQRS
Real World Event Sourcing and CQRS
 
55 New Features in JDK 9
55 New Features in JDK 955 New Features in JDK 9
55 New Features in JDK 9
 
Gradle Glam: Plugis Galore
Gradle Glam: Plugis GaloreGradle Glam: Plugis Galore
Gradle Glam: Plugis Galore
 
Griffon: what's new and what's coming
Griffon: what's new and what's comingGriffon: what's new and what's coming
Griffon: what's new and what's coming
 
Gradle Glam: Plugis Strike Back
Gradle Glam: Plugis Strike BackGradle Glam: Plugis Strike Back
Gradle Glam: Plugis Strike Back
 
Gr8conf - The Groovy Ecosystem Revisited
Gr8conf - The Groovy Ecosystem RevisitedGr8conf - The Groovy Ecosystem Revisited
Gr8conf - The Groovy Ecosystem Revisited
 
Asciidoctor, because documentation does not have to suck
Asciidoctor, because documentation does not have to suckAsciidoctor, because documentation does not have to suck
Asciidoctor, because documentation does not have to suck
 
Machine Learning for Developers
Machine Learning for DevelopersMachine Learning for Developers
Machine Learning for Developers
 
Get Value from Your Data
Get Value from Your DataGet Value from Your Data
Get Value from Your Data
 
Writing your CV & preparing for interview - Information for tax professionals
Writing your CV & preparing for interview - Information for tax professionalsWriting your CV & preparing for interview - Information for tax professionals
Writing your CV & preparing for interview - Information for tax professionals
 
Data i 3D-modeller for helhetlig planlegging
Data i 3D-modeller for helhetlig planleggingData i 3D-modeller for helhetlig planlegging
Data i 3D-modeller for helhetlig planlegging
 
Beyond the Bubble: Conservative Party Conference 2014
Beyond the Bubble: Conservative Party Conference 2014Beyond the Bubble: Conservative Party Conference 2014
Beyond the Bubble: Conservative Party Conference 2014
 
Food safety 101 reduced size
Food safety 101 reduced sizeFood safety 101 reduced size
Food safety 101 reduced size
 
Challenges for Post-PhD Career Development - Dr Ian Lyne
Challenges for Post-PhD Career Development - Dr Ian LyneChallenges for Post-PhD Career Development - Dr Ian Lyne
Challenges for Post-PhD Career Development - Dr Ian Lyne
 
Andrew Sentence: The "New Normal" for the global economy
Andrew Sentence: The "New Normal" for the global economyAndrew Sentence: The "New Normal" for the global economy
Andrew Sentence: The "New Normal" for the global economy
 
Pengaruh prosesing thd antioksidan
Pengaruh prosesing thd antioksidanPengaruh prosesing thd antioksidan
Pengaruh prosesing thd antioksidan
 

Similar to Java Libraries You Can’t Afford to Miss

Java Libraries You Can't Afford to Miss
Java Libraries You Can't Afford to MissJava Libraries You Can't Afford to Miss
Java Libraries You Can't Afford to Miss
Andres Almiray
 
Java Libraries You Can't Afford To Miss
Java Libraries You Can't Afford To MissJava Libraries You Can't Afford To Miss
Java Libraries You Can't Afford To Miss
Andres Almiray
 
Arquitecturas de microservicios - Medianet Software
Arquitecturas de microservicios   -  Medianet SoftwareArquitecturas de microservicios   -  Medianet Software
Arquitecturas de microservicios - Medianet Software
Ernesto Hernández Rodríguez
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
sickill
 
Plugin-based software design with Ruby and RubyGems
Plugin-based software design with Ruby and RubyGemsPlugin-based software design with Ruby and RubyGems
Plugin-based software design with Ruby and RubyGems
Sadayuki Furuhashi
 
What to expect from Java 9
What to expect from Java 9What to expect from Java 9
What to expect from Java 9
Ivan Krylov
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middleware
Alona Mekhovova
 
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...Guillaume Laforge
 
Creating a modern web application using Symfony API Platform, ReactJS and Red...
Creating a modern web application using Symfony API Platform, ReactJS and Red...Creating a modern web application using Symfony API Platform, ReactJS and Red...
Creating a modern web application using Symfony API Platform, ReactJS and Red...
Jesus Manuel Olivas
 
Gohan
GohanGohan
Gohan
Nachi Ueno
 
iOS Swift application architecture
iOS Swift application architectureiOS Swift application architecture
iOS Swift application architecture
Romain Rochegude
 
Ajax Tags Advanced
Ajax Tags AdvancedAjax Tags Advanced
Ajax Tags AdvancedAkramWaseem
 
"Xapi-lang For declarative code generation" By James Nelson
"Xapi-lang For declarative code generation" By James Nelson"Xapi-lang For declarative code generation" By James Nelson
"Xapi-lang For declarative code generation" By James Nelson
GWTcon
 
Plack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and serversPlack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and serversTatsuhiko Miyagawa
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing UpDavid Padbury
 
Java 8 Overview
Java 8 OverviewJava 8 Overview
Java 8 Overview
Nicola Pedot
 
Introduction of Java 8 with emphasis on Lambda Expressions and Streams
Introduction of Java 8 with emphasis on Lambda Expressions and StreamsIntroduction of Java 8 with emphasis on Lambda Expressions and Streams
Introduction of Java 8 with emphasis on Lambda Expressions and Streams
Emiel Paasschens
 
Java 7: Quo vadis?
Java 7: Quo vadis?Java 7: Quo vadis?
Java 7: Quo vadis?
Michal Malohlava
 
Cannibalising The Google App Engine
Cannibalising The  Google  App  EngineCannibalising The  Google  App  Engine
Cannibalising The Google App Enginecatherinewall
 

Similar to Java Libraries You Can’t Afford to Miss (20)

Java Libraries You Can't Afford to Miss
Java Libraries You Can't Afford to MissJava Libraries You Can't Afford to Miss
Java Libraries You Can't Afford to Miss
 
Java Libraries You Can't Afford To Miss
Java Libraries You Can't Afford To MissJava Libraries You Can't Afford To Miss
Java Libraries You Can't Afford To Miss
 
Arquitecturas de microservicios - Medianet Software
Arquitecturas de microservicios   -  Medianet SoftwareArquitecturas de microservicios   -  Medianet Software
Arquitecturas de microservicios - Medianet Software
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
 
Plugin-based software design with Ruby and RubyGems
Plugin-based software design with Ruby and RubyGemsPlugin-based software design with Ruby and RubyGems
Plugin-based software design with Ruby and RubyGems
 
What to expect from Java 9
What to expect from Java 9What to expect from Java 9
What to expect from Java 9
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middleware
 
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
 
Creating a modern web application using Symfony API Platform, ReactJS and Red...
Creating a modern web application using Symfony API Platform, ReactJS and Red...Creating a modern web application using Symfony API Platform, ReactJS and Red...
Creating a modern web application using Symfony API Platform, ReactJS and Red...
 
Gohan
GohanGohan
Gohan
 
iOS Swift application architecture
iOS Swift application architectureiOS Swift application architecture
iOS Swift application architecture
 
Ajax Tags Advanced
Ajax Tags AdvancedAjax Tags Advanced
Ajax Tags Advanced
 
Plack - LPW 2009
Plack - LPW 2009Plack - LPW 2009
Plack - LPW 2009
 
"Xapi-lang For declarative code generation" By James Nelson
"Xapi-lang For declarative code generation" By James Nelson"Xapi-lang For declarative code generation" By James Nelson
"Xapi-lang For declarative code generation" By James Nelson
 
Plack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and serversPlack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and servers
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
Java 8 Overview
Java 8 OverviewJava 8 Overview
Java 8 Overview
 
Introduction of Java 8 with emphasis on Lambda Expressions and Streams
Introduction of Java 8 with emphasis on Lambda Expressions and StreamsIntroduction of Java 8 with emphasis on Lambda Expressions and Streams
Introduction of Java 8 with emphasis on Lambda Expressions and Streams
 
Java 7: Quo vadis?
Java 7: Quo vadis?Java 7: Quo vadis?
Java 7: Quo vadis?
 
Cannibalising The Google App Engine
Cannibalising The  Google  App  EngineCannibalising The  Google  App  Engine
Cannibalising The Google App Engine
 

More from Andres Almiray

Creando, creciendo, y manteniendo una comunidad de codigo abierto
Creando, creciendo, y manteniendo una comunidad de codigo abiertoCreando, creciendo, y manteniendo una comunidad de codigo abierto
Creando, creciendo, y manteniendo una comunidad de codigo abierto
Andres Almiray
 
Liberando a produccion con confianza
Liberando a produccion con confianzaLiberando a produccion con confianza
Liberando a produccion con confianza
Andres Almiray
 
Liberando a produccion con confidencia
Liberando a produccion con confidenciaLiberando a produccion con confidencia
Liberando a produccion con confidencia
Andres Almiray
 
OracleDB Ecosystem for Java Developers
OracleDB Ecosystem for Java DevelopersOracleDB Ecosystem for Java Developers
OracleDB Ecosystem for Java Developers
Andres Almiray
 
Softcon.ph - Maven Puzzlers
Softcon.ph - Maven PuzzlersSoftcon.ph - Maven Puzzlers
Softcon.ph - Maven Puzzlers
Andres Almiray
 
Maven Puzzlers
Maven PuzzlersMaven Puzzlers
Maven Puzzlers
Andres Almiray
 
Oracle Database Ecosystem for Java Developers
Oracle Database Ecosystem for Java DevelopersOracle Database Ecosystem for Java Developers
Oracle Database Ecosystem for Java Developers
Andres Almiray
 
JReleaser - Releasing at the speed of light
JReleaser - Releasing at the speed of lightJReleaser - Releasing at the speed of light
JReleaser - Releasing at the speed of light
Andres Almiray
 
Building modular applications with the Java Platform Module System and Layrry
Building modular applications with the Java Platform Module System and LayrryBuilding modular applications with the Java Platform Module System and Layrry
Building modular applications with the Java Platform Module System and Layrry
Andres Almiray
 
Going Reactive with g rpc
Going Reactive with g rpcGoing Reactive with g rpc
Going Reactive with g rpc
Andres Almiray
 
Building modular applications with JPMS and Layrry
Building modular applications with JPMS and LayrryBuilding modular applications with JPMS and Layrry
Building modular applications with JPMS and Layrry
Andres Almiray
 
Taking Micronaut out for a spin
Taking Micronaut out for a spinTaking Micronaut out for a spin
Taking Micronaut out for a spin
Andres Almiray
 
Apache Groovy's Metaprogramming Options and You
Apache Groovy's Metaprogramming Options and YouApache Groovy's Metaprogramming Options and You
Apache Groovy's Metaprogramming Options and You
Andres Almiray
 
What I wish I knew about Maven years ago
What I wish I knew about Maven years agoWhat I wish I knew about Maven years ago
What I wish I knew about Maven years ago
Andres Almiray
 
What I wish I knew about maven years ago
What I wish I knew about maven years agoWhat I wish I knew about maven years ago
What I wish I knew about maven years ago
Andres Almiray
 
The impact of sci fi in tech
The impact of sci fi in techThe impact of sci fi in tech
The impact of sci fi in tech
Andres Almiray
 
Gradle Ex Machina - Devoxx 2019
Gradle Ex Machina - Devoxx 2019Gradle Ex Machina - Devoxx 2019
Gradle Ex Machina - Devoxx 2019
Andres Almiray
 
Creating Better Builds with Gradle
Creating Better Builds with GradleCreating Better Builds with Gradle
Creating Better Builds with Gradle
Andres Almiray
 
Interacting with the Oracle Cloud Java SDK with Gradle
Interacting with the Oracle Cloud Java SDK with GradleInteracting with the Oracle Cloud Java SDK with Gradle
Interacting with the Oracle Cloud Java SDK with Gradle
Andres Almiray
 
Gradle ex-machina
Gradle ex-machinaGradle ex-machina
Gradle ex-machina
Andres Almiray
 

More from Andres Almiray (20)

Creando, creciendo, y manteniendo una comunidad de codigo abierto
Creando, creciendo, y manteniendo una comunidad de codigo abiertoCreando, creciendo, y manteniendo una comunidad de codigo abierto
Creando, creciendo, y manteniendo una comunidad de codigo abierto
 
Liberando a produccion con confianza
Liberando a produccion con confianzaLiberando a produccion con confianza
Liberando a produccion con confianza
 
Liberando a produccion con confidencia
Liberando a produccion con confidenciaLiberando a produccion con confidencia
Liberando a produccion con confidencia
 
OracleDB Ecosystem for Java Developers
OracleDB Ecosystem for Java DevelopersOracleDB Ecosystem for Java Developers
OracleDB Ecosystem for Java Developers
 
Softcon.ph - Maven Puzzlers
Softcon.ph - Maven PuzzlersSoftcon.ph - Maven Puzzlers
Softcon.ph - Maven Puzzlers
 
Maven Puzzlers
Maven PuzzlersMaven Puzzlers
Maven Puzzlers
 
Oracle Database Ecosystem for Java Developers
Oracle Database Ecosystem for Java DevelopersOracle Database Ecosystem for Java Developers
Oracle Database Ecosystem for Java Developers
 
JReleaser - Releasing at the speed of light
JReleaser - Releasing at the speed of lightJReleaser - Releasing at the speed of light
JReleaser - Releasing at the speed of light
 
Building modular applications with the Java Platform Module System and Layrry
Building modular applications with the Java Platform Module System and LayrryBuilding modular applications with the Java Platform Module System and Layrry
Building modular applications with the Java Platform Module System and Layrry
 
Going Reactive with g rpc
Going Reactive with g rpcGoing Reactive with g rpc
Going Reactive with g rpc
 
Building modular applications with JPMS and Layrry
Building modular applications with JPMS and LayrryBuilding modular applications with JPMS and Layrry
Building modular applications with JPMS and Layrry
 
Taking Micronaut out for a spin
Taking Micronaut out for a spinTaking Micronaut out for a spin
Taking Micronaut out for a spin
 
Apache Groovy's Metaprogramming Options and You
Apache Groovy's Metaprogramming Options and YouApache Groovy's Metaprogramming Options and You
Apache Groovy's Metaprogramming Options and You
 
What I wish I knew about Maven years ago
What I wish I knew about Maven years agoWhat I wish I knew about Maven years ago
What I wish I knew about Maven years ago
 
What I wish I knew about maven years ago
What I wish I knew about maven years agoWhat I wish I knew about maven years ago
What I wish I knew about maven years ago
 
The impact of sci fi in tech
The impact of sci fi in techThe impact of sci fi in tech
The impact of sci fi in tech
 
Gradle Ex Machina - Devoxx 2019
Gradle Ex Machina - Devoxx 2019Gradle Ex Machina - Devoxx 2019
Gradle Ex Machina - Devoxx 2019
 
Creating Better Builds with Gradle
Creating Better Builds with GradleCreating Better Builds with Gradle
Creating Better Builds with Gradle
 
Interacting with the Oracle Cloud Java SDK with Gradle
Interacting with the Oracle Cloud Java SDK with GradleInteracting with the Oracle Cloud Java SDK with Gradle
Interacting with the Oracle Cloud Java SDK with Gradle
 
Gradle ex-machina
Gradle ex-machinaGradle ex-machina
Gradle ex-machina
 

Recently uploaded

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
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
Bhaskar Mitra
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
Paul Groth
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
Prayukth K V
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
Fwdays
 
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
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
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
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
UiPathCommunity
 
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
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Thierry Lestable
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 

Recently uploaded (20)

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
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
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...
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
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
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
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...
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 

Java Libraries You Can’t Afford to Miss

  • 1. JAVA LIBRARIES YOU CAN’T AFFORD TO MISS ANDRES ALMIRAY @AALMIRAY
  • 2.
  • 4.
  • 5.
  • 6. THE CHALLENGE Write an application that consumes a REST API. Components must be small and reusable. Say no to boilerplate code. Behavior should be easy to test.
  • 7. THE LIBRARIES PRODUCTION Guice | Spring OkHttp Retrofit JDeferred RxJava MBassador Lombok Slf4j | Log4j2 TEST JUnitParams Mockito Jukito Awaitility Spock WireMock
  • 8. GITHUB API Well documented REST API Latest version located at https://developer.github.com/v3/ We’re interested in the repositories operation for now
  • 9. QUERYING REPOSITORIES API described at https://developer.github.com/v3/repos/#list- organization-repositories Given a query of the form GET /orgs/${organization}/repos
  • 10. QUERY RESULT [ { "id": 1296269, "owner": { /* omitted for brevity */ }, "name": "Hello-World", "full_name": "octocat/Hello-World", "description": "This your first repo!", "html_url": "https://github.com/octocat/Hello-World", /* many other properties follow */ }, /* additional repositories if they exist */ ]
  • 11. WHAT WE’LL NEED Dependency Injection HTTP client & REST behavior JSON mapping Boilerplate buster Handle concurrency
  • 14. public interface Github { Promise<Collection<Repository>> repositories(String name); }
  • 15. public class AppController { @Inject private AppModel model; @Inject private Github github; public void loadRepositories() { model.setState(RUNNING); github.repositories(model.getOrganization()) .done(model.getRepositories()::addAll) .fail(this::handleException) .always((state, resolved, rejected) -> model.setState(READY)); } }
  • 16. Guice - https://github.com/google/guice Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Github.class) .to(GithubImpl.class) .in(Singleton.class); bind(AppModel.class) .in(Singleton.class); bind(GithubAPI.class) .toProvider(GithubAPIProvider.class) .in(Singleton.class); // additional bindings … } });
  • 17. Guice - https://github.com/google/guice • Reference implementation for JSR-330. • Can bind types, instances, constant values. • Can provide lazily evaluated instances, i.e, providers. • Extensible lifecycle.
  • 18. BONUS
  • 19. Guava - https://github.com/google/guava • New Collections: • MultiSet • BiMap • MultiMap • Table • Utility classes for Collections • Utility classes for String • Caches • Reflection • I/O • Functional programming support (JDK6+)
  • 20. Spring - http://projects.spring.io/spring- framework • More than just dependency injection • Supports JSR-330 • Assertions • MessageSource + MessageFormat • Serialization • JDBC, JPA • JMX • Validation • Scheduling • Testing
  • 22. Lombok - https://projectlombok.org import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Builder; import lombok.Data; import lombok.Setter; @Data @JsonIgnoreProperties(ignoreUnknown = true) public class Repository implements Comparable<Repository> { private String name; private String description; @Setter(onMethod = @__({@JsonProperty("full_name")})) private String fullName; @Setter(onMethod = @__({@JsonProperty("html_url")})) private String htmlUrl; // continued
  • 23. Lombok - https://projectlombok.org // continued @Builder public static Repository build(String name, String fullName, String description, String htmlUrl) { Repository repository = new Repository(); repository.name = name; repository.fullName = fullName; repository.description = description; repository.htmlUrl = htmlUrl; return repository; } }
  • 24. Lombok - https://projectlombok.org public class ApplicationEvent { } @lombok.Data @lombok.EqualsAndHashCode(callSuper = true) @lombok.ToString(callSuper = true) public class NewInstanceEvent extends ApplicationEvent { @javax.annotation.Nonnull private final Object instance; }
  • 25. Lombok - https://projectlombok.org • Reduce boilerplate source code by generating bytecode. • Relies on APT (Annotation Processing Tool). • Extensible but not for the faint of heart. • Common usages already covered, i.e, POJOs, builders. • Don’t forget to enable annotation processing in your IDE!
  • 27. SLF4J - http://www.slf4j.org • Wraps all other logging frameworks: • java.util.logging • Apache Commons Logging • Apache Log4j • Provides varargs methods
  • 28. HTTP How many options are out there to build an HTTP client? How many ways are there to build a REST client?
  • 29. OkHttp - http://square.github.io/okhttp public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); OkHttpClient client = new OkHttpClient(); String post(String url, String json) throws IOException { RequestBody body = RequestBody.create(JSON, json); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = client.newCall(request).execute(); return response.body().string(); }
  • 30. OkHttp - http://square.github.io/okhttp • Basic HTTP/HTTP2 Client API. • Configuration is extensible via factory classes. • HTTP lifecycle can be decorated via interceptors.
  • 31. ADDING JAVA ON TOP OF HTTP What steps do we must ensure in order to build an HTTP/REST client? How should HTTP error codes be handled? How to handle connection errors? Parsing results in format X or Y.
  • 32. Retrofit - http://square.github.io/retrofit public interface GithubAPI { @GET("/orgs/{name}/repos") Call<List<Repository>> repositories(@Path("name") String name); @GET Call<List<Repository>>> repositoriesPaginate(@Url String url); }
  • 33. Retrofit - http://square.github.io/retrofit Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com") .addConverterFactory( JacksonConverterFactory.create(objectMapper)) .build(); return retrofit.create(GithubAPI.class); githubApi.repositories("foo");
  • 34. Retrofit - http://square.github.io/retrofit • Wraps REST calls with Java interfaces. • Extensible via factories. • Relies on OkHttp.
  • 35. MULTI-THREADED CODE The golden rule of UI programming: - Everything related to UI must be executed inside the UI thread (read/write UI properties, paint/repaint, etc). - Everything else must be executed outside of the UI thread.
  • 36. JDeferred - http://jdeferred.org public interface Github { Promise<Collection<Repository>, Throwable, Void> repositories(String name); }
  • 37. JDeferred - http://jdeferred.org public class GithubImpl implements Github { @Inject private GithubAPI api; @Inject private DeferredManager deferredManager; @Override public Promise<Collection<Repository>, Throwable, Void> repositories(final String name) { return deferredManager.when(() -> { Response<List<Repository>> response = api.repositories(name).execute(); if (response.isSuccess()) { return response.body(); } throw new IllegalStateException(response.message()); }); } }
  • 38. JDeferred - http://jdeferred.org model.setState(RUNNING); int limit = model.getLimit(); limit = limit > 0 ? limit : Integer.MAX_VALUE; Promise<Collection<Repository>, Throwable, Repository> promise = github.repositories(model.getOrganization(), limit); promise.progress(model.getRepositories()::add) .fail(Throwable::printStackTrace) .always((state, resolved, rejected) -> model.setState(READY));
  • 39. JDeferred - http://jdeferred.org • Delivers the concept of Promises • Promises can be chained • Java8 friendly, i.e, lambda expressions can be used • One shot execution.
  • 40. REACTIVE PROGRAMMING It’s time to embrace a new paradigm. Reactive programming is a new name for old and well-known concepts: events and streams
  • 41. RxJava - http://reactivex.io Observable<Repository> observable = github.repositories(model.getOrganization()); if (model.getLimit() > 0) { observable = observable.take(model.getLimit()); } Subscription subscription = observable .timeout(10, TimeUnit.SECONDS) .doOnSubscribe(() -> model.setState(RUNNING)) .doOnTerminate(() -> model.setState(READY)) .subscribeOn(Schedulers.io()) .subscribe( model.getRepositories()::add, Throwable::printStackTrace); model.setSubscription(subscription);
  • 42. Retrofit + RxJava public interface GithubAPI { @GET("/orgs/{name}/repos") Observable<Response<List<Repository>>> repositories(@Path("name") String name); @GET Observable<Response<List<Repository>>> repositoriesPaginate(@Url String url); }
  • 43. Retrofit + RxJava Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com") .addConverterFactory(JacksonConverterFactory.create(objectMapper)) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); return retrofit.create(GithubAPI.class);
  • 44. Retrofit + RxJava // concatenating multiple results into a single Observable public Observable<Repository> repositories(String organization) { requireNonNull(organization, "Argument 'organization' must not be blank"); return paginatedObservable( () -> { LOG.info("Querying /orgs/{}/repos", organization); return api.repositories(organization); }, (Links links) -> { String next = links.next(); LOG.info("Querying {}", next); return api.repositoriesPaginate(next); }); }
  • 45. Retrofit + RxJava // concatenating multiple results into a single Observable private static <T> Observable<T> paginatedObservable(FirstPageSupplier<T> firstPage, NextPageSupplier<T> nextPage) { return processPage(nextPage, firstPage.get()); } private static <T> Observable<T> processPage(NextPageSupplier<T> supplier, Observable<Response<List<T>>> items) { return items.flatMap(response -> { Links links = Links.of(response.headers().get("Link")); Observable<T> currentPage = Observable.from(response.body()); if (links.hasNext()) { return currentPage.concatWith(processPage(supplier, supplier.get(links))); } return currentPage; }); }
  • 46. RxJava - http://reactivex.io • Implements the Observable pattern. • Delivers dozens of operations out of the box, e.g. zip, reduce, concat. • Supports backpressure, i.e, when the data producer is faster than the data consumer.
  • 47. COMPONENT COMMUNICATION How do you keep two unrelated components communicated with one another? How do you push data down the stream without forcing publishers to wait for consumers?
  • 48. MBassador - https://github.com/bennidi/mbassador // event publishing @Inject private ApplicationEventBus eventBus; model.setSubscription(observable .timeout(10, TimeUnit.SECONDS) .doOnSubscribe(() -> model.setState(RUNNING)) .doOnTerminate(() -> model.setState(READY)) .doOnError(throwable -> eventBus.publishAsync(new ThrowableEvent(throwable))) .subscribeOn(Schedulers.io()) .subscribe(model.getRepositories()::add));
  • 49. MBassador - https://github.com/bennidi/mbassador // event consuming import net.engio.mbassy.listener.Handler; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.inject.Inject; public class ApplicationEventHandler { @Inject private ApplicationEventBus eventBus; @PostConstruct private void init() { eventBus.subscribe(this); } @PreDestroy private void destroy() { eventBus.unsubscribe(this); } @Handler public void handleThrowable(ThrowableEvent event) { // handle event here !! } }
  • 50. MBassador - https://github.com/bennidi/mbassador • Configurable event bus based on annotations. • Faster implementation than Guava’s event bus. • https://github.com/bennidi/eventbus-performance • NOTE: project is no longer actively maintained, fixes and features will be slow to come.
  • 52. JUnitParams - https://github.com/Pragmatists/JUnitParams @RunWith(JUnitParamsRunner.class) public class SampleServiceTest { @Test @Parameters({",Howdy stranger!", "Test, Hello Test"}) public void sayHello(String input, String output) { // given: SampleService service = new SampleService(); // expect: assertThat(service.sayHello(input), equalTo(output)); } }
  • 53. JUnitParams - https://github.com/Pragmatists/JUnitParams • Parameterize multiple methods with different argument cardinality. • Different data provider strategies.
  • 54. Mockito - http://mockito.org @Test @Parameters({",Howdy stranger!", "Test, Hello Test"}) public void sayHelloAction(String input, String output) { // given: SampleController controller = new SampleController(); controller.setModel(new SampleModel()); controller.setService(mock(SampleService.class)); // expectations when(controller.getService().sayHello(input)).thenReturn(output); // when: controller.getModel().setInput(input); controller.sayHello(); // then: assertThat(controller.getModel().getOutput(), equalTo(output)); verify(controller.getService(), only()).sayHello(input); }
  • 55. Mockito - http://mockito.org • Fluid DSL based on static methods. • Provides support for Stubs, Mocks, and Spies. • Mock interfaces, abstract classes, and concrete classes.
  • 56. Jukito - https://github.com/ArcBees/Jukito @RunWith(JukitoRunner.class) public class SampleControllerJukitoTest { @Inject private SampleController controller; @Before public void setupMocks(SampleService sampleService) { when(sampleService.sayHello("Test")).thenReturn("Hello Test"); } @Test public void sayHelloAction() { controller.setModel(new SampleModel()); controller.getModel().setInput("Test"); controller.sayHello(); assertThat(controller.getModel().getOutput(), equalTo("Hello Test")); verify(controller.getService(), only()).sayHello("Test"); } }
  • 57. Jukito - https://github.com/ArcBees/Jukito • Combines JUnit, Guice, and Mockito • Bind multiple values to the same source type. • Can be used to parameterize test methods.
  • 58. Spock- http://spockframework.org @spock.lang.Unroll class SampleControllerSpec extends spock.lang.Specification { def "Invoke say hello with #input results in #output"() { given: SampleController controller = new SampleController() controller.model = new SampleModel() controller.service = Mock(SampleService) { sayHello(input) >> output } when: controller.model.input = input controller.sayHello() then: controller.model.output == output where: input << ['', 'Test'] output << ['Howdy, stranger!', 'Hello Test'] } }
  • 59. Spock- http://spockframework.org • Groovy based DSL. • Parameterize multiple methods with different argument cardinality. • Parameterize test method names. • JUnit friendly (can use extensions and rules).
  • 60. Awaitility - https://github.com/awaitility/awaitility @Test public void happyPath(Github github) { // given: Collection<Repository> repositories = createSampleRepositories(); when(github.repositories(ORGANIZATION)) .thenReturn(Observable.from(repositories)); // when: model.setOrganization(ORGANIZATION); controller.load(); await().timeout(2, SECONDS).until(model::getState, equalTo(State.READY)); // then: assertThat(model.getRepositories(), hasSize(10)); assertThat(model.getRepositories(), equalTo(repositories)); verify(github, only()).repositories(ORGANIZATION); }
  • 61. Awaitility - https://github.com/awaitility/awaitility • DSL for testing multi-threaded code. • Extensions available for Java8, Groovy, and Scala. • Conditions can be customized with Hamcrest matchers.
  • 62. WireMock- http://wiremock.org/ import static com.github.tomakehurst.wiremock.client.WireMock.*; String nextUrl = "/organizations/1/repos?page=2"; List<Repository> repositories = createSampleRepositories(); stubFor(get(urlEqualTo("/orgs/" + ORGANIZATION + "/repos")) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "text/json") .withHeader("Link", "<http://localhost:8080" + nextUrl + ">; rel="next"") .withBody(repositoriesAsJSON(repositories.subList(0, 5), objectMapper)))); stubFor(get(urlEqualTo(nextUrl )) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "text/json") .withBody(repositoriesAsJSON(repositories.subList(5, 10), objectMapper))));
  • 63. WireMock- http://wiremock.org/ • Supply custom HTTP response payloads. • DSL for matching HTTP requests. • Supports record and playback.
  • 64.

Editor's Notes

  1. LICENSE