Project Reactor (Part 3 of 3)

20 October 2020

So far…​

In the previous post we introduced Reactor testing and backpressure.

To summarize:

  1. Part 1: Getting started with Reactor

  2. Part 2: Flux, Mono, zipping, Tuples, and retry

  3. Part 3: WebFlux and WebClient with a dip into JHipster

Prerequisites

For this post you should have a good understanding of Java and Spring Boot and have read the previous posts about Reactor.

JHipster

JHipster is a code generation tool primarily for building Spring-Boot based projects with either a React or Angular front end - although it can be extended via blueprints and there are several that allow you to create a Vue.js front end or Micronaut back-end for two examples.

It also has a feature allowing you to create a Spring Boot WebFlux project.

WebFlux is Spring’s framework for asynchronous, non-blocking web applications - and it works with Reactive types, especially project Reactor (Flux, Mono, etc.).

To get started, install Node (>10.20.1) and JHipster (latest)

  • Then, from the terminal, make a new directory (named "hip-webflux"), and run jhipster

  • Follow the prompts, and choose monolith and then Reactive (this will create a Spring Boot WebFlux project)

  • For database, you can pick MongoDB, or Cassandra (the reactive generator doesn’t support SQL at the moment)

  • For front end, you can pick React or Angular

  • Pick Maven or Gradle

…​This takes a while since it has to load a bunch of dependencies…​

Then you should see output like the following:

Server application generated successfully.

Run your Spring Boot application:
./mvnw

Client application generated successfully.

Start your Webpack development server with:
 npm start


> hip@0.0.1-SNAPSHOT cleanup /home/adavis/github/adamldavis/hip-webflux
> rimraf target/classes/static/

INFO! Congratulations, JHipster execution is complete!

JDL

After creating the basic project, let’s add some entities.

One of the cool things about JHipster is JDL (Jhipster Domain Language). Its a DSL for creating projects and entities. Create a file named "hip.jdl" and put in the following:

entity Person {
  name String required
  age Integer min(0) max(142)
}

(Feel free to mess around with your JDL and make it more complicated, but for this example, let’s keep it simple)

Import the JDL by running jhipster import-jdl hip.jdl

Now open the project with your favorite IDE (like IntelliJ IDEA for example) and take a look at the PersonController.

JHipster automatically creates an AuditEvent database for auditing (create, update, delete record events). Open up the file named "AuditResource" under the "com.mycompany.myapp.web.rest" package (Under src/main/java/). It should have a "getAll" method that looks something like this:

@GetMapping
public Mono<ResponseEntity<Flux<AuditEvent>>> getAll(ServerHttpRequest request, Pageable pageable) {
    return auditEventService.count()
        .map(total -> new PageImpl<>(new ArrayList<>(), pageable, total))
        .map(page -> PaginationUtil.generatePaginationHttpHeaders(UriComponentsBuilder.fromHttpRequest(request), page))
        .map(headers -> ResponseEntity.ok().headers(headers).body(auditEventService.findAll(pageable)));
}

WebFlux allows you to return Reactor types like Mono and Flux from controller methods and implements a reactive, asynchronous web server using Netty by default.

A typical web server uses a large number of Threads and handles each request in one thread. The problem with this is that Threads in Java are kind of heavy weight in Java (this should be fixed by project Loom and virtual threads in Java 15+). This allows a single Thread to block without holding back the entire application, however if you have a lot of blocking threads, it can starve your application of available Threads.

Netty instead uses an EventLoop per Thread for I/O. WebFlux enables and simplifies the Java API using Reactive Streams (of which Reactor is one implementation).

No Blocking!

Since the threads in WebFlux are meant to be non-blocking, you must be careful not to block them. For example, don’t call block() or Thread.sleep. There’s a project called BlockHound to help enforce this rule throughout your application. (This doesn’t mean no threads can block; only blocking should happen in dedicated threads)

To implement this, your application should be reactive "all the way down". So if you have a database, reading from it should also be reactive and non-blocking. Projects like r2dbc and Spring spring-data-r2dbc help, among others.

WebClient

WebFlux also includes WebClient which is a reactive replacement for RestTemplate. It makes asynchronous, non-blocking HTTP requests.

You can create an instance of WebClient using the builder pattern starting from the static WebClient.builder() method. For example:

import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
// later on...
WebClient myWebClient = WebClient.builder()
 .baseUrl("http://localhost:8080/api-to-call/")
 .defaultCookie("cookieKey", "cookieValue")
 .defaultHeader(HttpHeaders.CONTENT_TYPE,
   MediaType.APPLICATION_JSON_VALUE)
 .build();

This builds a WebClient with given baseUrl. It also provides a cookie and header to use for every request. There are many more methods to configure the WebClient. Each request starts with defining the HTTP method, then you can specify an additional URL path (with or without path variables) and call exchange which returns a Mono<ClientResponse>. For example, to get a person from some /v1/persons REST api:

// get the Course with ID=1 and print it out:
myWebClient.get()
    .uri("/v1/persons/{id}", 1L)
    .exchange()
    .flatMap((ClientResponse response) ->
      response.bodyToMono(Person.class))
    .subscribe(person -> System.out.println("person = " + person));

The WebClient thus enables all of your HTTP calls to be reactive. The Spring team likes WebClient so much, they recommend everyone use it over RestTemplate.

Conclusion

I hope you got something from this three part series. Reactive programming in Java isn’t always necessary - it’s for enabling thousands of transactions a second, so you might not need it - but when any application becomes popular enough, you tend to need high throughput and performance.

Eventually when Java has virtual threads it will make threads more lightweight, however, Reactive will still be useful due to its backpressure handling, retry logic, and other benefits.

  1. Part 1: Getting started with Reactor

  2. Part 2: Flux, Mono, zipping, Tuples, and retry

  3. Part 3: WebFlux and WebClient

Project Reactor (Part 2)

29 July 2020

In the previous post we introduced Reactor and covered why reactor is important and some of the basics. We talked about Flux, Mono, zipping, Tuples, and retry. However, one of the most important aspects of reactive streams, is the ability to handle backpressure.

Backpressure is a mechanism for explicitly handling the problem of having too many items to process in real time. Without such a mechanism, you typically see the problem of services timing out and eventually the user sees either a very slow or unresponsive system. This is compounded by the fact that users will give up quickly if a system is slow to respond.

Many other techniques for handling concurrency do not have explicit mechanisms for handling backpressure. Instead, system engineers and architects must hope to scale the system either horizontally (more) servers, or vertically (a faster CPU/more cores/more memory).

Handling Backpressure in Reactor

Reactor, like all implementations of Reactive Streams, has the ability to handle backpressure. Use one of the following methods on a Flux (or others not listed) to specify which backpressure strategy you want to use:

  • onBackpressureBuffer(): Buffers all items until they can be handled downstream.

  • onBackpressureBuffer(maxSize): Buffers items up to the given count.

  • onBackpressureBuffer(maxSize, BufferOverflowStrategy): Buffers items up to the given count and allows you to specify the BufferOverflowStrategy, such as onBackpressureBuffer(100, BufferOverflowStrategy.DROP_OLDEST)

  • onBackpressureLatest(): Similar to keeping a buffer of only the last item added. If the downstream does not keep up with upstream, only the latest element will be given downstream.

  • onBackpressureError(): Ends the Flux with an error (calling the downstream Subscriber’s onError) with an IllegalStateException from Exceptions.failWithOverflow() if more items were produced upstream than requested downstream.

  • onBackpressureDrop(): Drops any items produced above what was requested.

  • onBackpressureDrop(Consumer): Drops any items produced above what was requested and calls the given Consumer for each dropped item.

With each of these methods, the strategy only applies when the stream produces items faster than they can be handled. If that’s not the case, for example with a cold stream, no backpressure strategy is necessary.

Also, keep in mind that Reactor is not magic and some care should be taken when considering backpressure strategies. For example, if each item in the stream is critical, do not use onBackpressureDrop(). If you use onBackpressureError(), you will cause an Exception to be thrown when there are too many items, so use this with extreme caution.

If you use any backpressure strategy, you should consider writing a test to validate that your whole system will work as expected. One way you could do this is to simulate a very slow downstream by using Thread.sleep(1000) for example.

Luckily, Project Reactor supplies us with some great testing features.

Testing

Automated testing is always a good idea, and it would be nice to have tools to directly test Reactive Streams. Luckily, Reactor comes with a few elements dedicated to testing which are gathered into their own artifact we already included: reactor-test. The two main uses of reactor-test are the following:

  • Testing a sequence follows a given scenario with StepVerifier.

  • Producing data to test the behavior of operators (including you own operators) downstream with TestPublisher.

StepVerifier

Reactor’s StepVerifier can be used to verify the behavior of a Reactor Publisher (Flux or Mono).

Here’s a simple example of a Junit test utilizing StepVerifier:

@Test
public void testStepVerifier_Mono_error() {
  Mono<String> monoError = Mono.error(new RuntimeException("error")); //1
  StepVerifier.create(monoError) //2
    .expectErrorMessage("error") //3
    .verify(); //4
}
  1. Create a Mono wrapping a RuntimeException imitating an actual error state.

  2. Create a StepVerifier wrapping that Mono.

  3. Declare that an onError event is expected and the Exception’s error message is “error”.

  4. We call verify() at the end. This will throw an AssertionError if any expectations are not met.

Next, we’ll create a Mono of just one string and verify it:

@Test public void testStepVerifier_Mono_foo() {
Mono<String> foo = Mono.just(“foo”); //1
StepVerifier.create(foo)             //2
.expectNext(“foo”)                 //3
.verifyComplete();                 //4
}
  1. Create a Mono wrapping one value, “foo”.

  2. Create a StepVerifier wrapping that Mono.

  3. Expect onNext is called with “foo”.

  4. Call verifyComplete() has the same effect as verify() but also expects onComplete was called.

Verifying Backpressure

Next we’ll test a Flux with four values and verify any additional values are dropped using backpressure handling.

@Test
public void testStepVerifier_Flux_backpressure() {
    Flux<Integer> source = Flux.<Integer>create(emitter -> { //1
        emitter.next(1);
        emitter.next(2);
        emitter.next(3);
        emitter.next(4);
        emitter.complete();
    }).onBackpressureDrop();                            //2

    StepVerifier.withVirtualTime(() -> source, 3)      //3
            .expectNext(1)
            .expectNext(2)
            .expectNext(3)
            .expectComplete()                       //4
            .verifyThenAssertThat()
            .tookLessThan(Duration.ofMillis(50));   //5
}
  1. Create a Flux of just four numbers using an emitter (this is a "hot" flux meaning it is time sensitive).

  2. Using onBackpressureDrop to drop any items that aren’t handled fast enough.

  3. Create a StepVerifier with the Flux using withVirtualTime and requesting only 3 items. Then call expectNext for each value expected.

  4. Then call expectComplete thus verifying that the backpressure logic worked!

  5. Finally, we verify that the Flux is complete and the whole process took less than a 50 milliseconds.

The main point of using withVirtualTime here is to specify that we only request three elements. This emulates the real-world experience that would happen if a down-stream (Subscriber) could not keep up with the upstream (Publisher), since the down-stream is what causes items to be requested in Reactive Streams.

Although this example only uses 1,2,3,4 you can imagine the stream (Flux) could be composed of any objects.

Virtual time (with StepVerifier) can also be useful for testing things like the Flux.interval.

TestPublisher

The TestPublisher<T> class offers the ability to provide finely tuned data for test purposes. TestPublisher<T> is a reactive-streams Publisher<T> but can be converted to either a Flux or Mono.

TextPublisher has the following methods:

  • next(T) and next(T, T…​) : Triggers 1-n onNext signals.

  • emit(T…​) : Does the same as next and terminates with an onComplete signal.

  • complete() : Terminates with an onComplete signal.

  • error(Throwable) : Terminates with an onError signal.

The following demonstrates how you might use TestPublisher<T>:

TestPublisher<Object> publisher = TestPublisher.create(); //1
Flux<Object> stringFlux = publisher.flux();               //2
List list = new ArrayList();                              //3
stringFlux.subscribe(next -> list.add(next),
                     ex -> ex.printStackTrace());         //4
publisher.emit("foo", "bar");                             //5
assertEquals(2, list.size());                             //6
assertEquals("foo", list.get(0));
assertEquals("bar", list.get(1));
  1. Create the TestPublisher instance.

  2. Convert it to a Flux.

  3. Create a new List. For test purposes we will use this list to collect values from the publisher.

  4. Subscribe to the publisher using two lambda expressions for onNext and onError. This will add each value emitted from the publisher to the list.

  5. Finally, emit the values “foo” and “bar” from the TestPublisher.

  6. Assert the list’s size is two as expected.

Note that you must subscribe to the TestPublisher (which is done by subscribing to the stringFlux in the above example) before emitting any values.

Coming Next…​

In this article I’ve shown how Reactor can be used to handle backpressure and how to test it. In my next article, we’ll look into how Reactor integrates with the whole Spring ecosystem - especially with WebFlux and WebClient.

Project Reactor (Part 1)

07 July 2020

What is Reactor?

The purpose of Reactor, and reactive steams in general is to enable operations on large amounts of data to be broken down and executed on many different threads (multi-threading) in the most efficient, scalable, and fast way possible. Although parallel processing can be achieved simply using Java 8’s parallel stream, reactive streams add a plethora of additional functionality and customization such as error handling, retry, caching and replaying streams, handling backpressure, and more.

You can think of a reactive stream as having three rails, the data rail, the completion rail (whether or not the stream has completed), and the error rail. Also, each of the rails can be converted into the other: complete streams could be replaced, an operation could throw an Exception, or an Exception could be handled and replaced with more data.

In addition, Reactor adds the concept of Context, which we will explore later on.

Getting Started

If you have a Maven build, add the following to your pom file:

<dependency>
  <groupId>io.projectreactor</groupId>
  <artifactId>reactor-core</artifactId>
  <version>3.3.5.RELEASE</version>
</dependency>
<dependency>
  <groupId>io.projectreactor</groupId>
  <artifactId>reactor-test</artifactId>
  <version>3.3.5.RELEASE</version>
  <scope>test</scope>
</dependency>

For Gradle builds, add the following to your Gradle build file’s dependencies:

implementation 'io.projectreactor:reactor-core:3.3.5.RELEASE'
testImplementation 'io.projectreactor:reactor-test:3.3.5.RELEASE'

Creating a Flux or Mono

You can create a Flux from fixed data (cold) or programmatically from dynamic data (hot).

The following are some different way to create a cold Flux:

Flux<String> flux1 = Flux.just("a", "b", "foobar"); //1

List<String> iterable = Arrays.asList("a", "b", "foobar");

Flux<String> flux2 = Flux.fromIterable(iterable); //2

Flux<Integer> numbers = Flux.range(1, 64); //3
  1. Create a Flux from a list of values.

  2. Create a Flux from an iterable.

  3. Create a range from 1 to 64.

You can create a simple Mono that is empty or has just one element like the following:

Mono<String> noData = Mono.empty(); //1

Mono<String> data = Mono.just("foo"); //2

Mono<String> monoError = Mono.error(new RuntimeException("error")); //3
  1. Create an empty Mono.

  2. Create a Mono with one element.

  3. Create a Mono wrapping a RuntimeException.

You can also programmatically create a (hot) Flux using one of the generate, create, or push methods.

Tuples and Zip

Tuples are strongly typed collections of two or more elements and Reactor comes with them built in. Some operations such as zipWith, return reactive streams of Tuples.

Flux has an instance method zipWith(Publisher<? extends T2> source2) which has a return type of Flux<Tuple2<T,T2>>. It waits for both Fluxes (the initial flux and source2) to emit an element and then combines the two into a Tuple. There’s also static method Flux.zip which is overloaded to take from two to eight Publishers and zip them together.

Zipping is useful when you want to perform multiple operations that return reactive results (Flux or Mono).

Mono has two main flavors of zipping (which both have a return type of Mono<Tuple2<T,T2>>):

  • zipWith(Mono<? extends T2> other) – Zips the current stream with another stream, giving the combination of each corresponding element in the form of Tuple2.

  • zipWhen(Function<T,Mono<? extends T2>> rightGenerator) – Zips the current Mono with another Mono, giving the combination of each corresponding element in the form of Tuple2, but only after the first stream’s operation has completed.

For example, given you have two methods which perform asynchronous operations Mono<Course> getCourse(Long id) and Mono<Integer> getStudentCount(Course course), imagine you want to get the student count from the course Id you could do the following:

Mono<Integer> getStudentCount(Long id) {
return getCourse(id)
.zipWhen(course -> getStudentCount(course))
.map(tuple2 -> tuple2.getT2());
}

This is a simple example but you can imagine combining two different entities, or performing logic on them before returning, or calling another method which takes two arguments, and so on.

Reactor Addons

Project Reactor provides additional functionality under the io.projectreactor.addons groupId. Reactor extra includes additional math functions, different ways to retry including Jitter and Backoff, and TupleUtils.

<dependency>
  <groupId>io.projectreactor.addons</groupId>
  <artifactId>reactor-extra</artifactId>
  <version>3.3.3.RELEASE</version>
</dependency>

For Gradle builds, add the following to your Gradle build file’s dependencies:

implementation 'io.projectreactor.addons:reactor-extra:3.3.3.RELEASE'

When your application fails at an integration point, such as when calling another RESTful service, to make your overall system reliable you might want to retry the call some number of times. However, to keep from overloading the failing service, you should employ Backoff, or increasing the time between each retry, and Jitter, randomly modifying the time so that the retries from many different instances do not happen at the same time (correlate). For example take a look at the following code:

var retry = Retry.anyOf(IOException.class) \\1
 .exponentialBackoff(Duration.ofMillis(100), \\2
    Duration.ofSeconds(60))
 .jitter(Jitter.random()) \\3
 .retryMax(5)
 .withApplicationContext(appContext) \\4
 .doOnRetry(context ->
    context.applicationContext().rollback()); return flux.retryWhen(retry); \\5
  1. We create the Retry with exception value of IOException, meaning it will retry only when that exception is thrown.

  2. We define exponential backoff with a starting value of 100 ms and maximum value of 60 seconds.

  3. We add random Jitter and set the retry max to 5, meaning it retry at most 5 times.

  4. We add the Spring ApplicationContext and use it to apply rollback after each failure.

  5. Finally we call retryWhen(retry) on a Flux instance to apply the Retry to that Flux.

For more information on retries, backoff, and jitter see this excellent article from Amazon’s builder library.

Spring Handbook

01 March 2020

It’s been a while since I’ve posted. There’s been a lot going on (I’ve been very busy). I started a new position at a large corporation here near Orlando (a mouse-themed amusement park; more on this later).

Meanwhile, I’ve finally started work on "Spring Handbook".

Spring Handbook

I’ve been using Spring for a long, long time (since 2005). It’s been there throughout almost my entire Java development career and it’s evolved substantially over the years. I’ve had "Spring Handbook" on my check-list of books to write for a long time.

It’s going to be picked up by Apress, and is currently under development. (*Edit\* It’s published!) I’m really excited about this one - there is so much to cover and it’s so relevant to software development today especially with Java. I’m going to cover so many things:

  • Core Spring

  • Spring Data

  • Spring Security

  • Spring Boot

  • Webflux and Reactor

  • and tons more…​

GraphQL

In other news, I’ve learned a lot about GraphQL at my new job.

It’s combines a typed schema with the ability for clients to tell the server exactly what they want. This reduces the amount of unnecessary data requested, the number of HTTP requests needed, thereby increasing performance overall of a software system. Although I was suspect at first, it’s actually very clever. I’ve learned a lot about it and hope that I can share more about it later on.

Groovy 3 Course and Gradle

30 September 2019

As I’ve mentioned I’ve been working on courses on Leanpub. I’m happy to announce that the first one is complete!

It has changed a lot since my initial thought process. Among other things, it has a new subtitle, "Go from beginner to expert Groovy Programmer with Groovy 3.0 and Gradle 5". I decided that it needed more specifics than "just Groovy" and Gradle is a popular build tool and a good reason to start learning Groovy. Check it out: "Groovy 3 Course".

In case you’re curious, this course contains tons of new material and is not simply a copy of Learning Groovy 3 - far from it. It could be seen as a companion but covers more of some topics and less of others.

I’ve also decided to launch it with a very low introduction price. I want the barrier to entry to be very low. Please share it someone you think might benefit from it if not yourself. As always, all feedback is welcome (adamd @ this website). Let me know what you’d like to see more about or less about.

Due to other projects I’m working on, I’m going to postpone for now working on "Advanced Groovy" (I hope to cover not just advanced Groovy but also some other projects in greater detail). I have a lot going on (including yet another second edition book) but I hope to get to it eventually.

Learning Groovy 3 Released

05 August 2019

Learning Groovy 3

The second edition of "Learning Groovy" (which covers Groovy 3.0 thus the name) is now available. After months of researching, writing, and editing, it has finally gone to print! I’m really excited to announce this and I hope it spreads the love of Groovy far and wide.

Groovy can be used as a dynamic or static language depending on your choice, however it’s hard to condense that into a short subtitle. We also wanted to include how it is closely related to Java, hence the subtitle, "Java-Based Dynamic Scripting."

The twitter announcement is here. And the book itself can be found on Apress or my books page or wherever you prefer to purchase books.

Groovy 3 beta-3 should come out shortly, with release candidates soon after, so this is book is out slightly before the final 3.0 release. However, if you like to stay ahead of the curve, now is a good time.

Courses

I’m currently in the process of creating courses on Leanpub. Please check out these two courses: "Beginning Groovy 3" and "Advanced Groovy". There may be more in the future but they’re in the beginning stages right now. These courses will include exercises, quizes, and probably video to go along with the course. All feedback is welcome.

Gr8Conf EU 2019

28 June 2019

I had the great privilege of leading a workshop and two talks at Gr8Conf EU 2019 in Copenhagen, Denmark. This was also my first time attending Gr8Conf EU (I did attend Gr8Conf US 2017). My life has finally quieted down enough now that I can write about my experience.

The conference was, in a word, great. I saw a few familiar faces, like Paul King, Jeff Scott Brown, Michael Carducci, Sergio del Amo Caballero, and Jeff Beck (all of whom I’ve seen before, mostly as just another audience member), and met some great new people whom I’ve never seen before but who certainly left a lasting impression that I won’t soon forget like Vladimír Oraný, Szymon Stepniak, Jennifer Strater, Charlotte Mays, and others. For an extremely introverted person such as myself, I don’t often talk to so many people at one time, and I’m grateful for the opportunity to converse and openness of everyone at this conference. (The coffee and food was great too!)

There were too many great talks to list, but some highlights for me were Paul King’s keynote on Groovy 2.5, 3 and 4 (which is available online), Jesper Steen Møller’s talk, “Reactive Web APIs with Micronaut” (which brilliantly showed how to use Reactive Streams within a micronaut based microservice including a demo of how to use a backpressure strategy), and the “Running a developer’s blog” talk by Szymon Stepniak (I hope to use some of his suggestions in the future if I ever get the time).

Oh and I did some talks too. Eventually these should make it onto youtube, but it might be many months. For now you can check out my github repo ( https://github.com/adamldavis/2019-gr8conf ) which has all of the code related to my talks/workshop plus a bit more. I tweeted out the slides at some point but it’s up to you to find them. Just kidding. Here ( https://www.slideshare.net/adam1davis/ ).

It was a really great conference and Copenhagen is beautiful. I hope to return again next year (or maybe in two years if not next year).

Meanwhile, I’m finished with the final updates to “Learning Groovy 3” which should be released later this year! I worked on this for several months this year and my technical reviewer gave me some great feedback so it should be a good one. In addition to updating the book for Groovy 3.0 and Grails 3.3, I’ve also updated and polished additional areas of the book based on my personal understanding of Groovy and things that have changed over the years.

Micronaut

31 March 2019

micronaut

Micronaut was built by many of same people behind Grails. It uses compile-time annotation processing to build an application with a deadly fast startup time, has support for reactive streams, netty, and a reactive http client, among other things.

It’s open-source (Apache 2) and supports applications written in Java, Groovy, or Kotlin.

Due to it’s non-reflective nature, it naturally enables applications to run on the GraalVM, which is described:

`"GraalVM is a new universal virtual machine from Oracle that supports a
polyglot runtime environment and the ability to compile Java
applications down to native machine code."` –https://micronaut.io/

GraalVM compiles applications to native code allowing for incredibly fast application start-up speeds even for large applications, which makes it best suited for “serverless” applications, like AWS Lambdas or the like.

Even running on a vanilla JVM, Micronaut has very low overhead (in both memory and processor time) and has profiles for targeting different platforms: server, function (like AWS Lambda), or command-line applications.

It came out not too long ago and I’ve only made a few applications with it but so far it looks really great!

I’ve added an example of using micronaut with groocss and the asset-pipeline. Check it out.

Groovy 2.5 & 3

13 February 2019

If you have followed me for any time, you know I’m a big fan of Groovy, the super-Java-like language that runs on the JVM. You’ve probably heard of it, maybe you even use it, but what is less known is that it’s constantly evolving and has some great new features coming soon (or already here).

Inspired by some recent news, here’s all about Groovy 2.5 and 3.

Updates in Groovy 2.5

Groovy 2.5 added support for JDK9+, added 11 new AST transformations, and added the macro feature which makes writing AST transformations much easier.

The annotations added in Groovy 2.5 include: @AutoFinal, @AutoImplement, @ImmutableBase, @ImmutableOptions, @MapConstructor, @NamedDelegate, @NamedParam, @NamedParams, @NamedVariant, @PropertyOptions, and @VisibilityOptions.

  • @AutoImplement: Automatically implements missing abstract methods (such as those from an Interface). You can specify an Exception to throw from those methods such as UnsupportedOperationException. It can be useful for generating test stubs or when you only need to implement a subset of inherited abstract methods.

  • @AutoFinal: Automatically adds final modifier to method parameters.

  • @MapConstructor: Adds a constructor to your class that has one Map parameter and expects field-names as keys and sets the corresponding field values.

Also many annotations were improved with additional attributes. For example, @TupleConstructor now includes seven more attributes. The @Immutable annotation was updated to recognize the Date/time classes added in Java 8 are immutable, and to handle Optional.

Updates in Groovy 3

Groovy 3 sports a completely rewritten parser that brings Groovy up to parity with the latest Java 11 syntax along with new Groovy-only features. It runs on JDK 8 minimum and has better support for JDK 9/10/11.

The Java-like syntax now includes Java-style lambda expressions and method references, array initialization, and do/while loops, which have eluded Groovy for many years.

Edit: There is hope that in the near future after working out some issues. The new parser also compiles to “indy” by default which uses Java’s invokedynamic feature. This has been available for years, but was not the default before. This, along with other changes, makes Groovy code more performant.

New Operators

Identity: === can now be used to express identity-equal and !== and not identity-equal. Since Groovy interprets == as “.equals”, it used “.is” for identity-equals in the past. The support of “===” should avoid some confusion. This is similar to JavaScript’s === operator.

Negative variants of operators: !instanceof and !in are now supported. This will simplify the syntax in these situations. Before you would have to type !(x instanceof Date) whereas now you can simply type x !instanceof Date.

Elvis Assignment: You may be familiar with the elvis operator (?:) in Groovy. In many cases you would use this operation to provide a default when assigning a value. For example: name = name ?: ‘None’. Now you can shorten this expression to have the same meaning in Groovy 3 with the following: name ?= 'None’

Safe indexing: Much like the safe-reference operator, there is now a safe-indexing operator, ?. This allows you to access an index of an array (or List), but if the array is null, it will return null instead of throwing an exception. For example the following would set the value to the first value of the array, or null if the array is null: value = array?[0]

Java Parity

Groovy 3 support new features added from Java 8 to 11, such as lambda expressions, method references, constructor references, and even local variables (var).

All flavours of lambda expressions are supported (and currently compiled to Closures):

  • No parameters: () → expression

  • Single paramter: x → expression

  • Explicit return is optional: (x, y) → { x * y }

  • Types are allowed: (int x, int y) → { return x + y }

  • Default values are allowed: (int x, int y = 10) → x+y

There’s much more….. in fact, I’m working on updating my book, Learning Groovy, and releasing a second edition later this year, so stay tuned!

Conclusion

As you can see there’s a ton to be excited about with Groovy 3. Groovy 3.0.0-alpha-4 is available right now so go check it out.

Learn more at http://groovy.apache.org

Upgrading to Java 11

11 December 2018

So you want to upgrade to Java 11?

Maybe you’ve put off upgrading Java for a while but are realizing that Oracle soon plans to stop supporting Java 8. Have no fear, since you’ve procrastinated, other people have gone through the pain already and shared what they learned!

First of all, what’s new in Java 9, 10, and 11? The big things are JShell, modularity, local variable declarations (var), and in 11 the removal of JavaEE, xml, and corba among other things. Davide Angelocola shared a good summary of the new features, as well as his notes on upgrading to Java 11 here in this tweet (pdf).

In another post by Giacomo Veneri gives a good overview of features from 8 to 11 including creating immutable collections, new String methods, and more and comes with a handy chart. image

Finally, Benjamin Winterberg gives a great overview of how to upgrade to Java 11 with Maven. The main takeaway is to update all your dependencies and add any missing libraries like jaxb and javax.annotations.

Due to Oracle’s change in licensing it is highly recommended you use OpenJDK in production now (it’s mostly identical to Oracle Java and Oracle now charges for Oracle JDK in production). Other editions of Java exist or will exist in the future such as Amazon Coretto due to the changes.

Happy upgrading!

Test Driven Design (TDD)

27 November 2018

When I first started to learn programming, first on a TI-89 calculator and then QBASIC, and even later in Java, I had no idea what testing was all about. I thought testing was running the program and making sure it worked. Maybe even put some debug print statements here and there. It was years later I learned about automated testing and test frameworks like JUnit.

As the years went by, mainly after starting to work, I learned the benefit of writing tests - not only to ensure the correctness of code, but also to enable future changes without the fear of breaking things. This is the strongest quality of tests: to enable change.

Writing tests also helps you think the problem you’re trying to solve and clarifies your thinking. As you write the test you have to figure out what exactly your code does, what are the edges cases, and what could go wrong. With TDD (Test Driven Development), it simply goes one step further: you write the tests first, then the code. Instead of blindly typing out the code for a solution you vaguely hold in your head, you specify what you want your code to do - the solution space - then go about making it happen - the implementation. It has the added benefit that your code is always well tested, since you wrote the tests first, rather than an after-thought.

The last D in TDD could also stand for “Design” since when you write tests you are often forced to design the code to be more easily testable. This helps keep code clear and concise with a good separation of concerns. You should divide you logic into the smallest units possible and TDD helps you do this.

I don’t always do TDD - many times the code is so simple that writing tests feels like repeating yourself - but when I do I find the resulting code to be clear, correct, and well designed. If you haven’t tried it, I highly suggest trying TDD today.

Beyond Java 9

18 July 2018

I’m at UberConf this week - it’s going great. Last night I sat through a talk by Venkat Subramaniam called “Beyond Java 9″. I’ve always been curious about what’s coming up (and already here in Java 10) and Venkat always is a great speaker so I was excited to go to this one. Here are my notes:

CompleteableFuture was added in Java 8. Many of us missed it because we were so focused on Streams. Java 9 added modules.

Oracle has decided to start releasing a new major version of Java every 6 months.Not so much for the end developers, this is to make adding new features to language easier and less stressful for the teams behind Java.

At the same time, Oracle is changing their support of previous versions to some degree. If you do not pay for service, this doesn’t effect you except that if you want to be using a “supported” version of Java at all times, you will have to upgrade every six months.

If you do pay for standard support, you can get up to three years of support for long-term-service (LTS) versions of which Java 11 is the next one.

The standard reliability of Java is not changing. Despite the appearance of faster releases, the actual development of the Java the language is not getting much faster. By changing to a major release every six months, the Java language features that are in development for years (sometimes more than ten years) don’t have the added pressure of fitting into one release every three or four years. This way each release can add one or two major features, rather than cramming tons of new features into each major release - as has been the case in the past.

Meanwhile, Oracle is continuing to release OpenJDK as open source. This allows other companies, such as Azul, to modify it and provide their own support contracts, effectively creating a marketplace for JVMs (which is a good thing for many reasons). This allows some competition and is a force towards innovation.

Which comes to one of the most important points I took from this talk: “Java will not innovate on language features. It will innovate on Implementation.”

Java has never been on the cutting edge of language features, instead the people behind Java take a long look at what works in other languages and takes time to implement these features in the best way possible. For example, Java 8 lambdas expressions use invoke-dynamic. The behind the scenes implementation allows lambdas to be extremely performant and at the same time allow for future improvements.

Venkat then went on to talk about upcoming projects in Java: Project Panama, Project Valhalla, Project Amber, and Project Loom, which I will not go into right now. This talk was both entertaining and informative (Venkat uses metaphors and jokes sprinkled throughout his talks).

Although this is a large change in the Java language development cycle, in the end this is a good thing because it will encourage Java developers to update more often and spread out new features over more time, not bundling them all at once.

Reactive Streams in Java

08 July 2018

picture of books

So… I’m working on a thing, Reactive Streams in Java. This has been on my back burner for a long time, and I started work on it for real early this year.

Here’s the description from the book’s landing page:

"Reactive Streams are a standard approach to handling concurrency in modern applications. The Java 9 release includes new support for reactive streams. This book attempts to provide an easy introduction to Reactive Streams in Java including in depth introductions to RxJava, Akka Streams, and Reactor and how they can be used."

This book will cover everything you need to know about existing projects and how they translate in Java 9 (and 10 and 11). Mainly in Java 10 they’ve introduced “var” and this can be used for intermediate variables.

This book uses a progressive publishing model. As the book grows, so does the price. This encourages early adopters, so… maybe think about buying it. I’m not expecting a lot of sales so I appreciate every reader. Feel free to ask me questions (or pester me to keep writing).

This book has been picked up by a publisher - I’d rather not say who because I’m not sure I’m allowed to :) - and will be published in a complete, edited, and polished version later this year (winter 2018). However, the only way to get it right now is from leanpub. Thanks!

Modern Java: 2nd Edition

07 December 2017

In case you didn’t know, I’ve been working on Modern Java: 2nd Edition for more than a year now. Over that time I’ve decided to add Java 9 and cover more libraries and frameworks like Hibernate and RxJava. I’ve also fleshed out some existing sections more fully. After many distractions and other projects getting in the way, I finally feel like I’m coming close to finishing it! It’s now more of a full introduction to Java and the Java ecosystem from features of Java 8 and 9 all the way to testing, building, web frameworks, reactive streams, and a lot more.

RxJava

15 November 2017

(This is an excerpt from Modern Java: Second Edition)

RxJava is the open-source library for reactive programming that is part of the ReactiveX project. ReactiveX includes implementations in several different languages including rxjs, RxRuby, RxSwift, RxPHP, RxGroovy and many more.

RxJava 2 was rebuilt to be compatible with the Reactive Streams specification and is preferable to RxJava 1.x since it is scheduled for end-of-life. There were many changes from version 1 to 2 that could be confusing. To avoid confusion we will focus on RxJava 2.

Flowable

The basic entry class in RxJava is io.reactivex.Flowable. It implements the Reactive-Streams Pattern and offers factory methods, intermediate operators and the ability to consume reactive dataflows.

The following example demonstrates using RxJava to do a simple calculation on a range of numbers:

public static List doSquares() {
   List squares = new ArrayList();
   Flowable.range(1, 64) // (1)
       .observeOn(Schedulers.computation()) // (2)
       .map(v -> v * v) // (3)
       .blockingSubscribe(squares::add); // (4)
   return squares;
}
  1. Create a range from 1 to 64.

  2. Call the method observeOn to determine which Scheduler to use. This determines on which Thread the flow will run.

  3. The map method transforms each value. In this case we calculate the square.

  4. Finally, we initiate the flow by calling a “subscribe” method. In this case, blockingSubscribe blocks until the entire flow has completed. This means that the squares list will be populated before the return statement. Otherwise the flow would run on a different thread and the values in the squares list would be unpredictable at any given time.

(This is an excerpt from Modern Java: Second Edition)

Gr8Conf US and other things…

05 August 2017

I just back from Gr8Conf in Minneapolis last week and I had a great time. In case you missed it, I led a three hour workshop on Groovy and the slides and code are available (I did some practice screen-casts on youtube as well). Although I was pretty nervous leading up to it, I think it went really well. To those who attended: Thank you for listening and asking such great questions, I hope you enjoyed it! This was my first such workshop and everyone was super nice, so thank you again. I look forward to doing talks and/or workshops again in the future.

There were tons of great talks at Gr8Conf and although I didn’t get to go to all of them (I wish I could) I learned a lot and loved the energy from the conference in general. The “hallway discussions” and lunches were great as well.

In other news, “Learning Groovy” is now featured on the official Groovy website, and was featured in "Groovy Calamari"! I can’t stress enough how thrilled I am about this! Meanwhile, thank you to my company the SDG for supporting me in all these endeavors as well as just being a great company.

Modern Java: Second Edition is still in the works and I’ve expanded it to include Java 9. I’m sorry this one has been in production for so long. I hope to get it wrapped up before the final release of Java 9 in September. :-) There’s been a lot going on in the past year …but I won’t make excuses. The good thing is the final product is going to be great. With all the new stuff in Java 9, plus more experience with Java 8 and other things, it should be interesting. I’m also mulling over next books, but nothing to announce yet.

I met and talked with tons of people at Gr8Conf, but one in particular is Eric Helgeson @nulleric. If you’re at all interested in Grails 3, check out his book, Practical Grails 3. The cool thing about it is he’s selling his book completely on his own and the book covers the app he wrote to sell the book.

Also, I’m still working on GrooCSS and have tons of ideas for it.

Thanks for reading! Hopefully I’ll write again soon…

Groovy News!

28 July 2016

Great news everyone!

I can now announce, Learning Groovy is available for pre-order on Apress! They have been great to work with and it is much improved from the original version due to their feedback and the technical editor.

Modern Java: Second Edition is available in beta-mode on Leanpub! This book joins together my original Modern Java book, with all of the stuff on Java 8 and some new stuff will be coming soon!

I’ve launched GrooCSS, a little pet project of mine. More to come on this later. Check it out!




Older posts are available in the archive.