Skip to content
accelerando

Tag Archives: Spring

Upgrading to Tomcat 8.0.24

15-Jul-15

If you upgrade your Tomcat installation to 8.0.24, released on July 6th, and all your POST requests suddenly starts to fail, check

 maxPostSize

of your connectors.

The Tomcat team actually fixed it’s behavior:

The meaning of the value zero for the maxPostSize has also been changed to mean a limit of zero rather than no limit to align it with maxSavePostSize and to be more intuitive

The maximum size in bytes of the POST which will be handled by the container FORM URL parameter parsing. The limit can be disabled by setting this attribute to a value less than zero. If not specified, this attribute is set to 2097152 (2 megabytes).

I had a 0 (zero) in it… That means absolutely no post data. If the setting makes sense or not is irrelevant, it’s correct that way. So, if you’re post requests fail and you wanted to disable the maximum post size, set it to -1.

Ah, and by the way, since Tomcat 8 you can drop the spring-instrument-tomcat module and the stanza in context.xml:

<Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>

Tomcat 8 supports load-time weaving of aspects out of the box and for me, having that module on the class path and using the Spring provided class loader, weaving didn’t work.

Spring: Provide Interoperability between JMS and Springs simple WebSocket messaging

03-Mar-15

Nearly 2 years ago, excellent WebSocket Support appeared in Spring 4, easily usable using STOMP over Websockets / SockJS on the client side, backed by a pluggable broker on the server side, which can either be simple broker using scheduled executor services to handle message or a full fledged RabbitMQ or ActiveMQ solution.

Using

@EnableWebSocketMessageBroker

enables the first solution without much fuss, integrating an existing and running ActiveMQ STOMP transport is nearly as easy:

@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
    registry.enableStompBrokerRelay("/topic")
	.setRelayPort(1234)
	.setClientLogin("client-user")
	.setClientPasscode("client-password")
	.setSystemLogin("sys-user")
	.setSystemPasscode("sys-password");
    registry.setApplicationDestinationPrefixes("/app");
}

I’ve already used (and i am using) such a solution in this application, as described here. What you’re doing is not instantiating your own scheduler and transport, but relaying everything to the existing transport which is nice when you don’t want to was resources.

What’s missing here, is some deeper integration.

Using Springs JmsTemplate it’s really easy to send JMS messages and it’s also easy to connect simple beans or services through messages:

Imagine an arbitrary service, not knowing anything about jms:

class SomeCmd {
}
 
public class SomeService {
  public void someVoidMethod(final SomeCmd someCmd) {
    System.out.println("Something incredible");
  }
}

Connecting this to a queue is as easy as:

import javax.jms.ConnectionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.listener.SimpleMessageListenerContainer;
import org.springframework.jms.listener.adapter.MessageListenerAdapter;
 
@Configuration
class Config {
 
  @Bean
  public SimpleMessageListenerContainer someServiceContainer(final SomeService someService, final ConnectionFactory connectionFactory) {
 
    // Create an adapter for some service
    final MessageListenerAdapter messageListener = new MessageListenerAdapter(someService);
    // Connect the method 
    messageListener.setDefaultListenerMethod("someVoidMethod");
    // to a queue	
    final SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setDestinationName("some.queue");
    container.setMessageListener(messageListener);
    container.setConnectionFactory(connectionFactory);
 
    return container;
  }
}

Sending messages is a onliner:

jmsTemplate.convertAndSend("some.queue", new SomeCmd());

If that method isn’t a void method, the result can automatically be passed to another queue:

class SomeCmd {
}
 
class SomeResult {    
}
 
public class SomeService {
  public SomeResult someNonVoidMethod(final SomeCmd someCmd) {
    return new SomeResult();
  }
}
 
// Change in the config
messageListener.setDefaultListenerMethod("someNonVoidMethod");
 
// And added to the config:
messageListener.setDefaultResponseQueueName("some.response.queue");

What if i want to have the result right available on a web site using WebSockets and STOMP? Although the name sounds similar, the SimpMessagingTemplate has nothing todo with the JmsTemplate, at least not immediately.

As it turns out, it’s relatively simple redirecting the output of bean to the STOMP queue, knowing

Note that the prefix in stomp /queue/ or /topic/ is removed from the string before passing it to ActiveMQ as a JMS destination. Also note that the default separator in MOM systems is . (DOT). So FOO.BAR is the normal syntax of a MOM queue – the Stomp equivalent would be /queue/FOO.BAR

Working with Destinations with Stomp

In the above example

messageListener.setDefaultResponseQueueName("some.response.queue");
// becomes
messageListener.setDefaultResponseTopicName("some/response/topic");

Which means: Everything SomeService#someNonVoidMethod returns is send to a STOMP topic call /topic/some/response/topic.

Nice. But it turns out, SimpMessagingTemplate converts the messages body to a nice, readable JSON format, internally proceeded by Jacksons Object Mapper. Without a custom converter, we’ll end up with a MapMessage. To make the outcome of the topic the same, regardless wether produced using SimpMessagingTemplate or redirecting the outcome from a JMS queue, we need a converter. If you’re using ActiveMQ like i you can use a “Message transformations”, but that has some drawbacks: The connection needs to be opened with a special header and what is worse, the Json generation is based on Jettison (which i cannot link anymore because the Codehause page stopped working) which is basically impossible to customize.

So instead, i assume there are ObjectMessages entering my queue (send through JmsTemplate to reach my service) and outgoing stuff should be in form of TextMessages. With that assumption, just use a slightly adapted MappingJackson2MessageConverter:

import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.listener.SimpleMessageListenerContainer;
import org.springframework.jms.listener.adapter.MessageListenerAdapter;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageType;
 
@Configuration
class Config {
 
  @Bean
  public SimpleMessageListenerContainer someServiceContainer(final SomeService someService, final ConnectionFactory connectionFactory) {
 
  	// Create an adapter for some service
  	final MessageListenerAdapter messageListener = new MessageListenerAdapter(someService);
  	// Connect the method [1]
  	messageListener.setDefaultListenerMethod("someNonVoidMethod");
 
  	// Direct every outcome of "someNonVoidMethod" to a topic, that is 
  	// subscribable via  stompClient.subscribe('/topic/some/response/topic', {});
  	messageListener.setDefaultResponseTopicName("some/response/topic");
  	// and take care of converting someResult to a JSON payload, otherwise we'll end up with a 
  	final MappingJackson2MessageConverter messageConverter = new MappingJackson2MessageConverter() {
  	  @Override
  	  public Object fromMessage(Message message) throws JMSException, MessageConversionException {
  		  return message instanceof ObjectMessage ? ((ObjectMessage) message).getObject() : super.fromMessage(message);
  	  }
 
  	  @Override
  	  protected TextMessage mapToTextMessage(Object object, Session session, ObjectMapper objectMapper) throws JMSException, IOException {
  		  final TextMessage rv = super.mapToTextMessage(object, session, objectMapper);
  		  rv.setStringProperty("content-type", "application/json;charset=UTF-8");
  		  return rv;
  	  }
  	};
  	messageConverter.setTargetType(MessageType.TEXT);
 
  	// [2] to a queue	
  	final SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
  	container.setDestinationName("some.queue");
  	container.setMessageListener(messageListener);
  	container.setConnectionFactory(connectionFactory);
 
  	return container;
  }
}

This creates a configuration for creating a JMS Message Queue who’s outcome is send to a topic in the same format as Springs SimpMessagingTemplate would create, allowing to send messages to an arbitrary service whose return values are in turn passed (among others) to listeners on a WebSocket. This prevents manually connecting return values from a service to SimpMessagingTemplate, for example by injecting SimpMessagingTemplate into the service and manually calling convert and send. The service can therefore be a simple bean, not knowing anything about Spring, Jms, STOMP or Websockets.

Creating Specification<> instances for Spring Data JPA with Spring MVC

24-Sep-14

One common requirement in web applications is to be able to filter a given set of data through request parameters. One way to do this is fetch everything from the server and filter it on the client. Me, i’m more of a server guy and i tend to do this inside a database.

Many projects of mine are developed with JPA based beans for the data model and recently i’ve come to really love Spring Data JPA. With the plain declaration of an interface extending a repository interface, you get everything you need to query your domain. Through in a second interface and you can execute JPA based criteria queries:

import entities.Projekt;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 
public interface ProjektRepository extends JpaRepository<Projekt, Long>, JpaSpecificationExecutor {    
}

My goal: Create controller methods for Spring MVC like so

@RequestMapping(value = "", method = GET)
public Page<Projekt> getProjekte(
    final @RequestParam(defaultValue = "0", required = false) int page,
    final @RequestParam(defaultValue = "10", required = false) int pageSize,	    
    final @RequestParam(required = false, defaultValue = "lieferjahr") String orderBy,
    final @RequestParam(required = false, defaultValue = "ASC") Direction orderByDirection,
    final @FilterDefinition(paths = FilteredPathsOnProjekt.class) Specification<Projekt> filter	    
) {
    return this.projektRepository.findAll(filter, new PageRequest(page, pageSize, new Sort(orderByDirection, orderBy)));
}

where the filter parameter is of type Specification and where i can define which fields are to be filtered in which way in a type-safe way that is checked on compile time like so:

public static class FilteredPathsOnProjekt<Projekt> extends FilteredPaths<Projekt> {
    public FilteredPathsOnProjekt() {	    
        filter(Projekt_.lieferjahr)
            .with((cb, p, value) -> cb.like(cb.function("to_char", String.class, p, cb.literal("YYYY")), value + "%" ))
        .filter(Projekt_.angelegtAm)
            .with((cb, p, value) -> cb.like(cb.function("to_char", String.class, p, cb.literal("DD.MM.YYYY")), "%" + value + "%"))
        .filter(Projekt_.anwender, Anwender_.name)
            .with((cb, p, value) -> cb.like(cb.lower((Path<String>)p), "%" + value.toLowerCase() + "%"))
        .filter(Projekt_.marktteilnehmer, Marktteilnehmer_.name)
            .with((cb, p, value) -> cb.like(cb.lower((Path<String>)p), "%" + value.toLowerCase() + "%"))
        .filter(Projekt_.versorgungsart)
            .with((cb, p, value) -> cb.like(cb.lower((Path<String>)p), "%" + value.toLowerCase() + "%"));		
    }
}

I found this very inspiring post An alternative API for filtering data with Spring MVC & Spring Data JPA by Tomasz and here again, i big thank you.

My solution is similar, but uses the JPA Metamodel API that generates a metamodel from the annotated entity classes. In the above example, the entity is Projekt, the metamodel Projekt_ that lists all attributes that are mapped from the database.

Let’s start with the controller. Parameter filter is of type Specification and is annotated with @FilterDefinition:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface FilterDefinition {
    Class<? extends FilteredPaths> paths();
 
    Class<? extends FilterSpecification> implementation() default FilterSpecification.class;
}

I need to wrap the paths i want to filter with a class because only are small list of types are allowed in annotations. The class looks like this:

import java.util.List;
import java.util.Map;
import javax.persistence.metamodel.SingularAttribute;
 
public abstract class FilteredPaths<T> {
    protected final FilteredPathsBuilder<T> builder = new FilteredPathsBuilder<>();
 
    public final Map<List<SingularAttribute<?, ?>>, PathOperation<T>> getValue() {
        return this.builder.getFilterablePaths();
    }
 
    protected FilteredPathsBuilder<T> filter(SingularAttribute<?, ?>... path) {
        return builder.filter(path);
    }
}

The core of this is the getValue method. It returns a map of lists of SingularAttributes (a list of them to do queries on sub elements) and a PathOperation. PathOperation is a functional interface:

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import org.springframework.data.jpa.domain.Specification;
 
@FunctionalInterface
public interface PathOperation<T> {
    public Predicate buildPredicate(CriteriaBuilder cb, Path<?> path, String value);
}

that is used by my FilterSpecification to build the predicate:

import java.util.Map;
import java.util.function.Function;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.data.jpa.domain.Specification;
 
import static java.util.stream.Collectors.reducing;
 
public class FilterSpecification<T> implements Specification<T> {
 
    protected final Map<PathOperation, PathAndValue> filteredPaths;
 
    public FilterSpecification(Map<PathOperation, PathAndValue> filteredPaths) {
        this.filteredPaths = filteredPaths;
    }
 
    @Override
    public final Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        this.customizeQuery(root, query);
        return this.filteredPaths.entrySet().stream()
            .map(entry -> entry.getKey().buildPredicate(cb, entry.getValue().getPath(root), entry.getValue().getValue()))
            .collect(
                reducing(cb.conjunction(), Function.<Predicate>identity(), (p1, p2) -> cb.and(p1, p2))
            );
    }
 
    protected void customizeQuery(Root<T> root, final CriteriaQuery<?> query) {
    }
}

As you see there’s one big difference to Tomasz solution: I don’t support OR’ing the filters, i’ve only support AND. I like the way i can use the Java 8 stream api and the reduction method to add them together very much.

How get’s this class instantiated? Here come’s the additional Spring MVC argument resolver:

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.persistence.metamodel.SingularAttribute;
import org.springframework.core.MethodParameter;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
 
public class FilteringSpecificationArgumentResolver implements HandlerMethodArgumentResolver {
 
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(FilterDefinition.class) && parameter.getParameterType() == Specification.class;
    }
 
    @Override
    public Object resolveArgument(
        MethodParameter parameter,
        ModelAndViewContainer mavContainer,
        NativeWebRequest webRequest,
        WebDataBinderFactory binderFactory
    ) throws Exception {
        final FilterDefinition filterDefinition = parameter.getParameterAnnotation(FilterDefinition.class);	
        final FilteredPaths<?> paths = filterDefinition.paths().newInstance();
 
        final Map<PathOperation<?>, PathAndValue> filterValues = new HashMap<>();
        paths.getValue().entrySet().forEach(entry -> {
            final String param = entry.getKey().stream().map(SingularAttribute::getName).collect(Collectors.joining("."));
            final String paramValue = Optional.ofNullable(webRequest.getParameter(param)).orElse("");
            if (!paramValue.isEmpty()) {
                filterValues.put(entry.getValue(), new PathAndValue(entry.getKey(), paramValue));
            }
        });
 
        return filterDefinition.implementation().getConstructor(Map.class).newInstance(filterValues);
    }
}

It supports controller arguments of type Specification annotated with @FilterDefinition. To resolver the argument it gets the annotation and then instantiates the class that holds the lists of paths that should be filtered. The lists actually contains the path and the filter operation. It’s iterated and each list of singular attributes is joined together with a “.”, so one attribute becomes “versorgungsart” and a nested becomes “marktteilnehmer.name” for example. It then checks the web requests if there are request params with those names. If so, the filter operation is added together with the path and the value for that path (from the request) to a new map (the operations are the key). This map than is passed to the implementation of the Specification.

What’s nice here: I don’t need to check if the attributes that are requested from the outside exists. As i start with the attributes of the entity from the start, there’s no chance i try to access one that doesn’t exists.

What’s missing is the pair type PathAndValue

import java.util.List;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.SingularAttribute;
 
public class PathAndValue {
 
    private final List<SingularAttribute<?, ?>> path;
    private final String value;
 
    public PathAndValue(List<SingularAttribute<?, ?>> path, String value) {
        this.path = path;
        this.value = value;
    }
 
    public String getValue() {
        return value;
    }
 
    public Path<?> getPath(final Root<?> root) {
        Path<?> rv = root;
        for (SingularAttribute attribute : path) {
            rv = rv.get(attribute);
        }
        return rv;
    }
}

that not only holds both the path (as a list of attributes) to be filtered and value to be filtered with, but also generates a complete JPA criteria path that is given to the PathOperation.

And last but not least is the little FilteredPathsBuilder that allows me to write the filter definition in a readable way and not obstructed with map and list operations as shown in FilteredPathsOnProjekt above:

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.metamodel.SingularAttribute;
 
public class FilteredPathsBuilder<T> {
    private final Map<List<SingularAttribute<?, ?>>, PathOperation<T>> filterablePaths = new HashMap<>();
 
    private List<SingularAttribute<?, ?>> lastPath;
    private PathOperation<T> lastOp;
 
    public FilteredPathsBuilder<T> filter(SingularAttribute<?, ?>... path) {
        if(lastPath != null && lastOp != null) {
            filterablePaths.put(lastPath, lastOp);	    
        }
        this.lastPath = Collections.unmodifiableList(Arrays.asList(path));
        this.lastOp = null;
        return this;
    }
 
    public FilteredPathsBuilder<T> with(PathOperation<T> op) {
        this.lastOp = op;
        return this;
    }
 
    public Map<List<SingularAttribute<?, ?>>, PathOperation<T>> getFilterablePaths() {
        if(lastPath != null && lastOp != null) {
            filterablePaths.put(lastPath, lastOp);	    
        }
        this.lastPath = null;
        this.lastOp = null;
        return Collections.unmodifiableMap(filterablePaths);
    }    
}

As you can see in FilteredPathsOnProjekt above i have now a little DSL that i use to define which attribute of my entity should be filtered. Writing down the PathOperation as lambdas and using the generated MetaModel to specify the attributes i have not only filters that are checked on compile time but also have the the attributes definition only in one place. All solutions that require writing down lists of request parameters or fiddling with map parameters are too error prone and in the end, way too much work to write.

The above solution works fine with Spring 4.0.x and 4.1.x and certainly with Spring Boot. I’ve got tests for all of the code above and should anyone find this solution useful, i’m gonna prepare a standalone project with it.

Let me know, what you think.

Spring Boot as a backend for AngularJS

15-Apr-14

This is the fourth Post in my series Developing a web application with Spring Boot, AngularJS and Java 8.

I’m more a backend and database guy than a frontend developer, but i know how to write valid HTML and add some unobtrusive JavaScript to it, for example in my daily photo project. Daily Fratze is an “old-school” website for visitors and a more interactive site for users.

For my Biking Project and this series of blog posts i wanted to try out something new (for me) and i picked AngularJS to create a single page web application.

Most of the things i’ve done in AngularJS are pretty standard (i guess), but have a look at the sources yourself: bikings js.

Therefor i want to highlight just a few things that made Spring Boot play nicely with AngularJS:

“Routes”

I wanted biking.michael-simons.eu as well as biking.michael-simons.eu/about too work when entered in the address bar or followed through a link. To achieve this, i’m using AngularJS in HTML5 mode. Really, for this project i couldn’t care less about browser which don’t support this:

The whole html “application” lives in webapp/public/index.html which is served as a static resource by Spring Boot without any further server interaction.

To create “routes” for all URLs in app.js, i’ve created a super simple @Controller:

This forwards all mapped urls to the static resource without any further view resolving. Nice!

WebJars

Spring Boot has excellent support for WebJars and automatically creates resolvers for them. Using web jars i can manage all dependencies for AngularJS and co. with Maven (yeah, i’m still using maven… 😉 ):

and for example

And in index.html

Those placeholders work because i’ve enabled resource filtering in maven for selected resources in webapp. I know that there are a lot of JavaScript dependency managers out there, but this solution works very well for me. An option is to add wro4j to the mix.

Authentication

I’m using plain old http basic auth. Yes, i do know that the password is transmitted in plain text but for this app and this purpose, i just don’t care. For your interest, here’s the Spring Security configuration for stateless http basic auth:

I’ve got to disable csrf protection because i don’t want to handle that in AngularJS and also, i’ve disable frame headers because the application acts as an oembed provider with frames.

I didn’t protect the whole app, but only backend methods with write access through annotations which is enabled via @EnableGlobalMethodSecurity and looks like:

Using @RestController from AngularJS

The above quoted method can easily be used from AngularJS:

“$scope.bike” is a JSON object representing an instance NewBikeCmd. AngularJS maps this correctly as a @RequestBody, the thing is validated and everything else. Really nice.

Fancy things created with AngularJS

I’m not using AngularJS not long enough to rate this, but i really like the automatically refreshing about page which is created using through highcharts-ng and the nice OpenLayers integration for the tracks, written by myself: track-map-ng (OpenLayers), see an example here: Aachen – Domburg.

Summary

Rewriting this existing application from scratch (apart from the database model, that was fine), was real fun. Not only i could test and enjoy many new Java 8 features, but starting fresh, using well designed frameworks like Spring, Spring Boot and Spring Data JPA fixed many things for me i used to do wrong, sometimes because of some cargo cult i hand in mind, sometimes because i just didn’t get them right from the start.

Spring Boot together with Spring Data JPA are an excellent choice for me to write lightweight backends for JavaScript applications without loosing any functionality.

Look at some other projects of mine, i have no doubt that Boot is also a good choice for writing bigger applications, maybe with a more classical frontend, either JSP or Thymeleaf based.

Also: Java is not dead yet, in 2014 more far from than ever.

Thanks for reading so far.

Messaging and Websockets with Spring 4

21-Mar-14

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

like this

In the simples case you would now add @EnableWebSocketMessageBroker to a configuration class and be done, but i wanted to use

  1. My own broker
  2. A username/password protected broker
  3. 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.

At the moment the location site runs on an uberspace behind a proxy, but STOMP together with SockJS handles this situation gracefully (and are actually dead simple to use):

It’s amazing what you can achieve with Java and Spring with little effort those days.