Tuesday, November 17, 2015

µCon 2015: The Microservices Conference #muCon 2015


Few days ago Marcin Grzejszczak anounced that he has had a spare ticket to muCon 2015. My boss said OK for additional expenses like flight and hotel and suddenly I was more than happy that I could attend muCon 2015.
muCon took place in CodeNode London - this is new HQ of well known Skills Matter organization. Previous location was smaller than new one and less comfortable.


TL;DR;


One tap conference - Polish conferences are more like imperial taps or even like multitap bars (there are at least 2 independent paths or more), but muCon 2015 was just one tap (so continental approach - shame on you).
We do a lot of stuff with microservices. Thanks to this and other conferences we are sure that we follow good path and we have already done a great job. I have met interesting people and talked with them a lot. Not much new products/ technologies/ frameworks/ approaches - maybe few complementary tools to consider evaluating. More theoretical than technical conference.


Greg Young: Keynote: "Microservices"

Excellent talk given by Greg Young. 
Rewriteability - focus your effort on domain modeling. Your business constantly changes requirements and your model should adapt to those changes. One day you realize that your model doesn't have sense at all and you need to rewrite it. Rewriteability is key feature of microservices.
Read Big ball of mud: http://www.laputan.org/mud
Independent failures as the another key feature of microservices. One system failure should not affect other systems if they can operate without this functionality.
Key points:
  • Find out what lexer lang is all about 
  • Read big ball of mud paper


Dave Syer: Microservices Developer Experience with Spring Cloud

Dave showed a lot of Spring Cloud products. I was happy that he mentioned libraries we use on daily basis or that we developed on our own in 4FinanceIT like micro-infra-spring or stubrunner.

Finally I have met Dave and it was really nice to see him in person. During lunch we have a occasion to talk about adjacency matrix in collaborators view. This is one of not so trivial features in micro-infra-view, but I think this is more important than visualization of collaborators graph in itself.


David A. Dawson: Microservices Pain Points: Testing & Security


Thanks to this presentation I have learned that using mocks in tests is known as the London style. Here in Warsaw we call it tests with mocks, but who cares anyways. No matter how you call it, it is important to take the same approach with testing microservices.

Robert Firek: Devops Toolbox for Microservices 

Robert had a great talk during the conference. It was nice to hear that he totally independently chose almost the same components that we have already used or planned to use in the nearest future.




Key points:
  • Infrastructure as a code
  • Pick one: Datadog loggly splunk


Stephen Judd: Zen and the Art of REST API documentation

Michael Kuehne: How to build an API your developers will love? 


We don't thinking about our APIs as a products. More or less they are products and they should be commercialized. How to attract our users with our APIs? Do the same tricks that GUI designers use.

Sylvain Hellegouarch: Conduct your microservices 

Marathon...

Russel Winder: On the Architectures of Microservices 

Dataflow:

ps ax|grep watchdog|grep -v grep|wc -l
This "simple" bash looks like stream in java8. 

Steve Freeman and Hilverd Reker: A meta-pipeline for generating continuous delivery pipelines for microservices

This presentation was about pipelines for microservices. Since few months I have been involved in creating one. A nice idea was to add some metadata and check if those metadata is valid. For example, we can expect that developers should provide their contact emails in specific file in repo. We should fail a build if this file is invalid.

Ian Cooper: From monolith to microservice

Blue book, Vernon all this DDD stuff and you are ready to go... really?

Kai Davenport: Running database containers using Marathon and Flocker  

Marathon again, but this time Kai almost missed his point because he thought that he had two half hour time slots, but suddenly it come out that one should be enough.
Things to investigate: Docker plugins, EBS, SDS.
why-should-i-care-about-stateful-containers

William Louth: Beyond Reactive with QoS and Adaptive Control 

Software as a network devices with QoS. These kinds of tweaks allow you to provide finest granularity of control over resources management. Besides, that it looks like a lot of fun.

Asher Glynn and Kingsley Davies: Sado MicroServices: compelling factors driving microservices and useful safety words 

During this talk: "There is a level of pain which you face by the ball gag before the pleasure kicks in".

Peter Rodgers: MicroWebs and NanoServices: an introduction to Resource Oriented Computing 

Erik Lindblad: Microservices @Klarna, scaling to 300 engineers and beyond 

Code as cattle not pets. Rewrite or kill quickly and often.
Standards: do or do not, there is no try.
PRY: Please repeat yourself (!DRY)
Burning things to the ground.

Tomasz Szymanski and Marcin Grzejszczak: Microservices - enough with theory, let's do some coding 


The same presentation as this one in Warsaw (but in English of course):
https://www.youtube.com/watch?v=L7zrYHXSCKM
It was faster, less jokes and almost no pauses. A lot of guys were lost during this presentation.
During live coding session hints of  intellij idea obstruct written code. It was too quick to find out what was going on.
Polish names of microservices like "dojrzewatr" did their job - they distract the audience.

To sum up

Poland was well represented by Marcin, Tomek and Robert.
Finally, I have met Kasia Mrowca and Marcin Erdmann. We did quite peaceful invasion of London.

Tuesday, October 20, 2015

Brain teaser

Friend of mine ask me a question: how to switch values of two variables (Integer type to be strict) but without using another one?

Use this spock spec as problem definition:
@Unroll
def "should switch variables (#a,#b) without additional variable"() {
expect:
new Switcher(a, b).switchVariables().toString() == result
where:
a | b | result
1 | 2 | "a=2 b=1"
10 | 20 | "a=20 b=10"
-10 | -20 | "a=-20 b=-10"
20 | 10 | "a=10 b=20"
-20 | -10 | "a=-10 b=-20"
0 | 10 | "a=10 b=0"
10 | 0 | "a=0 b=10"
-10 | 0 | "a=0 b=-10"
0 | 0 | "a=0 b=0"
0 | -1 | "a=-1 b=0"
10 | 10 | "a=10 b=10"
Integer.MAX_VALUE | Integer.MAX_VALUE | "a=" + Integer.MAX_VALUE + " b=" + Integer.MAX_VALUE
Integer.MIN_VALUE | Integer.MAX_VALUE | "a=" + Integer.MAX_VALUE + " b=" + Integer.MIN_VALUE
Integer.MIN_VALUE | Integer.MIN_VALUE | "a=" + Integer.MIN_VALUE + " b=" + Integer.MIN_VALUE
1 | Integer.MAX_VALUE | "a=" + Integer.MAX_VALUE + " b=1"
Integer.MIN_VALUE | 1 | "a=1 b=" + Integer.MIN_VALUE
-1 | Integer.MIN_VALUE | "a=" + Integer.MIN_VALUE + " b=-1"
}
You can find working solution on https://github.com/piotrpietrzak/gatchaman/tree/swicher
Have fun!

Monday, August 31, 2015

Kubernetes, Docker

Kubernetes

 This article is only to hold links and ready to use commands. You can find more in documentation.

Running Kubernetes locally via Docker 

docker run --net=host -d gcr.io/google_containers/etcd:2.0.9 /usr/local/bin/etcd --addr=127.0.0.1:4001 --bind-addr=0.0.0.0:4001 --data-dir=/var/etcd/data
 
docker run --net=host -d -v /var/run/docker.sock:/var/run/docker.sock  gcr.io/google_containers/hyperkube:v0.21.2 /hyperkube kubelet --api_servers=http://localhost:8080 --v=2 --address=0.0.0.0 --enable_server --hostname_override=127.0.0.1 --config=/etc/kubernetes/manifests
 
docker run -d --net=host --privileged gcr.io/google_containers/hyperkube:v0.21.2 /hyperkube proxy --master=http://127.0.0.1:8080 --v=2
 

Running an application

kubectl -s http://localhost:8080 run-container nginx --image=nginx --port=80

Expose it as a service

kubectl expose rc nginx --port=80

Turn down cluster

docker ps -a | awk '{print $1}' | xargs docker kill
 

Docker

Show available images

docker images

Build image

docker build -t approdorix/appname .

Stop, remove containers/images

docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
docker rmi $(docker images -q) 
 

Troubleshooting docker

You want to run screen but no tty in docker:
exec >/dev/tty 2>/dev/tty </dev/tty

Monday, July 6, 2015

Devoxx Poland

Kraków 22nd-25th June Devoxx Poland took place. This conference center was brand new, shiny and glamourous - just like it should be. With our 4finance team we stayed at a hotel nearby - as shiny and glamourous as conference center itself.

It was my second Devoxx in 2015 because on 30th of May we were with Natalia at Devoxx4kids. Both conferences were really great, but there were some pitfalls. Let's stick with Devoxx Poland, because Devoxx4kids I can encapsulate in 4 words: "Daddy it was awesome".

Most of the time I spent listening to talks and chatting with people attending our stand. This year the  hot topics was: "microservices" and "functional programming". I feel like we were riding on this wave - even Josh Long from Pivotal gave some credit to 4FinanceIT for commitment to Spring Cloud during his talk. The next nice moment during this conference was after Grzejszczak's and Szymański's talk about microservices. Lots of guys were interested in the technical details of their presentation. They were asking how to do this, how to do that and they were making big WOWs. I think that this presentation was awesome because: it was highly technical and was based on life coding. I know how hard it is to make such a presentation - because under pressure many small things start to conk out and you can't find any solution to repair these small typos or other non important errors. The guys managed to show everything - from git push to hystrix dashboard and interaction between microservices. They just forgot to show the collaborators view, but OK - this was just the eye candy part of microservices framework.

As I mentioned about some pitfalls, one of those was "Things about microservices you wish you never know". I admire Marek for his brave but lone charge against the microservices wave. When he detailed his reluctance for microservices  he started to give us a monolith talk. This was just not for me - I was there - I have seen this specific one and other monoliths. I do not know if microservices are the only way to go, but certainly monolith is not the alternative. I like unix like computing - small programs you can arrange in a way you like. This talk showed me that there is the other side - guys with their fat tools which can't be used in a way they weren't invented before development. All those analysts, architects, managers can't be fired in one day.

There were also some mind blowing talks. Some small but important thoughts I did remember from that talks:
1. FISH - Fuck It Shit Happens. We should not avoid failure at all costs.
2. Write more, try and test - do not try to polish your ideas endlessly.
3. Saboteur - try what happens if some of your network stack goes crazy.
4. This famous plugin to make pipelines for microservices: https://github.com/jenkinsci/job-dsl-plugin

Stay calm and write some microservices - do not follow hype, but try if this approach meets your expectations and keep searching if not.

Sunday, April 19, 2015

Bad URL day

When you create URL from string parameters it is crucial to encode those parameters properly (and then decode them). Imagine that yours REST service is consumed by client like this:
Response response = myServiceRestClient.getWebTarget().path("/queries/something").path(stringParameter)
        .queryParam("a", a)
        .queryParam("b", b)
        .request().get();
This is standard javax.ws.rs.core way to do things, but you can expect different behavior from path method. Let me introduce the wrongdoer:
/** * Create a new {@code WebTarget} instance by appending path to the URI of * the current target instance. * <p> * When constructing the final path, a '/' separator will be inserted between * the existing path and the supplied path if necessary. Existing '/' characters * are preserved thus a single value can represent multiple URI path segments. * </p> * <p> * A snapshot of the present configuration of the current (parent) target * instance is taken and is inherited by the newly constructed (child) target * instance. * </p> * * @param path the path, may contain URI template parameters. * @return a new target instance. * @throws NullPointerException if path is {@code null}. */public WebTarget path(String path);
Do you know how wrong will be your URL when you pass "a/b" as a path string? Of course you can easily pass / as part of URL in many ways. What can go wrong this time? Crucial is this sentence "single value can represent multiple URI path segments". As you can expect "/" will cause problems (I have found a lot of 404s in logs and this is why I called this Bad URL day).

How to repair this?
Of course it is very easy to replace / with something different in url and then back to / on the other side.

A. To guava or not to guava?
In guava we can find UrlEscapers. They are quite nice, but do we need guava in every project we do? What about other languages? In microservices environment every node should know about guava way of doing encoding to communicate with other parties.

B. Java API
Java API has two quite useful classes: URLEncoder and URLDecoder. They will allow us to do things we want to. I will present few tests:
@Unrolldef "should return space for encoded space [#character]"() {
    when:
    String result = RequestUtils.decodeParameterFromUrl(character)
    then:
    result == ' '    where:
    character << [' ', '%20', '+']
}
This means that we can write space(' ') in three different ways: ' ', '%20' and '+'.
Of course we should take a look at method definition:
import java.io.UnsupportedEncodingException;import java.net.URLDecoder;import java.nio.charset.StandardCharsets;
public class RequestUtils {

    public static String decodeParameterFromUrl(String parameterFromUrl) {
        try {
            return URLDecoder.decode(parameterFromUrl, StandardCharsets.UTF_8.name());        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException("JVM should implement encoding from StandardCharsets set");        }
    }
}
This is quite hard to test 100% of code above because UnsupportedEncodingException is thrown only on JVMs that do not implement StandardCharsets.UTF_8, but charsets from Standard Charsets should be implemented in every JVM. According to javadoc:
package java.nio.charset;
/** * Constant definitions for the standard {@link Charset Charsets}. These * charsets are guaranteed to be available on every implementation of the Java * platform. * * @see <a href="Charset#standard">Standard Charsets</a> * @since 1.7 */public final class StandardCharsets {
/..../
What about our "/":
@Unrolldef "should allow me to pass / encoded to [#character]"() {
    when:
    String result = RequestUtils.decodeParameterFromUrl(character)
    then:
    result == '/'    where:
    character << ['/', '%2F', '%2f']
}
And what out our famous ĄĘ characters?


Do you think I did forgot about something? Maybe there is another way of testing this part with UnsupportedEncodingException? Please leave suggestions in comments below - I will try every hint and describe my trial on this blog.

Spock even more advanced

On Fridays we have technological meetings in our company. Everyone can prepare presentation and "test" this presentation in friendly environment. This time Marcin Zajączkowski - from blog: solidsoft.wordpress.com was presenting his brand new "Advanced Spock". If you work with Spock on daily basis you should attend this presentation (even if you don't feel you need the »advanced« part).
During presentation I was curious what will happen in "where:" section when we pass two arrays with different length and how to cycle over values to test every combination of parameters. Marcin told me he wants to read answers on my blog. Challenge accepted:
First things first, but not necessarily in that order - I will start with combinations. How to test all combinations of parameters?
@Unrolldef "should return combinations pair (#a,#b)" () {
    when:
    println("a=${a} b=${b}")
    then:
    (...)
    where:
    [a,b] << [[1,2,3],[8,9]].combinations()
}
This test will end up with:
a=1 b=8
a=2 b=8
a=3 b=8
a=1 b=9
a=2 b=9
a=3 b=9
Now original problem - what will happen when you pass two arrays of different size?
@Unrolldef "should return combinations pair (#a,#b)" () {
    when:
    println("a = ${a} b=${b}")
    then:
    1==1    where:
    a << [1,2,3]
    b << [8,9]
}
a = 1 b=8
a = 2 b=9

org.spockframework.runtime.SpockExecutionException: Data provider for variable 'b' has fewer values than previous data provider(s)
at com.ofg.loans.domain.model.ledger.acl.RequestUtilsSpec.should return combinations pair (#a,#b)(RequestUtilsSpec.groovy:60)

This error doesn't leave us any hope - we can't pass two arrays of different length.

Thursday, April 9, 2015

JavaScript (-1)*0

JavaScript implemented in Chrome and in Nodejs should give the same results? Lets try multiply (-1) and 0:
Chrome:

Nodejs:

Wednesday, April 1, 2015

Lanterna Scroll

This was my second attempt to build something with lanterna library from:
https://code.google.com/p/lanterna/
For the very first time I did slightly different project. This time I focused on producing something completely useless like old school scroll but on terminal output and via telnet on the net.

You can find my scroll on github:
https://github.com/piotrpietrzak/lanternaScroll
It looks something like this:
this is scroll rendered on telnet localhost 1024 with atari characters set. This is very tricky way of rendering this text.
To understand how it works first you have to visit: http://www.atariarchives.org/c3ba/charset_full.php
Now you are ready to read code - especially this:
boolean bitForCharAtXY(String symbol, int x, int y) {
    return charset[symbol][y] >> x & 1}
<sad_jokes>
This time bit shift operator was used to ... well this time this was sad bit shift. Of course our & operator ... oh wait - this is and.
No operator overloading - is this groovy or what?
</sad_jokes>

This was so '80 to encode chars as bits and then shift them and apply bit mask to check if they are 1 or 0. But how to encode entire message?
def computeBit(String message, int i, int j) {
    return atariFont.bitForCharAtXY(message[(int) Math.floor(i / 8) % message.length()], 7 - i % 8, j)
}
So - we can provide message and then at any (i,j) position of bits we can find if we should flash or turn off our "pixel".

Lets go "forward" to the early internet. Telnet was the king. Hackers was too busy to hack other people and plain text passwords in public net was accepted by admins so they use telnet even to manage their servers.

Lanterna in new version allows us to provide telnet service. This is really easy - we have to setup server:
TelnetTerminalServer server = new TelnetTerminalServer(1024, Charset.forName("utf-8"));
Then we can accept connections:
TelnetTerminal telnetTerminal = server.acceptConnection();
Then we can start new thread per connection:
new ConnectionHandler().handleNewConnection(telnetTerminal, {
    String message, Exception e ->
        log.error(message,e)
})
In this thread we can run our scroll:
new AtariFontScroll().scroll(terminal, screen, writer);
or even modern ascii art version:
new SimpleScroll().scroll(terminal, screen, writer);

This project was just for fun, but I plan to use lanterna in gradle plugin to show progress bar via net - directly from your CI to your laptop. I hope security will not cool down my enthusiasm...
OK, with apache mina I can upgrade telnet to ssh.

Friday, March 20, 2015

Test profiler

I guess you have seen this many times - your tests last so long and you skip them once, maybe even twice and then you skip them all the times.

We want to prevent this situation with team I am working with. To do this my colleagues invent many tweaks to improve build time and they cut this significantly.

Main trick was to run tests in parallel. This is quite simple with gradle, but how to measure the results?

Example 1:
First we will start with simple project for example we can use groovypi - this project have two long lasting tests: one for pi and other for sqrt(2).

Sequential:

01:27:12: Executing external tasks 'clean build profileTests'...
:clean
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:compileTestGroovy
:addTimeout
:processTestResources UP-TO-DATE
:testClasses
:test
Your tests report is ready at [/Users/piotr/github/gatchaman/build/reports/test_profiling/testsProfile.csv]
:buildDashboard
:check
:build
:profileTests
Your combined report is available here [/Users/piotr/github/gatchaman/build/reports/test_profiling/summary.csv]

BUILD SUCCESSFUL

Total time: 39.538 secs
01:27:51: External tasks execution finished 'clean build profileTests'.

Parallel:

01:29:47: Executing external tasks 'clean build profileTests'...
Parallel execution is an incubating feature.
:clean
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:compileTestGroovy
:addTimeout
:processTestResources UP-TO-DATE
:testClasses
:test
Your tests report is ready at [/Users/piotr/github/gatchaman/build/reports/test_profiling/testsProfile.csv]
:buildDashboard
:check
:build
:profileTests
Your combined report is available here [/Users/piotr/github/gatchaman/build/reports/test_profiling/summary.csv]

BUILD SUCCESSFUL

Total time: 39.082 secs
01:30:27: External tasks execution finished 'clean build profileTests'.

Important lines from those two runs was:

sequential:
Total time: 39.538 secs
parallel:
Total time: 39.082 secs

It was not that fast I was expecting. Why? Where is the field to improvements?
To find the answer lets go back to tests - our build process in some parts will be sequential by nature of matter. We can improve only tasks that can run in parallel. Tests are obvious candidate.

How to measure test performance?
We can use plugin (authored by my colleagues: Adam Chudzik and Marcin Grzejszczak) named: gradle-test-profiler.

To apply this plugin to project you have to add few lines to your build.gradle file:
buildscript {
    repositories {
        mavenLocal()
        jcenter()
    }
    dependencies {
        classpath 'com.blogspot.toomuchcoding:gradle-test-profiler:0.2.3-SNAPSHOT'    }
}

apply plugin: 'com.blogspot.toomuchcoding.testprofiler'

Next we have to setup new task (profileTests) in gradle. In my case it was as simple as this:

Because I have written down those results we can compare results of runing tests in parallel and sequentially:

Sequential:

module test class name test name test execution time in [s] test class execution time in [s]
: SquarRooteOfTwoSpec should converge to square root of two 27.398 27.398
: PiSpec should converge to pi 8.405 8.405

Parallel:
module test class name test name test execution time in [s] test class execution time in [s]
: SquarRooteOfTwoSpec should converge to square root of two 28.044 28.044
: PiSpec should converge to pi 7.582 7.582

How we should interpret the results?
Can we identify long lasting tests?
Can we break build with long lasting tests?

Saturday, March 14, 2015

3.14.15 Pi Day

Today we have Pi Day! As you probably know my favorite number is Pi and approximation of Pi number is my favorite activity on this blog. Lets focus on new version of groovy closure to count Pi:
Closure<BigDecimal> functionToIntegrate = { Math.sin(it) }
integrate(scale, sumToLimit, functionToIntegrate)  * 2 == expectedResult
Because we can't improve this API without groovy DSL someday I will get back to this  (when I will have to learn more about groovy DSL).
My colleague helped me with this improvement, but also he told me about groovy DSL. Now I can imagine API as beauty as:
integrate functionToIntegrate using scale untilReach sumToLimit andReturnX == expectedResult
This will be nice, but for now I have added a new library to show how long our tests lasted.
With this library we can profile our tests:
PiSpec  should converge to pi   9.252[s] on my laptop.
It's quite nice to achieve proper 3.1415 in 9 seconds.
I found very interesting article on wikipedia about pi approximation history:
http://en.wikipedia.org/wiki/Approximations_of_%CF%80

Wednesday, March 11, 2015

Groovy closure to find Pi and sqrt(2)

I want to start with very simple math fact - if we draw right triangle and two of edges of this triangle have length equal to sqrt(2). Area of this triangle is of course 1 (because: 1/2*a*h).

Another fact is that area under function sin(x) from 0 to pi/2 is also equal to 1.

Let's use those facts to exploit groovy closures to estimate pi and sqrt(2).

Clone repo: git clone https://github.com/piotrpietrzak/gatchaman.git
git checkout origin/groovypi

We should start with tests - this time we will use spock with "where:" block.

def "should converge to square root of two"(scale, sumToLimit, expectedResult) {
    expect:
    new DefiniteIntegral()
            .compute(scale, sumToLimit , { it }) == expectedResult

    where:
    scale | sumToLimit | expectedResult
    1     | 1          | 1.4
    2     | 1          | 1.41
    3     | 1          | 1.414
    4     | 1          | 1.4142
    5     | 1          | 1.41421
    6     | 1          | 1.414214
}

For pi this is also very simple test:

def "should converge to pi"(scale, sumToLimit, expectedResult) {
    expect:
    new DefiniteIntegral()
            .compute(scale, sumToLimit, { Math.sin(it) }) * 2 == expectedResult

    where:
    scale | sumToLimit | expectedResult
    1     | 1          | 3.2    
    2     | 1          | 3.14
    3     | 1          | 3.142
    4     | 1          | 3.1416
    5     | 1          | 3.14160
    6     | 1          | 3.141592
}

Definite integral is quite simple (from the numerical recipes point of view we can achieve much better results even with this naive approach but I want to keep this simple).

while (sum < integrateTo) {
    x += step
    sum += function(x) * step
}

After this loop we should return x which is our result.

What else can we do better?

Every math lover will tell us other things but IT guys will focus on poor API and unnecessary method. Lets replace this simple solution with this:
class IntegrationClosure {
    final Closure<BigInteger> compute = {
        Integer scale, BigDecimal integrateTo, Closure<BigDecimal> function ->
            BigDecimal sum = 0;
            BigDecimal x = 0;
            BigDecimal step = BigDecimal.valueOf(1, scale)

            while (sum < integrateTo) {
                x += step
                sum += function(x) * step
            }
            x
    }
}


Sunday, March 8, 2015

Port conflicts during tests

When I was running tests in very large and sophisticated system I found very interesting problem. During integration tests run in parallel there was port conflicts and port collision prevents tests to run smoothly and in the end they failed. To avoid this behavior I suggested to use very simple solution. My colleagues confirm the need and implementation was done in very short time. Just before you read the solution - please reconsider situation on your own:
  • Tests runs on many JVMs
  • You don't want to share state between mentioned above JVMs
  • You don't want to manually change every test to enter code
The solution suggested was to use random port in range and repeat this until success. Really simple and it just works. 
From technical perspective please focus on this closure from tests:
Server server = new AvailablePortScanner(minPort, maxPort).tryToExecuteWithFreePort(new Closure<Server>(this) {
    @Override    public Server call(Object... args) {
        Integer freePort = (Integer) args[0];
        Server server = new Server(freePort);
        System.setProperty("port", freePort.toString());
        return server;
    }
});
Checkout on branch:
origin/groovy/closure_port_scanner
to play with it. Have fun

Saturday, March 7, 2015

Groovy overloaded operator

Groovy overloaded operator (bit shift on objects)

This example come from "Groovy Goodness Notebook".

Clone repo:
git clone https://github.com/piotrpietrzak/gatchaman.git
Switch to branch:
git checkout origin/groovy/multiple_overloaded_operator_methods
Test in spock is quite interesting:
def "should add operation for user" () {
    setup:
    Priviledge priviledge = new Priviledge()
    User user = new User(name: 'Test name')
    Operation operation = new Operation(name: 'Test operation')

    when:
    priviledge << user << operation

    then:
    priviledge.users.contains user
    priviledge.operations.contains operation
}