Speaking at Confitura and JDD

13 01 2020

World class conferences in Poland – Confitura and JDD – hosted me as a speaker. Both are important events.

JDD was so special because I was there as a selected speaker from Warsaw JUG to take part in JUG Master contest. Didn’t win, I must admit, but anyway – It was fun :) and this afterparty… Well, that was something! Recording is below. From speech, not the afterparty ;)

On Confitura there was a huge audience and very good questions after the lecture. Participants of Confitura are true experts, searching for a new inspirations!

Confitura recording:

On both conferences I had a strong support from my company. Good feeling :)





Speaking at Devoxx Poland!

5 08 2019

Devoxx Poland is the biggest and the greatest Java conference in Poland. Since its beginning I missed only one edition. And this year was special as I joined it as a speaker!

Being selected as a speaker is a truly meaningful fact. Proving that what I have to say is interesting for the event at that scale.

I was thrilled to see 250 people from all over the Europe, listening to the idea I’m sharing. And getting feedback that they not only liked it, but also will try to use it in their daily work!

I hope it was a mind-opening session that everyone expects to see at the event of this brand.

Was it? Go on, check by yourself :)





J/vaCon Warsaw!

13 04 2019

54236883_2051852334862283_4618632440833900544_n

It was just a third meeting of this new meetup group but they’re already at the full speed! J/vaCon #3 was a very nice event! Organizers are full of energy and very commited.

I was there talking about automated tests – explaining what is the unit in unit tests and why it should be more than a method or a class.

Audience was big and very open! Thank you all! :)

20190326_183013

cof

 





Speaking at Warsaw Java User Group

28 03 2019

I was speaking about automated tests: unit and integration testing approach. See description here: https://www.meetup.com/Warszawa-JUG/events/258813049/ 

It was a very good meeting! The room was full and we had interesting discussions during that evening.

Video is here (in Polish)

And materials (slides + source code) here: https://github.com/yacekmm/testingDemo 

DSC_0087.JPG





Automated tests for Spring Boot WebSocket server

20 05 2017

Developing WebSocket server for your Spring Boot app is fairly simple and well described and documented. However when it comes to making sure that it ‘actually works’ is done manually in most cases.

Below I will show how I do the automated integration tests for Websocket server using Spring’s StompClient. I assume that you are familiar with the idea of WebSockets in Spring. If not, here is a very good article: https://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html

Source Code

Code of this tutorial is for you to see here: https://github.com/yacekmm/looksok/tree/WebSocketDemo/Spring/WebSocket

System under test: configuration

The demo will be presented on the simpliest WS configuration which consists of one entry point endpoint (`/ws`) and in-memory message broker (under `/queue`):

@Configuration
@EnableWebSocketMessageBroker
public class WsConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) { 
        registry.addEndpoint("/ws");
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/queue");
    }
}

The idea behind the integration test

In the test I’m going to:
– use SpringRunner to start up the whole application with the full context
– Autowire Component that in production will be responsible for sending messages to WebSocket clients
– Build and configure Spring’s StompClient and connect a StompSession to my WebSocket server
send a message over WebSocket and verify if my test client received it

Starting the application for tests

With SpringRunner.class used within jUnit test I start the app context and autowire the WSProxy component (the one that sends messages to WS clients):

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
public class WsConfigIntegrationTest {

    @Value("${local.server.port}")
    private int port;
    @Autowired
    private WsProxy wsProxy;

WsProxy in this demo is a simple component sending message with a SimpMessagingTemplate:

@Component
public class WsProxy {

    private SimpMessagingTemplate messagingTemplate;

    @Autowired
    public WsProxy(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    public void sendMessage(@RequestParam String clientId,
                            @RequestParam String payload){
        messagingTemplate.convertAndSend("/queue/" + clientId, payload);
    }
}

In this configuration, the url of WS endpoint is:

String wsUrl = "ws://127.0.0.1:" + port + "/ws";

Configuring StompClient and connecting StompSession

Using the StompClient with a minimum configuration:

WebSocketStompClient stompClient = new WebSocketStompClient(new StandardWebSocketClient());
stompClient.setMessageConverter(new StringMessageConverter());

I create StompSession to my WS url:

StompSession stompSession = stompClient.connect(wsUrl, new MyStompSessionHandler()).get();

The connect() method returns a future, but here, in tests, I wait synchronously until this session is ready by calling get() on it to get the session instantly.

Oh, and don’t worry about the MyStompSessionHandler – in this configuration it does nothing, except debug logging on the ‘Connect to WS’ event (just overrides the StompSessionHandlerAdapter)

Now it’s time to subscribe the /queue/my-id Channel within the session:

stompSession.subscribe(
    "/queue/my-id", 
    new MyStompFrameHandler((payload) -> resultKeeper.complete(payload.toString())));

The MyStompFrameHandler class is responsible for handling the incoming message in within the session and completing the CompletableFuture promise that it received as an argument. CompletableFuture is a helper variable needed to test asynchronous code:

CompletableFuture<String> resultKeeper = new CompletableFuture<>();

And the handler uses it as follows:

public class MyStompFrameHandler implements StompFrameHandler {

    private final Consumer<String> frameHandler;

    public MyStompFrameHandler(Consumer<String> frameHandler) {
        this.frameHandler = frameHandler;
    }

    ...

    @Override
    public void handleFrame(StompHeaders headers, Object payload) {
        log.info("received message: {} with headers: {}", payload, headers);
        frameHandler.accept(payload.toString());
    }
}

Sending the message

Message is sent by a WsProxy with SimpMessagingTemplate:

@Component
public class WsProxy {

    private SimpMessagingTemplate messagingTemplate;

    @Autowired
    public WsProxy(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    public void sendMessage(String clientId, String payload){
        messagingTemplate.convertAndSend("/queue/" + clientId, payload);
    }
}

On some machines it’s also good to wait until the connection is fully established so don’t hesitate to add good old:

Thread.currentThread().sleep(1000);

Testing the result asynchronously

The code in test is async so I pass the Future and wait until it completes with the expected result, or to fail test after timeout on waiting for the response, verifying its body:

assertThat(resultKeeper.get(2, SECONDS)).isEqualTo("test-payload");

That’s it

Now you can run the test, it will start your app, send a message, receive it and verify the contents. Which is everything you need to implement the WebSockets.

Source Code

I’m sure that seeing the source code will make you understand the article better. Grab it from my GitHub: https://github.com/yacekmm/looksok/tree/WebSocketDemo/Spring/WebSocket





Proxy configuration for Gradle

6 05 2017

Are you using gradle behind corporate proxy? Here is how to configure proxy data for gradle (urls and credentials)

gradle.properties file

Gradle (and gradlew as well) is automatically reading gradle.properties file that is either in project directory or in USER_HOME/.gradle directory.

Inside of gradle.properties file set properties:

systemProp.http.proxyHost=http_proxy_ip_or_url
systemProp.http.proxyPort=port
systemProp.http.proxyUser=username
systemProp.http.proxyPassword=pwd
systemProp.https.proxyHost=https_proxy_ip_or_url
systemProp.https.proxyPort=port
systemProp.https.proxyUser=username
systemProp.https.proxyPassword=password

The configuration above concerns both http and https traffic.

Inline properties

As an alternative you can specify properties in each gradle command by:

gradle build -Dhttp.proxyHost=http_proxy_ip_or_url ...




Free weekend on CodeSchool!

19 11 2016

Get off from beaten track with new technology you always wanted to learn – CodeSchool.com gives free access to all its courses over this weekend! 

Try it: https://www.codeschool.com/free-weekend

There are several courses that takes 2 to 4 hours to attend so no excuses :)








%d bloggers like this: