2017-04-19

Uwierzytelnianie przez ePUAP (Dostawca Tożsamości) i wywołanie usług Profilu Zaufanego

Uwierzytelnianie przez system ePUAP może przysporzyć wielu problemów, m.in. z powodu ubogiej dokumentacji i wykorzystywania dość ekscentrycznego protokołu bazującego na XML jakim jest SAML 2.0 (Security Assertion Markup Language). Udane zalogowanie to jednak nie koniec problemów - wszystkie wywołania SOAP muszą być realizowane w standardzie WS-Security w celu zapewnienia odpowiedniego bezpieczeństwa, co ponownie może sprawić problemy bez dogłębnej znajomości tematu. W tym artykule przedstawione zostanie logowanie, wylogowanie oraz wywołanie podstawowej usługi TpUserInfo. Aby osiągnąć cel użyjemy frameworku Spring Boot oraz bibliotek OpenSAML3 i Apache CXF. Biblioteka openSAML w wersji 3 praktycznie nie posiada dokumentacji, a w Internecie jest bardzo mało przykładów co skutecznie utrudnia pracę z nią. Niemożliwe jest jednak użycie starszej wersji openSAML2 z dwóch powodów:
1.     Zakończenia wsparcia, co może wiązać się z niezałatanymi lukami bezpieczeństwa
2.     Wykorzystanie starych wersji bibliotek, co powoduje różne dziwne wyjątki podczas uruchamiania aplikacji.
Z dwojga złego lepiej wybrać wersję 3.

Zanim zaczniemy - przyszedł czas na pewną kwestię, której nie mógłbym pominąć w kontekście ePUAPu. Według dokumentacji i wszystkich oficjalnych komunikatów, odpowiedzi z ePUAPU są podpisane certyfikatem, który można pobrać z zakładki „Dla integratorów” na stronie internetowej systemu. Problem w tym, że o ile jest to prawdą dla środowiska produkcyjnego, o tyle na środowisku testowym odpowiedzi są podpisane zupełnie innym certyfikatem. Jest to certyfikat self-signed wystawiony przez/dla firmy Pentacomp. Nigdzie nie znalazłem żadnej informacji o tym fakcie, certyfikat również jest niedostępny do pobrania. Ostatecznie certyfikat wyciągnąłem z przychodzącej odpowiedz SAML i dodałem go do keystore „penta.jks”, który załączony jest do niniejszego artykułu. Dzięki temu odpowiedzi są poprawnie weryfikowane i nie dostajemy na twarz irytujących wyjątków.

Dostęp do usług ePUAPu realizowany jest przez adres https://pz.gov.pl/. W przypadku środowiska testowego należy użyć subdomeny “int” - https://int.pz.gov.pl.

Jak w skrócie wygląda uwierzytelnianie za pomocą protokołu SAML 2.0 wraz z pobraniem szczegółów użytkownika:

#
Działanie
Adres produkcyjny
Adres testowy
1
Wysłanie AuthnRequest
2
Odebranie odpowiedzi w postaci artefaktu SAMLart
3
Wysłanie ArtifactResolve z parametrem SAMLart
4
Odebranie odpowiedzi ArtifactResponse z tokenem sesji
5
Wywołanie usługi TpUserInfo
6
Wysłanie LogoutRequest z nazwą wylogowywanego użytkownika
7
Odebranie i weryfikacja odpowiedzi LogoutResponse

To tyle na wstępie, przejdźmy do sedna sprawy. Tak wygląda kwestia techniczna logowania przez ePUAP: nasza aplikacja generuje zapytanie SAML AuthnRequest (zwyczajny XML), następnie do zapytania dodawany jest element <DigestValue>, <SignatureValue> oraz certyfikat w formie binarnej zakodowany w base64. Tak przygotowane zapytanie jest kompresowane oraz kodowane w base64. W kolejnym kroku biblioteka generuje stronę HTML ze standardowym formularzem. Do formularza dodawane jest pole SAMLRequest o wartości przygotowanego wcześniej zapytania SAML. Formularz jest automatycznie wysyłany metodą POST na adres ePUAPu (chyba że mamy wyłączony JavaScript, wtedy konieczne jest ręczne wysłanie formularza). ePUAP odbiera nasz formularz, parsuje zapytanie zawarte w polu SAMLRequest, weryfikuje podpis i jeśli wszystko jest w porządku pokazuje nam formularz logowania.

Wysłanie żądania uwierzytelniania w praktyce:

private Element marshallAndSign(SignableSAMLObject object) throws IllegalStateException {
    Signature signature = Util.createClientSignature();
    object.setSignature(signature);
    try {
        Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory()
         .getMarshaller(object);
        Element dom = marshaller.marshall(object);
        Signer.signObject(signature);
        return dom;
    } catch (MarshallingException | SignatureException e) {
        throw new IllegalStateException(e.getMessage(), e);
    }
}

@RequestMapping("/login")
public void sendSignedAuthnRequest(HttpServletResponse response) {
    AuthnRequest authnRequest = new AuthnRequestBuilder().buildObject();
    authnRequest.setDestination("https://pz.gov.pl/dt/SingleSignOnService");
    authnRequest.setIssueInstant(new DateTime());
    authnRequest.setProtocolBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact");
    authnRequest.setAssertionConsumerServiceURL("apilia.pl/login/callback");
    authnRequest.setID("ID_" + UUID.randomUUID().toString());
    authnRequest.setVersion(SAMLVersion.VERSION_20);

    Issuer issuer = new IssuerBuilder().buildObject();
    issuer.setValue("apilia.pl");
    authnRequest.setIssuer(issuer);

    NameIDPolicy pol = new NameIDPolicyBuilder().buildObject();
    pol.setFormat("urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified");
    pol.setAllowCreate(false);
    authnRequest.setNameIDPolicy(pol);

    marshallAndSign(authnRequest);
    SAMLPeerEntityContext peerEntityContext = context.getSubcontext(SAMLPeerEntityContext.class, true);
    SAMLEndpointContext endpointContext = peerEntityContext.getSubcontext(SAMLEndpointContext.class, true);
    SingleSignOnService idpEndpoint = SamlUtil.buildXmlObject(null, SingleSignOnService.class, SingleSignOnService.DEFAULT_ELEMENT_NAME);
    idpEndpoint.setLocation("https://pz.gov.pl/dt/SingleSignOnService");
    idpEndpoint.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
    endpointContext.setEndpoint(idpEndpoint);

    HTTPPostEncoder encoder = new HTTPPostEncoder();
    encoder.setVelocityEngine(velocityEngine);
    encoder.setMessageContext(context);
    encoder.setHttpServletResponse(response);

    try {
        encoder.initialize();
        encoder.encode();
    } catch (ComponentInitializationException | MessageEncodingException ex) {
        ex.printStackTrace();
    }
}

Podczas generowania ID, np. authnRequest.setID("ID_" + UUID.randomUUID().toString()); ważne jest aby ID nie rozpoczynało się cyfrą
Jeśli wpisaliśmy poprawne dane logowania, ePUAP wysyła żądanie POST do naszej aplikacji, na adres skonfigurowany podczas rejestracji aplikacji w ePUAPie. W żądaniu przesyłane jest pole SAMLart, które poprzez wysłanie zapytania ArtifactResolve pozwoli na uzyskanie tokenu sesji tgsid pozwalającego na autoryzowanie zapytań do webserwisu. Po odebraniu z żądania ArtifactResolve odpowiedzi (ArtifactResponse), weryfikujemy poprawność podpisu. Cały proces zaprezentowano poniżej:
@RequestMapping(value = "/login/callback", method = RequestMethod.POST)
public void sendArtifactResolve(@RequestParam String SAMLart) {
    ArtifactResolve artifactResolve = new ArtifactResolveBuilder().buildObject();
    artifactResolve.setID("ID_" + UUID.randomUUID().toString());
    artifactResolve.setIssueInstant(new DateTime());

    Artifact artifact = new ArtifactBuilder().buildObject();
    artifact.setArtifact(SAMLart);
    artifactResolve.setArtifact(artifact);

    Issuer issuer = new IssuerBuilder().buildObject();
    issuer.setValue("apilia.pl");
    artifactResolve.setIssuer(issuer);

    Element element = marshallAndSign(artifactResolve); 
    try {
        WebServiceTemplate template = new WebServiceTemplate();
        ArtifactResponse artifactResponse =
            template.sendSourceAndReceive("https://int.pz.gov.pl/dt-services/idpArtifactResolutionService",
            new DOMSource(element), this::processResponse);

        Response msg = (Response) artifactResponse.getMessage();
        Optional<Assertion> assertion = msg.getAssertions().stream().findFirst();
        if (!assertion.isPresent()) {
            return;
        }

        SignatureValidator.validate(artifactResponse.getSignature(), Util.createServiceCredential());
        String tgsid = assertion.get().getID(); //identyfikator sesji
    } catch (SignatureException | TpUserInfoException e) {
        e.printStackTrace();
    }
}

private ArtifactResponse processResponse(Source source) {
    try {
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        DOMResult result = new DOMResult();
        transformer.transform(source, result);
        Document el = (Document) result.getNode();
        return (ArtifactResponse) new ArtifactResponseUnmarshaller()
            .unmarshall(el.getDocumentElement());
    } catch (TransformerException | UnmarshallingException ex) {
        ex.printStackTrace();
    }
    return null;
}


Wylogowanie przebiega podobnie do logowania: nasza aplikacje generuje zapytanie SAML LogoutRequest, dodaje wymagane elementy oraz nazwę wylogowywanego użytkownika i koduje całość przy pomocy base64. Następnie generowany jest formularz HTML z polem SAMLRequest, którego wartością jest zapytanie, a formularz jest wysyłany POSTem do ePUAPu. ePUAP odbiera i parsuje zapytanie, jeśli wszystko jest w porządku to teraz on generuje formularz HTML który jest automatycznie wysyłany na adres naszej aplikacji skonfigurowany w ePUAPie. Ten formularz posiada pole SAMLResponse z zapytaniem LogoutResponse, które następnie nasza aplikacja weryfikuje i sprawdza czy wylogowanie się powiodło.
Wysyłanie żądania wylogowania w praktyce:
@RequestMapping("/logout")
public void sendSignedLogoutRequest(@RequestParam String username) {
    LogoutRequest logoutRequest = new LogoutRequestBuilder().buildObject();
    logoutRequest.setID("ID_" + UUID.randomUUID().toString());
    logoutRequest.setDestination("https://pz.gov.pl/dt/SingleLogoutService");
    logoutRequest.setIssueInstant(new DateTime());
    logoutRequest.setVersion(SAMLVersion.VERSION_20);

    Issuer issuer = new IssuerBuilder().buildObject();
    issuer.setValue("apilia.pl");
    logoutRequest.setIssuer(issuer);

    NameID pol = new NameIDBuilder().buildObject();
    pol.setFormat("urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified");
    pol.setValue(username);
    logoutRequest.setNameID(pol);

    marshallAndSign(logoutRequest);

    SAMLPeerEntityContext peerEntityContext = context.getSubcontext(SAMLPeerEntityContext.class, true);
    SAMLEndpointContext endpointContext = peerEntityContext.getSubcontext(SAMLEndpointContext.class, true);
    SingleLogoutService idpEndpoint = SamlUtil.buildXmlObject(null, SingleLogoutService.class, SingleLogoutService.DEFAULT_ELEMENT_NAME);
    idpEndpoint.setLocation("https://pz.gov.pl/dt/SingleLogoutService");
    idpEndpoint.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
    endpointContext.setEndpoint(idpEndpoint);

    HTTPPostEncoder encoder = new HTTPPostEncoder();
    encoder.setVelocityEngine(velocityEngine);
    encoder.setMessageContext(context);
    encoder.setHttpServletResponse(response);

    try {
        encoder.initialize();
        encoder.encode();
    } catch (ComponentInitializationException | MessageEncodingException ex) {
        ex.printStackTrace();
    }
}

Odebranie i weryfikacja odpowiedzi:
@RequestMapping(value = "/logout/callback", method = RequestMethod.POST)
public void logoutCallback(HttpServletRequest request, HttpServletResponse response) throws IOException {
    try {
        HTTPPostDecoder decoder = new HTTPPostDecoder();
        decoder.setHttpServletRequest(request);
        decoder.initialize();
        decoder.decode();
        LogoutResponse logoutResponse = (LogoutResponse) decoder.getMessageContext().getMessage();
     
        // walidacja certyfikatu odpowiedzi
        SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
        profileValidator.validate(logoutResponse.getSignature());
        SignatureValidator.validate(logoutResponse.getSignature(), Util.createServiceCredential());
    } catch (MessageDecodingException | SignatureException e) {
        e.printStackTrace();
    }
}


Na koniec została jeszcze konfiguracja usługi TpUserInfo. Samo wywołanie przebiega dokładnie tak samo jak w przypadku wszystkich innych usług wygenerowanych przez CXF, jednak ustawienie wszystkich parametrów może przysporzyć pewnych problemów.

WSDL do usług można znaleźć dodając „?wsdl” do adresu usługi, np. https://int.pz.gov.pl/pz-services/tpUserInfo?wsdl

WSProviderConfig.init(true, false, true);
TpUserInfoServiceService ss = new TpUserInfoServiceService();
TpUserInfoService port = ss.getTpUserInfoService();
Client client = ClientProxy.getClient(port);
Endpoint cxfEndpoint = client.getEndpoint();

Map<String, Object> requestContext = client.getRequestContext();

// dane certyfikatu klienta
Properties securityProperties = new Properties();
securityProperties.setProperty("org.apache.ws.security.certificate", "cert");
securityProperties.setProperty("org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin");
securityProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", "jks");
securityProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", "12345");
securityProperties.setProperty("org.apache.ws.security.crypto.merlin.file", "/ścieżka/do/keystore.jks");
securityProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.private.password", "12345");
securityProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.alias", "cert");

// dane certyfikatu ePUAP
Properties responseProperties = new Properties();
responseProperties.setProperty("org.apache.ws.security.certificate", "cert");
responseProperties.setProperty("org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin");
responseProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", "jks");
responseProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.alias", "penta");
responseProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", "sspass");
responseProperties.setProperty("org.apache.ws.security.crypto.merlin.file", "/ścieżka/do/penta.jks");
requestContext.put("ws-security.signature.properties", securityProperties);
requestContext.put("ws-security.encryption.properties", responseProperties);

// nie wykorzystujemy adresu z WSDLa, gdyż na zmianę używamy adresu testowego i produkcyjnego
BindingProvider bp = (BindingProvider) port;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https://pz.gov.pl/pz-services/tpUserInfo");
 
//tgsid to identyfikator sesji uzyskany przy pomocy zapytania ArtifactResolve
TpUserInfo tpUserInfo = port.getTpUserInfo(tgsid, null);

Procedurę tworzenia keystore i dodawania certyfikatów można bez problemu znaleźć w Internecie (o, np. tutaj).

Dzięki zaprezentowanym w artykule procesom i metodom możliwe jest uwierzytelnienie i wywołanie usług ePUAPu.

Certyfikat testowego ePUAPu: penta.jks

2014-07-15

Confitura 2014

20140705_144131

 

A few days ago the majority of our company went to Warszawa (Warsaw) to participate in the biggest Java event in our country which is a conference called Confitura (strange wordplay making sense only in Polish). We chose two means of transport and have some competition to check who would be the first, a team going by car or by train. Getting back to the conference, I personally think Confitura is the best IT conference in Poland. It has the largest audience (over 1200) and the best positive vibe of all other. The last three events were organized in Warsaw University campus situated in the center of city. The place always gives us some urge to learn something new, to leave the place with new knowledge. This year registration has suprised us in an unforseen and somehow funny way. Similarly to many other people we were waiting for the opening of registration process. We knew when it would be about, however it surprised us during work. The tickets (free) were "sold out" within just 2 hours! It was rather suprsing, mostly for those who didn't manage to get the ticket. This note was written by Kacper Kaśków (me) and my teammate Łukasz Walaszczyk (walák). And now lets go to the lectures:

1. Type Driven Development by Maciek Próchniak

kacperk:
The day started with a lecture about types. Mostly about using types in secure way. Samples were based on Scala and for people who did not touch that language it would be tiring to understand everything on the fly. Maybe i should learn Scala in the near future.

2. Java performance tricks and traps by Michał Warecki

walák:
It was a lecture about how to approach to so-called microbenchmarks correctly. The main theme was how to measure performance of creating bunch of objects. Author said about factors which can make measurement inaccurate – compiler optimalization, garbage collecting, etc. What I was missing were live examples.

3. Archeologia kodu źródłowego by Paweł Ślusarz

kacperk:
Paweł introduce me to the subject of source code archeology. In an interesting way it was shown to us how to deal with application dependencies and source code statistics. He was talking about his experience in tiding very large project in USA and also reminded us about pros and cons of Sonar.

4. Grzechy główne liderów technicznych by Mariusz Sieraczkiewicz

walák:
It was one of the best talks on this conference. Only #10 in this list seems to be a bit better. Author (acting as the Devil) presented the main ‘sins’ of technical leaders ending all of it with a sentence: “…because when the devil has nothing to do, It becomes mad. Fortunately, you make mistakes. And I have something to do.” The sins were concentrated around process of developing: spending time on technical stuff, lack of communication, yielding to pressure from business, abandoning rules, etc. Personally I find this talk as very enlightening, giving opportunity to improve work of team I’m working in.

5. Efektywna Refaktoryzacja by Włodek Krakowski

kacperk:
It was my favorite presentation on the conference, very important for all programmers to remind about necessity of source code maintenance. The beginning was taken from the famous book Refactoring by Martin Fowler, but shown in nice way with many comments and already prepared source code (of course with tests). Second part was about soft skills. There wouldn’t be lack of well known The Seven Habits… by Stephen Covey
smoothly combined with the flow of refactoring. Włodek explained to us the problems of people's attitude.

6. Twórz i Rządź, czyli jak developer może pobawić się hardwarem – iBeacony, RaspberryPi, druk 3D itd. by Tomasz Szymanski & Jarosław Kijanowski

walák:
A bit of fun, a bit of interesting and useful hardware stuff:

  • simple electronics ‘not for PhD’ like Adruino and Raspberry PI. Actually I haven’t learned anything new. Even examples were trivial: measuring a distance with ultrasound rangefinder. Authors didn’t write their own code, they just copy it from the Internet so it was kind of BDD (Blog Driven Development), but I believe it is noting wrong as point of the presentation was to give some kind of overall look rather than checking details.

  • 3D printing – as above, noting groundbreaking, but authors drawn our attention to problems about which you can’t hear from 3D printers manufacturers. It means problems with stable printing – things are likely to move and thus get broken during priniting. Moreover you need some specialized software compatible with your printer. And you can even burn your fingers if you put them where you should not :)

  • iBeacons – small ‘stones’ equipped with Bluetooth adapaters. You can use it as local navigation in room but It will not be accurate. You can use it as advertising device but nobody has Bluetooth turned on. To sum up, you can use it for everything you can imagine but there is a big chance it will not work, at least not the way you want.


7. Clean architecture – jak uporządkować architekturę Twojej aplikacji. Wnioski z projektu by Andrzej Bednarz

kacperk:
I was disappointed after this lecture. The presentation was too similar to Uncle Bob’s “Clean architecture” (Architecture: The lost years) that I couldn't focus on the presentation, but for people who didn’t see other presentations it would obviously be a “must see”.

8. Wykrywanie i eliminacja zagrożeń w czasie rzeczywistym – Appsensor w akcji by Leszek Miś

walák:
Quite interesting lecture about defending web apps from attacks in real time by Web Applications Firewalls (WAFs). Presented software – WALLF which is developed by authors’ company – Linux Polska, can detect and identify the type of threat. It can determine if it was just mistyped data from user (e. g. letters in phone field) or more serious accident (e. g. use POST instead of GET method). This kind of applications are also designed to collect traces during real attack or just block attacker.

9. NoSQL – tylko nie NoSQL. Jak sobie radzić z nowym podejściem do baz danych by Marcin Karkocha

kacperk:
In my short career time I didn’t spend much of it on NoSQL database systems. It might have been why I've decided to see this presentation. It was really not what I expected, but I wassomehow satisfie. Marcin explained to us his point of view to that piece of it world. He was talking about his own experience on development and on production. For me a comparison on relational dbs and nosql ones was the important part. It motivated me to learn more in that subject.

10. Nie koduj, pisz prozę – lingwistyczne techniki wychodzące daleko poza Clean Code by Sławomir Sobótka

kacperk:
It isn’t easy to describe shortly presentations done by him. One should see it by himself. It was great and inspiring as always. Good job!

Summary

walák:

I find the conference as enlightening. From the lectures I saw none was definitively weak but of course some were better than another. The way I chose through Confitura almost did not meet any Java-strictly lectures so I can learn about some things being around. I will join Confitura next year for sure.

kacperk:

It is surely one of the best IT conferences in Poland. It is a good place to get know people and companies connected to Java world. Good think about Confitura is that people who don't program at all can find something for themselves. I can complain only about amount of awards that were alloted at the end, in comparison to previous year it was to little, but it is not important. Important is the fact we get out from there as more confident software developers, having broader view on ours lacks and thought about getting better and better.

walák: PS. Train was faster to Warsaw but we were back earlier :)


kacperk: PPS: But you missed after-party:P

 

2014-05-21

Rekrutacja

Szukamy pracowników na stanowiska Programista Java, Programista JavaScript, Projektant HTML. Oferujemy możliwość dokształcenia się podczas realizacji ciekawych projektów oraz elastyczne godziny pracy w przyjaznej atmosferze. Organizujemy hackathony, wyjazdy na konferencje, prezentacje techniczne oraz różne formy integracji.

Programista JavaScript


Wymagania:

  • bardzo dobra znajomość języka JavaScript

  • znajomość technologii HTML, CSS, XML, SQL

  • zdolność szybkiego uczenia się

  • umiejętność pracy w zespole

  • dobra znajomość języka angielskiego


Mile widziane doświadczenie w AngularJS oraz Ext JS oraz znajomość Javy i platformy Java EE.

@ InfoPraca.pl

Programista Java


Wymagania:

  • bardzo dobra znajomość języka Java

  • znajomość technologii HTML, CSS, JavaScript, XML, SQL

  • zdolność szybkiego uczenia się

  • umiejętność pracy w zespole

  • dobra znajomość języka angielskiego


Mile widziana znajomość platformy Java EE i frameworków webowych (np. Spring, Struts, Wicket, Hibernate)

@ InfoPraca.pl

Projektant HTML, CSS


Wymagania:

  • znajomość technologii HTML, CSS

  • znajomość Photoshopa lub innego programu graficznego

  • zdolność szybkiego uczenia się

  • umiejętność pracy w zespole

  • dobra znajomość języka angielskiego


Mile widziana znajomość języka JavaScript.

2014-05-16

GeeCON 2014 - podsumowanie

IMG_3360

IMG_3364

W tym roku wybraliśmy się wspólnie na konferencję GeeCON. Podsumowanie naszych wrażeń z tego wyjazdu można przeczytać tutaj.

2014-05-16

GeeCON 2014 summary

As a java company we think going to arguably the best java conference in Poland (and definitely the most community driven one) was a must. Fresh from the train back home, I thought a summary would be in order.

IMG_3360

IMG_3364

If not for the content itself, the 3 days in Krakow were a great bonding experience for us. As always though, the content was of high quality. I will summarise the talks that I have found personally the most appealing.



1. Kevlin Henney - "Seven Ineffective Coding Habits of Many Java Programmers"
This was a classic keynote material, perhaps more suited for a keynote then the following speech that Kevlin has delivered later on the same day. Extremely entertaining, the audience was kept alive for the whole speech duration. Many jokes kept everyone fresh while Kevlin enumerated the most "ineffective coding habits of java programmers". Some suggestions were probably perceived by most as rather controversive (i.e. putting the opening curly bracket in the next line), but all held up tight with strong arguments behind them.

This talk (even though not technical) touched on an important aspect of every coders life - how to make your code readable, which is something we struggle with even while reading our own code. In my opinion a good keynote is light, inspiring, entertaining yet thought provoking and this is exactly what this talk was.

2. Kevlin Henney - "Worse Is Better, for Better or for Worse"
Kevlin's keynote was also a great talk, though I'd switch the two around if it was for me. A great talk nonetheless, explaining how "worse is better" should be understood. The suggested philosophy was to (quite unlike the name suggests) focus on quality and fully implementing selected features, instead of going for a "feature complete" software. Not as entertaining, but equally thought provoking talk - another great one from Kevlin.

3. Johan Haleby - "Feel at ease and REST Assured"
This talk explored Johan's "REST Assured" framework for testing REST services. It was delivered with a perfect tempo and featured tons of code samples and short demos of how the framework works. Cool features with a very natural and clean syntax - I am looking forward to checking out the framework back home :) I really like Johan's presenting style - well paced talk with a lot of sample code to help grasp the basic and more advanced concepts offered by "REST Assured". Kudos!

4. Kirk Pepperdine - "Looking To Better Concurrency in Java 8"
Kirk touched on many interesting aspects of performance in Java (and in context of how PCs work internally), however never got into any details or haven't even fully explained what stand behind suggested concepts. This was perhaps due to the lack of time, but I found the talk hard to follow. Many interesting features shown though, so overall a solid talk for it's short time constraint :)

5. Peter Lawrey - "GC Free Coding"
Peter has an interesting presenting style - very calm and serene, down to the fact with many pauses. I was fairly tired after the previous day's party and this made me feel a little bit sleepy. Do not get me wrong though, Peter's talk was not boring, but, for lack of a better word, well planned and delivered.
Peter investigated many ways to keep garbage amount low in order to minimize the full GC, how and when to profile and some interesting and more or less hackish attempts to keep garbage from growing in the identified critical sections. Great talk!

6. Tom Enebo - "Modding Minecraft with a dash of Ruby"
I always enjoy Tom's talks - he keeps it fresh and entertaining. How else could it be if he was talking about modding Minecraft. Tom has started of with his first experience with the game, where he tried to dig down as far as he could, only to realise that the tools in the game decay when his pickaxe broke. Left stranded in a deep hole (after restarting the game he was in the same spot with no pickaxe) he decided to write a GoodbyeWorld mod that would allow him to "/die" :)

The talk followed with more madness, hooking up into events in order to spawn thousands of chickens or creating a huge TNT explosion. Great one by Tom!

The conference itself was very neatly organised. Kudos to the team.

Here is the short ranking of the 3 best talks as elected by our team:

1. Kevlin Henney - Seven Ineffective Coding Habits of Many Java Programmers
2. Jurgen Appelo - The 7 Duties of Great Software Professionals
3. Tom Enebo - Modding Minecraft with a dash of Ruby

2014-04-16

Devcrowd 2014

Some weeks ago me and Łukasz went to Szczecin in purpose to take part in DevCrowd'14, local software development conference. Szczecin is not far from Poznań, but required from us to get up early. The conference is getting better year by year. Also more partakers went ( some more informations. I had the pleasure to listen to following talks:

1. "Designing API for Mobile App" by Maciej Opała i Wojtek Erbetowski

Speakers were describing they way of solving problems with API used in mobile applications created by they company. They started with some introduction to REST architecture and went through some problems they solved. I know that this talk is to be on Geecon conference, so i recommend to go there or just watch it later online.


2. "StackOverflow, GitHub i twitter jako narzędzia profesjonalnego rozwoju programisty" by Jacek Laskowski

Jacek, as always, had an amazing talk. This one was somehow unusual. He described the adventages of using actively following tools: StackOverflow, GitHub and Twitter. Stackoverflow is for him a way to perform continous learning. He spends some time every day for answering questions on a topic chosen by him. Also there is some kind of gamefication, what is important for him. In case of Github i remember part when Jacek was talking that best representation of programmer is his own code. I realy liked that one talk.

3. "Programista to za mało" by Bartłomiej Nićka

The talk was about programmers career grow. He claimed that being simple code maker is not enough. Programmers should aim more to clients and usability of applications than just creating code. They should become software developers, somehow new level of their being. I agree with him in some way.

4. "How To Tackle Java EE 7" by Adam Bien

I was really disappointed about that presentation. It was remote, but that was not a problem. Problem was in complexity of that presentation. I expected something more than simple CRUD application, that are many on his youtube channel.

5. Jak nie zwariować by Koziołek

He made really nice summary of tools that we, as programmers, use every day. Starting from choosing good keyboard, to configuring properly IDE and through buying comfortable chair. I liked his idea of making chair just for himself.

 

devcrowd_2014

And We enjoying presentation:)

 

2014-04-07

Spring XD - Statystyki w czasie rzeczywistym

W nawiązaniu do ostatniej prezentacji na kanale springa przygotowaliśmy prosty przykład jak utworzyć statystyki dostępne w czasie rzeczywistym z wykorzystaniem projektu Spring XD (eXtreme Data). Artykuł dostępny jest tutaj w wersji angielskiej.