This is the third Post in my series Developing a web application with Spring Boot, AngularJS and Java 8.
My old application had a J2ME(!) companion on my dump phone that send my location to the app, showing it on the page.
This was 2009… Before my iPhone time.
Planning a longer bike tour in 2014, i wanted this feature back but i have not the slightest ambition on writing an iPhone app anytime soon, so i asked around on twitter and Darko came up with OwnTracks which uses the MQ Telemetry Transport protocol for publishing (and subscribing to) location updates.
So what ingredients do we need to implement this in a standalone Java application? Actually, not many. I’ve added Apache Active MQ, Spring JMS and Messaging as well as Spring Websocket support for the frontend fun:
Spring Boot has a managed dependency for ActiveMQ but only 5.7 which has some bugs regarding the MQTT broker, therefor i use 5.9.
With those components given, it’s incredible easy to configure brokers for:
- STOMP over WebSocket
- Local (VM based) messaging
- External messaging via MQTT
In the simples case you would now add @EnableWebSocketMessageBroker to a configuration class and be done, but i wanted to use
- My own broker
- A username/password protected broker
- Also use @EnableScheduling
1. To use a custom broker, implement WebSocketMessageBrokerConfigurer (or extend AbstractWebSocketMessageBrokerConfigurer) in a configuration class and configure the relay
If you do this, be sure to add “org.projectreactor:reactor-tcp” to you dependencies, otherwise a weird ClassNotFoundException pops up…
While you’re at it, configure the thread pool size for in- and outbound channels in #configureClientInboundChannel and #configureClientOutboundChannel according to your needs.
2. See above, just use a simple Java based approach to configure the embedded broker.
3. Now this is fun… If you use some scheduled jobs in your application as i do, you’ll end up with the following exception: “More than one TaskScheduler and/or ScheduledExecutorService exist within the context”. Yeah, great… If you don’t configure a default scheduler, the ScheduledAnnotationBeanPostProcessor tries to find all beans of type TaskScheduler or ScheduledExecutorService… If it finds none, it uses the default, if it finds one, uses this, if it finds more, everything breaks… @EnableWebSocketMessageBroker creates 2 schedulers… So you need to configure your own:
I wish there is more to say, but the rest is standard… Putting together some listener that reacts on incoming locations, calls the Spring Data Repository and uses SimpMessagingTemplate to notify all subscribed STOMP clients. For details regarding WebSocket and STOMP have a look at the Spring reference. As i didn’t have any luck with the Atmosphere frameworks in 3 different applications since 2011, i’m really happy how the Spring solution turned out. Maybe she is still a little buggy, but i’m quite sure this will be fixed.
It’s amazing what you can achieve with Java and Spring with little effort those days.