SlideShare a Scribd company logo
JAVA LIBRARIES
YOU CAN’T
AFFORD TO MISS
ANDRES ALMIRAY
@AALMIRAY
ANDRESALMIRAY.COM
@aalmiray
USE CASE
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.
@aalmiray
THE LIBRARIES
PRODUCTION
Guice | Spring
OkHttp
Retrofit
JDeferred
RxJava | Reactor
MBassador
Lombok
Slf4j | Log4j2
TEST
JUnitParams
Mockito
Jukito
Awaitility
Spock
WireMock
@aalmiray
DISCLAIMER
@aalmiray
@aalmiray
@aalmiray
@aalmiray
USE CASE
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.
@aalmiray
GITHUB API
Well documented REST API
Latest version located at
https://developer.github.com/v3/
We’re interested in the repositories
operation for now
@aalmiray
QUERYING REPOSITORIES
API described at
https://developer.github.com/v3/repos/#list-
organization-repositories
Given a query of the form
GET /orgs/${organization}/repos
@aalmiray
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 */
]
@aalmiray
WHAT WE’LL NEED
Dependency Injection
HTTP client & REST behavior
JSON mapping
Boilerplate buster
Handle concurrency
@aalmiray
GET THE CODE
https://github.com/aalmiray/javatrove/
@aalmiray
DEPENDENCY
INJECTION
@aalmiray
public interface Github {
Promise<Collection<Repository>> repositories(String name);
}
@aalmiray
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));
}
}
@aalmiray
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 …
}
});
@aalmiray
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.
@aalmiray
BONUS
@aalmiray
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+)
@aalmiray
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
@aalmiray
REDUCING
BOILERPLATE
CODE
@aalmiray
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
@aalmiray
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;
}
}
@aalmiray
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;
}
@aalmiray
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!
@aalmiray
BEHAVIOR
@aalmiray
SLF4J - http://www.slf4j.org
• Wraps all other logging frameworks:
• java.util.logging
• Apache Commons Logging
• Apache Log4j
• Provides varargs methods
@aalmiray
HTTP
How many options are out there to build an
HTTP client?
How many ways are there to build a REST
client?
@aalmiray
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();
}
@aalmiray
OkHttp - http://square.github.io/okhttp
• Basic HTTP/HTTP2 Client API.
• Configuration is extensible via factory classes.
• HTTP lifecycle can be decorated via interceptors.
@aalmiray
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.
@aalmiray
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);
}
@aalmiray
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");
@aalmiray
Retrofit - http://square.github.io/retrofit
• Wraps REST calls with Java interfaces.
• Extensible via factories.
• Relies on OkHttp.
@aalmiray
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.
@aalmiray
JDeferred - http://jdeferred.org
public interface Github {
Promise<Collection<Repository>, Throwable, Void> repositories(String name);
}
@aalmiray
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());
});
}
}
@aalmiray
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));
@aalmiray
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.
@aalmiray
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
@aalmiray
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);
@aalmiray
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);
}
@aalmiray
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);
@aalmiray
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);
});
}
@aalmiray
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;
});
}
@aalmiray
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.
@aalmiray
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?
@aalmiray
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));
@aalmiray
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 !!
}
}
@aalmiray
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.
@aalmiray
TESTING
@aalmiray
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));
}
}
@aalmiray
JUnitParams -
https://github.com/Pragmatists/JUnitParams
• Parameterize multiple methods with different argument
cardinality.
• Different data provider strategies.
@aalmiray
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);
}
@aalmiray
Mockito - http://mockito.org
• Fluid DSL based on static methods.
• Provides support for Stubs, Mocks, and Spies.
• Mock interfaces, abstract classes, and concrete classes.
@aalmiray
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");
}
}
@aalmiray
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.
@aalmiray
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']
}
}
@aalmiray
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).
@aalmiray
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);
}
@aalmiray
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.
@aalmiray
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))));
@aalmiray
WireMock- http://wiremock.org/
• Supply custom HTTP response payloads.
• DSL for matching HTTP requests.
• Supports record and playback.
@aalmiray
@aalmiray
HTTP://ANDRESALMIRAY.COM/NEWSLETTER
HTTP://ANDRESALMIRAY.COM/EDITORIAL
THANK YOU!
ANDRES ALMIRAY
@AALMIRAY
ANDRESALMIRAY.COM

More Related Content

What's hot

Retrofit
RetrofitRetrofit
Retrofit
bresiu
 
Rxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJavaRxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJava
Kros Huang
 
Going native with less coupling: Dependency Injection in C++
Going native with less coupling: Dependency Injection in C++Going native with less coupling: Dependency Injection in C++
Going native with less coupling: Dependency Injection in C++
Daniele Pallastrelli
 
Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018
Loiane Groner
 
Introduction to Retrofit and RxJava
Introduction to Retrofit and RxJavaIntroduction to Retrofit and RxJava
Introduction to Retrofit and RxJava
Fabio Collini
 
Containers & Dependency in Ember.js
Containers & Dependency in Ember.jsContainers & Dependency in Ember.js
Containers & Dependency in Ember.js
Matthew Beale
 
Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹
Kros Huang
 
Reactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-JavaReactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-Java
Kasun Indrasiri
 
Spring AOP
Spring AOPSpring AOP
Spring AOP
Lhouceine OUHAMZA
 
Full-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConf
Full-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConfFull-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConf
Full-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConf
Loiane Groner
 
Dev Day 2019: Mike Sperber – Software Design für die Seele
Dev Day 2019: Mike Sperber – Software Design für die SeeleDev Day 2019: Mike Sperber – Software Design für die Seele
Dev Day 2019: Mike Sperber – Software Design für die Seele
DevDay Dresden
 
Real world functional reactive programming
Real world functional reactive programmingReal world functional reactive programming
Real world functional reactive programming
Eric Polerecky
 
Reactive Java (33rd Degree)
Reactive Java (33rd Degree)Reactive Java (33rd Degree)
Reactive Java (33rd Degree)
Tomasz Kowalczewski
 
Dependency Injection with CDI in 15 minutes
Dependency Injection with CDI in 15 minutesDependency Injection with CDI in 15 minutes
Dependency Injection with CDI in 15 minutes
Antonio Goncalves
 
Gerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRxGerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRx
Loiane Groner
 
Completable future
Completable futureCompletable future
Completable future
Srinivasan Raghvan
 
React table tutorial use filter (part 2)
React table tutorial use filter (part 2)React table tutorial use filter (part 2)
React table tutorial use filter (part 2)
Katy Slemon
 
The Future of Futures - A Talk About Java 8 CompletableFutures
The Future of Futures - A Talk About Java 8 CompletableFuturesThe Future of Futures - A Talk About Java 8 CompletableFutures
The Future of Futures - A Talk About Java 8 CompletableFutures
Haim Yadid
 
CDI: How do I ?
CDI: How do I ?CDI: How do I ?
CDI: How do I ?
Antonio Goncalves
 

What's hot (20)

Retrofit
RetrofitRetrofit
Retrofit
 
Rxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJavaRxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJava
 
Going native with less coupling: Dependency Injection in C++
Going native with less coupling: Dependency Injection in C++Going native with less coupling: Dependency Injection in C++
Going native with less coupling: Dependency Injection in C++
 
Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018
 
Introduction to Retrofit and RxJava
Introduction to Retrofit and RxJavaIntroduction to Retrofit and RxJava
Introduction to Retrofit and RxJava
 
Containers & Dependency in Ember.js
Containers & Dependency in Ember.jsContainers & Dependency in Ember.js
Containers & Dependency in Ember.js
 
Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹
 
Reactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-JavaReactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-Java
 
Spring AOP
Spring AOPSpring AOP
Spring AOP
 
Jasmine BDD for Javascript
Jasmine BDD for JavascriptJasmine BDD for Javascript
Jasmine BDD for Javascript
 
Full-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConf
Full-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConfFull-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConf
Full-Stack Reativo com Spring WebFlux + Angular - FiqueEmCasaConf
 
Dev Day 2019: Mike Sperber – Software Design für die Seele
Dev Day 2019: Mike Sperber – Software Design für die SeeleDev Day 2019: Mike Sperber – Software Design für die Seele
Dev Day 2019: Mike Sperber – Software Design für die Seele
 
Real world functional reactive programming
Real world functional reactive programmingReal world functional reactive programming
Real world functional reactive programming
 
Reactive Java (33rd Degree)
Reactive Java (33rd Degree)Reactive Java (33rd Degree)
Reactive Java (33rd Degree)
 
Dependency Injection with CDI in 15 minutes
Dependency Injection with CDI in 15 minutesDependency Injection with CDI in 15 minutes
Dependency Injection with CDI in 15 minutes
 
Gerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRxGerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRx
 
Completable future
Completable futureCompletable future
Completable future
 
React table tutorial use filter (part 2)
React table tutorial use filter (part 2)React table tutorial use filter (part 2)
React table tutorial use filter (part 2)
 
The Future of Futures - A Talk About Java 8 CompletableFutures
The Future of Futures - A Talk About Java 8 CompletableFuturesThe Future of Futures - A Talk About Java 8 CompletableFutures
The Future of Futures - A Talk About Java 8 CompletableFutures
 
CDI: How do I ?
CDI: How do I ?CDI: How do I ?
CDI: How do I ?
 

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
 
Java 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 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
 
Annotation Processing - Demystifying Java's Dark Arts
Annotation Processing - Demystifying Java's Dark ArtsAnnotation Processing - Demystifying Java's Dark Arts
Annotation Processing - Demystifying Java's Dark Arts
James Kirkbride
 
Understanding Reactive Programming
Understanding Reactive ProgrammingUnderstanding Reactive Programming
Understanding Reactive Programming
Andres Almiray
 
Building maintainable javascript applications
Building maintainable javascript applicationsBuilding maintainable javascript applications
Building maintainable javascript applications
equisodie
 
Google Cloud Endpoints: Building Third-Party APIs on Google AppEngine
Google Cloud Endpoints: Building Third-Party APIs on Google AppEngineGoogle Cloud Endpoints: Building Third-Party APIs on Google AppEngine
Google Cloud Endpoints: Building Third-Party APIs on Google AppEngine
Roman Kirillov
 
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
 
"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
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
sickill
 
The new and smart way to build microservices - Eclipse MicroProfile
The new and smart way to build microservices - Eclipse MicroProfileThe new and smart way to build microservices - Eclipse MicroProfile
The new and smart way to build microservices - Eclipse MicroProfile
Emily Jiang
 
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
 
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
 
Maintaining a dependency graph with weaver
Maintaining a dependency graph with weaverMaintaining a dependency graph with weaver
Maintaining a dependency graph with weaver
Scribd
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to java
ciklum_ods
 
Mastering the Sling Rewriter by Justin Edelson
Mastering the Sling Rewriter by Justin EdelsonMastering the Sling Rewriter by Justin Edelson
Mastering the Sling Rewriter by Justin Edelson
AEM HUB
 
Mastering the Sling Rewriter
Mastering the Sling RewriterMastering the Sling Rewriter
Mastering the Sling Rewriter
Justin Edelson
 
Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.
scalaconfjp
 

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
 
Java 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 Miss
 
Arquitecturas de microservicios - Medianet Software
Arquitecturas de microservicios   -  Medianet SoftwareArquitecturas de microservicios   -  Medianet Software
Arquitecturas de microservicios - Medianet Software
 
Annotation Processing - Demystifying Java's Dark Arts
Annotation Processing - Demystifying Java's Dark ArtsAnnotation Processing - Demystifying Java's Dark Arts
Annotation Processing - Demystifying Java's Dark Arts
 
Understanding Reactive Programming
Understanding Reactive ProgrammingUnderstanding Reactive Programming
Understanding Reactive Programming
 
Building maintainable javascript applications
Building maintainable javascript applicationsBuilding maintainable javascript applications
Building maintainable javascript applications
 
Google Cloud Endpoints: Building Third-Party APIs on Google AppEngine
Google Cloud Endpoints: Building Third-Party APIs on Google AppEngineGoogle Cloud Endpoints: Building Third-Party APIs on Google AppEngine
Google Cloud Endpoints: Building Third-Party APIs on Google AppEngine
 
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...
 
"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
 
Designing Better API
Designing Better APIDesigning Better API
Designing Better API
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
 
The new and smart way to build microservices - Eclipse MicroProfile
The new and smart way to build microservices - Eclipse MicroProfileThe new and smart way to build microservices - Eclipse MicroProfile
The new and smart way to build microservices - Eclipse MicroProfile
 
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...
 
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
 
Maintaining a dependency graph with weaver
Maintaining a dependency graph with weaverMaintaining a dependency graph with weaver
Maintaining a dependency graph with weaver
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to java
 
Mastering the Sling Rewriter by Justin Edelson
Mastering the Sling Rewriter by Justin EdelsonMastering the Sling Rewriter by Justin Edelson
Mastering the Sling Rewriter by Justin Edelson
 
Mastering the Sling Rewriter
Mastering the Sling RewriterMastering the Sling Rewriter
Mastering the Sling Rewriter
 
Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.
 

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

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
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
SOFTTECHHUB
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
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
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
Sri Ambati
 
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
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
Adtran
 
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
 
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
 
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
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Aggregage
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Nexer Digital
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
Pierluigi Pugliese
 
Enhancing Performance with Globus and the Science DMZ
Enhancing Performance with Globus and the Science DMZEnhancing Performance with Globus and the Science DMZ
Enhancing Performance with Globus and the Science DMZ
Globus
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
UiPathCommunity
 
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
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
James Anderson
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
Alex Pruden
 

Recently uploaded (20)

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
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
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
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
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
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
 
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)
 
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
 
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
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
 
Enhancing Performance with Globus and the Science DMZ
Enhancing Performance with Globus and the Science DMZEnhancing Performance with Globus and the Science DMZ
Enhancing Performance with Globus and the Science DMZ
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
 
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
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
 

Java Libraries You Can't Afford to Miss

  • 1. JAVA LIBRARIES YOU CAN’T AFFORD TO MISS ANDRES ALMIRAY @AALMIRAY ANDRESALMIRAY.COM
  • 2. @aalmiray USE CASE 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.
  • 3. @aalmiray THE LIBRARIES PRODUCTION Guice | Spring OkHttp Retrofit JDeferred RxJava | Reactor MBassador Lombok Slf4j | Log4j2 TEST JUnitParams Mockito Jukito Awaitility Spock WireMock
  • 8. @aalmiray USE CASE 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.
  • 9. @aalmiray GITHUB API Well documented REST API Latest version located at https://developer.github.com/v3/ We’re interested in the repositories operation for now
  • 10. @aalmiray QUERYING REPOSITORIES API described at https://developer.github.com/v3/repos/#list- organization-repositories Given a query of the form GET /orgs/${organization}/repos
  • 11. @aalmiray 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 */ ]
  • 12. @aalmiray WHAT WE’LL NEED Dependency Injection HTTP client & REST behavior JSON mapping Boilerplate buster Handle concurrency
  • 15. @aalmiray public interface Github { Promise<Collection<Repository>> repositories(String name); }
  • 16. @aalmiray 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)); } }
  • 17. @aalmiray 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 … } });
  • 18. @aalmiray 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.
  • 20. @aalmiray 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+)
  • 21. @aalmiray 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
  • 23. @aalmiray 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
  • 24. @aalmiray 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; } }
  • 25. @aalmiray 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; }
  • 26. @aalmiray 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!
  • 28. @aalmiray SLF4J - http://www.slf4j.org • Wraps all other logging frameworks: • java.util.logging • Apache Commons Logging • Apache Log4j • Provides varargs methods
  • 29. @aalmiray HTTP How many options are out there to build an HTTP client? How many ways are there to build a REST client?
  • 30. @aalmiray 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(); }
  • 31. @aalmiray OkHttp - http://square.github.io/okhttp • Basic HTTP/HTTP2 Client API. • Configuration is extensible via factory classes. • HTTP lifecycle can be decorated via interceptors.
  • 32. @aalmiray 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.
  • 33. @aalmiray 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); }
  • 34. @aalmiray 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");
  • 35. @aalmiray Retrofit - http://square.github.io/retrofit • Wraps REST calls with Java interfaces. • Extensible via factories. • Relies on OkHttp.
  • 36. @aalmiray 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.
  • 37. @aalmiray JDeferred - http://jdeferred.org public interface Github { Promise<Collection<Repository>, Throwable, Void> repositories(String name); }
  • 38. @aalmiray 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()); }); } }
  • 39. @aalmiray 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));
  • 40. @aalmiray 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.
  • 41. @aalmiray 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
  • 42. @aalmiray 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);
  • 43. @aalmiray 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); }
  • 44. @aalmiray 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);
  • 45. @aalmiray 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); }); }
  • 46. @aalmiray 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; }); }
  • 47. @aalmiray 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.
  • 48. @aalmiray 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?
  • 49. @aalmiray 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));
  • 50. @aalmiray 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 !! } }
  • 51. @aalmiray 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.
  • 53. @aalmiray 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)); } }
  • 54. @aalmiray JUnitParams - https://github.com/Pragmatists/JUnitParams • Parameterize multiple methods with different argument cardinality. • Different data provider strategies.
  • 55. @aalmiray 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); }
  • 56. @aalmiray Mockito - http://mockito.org • Fluid DSL based on static methods. • Provides support for Stubs, Mocks, and Spies. • Mock interfaces, abstract classes, and concrete classes.
  • 57. @aalmiray 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"); } }
  • 58. @aalmiray 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.
  • 59. @aalmiray 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'] } }
  • 60. @aalmiray 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).
  • 61. @aalmiray 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); }
  • 62. @aalmiray 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.
  • 63. @aalmiray 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))));
  • 64. @aalmiray WireMock- http://wiremock.org/ • Supply custom HTTP response payloads. • DSL for matching HTTP requests. • Supports record and playback.

Editor's Notes

  1. LICENSE