Skip to content
accelerando

JavaLand 2015 result: JavaFX 3d mosaic for dailyfratze.de

31-Mar-15

JavaLand 2015 resulted in a sweet little toy project for me (See my little reviews of the conference itself here: 24.3, 25.3 and 26.3, JavaLand 2015 was one of the best conferences i attend. Lots of fun, lots of good talking, i really enjoyed it).
Wolf Nkole Helzle had this My-Matrix project going on there and i thought, well, this year i’m doing Daily Fratze for ten years and i alone will have 3650 pictures of myself uploaded to the internet by August and in sum there are over 50.000 images right now, that should be a pretty good idea, creating an interactive mosaic as well (Adastra has already created a beautiful mosaic on her 8th anniverary).

As i don’t want to share the images anywhere else but only in my own daily picture project i had the opportunity to learn some more stuff which you can find here.

The basic idea for this mosaic generator is: Create an accurate color matching algorithm as readible as possible. Lukas Eder had this nice article on dzone why It’s Okay to Stick With SQL and i wanted to see how far can i get with SQL for my goal.

This project includes:

  • Flyway for creating and migrating databases (i didn’t want to run sql-scripts myself)
  • Flyway and jOOQ maven integration for effortless generating dao code at compile time
  • jOOQ in common for all database access
  • An CIE94 color distance algorithm
  • JavaFX 3d for creating a spherical image wall. Kudos and thanks to José Pereda for inviting me and giving me a real great introduction not only to his cool JavaFX presentation tool (which gives live coding a whole new dimension), but also to JavaFX 3D. Next time i try to be not that shy, but was too impressed by this massive Java knowledge all around me.

Also personal thanks to mentioned Lukas Eder, maybe you didn’t notice but you encouraged me a lot in what I am doing at the moment.

You’ll finde the complete source code for this project at github:

dfx-mosaic @ github.

So, how far did i come? Far! First have a look at the JavaFX application, selecting the tiles and rendering them on an image wall and me exploring the scene:

Mosaic generation is done in two steps: Create a database of images including their average color (Average color defined by the arithmetical average of all rgb values in an image). You gotta love Java 8s stream for how simple such things have become:

And then (for example):

Those list of images records: Just put them in a SQL database. I choose H2 for simplicity and i’ve gotta say, Flyway and jOOQ are really a dream time. I used this tutorial and had my Records and DAOs in no time.

I like jOOQs batch api, way easier then to this by hand:

create.batchInsert(records).execute();

Writing the CIE94 color distance was the hard part, making it usable inside an H2 database is really easy:

create.execute("create alias if not exists f_CIE94_color_distance deterministic for \"de.dailyfratze.mosaic.images.CIE94ColorDistance.compute\"");

I’d prefer having this done also in migration, but the referenced method must be defined at runtime, so no chance here.

The basic idea for my mosaic algorithm is selecting the source image with the least color distance which has not been used in box of 10 by 10 tiles. I could have come up with a more performant algorithm but that would have been as easy as just iterating the tiles of the target image and just selecting it (the variable tiles contains all selected tiles so far):

SQL checked by the compiler, correct in statement, calling stored procedures. All there, readable and really easy to use.

The JavaFX 3d application is nearly identical to the VideoWall on Stack Overflow but serves me well for further experiments.

I plan to arrange the images by year on the z-axis (done, see below), create some dialogs for choosing creating and choosing libraries, settings for tile size and such. If i should have to much time on my hand, i’d love to see touch support, a Raspberry Pie and a touch screen for doing some kind of installment on my 10th anniversary of daily self portraits.

I’ve also included a little terminal application which just writes mosaics to file, the result looking like so:

2014-10-03_mosaic

Compare to the original (taken at Mavericks beach on my trip to JavaOne 2014):

2014-10-03_original

And a screenshot from the JavaFX app with the images spread by year on the z-axis:

mosaic_3d

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.

ALT+Click all the things

05-Dec-14

Here’s a list of things you can ALT+Click (Option key ⌥ + left mouse button) in Mac OS X:

  • ALT+Click on the WiFi icon in the menubar gives you detailed information about your selected WiFi network
  • ALT+Click on the volume icon in the menubar lets you quickly select audio input and output device
  • ALT+Click on any of the triangles on a tree-ish view (Finder in listmode, IDEs etc.) expands or collapses all subitems
  • If you have multiple Time Machine volumes attached, ALT+Click on the Time Machine icon in the menubar lets you browse other Backups than the default with that spacy interface
  • ALT+Click on the BlueTooth icon shows some information about your device id
  • ALT+Click on the battery icon shows the health of your laptops battery
  • ALT+Click on the maximize icon in the title bar restores the old behavior of Mac OS X to maximize the window to the desktop and not going fullscreen
  • ALT+Click on the notification icon in the menubar toggles “Do not disturb” mode for notifications
  • ALT+Shift+Volume keys changes the volume in ¼ increments or decrements
  • ALT+Shift+Brightness keys changes the brightness in ¼ increments or decrements
  • ALT+Click on the (green) fullscreen button in the title bar of application windows maximizes them “the old way”, that is: maximum size on the screen, not fullscreen. Same effect as double click on the title bar

If you know more, please leave a comment because:

56833531

Detailed CPU Information on Mac OS X

28-Oct-14

To get somewhat more detailed CPU information on your Mac than the system profiler shows, use the following command:

sysctl -n machdep.cpu.brand_string

Custom editor components in JavaFX TableCells

27-Oct-14

There’s a lot of confusion about custom editor components in TableCells for JavaFX applications. The problem: Someone (like me) implements a custom TableCell with a DatePicker or a ColorPicker for example. A naive solution maybe looks like this.

That works in so far that the value is correctly displayed in the ColorPicker and the ColorPicker is active and can be changed. But, given that the cell is editable, the property of the cells item is editable, the value of it never changes, regardless what is selected in the ColorPicker.

You’ll find a lot of tips like this or this. They have in common that they are either rather complex and most of the time uses a stanza like this:

TableCell cell;
cell.contentDisplayProperty().bind(Bindings.when(editingProperty())
                    .then(ContentDisplay.GRAPHIC_ONLY)
                    .otherwise(ContentDisplay.TEXT_ONLY));

Although pretty cool feature that bindings can be conditionally expressed, but not so useful. What is stated there is: “If the table is not in editing mode, use the text set with setText (in that case a formatted date), otherwise, if editing mode, use the node provided through setGraphic”. So the date picker in that case or my color picker is only available when editing. What might work with a date picker isn’t an option with the color picker. Also, the user need to do 2 clicks.

So i came up with that solution:

public class ColorTableCell<T> extends TableCell<T, Color> {    
    private final ColorPicker colorPicker;
 
    public ColorTableCell(TableColumn<T, Color> column) {
	this.colorPicker = new ColorPicker();
	this.colorPicker.editableProperty().bind(column.editableProperty());
	this.colorPicker.disableProperty().bind(column.editableProperty().not());
	this.colorPicker.setOnShowing(event -> {
	    final TableView<T> tableView = getTableView();
	    tableView.getSelectionModel().select(getTableRow().getIndex());
	    tableView.edit(tableView.getSelectionModel().getSelectedIndex(), column);	    
	});
	this.colorPicker.valueProperty().addListener((observable, oldValue, newValue) -> {
	    if(isEditing()) {
		commitEdit(newValue);
	    }
	});		
	setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
    }
 
    @Override
    protected void updateItem(Color item, boolean empty) {
	super.updateItem(item, empty);	
 
	setText(null);	
	if(empty) {	    
	    setGraphic(null);
	} else {	    
	    this.colorPicker.setValue(item);
	    this.setGraphic(this.colorPicker);
	} 
    }
}

Let me explain:

  1. this.colorPicker.setOnShowing() adds a handler that is executed just before the color picker popups up. It retrieves the TableView from the cell and also the currently selected row (which only works in single selection mode). It than starts the edit by calling tableView.edit. There’s no need to call startEdit() from TableCell, which actually will lead to a NPE somewhere…
  2. Than i watch the valueProperty() of the color picker and not the onAction or keypressed or whatsoever event, i want the value. That value is then committed. All further actions on the table are automatically, no need to manually call updateItem and the like.

That solution can be easily transferred to LocalDate cells etc. It’s benefits: It’s trivial and easy to implement, better user experience (no vanishing controls, no 2 clicks). Everything that fiddles with setContentDisplay(text or graphic) is just working around to get the table into edit mode when the user clicks often enough.

The classes shown here are part of my JavaFX demo project BikingFX, which is available on GitHub.

What do you think?