In a modern service landscape, especially when using containers, you are probably using something like the ELK stack (Elasticsearch, Logstash, Kibana) to flow all the logging into.
But how to find from all those loglines what caused the nasty bug after a innocent buttonpress?
One of the easy answers to this is what’s called a correlation id – basically a unique number assigned to that buttonpress which gets carried around between the services and added to every logline.
Sounds good you say? it is so let’s see how to do this.
When we want to transform a
Promise value we can use the
flatMap methods. There are also variants to this methods that will only transform a value when a given predicate is true:
flatMapIf. We provide a predicate and function to the methods. If the predicate is true the function is invoked, otherwise the function is not invoked and the promised value is returned as is.
Promise class has a lot of methods. One of the methods is the
time method. We can invoke this method an a
Promise instance. The method creates a
Duration object that we can use inside the method. The duration is the time taken from when the promise is subscribed to to when the result is available. The promise value is not changed, so we can add the
time method at any position of a method chain for the
To run external Groovy scripts in our Java or Groovy application is easy to do. For example we can use
GroovyShell to evaluate Groovy code in our applications. If our script contains print methods like
println we can redirect the output of these methods. The
Script class, which is a base class to run script code, has an implementation for the
println methods. The implementation of the method is to look for a property
out, either as part of a
Script subclass or in the binding added to a
Script class. If the property
out is available than all calls to
println methods are delegated to the object assigned to the
out property. When we use a
PrintWriter instance we have such an object, but we could also write our own class with an implementation for the
print methods. Without an assignment to the
out property the fallback is to print on
In a previous post we saw how we can use Spring Boot in a Ratpack application. But the integration can also be the other way around: using Ratpack in a Spring Boot application. This way we can use Ratpack’s power to handle requests sent to our Spring Boot application and still use all Spring Boot features in our application. The easiest way to add Ratpack to a Spring Boot application is adding a Ratpack dependency and use the
@EnableRatpack annotation. With this annotation a
RatpackServer instance is created and started along with configuration options.
When we start a Spring Boot application and pass arguments to the application, Spring Boot will capture those arguments and creates a Spring bean of type
ApplicationArguments and puts it in the application context. We can use this Spring bean to access the arguments passed to the application. We could for example auto wire the bean in another bean and use the provided argument values. The
ApplicationArguments interface has methods to get arguments values that are options and plain argument values. An option argument is prefixed with
--, for example
--format=xml is a valid option argument. If the argument value is not prefixed with
-- it is a plain argument.
When we write a Spring Boot application a lot of things are done for us. For example when an exception in the application occurs when we start our application, Spring Boot will exit the application with exit code
1. If everything goes well and the we stop the application the exit code is
0. When we use the
run method of
SpringApplication and an exception is not handled by our code, Spring Boot will catch it and will check if the exception implements the
ExitCodeGenerator interface. The
ExitCodeGenerator interface has one method
getExitCode() which must return a exit code value. This value is used as input argument for the method
System.exit() that is invoke by Spring Boot to stop the application.
Testing a Ratpack application is not difficult. Ratpack has excellent support for writing unit and integration tests. When we create the fixture
MainClassApplicationUnderTest we can override the method
addImpositions to add mock objects to the application. We can add them using the
ImpositionsSpec object. When the application starts with the test fixture the provided mock objects are used instead of the original objects. For a Groovy based Ratpack application we can do the same thing when we create the fixture
We have several options to define a Ratpack application. We can use a Java syntax to set up the bindings and handlers. Or we can use the very nice Groovy DSL. It turns out we can use both together as well. For example we can define the handlers with the Groovy DSL and the rest of the application definition is written in Java. To combine both we start with the Java configuration and use the
handlers method of the
Groovy.Script class to inject the files with the Groovy DSL.
One of the very nice features of Ratpack is the Groovy DSL to define our application. We get a nice DSL to set up the registry, to define handlers and more. Because of clever use of the
@DelegateTo annotation we get good code completion in our IDE. We can also add static compilation of our Groovy DSL when we start our Ratpack application. With static compilation the script is type checked at compile time so we get earlier feedback on possible errors in the script. To configure static compilation we must invoke the
app method of the
Groovy.Script class with the argument