Skip to content
accelerando

Category Archives: Java

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.

Developing a web application with Spring Boot, AngularJS and Java 8

20-Feb-14

And if you’re feeling
You’ve got everything you came for
If you got everything
And you don’t want no more

You’ve got to just
Keep on pushing
Keep on pushing
Push the sky away

“Push The Sky Away” by Nick Cave & The Bad Seeds.

This is gonna be a lengthy post about always learning new things and improving old ones.

This is gonna be the 1st post of a series about learning new things and creating a modern Java application from start. In the first part I’m gonna write about the idea, the tools and the project itself.

All posts

  1. Part 1: Boot your application with Spring Boot
  2. Part 2: Using Java 8 .now()
  3. Part 3: Messaging and Websockets with Spring 4
  4. Part 4: Spring Boot as a backend for AngularJS

The idea and purpose of this thing

I had several reasons to create a project with well defined goals and requirements the way it should be.

The last weeks i had often discussions with current and possible future customers about the number or the price of my hours and i tried to tell them, that neither the price was too high or the number of estimated hours, especially the later, far from. I needed a reasonable sized and manageable project to prove this.

I also need to convince my colleges that near 100% test coverage and that database testing is possible and i also need to demonstrate that today a “one-guy-does-the-whole-stack” thing is nearly impossible if you don’t want to not sleep like me for about 2 weeks (or you’re just crazy about this stuff (also like me)).

And the most important reason for me is to learn something new, in this case learn about the new features in the upcoming release of Java 8.

Choosing the tools of the trade

Since 2010/11 i had real fun migration my daily picture project Daily Fratze from Ruby on Rails to Java, using the great Spring framework, so the first ingredient will be Spring but with it’s latest incarnation, Spring Boot: “Spring Boot favors convention over configuration and is designed to get you up and running as quickly as possible.”.

Certainly a new app will be written using Java 8. Just have a look at this post “Everything about Java 8″ if you need reasons.

I need a database and i’m still a huge fan of relational databases and so i need some JPA 2.1. To make my life easier, i chose Spring Data JPA together with a little embedded H2 Database.

And finally AngularJS. I’m a little bit old school, i like my html pages server generated but i wanted to know what all the cool kids are doing and learn something fresh. Also, i thought it would be useful in the goal of designing a nice api.

Putting it all together with: NetBeans. I’m an Eclipse user since about 2002 and it’s hard to teach an old dog new tricks, but Eclipse has no Java 8 support. The alternative, IntelliJ didn’t really click with my. It incredible slow on an 2012 iMac with 16Gb Ram, doesn’t feel right to me and has some things i really hate (for example, what’s with those xml files that are created for every maven dependency?) so i thought why not given NetBeans another try.

I remember NetBeans being slow (and ugly), but 7.4 just proved me wrong. It’s fast and snappy and as i mentioned, it’s Maven support just outstanding, namely: It just works. Just 2 additional config files in a Maven project and that’s it. All the pain i had to go through to make Eclipse m2e work with generated source file, assisted JPA classes and aspects: It just worked in NetBeans. Awesome.

The project

Simple, recreating my Ruby / Sinatra based biking application: biking.michael-simons.eu. The original application is a very condensed Ruby script, which worked very well, but it’s not very maintainable.

So goto biking.michael-simons.eu and have a look. The thing is live and runs on the Java 8 release candidate. The source code is available at GitHub.

I’d be more than happy about comments, recommendations and ideas.

On my way to Java 8

12-Feb-14

This is a post where i want to collect some new expressions i’m learning on my way to Java 8. Hopefully i’ll keep updating it…

Use an IntStream to generate an Array with constant default values

// The "() -> 23" is a lambda that matches the functional interface of a Supplier 
// The the stream itself is infinite, but the array can certainly be not, so we must limit it
IntStream.generate(() -> 23).limit(42).toArray()

Use a similar construct to fill a list with constant values:

// The IntStream has a collect method that uses a supplier to instantiate a new target, 
// an accumulator to add to the new target and combiner to merge two targets to perform 
// a reduction of the given elements
IntStream.generate(() -> 23).limit(42).collect(ArrayList::new, ArrayList::add, ArrayList::addAll)

Use a range to zip elements of an indexable collection together:

List<Foobar> foobars = new ArrayList<>();
List<Double> differences = IntStream.range(1, foobars.size()) // create exclusive range
	.mapToObj(i -> { // map this to your result of pairwise combining elements
	    final Foobar left = foobars.get(i - 1);
	    return foobars.get(i).getAmount() - left.getAmount();
	}).collect(Collectors.toList()); // collect it in a list

Last update: 2014/02/12

Modify memory settings of the Oracle Aurora JVM

07-Feb-14

Use the following class to view and modify the settings of the embedded JVM inside an Oracle database. The class has been tested on 10g and 11g, memory settings and information are in Megabyte.

SET DEFINE OFF
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "MemoryStatistics" AS
import oracle.aurora.vm.OracleRuntime;
 
public class MemoryStatistics {
    public final static INT MB_MULTIPLICATOR = 1024*1024;
 
	public static String getStatistics() {
		final Runtime runtime = Runtime.getRuntime();
 
		final long totalMemory = runtime.totalMemory();
		final long maxMemory = runtime.maxMemory();
		final long usedMemory = totalMemory - runtime.freeMemory();
 
        RETURN NEW StringBuffer()
        	.append(usedMemory/MB_MULTIPLICATOR)
        	.append(" / ")
        	.append(totalMemory/MB_MULTIPLICATOR)
        	.append(" MB (used / total), Maximum ")
        	.append(OracleRuntime.getMaxMemorySize()/MB_MULTIPLICATOR)
        	.append(", running on ")
        	.append(System.getProperty("java.version"))
        	.toString();
	}
 
    public static long getMaxMemorySize() {
        RETURN OracleRuntime.getMaxMemorySize() / MB_MULTIPLICATOR;
    }
 
    public static void setMaxMemorySize(final long maxMemorySize) {
        OracleRuntime.setMaxMemorySize(maxMemorySize*MB_MULTIPLICATOR);
    }
}
/
 
SHO ERR;
 
CREATE OR REPLACE PROCEDURE p_set_max_memory_size(p_max_memory_size IN NUMBER) IS LANGUAGE JAVA
    NAME 'MemoryStatistics.setMaxMemorySize(long)';
/
 
CREATE OR REPLACE FUNCTION f_get_max_memory_size RETURN NUMBER IS LANGUAGE JAVA
    NAME 'MemoryStatistics.getMaxMemorySize() return java.lang.Long';
/
 
CREATE OR REPLACE FUNCTION f_get_memory_statistics RETURN VARCHAR2 IS LANGUAGE JAVA
    NAME 'MemoryStatistics.getStatistics() return java.lang.String';
/
 
SELECT f_get_max_memory_size() FROM dual;
 
SELECT f_get_memory_statistics() FROM dual;
 
BEGIN
    p_set_max_memory_size(512);
END;
/
 
SELECT f_get_memory_statistics() FROM dual;

The memory settings is persistent across sessions, at least with my current setup.

CSRF protection with Spring Security revisited

29-Jan-14

At the end of last year, Spring Security 3.2 was released and brought a lot of new features, among them a built-in “Cross Site Request Forgery” protection”.

Nearly two years earlier i wrote my CSRF protection implementation with Spring Security 3.1, have a look here.

I really like the built-in implementation and most of it is very similar to my solution. The main difference is that the protection is at security filter level and not at application level like mine was. Also they use a token class for encapsulating the tokens name and value.

My solution can be very easily adapted to Spring Security 3.2.

First of all, configure it with the onliner

<csrf  />

or use the new annotation based configuration method.

Then throw away everything from my solution except the CSRFTokenTag. Edit the later one to contain the following code:

import java.io.IOException;
import java.util.Random;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
 
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;
 
/**
 * Creates a hidden input field with the CSRF Token
 * @author michael.simons, 2011-09-20
 */
@Configurable
public class CSRFTokenTag extends TagSupport {
	private final static Random random = new Random(System.currentTimeMillis());
 
	private static final long serialVersionUID = 745177955805541350L;
 
	private boolean plainToken = false;
	private String elementId;
 
	@Autowired
	private CsrfTokenRepository csrfTokenRepository;
 
	@Override
	public int doStartTag() throws JspException {		
		final CsrfToken token = csrfTokenRepository.loadToken((HttpServletRequest) super.pageContext.getRequest());
		if(token != null)
			try {
				if(plainToken)
					pageContext.getOut().write(token.getToken());
				else
					pageContext.getOut().write(String.format("<input type=\"hidden\" name=\"%s\" id=\"%s\" value=\"%s\" />", token.getParameterName(), StringUtils.isNotBlank(this.elementId) ? this.elementId : String.format("%s_%d", token.getParameterName(), random.nextInt()), token.getToken()));
			} catch (IOException e) {
			}
		return SKIP_BODY;
	}
 
	@Override
	public int doEndTag() throws JspException {
		return EVAL_PAGE;
	}
 
	public boolean isPlainToken() {
		return plainToken;
	}
 
	public void setPlainToken(boolean plainToken) {
		this.plainToken = plainToken;
	}
 
	public String getElementId() {
		return elementId;
	}
 
	public void setElementId(String elementId) {
		this.elementId = elementId;
	}	
}

The guys at Spring have a nice suggestions for including the token for AJAX/Jsons request. The new filter also validates request headers. The recommend adding the header name and token value to the pages meta information like so

  <meta name="_csrf" content="${_csrf.token}"/>
  <meta name="_csrf_header" content="${_csrf.headerName}"/>

and then manually add the header to each JavaScript request made with jQuery.

An alternative for jQuery users would be the following pre filter:

$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
	var token = $("meta[name='_csrf']").attr("content");
	var header = $("meta[name='_csrf_header']").attr("content");		  
	jqXHR.setRequestHeader(header, token);
});

I’m happy to be able to get rid of some code of mine, though the solution worked quite well for 2 years now.