Building a BuzzwordClock with Reactor, Atmosphere, Spring-Boot and Vaadin

Posted on October 5, 2015

Recently I started working with reactive streams and event based systems using projectreactor.io. I thought it would be nice to use an event based approach to communicate between UI and server, so I dug around a bit and found vaadin-spring and vaadin-push.

So here is my buzzword-clock, a single file application that shows the current time using as many fancy technologies as possible:

  • Spring Boot with web-starter
  • Spring @Scheduled for the ticking clock
  • vaadin spring for the UI
  • vaadin push with atmosphere for updating the web-UI from the server
  • Reactor for the (async) EventBus.

For a full pom.xml, check out the repo.

![the clock in action](/img/buzzwordclock.png)
package io.github.jangalinski.playground.clock;
import com.vaadin.annotations.Push;
import com.vaadin.server.VaadinRequest;
import com.vaadin.spring.annotation.SpringUI;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import reactor.Environment;
import reactor.bus.Event;
import reactor.bus.EventBus;
import reactor.fn.Consumer;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static reactor.bus.selector.Selectors.$;
@SpringBootApplication
public class BuzzwordClockApplication {
public static String TOPIC = "clock";
public static void main(String... args) {
SpringApplication.run(BuzzwordClockApplication.class, args);
}
@Configuration
public static class ReactorConfiguration {
static {
Environment.initializeIfEmpty().assignErrorJournal();
}
@Bean
public EventBus eventBus() {
return EventBus.create(Environment.get());
}
}
@Component
@EnableScheduling
public static class Clock {
@Autowired
private EventBus eventBus;
@Scheduled(fixedDelay = 1000L)
public void everySecond() {
eventBus.notify(TOPIC, Event.wrap(LocalTime.now()));
}
}
@SpringUI
@Push
public static class ApplicationUI extends UI implements Consumer<Event<LocalTime>> {
private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
@Autowired
private EventBus eventBus;
private final Label labelTime = new Label(LocalTime.now().format(dateTimeFormatter));
@Override
protected void init(VaadinRequest vaadinRequest) {
labelTime.setStyleName("h1");
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
layout.setSpacing(true);
layout.addComponent(labelTime);
setContent(layout);
eventBus.on($(TOPIC), this);
}
@Override
public void accept(reactor.bus.Event<LocalTime> event) {
access(() -> labelTime.setValue(event.getData().format(dateTimeFormatter)));
}
}
}

Main Building blocks

  1. It is a spring-boot application, starting an embedded tomcat servlet container.
  2. It defines a Vaadin UI spring bean that is discovered and bound to “/”
  3. The “clock” bean is scheduled, its method is triggered every second.
  4. Using the reactor framework, it defines an Environment and an EventBus bean that loosly couples the server and the UI.
  5. Every second an event is fired (notify) containing the current local time as payload
  6. The UI consumes the localtime event and updates the label with the formatted time

Thanks to

For the push part, I leveraged the Using Server-Push in a Vaadin app example by P.J.Meisch.

Open points

Seams like I didn’t get the @EnableReactor annotation … I had to configure the reactor environment in a static block.