If you're interested in functional programming, you might also want to checkout my second blog which i'm actively working on!!

Wednesday, January 29, 2014

Code puzzler: Tape Equilibrium

Suppose you get an array of ints of arbitrary length. Now we need to find out what is the mimimal absolute difference of the 2 sums of numbers if you split the array at any position in a left and right array. And preferably in a efficient way.
import java.util.ArrayList;
import java.util.List;
public class TapeEquilibrium {
public static void main(String[] args) {
int [] numbers1 = {1,3,2,7};
int [] numbers2 = {5,2,8,4};
evaluate(numbers1, 1);
evaluate(numbers2, 5);
}
public static void evaluate(int [] numbers, int expected) {
int answer = solution(numbers);
System.out.println("Expected answer = " + expected + ", got " + answer);
}
public static int solution(int[] A) {
List<Integer> numbers = toList(A);
int size = numbers.size();
int sumLeft = numbers.get(0);
int sumRight = sum(numbers.subList(1, size));
int minDifference = Math.abs(sumLeft - sumRight);
for (int i : numbers.subList(1, size -1)) {
sumLeft = sumLeft + i;
sumRight = sumRight - i;
int difference = Math.abs(sumLeft - sumRight);
if (difference < minDifference) {
minDifference = difference;
}
}
return minDifference;
}
public static List<Integer> toList(int [] array) {
List<Integer> result = new ArrayList<Integer>();
for (int ele : array) {
result.add(new Integer(ele));
}
return result;
}
public static int sum(List<Integer> numbers) {
int sumRight = 0;
for (int i : numbers) {
sumRight += i;
}
return sumRight;
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Friday, January 10, 2014

AxonFramework - initial exploration

For the record, this demo is kind of copied from the quickstart but it is in some ways more elaborate and using the latest and greatest version 2.0.7
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.pelssers</groupId>
<artifactId>axondemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<spring.version>3.1.2.RELEASE</spring.version>
<axon.version>2.0.7</axon.version>
<junit.version>4.11</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-core</artifactId>
<version>${axon.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-test</artifactId>
<version>${axon.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
view raw gistfile1.xml hosted with ❤ by GitHub
Now we start thinking about the behaviour of our little demo application. A user can create a new todo item and he can mark an existing item as completed.
package nl.pelssers.axondemo.api;
import org.axonframework.commandhandling.annotation.TargetAggregateIdentifier;
public class CreateToDoItemCommand {
@TargetAggregateIdentifier
private final String todoId;
private final String description;
public CreateToDoItemCommand(String todoId, String description) {
this.todoId = todoId;
this.description = description;
}
public String getTodoId() {
return todoId;
}
public String getDescription() {
return description;
}
}
view raw gistfile1.java hosted with ❤ by GitHub
package nl.pelssers.axondemo.api;
import org.axonframework.commandhandling.annotation.TargetAggregateIdentifier;
public class MarkCompletedCommand {
@TargetAggregateIdentifier
private String todoId;
public MarkCompletedCommand(String todoId) {
this.todoId = todoId;
}
public String getTodoId() {
return todoId;
}
}
view raw gistfile1.java hosted with ❤ by GitHub
When commands are issued, something is bound to happen, so we also need to think about what events occur.
package nl.pelssers.axondemo.api;
public class ToDoItemCreatedEvent {
private final String todoId;
private final String description;
public ToDoItemCreatedEvent(String todoId, String description) {
this.todoId = todoId;
this.description = description;
}
public String getTodoId() {
return todoId;
}
public String getDescription() {
return description;
}
}
view raw gistfile1.java hosted with ❤ by GitHub
package nl.pelssers.axondemo.api;
public class ToDoItemCompletedEvent {
private final String todoId;
public ToDoItemCompletedEvent(String todoId) {
this.todoId = todoId;
}
public String getTodoId() {
return todoId;
}
}
view raw gistfile1.java hosted with ❤ by GitHub
We also need to think about our aggregate, in this case our ToDoItem
package nl.pelssers.axondemo.api;
import org.axonframework.commandhandling.annotation.CommandHandler;
import org.axonframework.eventhandling.annotation.EventHandler;
import org.axonframework.eventsourcing.annotation.AbstractAnnotatedAggregateRoot;
import org.axonframework.eventsourcing.annotation.AggregateIdentifier;
public class ToDoItem extends AbstractAnnotatedAggregateRoot<ToDoItem>{
private static final long serialVersionUID = 5438310735257852739L;
@AggregateIdentifier
private String id;
public ToDoItem() {
}
/**
* This is a constructor annotated with a CommandHandler. It makes sense that a ToDoItem
* instance gets created whenever a CreateToDoItemCommand is issued. The command handler
* creates a ToDoItemCreatedEvent which gets registered with the EventContainer by calling apply
* @param command
*/
@CommandHandler
public ToDoItem(CreateToDoItemCommand command) {
apply(new ToDoItemCreatedEvent(command.getTodoId(), command.getDescription()));
}
@EventHandler
public void on(ToDoItemCreatedEvent event) {
this.id = event.getTodoId();
}
@CommandHandler
public void markCompleted(MarkCompletedCommand command) {
apply(new ToDoItemCompletedEvent(id));
}
}
view raw gistfile1.java hosted with ❤ by GitHub
Of course we need to test if events are properly created when a command is issued.
package nl.pelssers.axondemo;
import nl.pelssers.axondemo.api.CreateToDoItemCommand;
import nl.pelssers.axondemo.api.MarkCompletedCommand;
import nl.pelssers.axondemo.api.ToDoItem;
import nl.pelssers.axondemo.api.ToDoItemCompletedEvent;
import nl.pelssers.axondemo.api.ToDoItemCreatedEvent;
import org.axonframework.test.FixtureConfiguration;
import org.axonframework.test.Fixtures;
import org.junit.Before;
import org.junit.Test;
public class ToDoItemTest {
private FixtureConfiguration<ToDoItem> fixture;
private final static String ITEM1_ID = "TODO-1";
private final static String ITEM1_DESCRIPTION = "Clean house";
@Before
public void setUp() throws Exception {
fixture = Fixtures.newGivenWhenThenFixture(ToDoItem.class);
}
@Test
public void testCreateToDoItem() throws Exception {
fixture
.given()
.when(new CreateToDoItemCommand(ITEM1_ID, ITEM1_DESCRIPTION))
.expectEvents(new ToDoItemCreatedEvent(ITEM1_ID, ITEM1_DESCRIPTION));
}
@Test
public void testMarkToDoItemAsCompleted() throws Exception {
fixture
.given(new ToDoItemCreatedEvent(ITEM1_ID, ITEM1_DESCRIPTION))
.when(new MarkCompletedCommand(ITEM1_ID))
.expectEvents(new ToDoItemCompletedEvent(ITEM1_ID));
}
}
view raw gistfile1.java hosted with ❤ by GitHub
We also need to configure the application, as usual we will use Spring to wire our app.
package nl.pelssers.axondemo.configuration;
import java.io.File;
import nl.pelssers.axondemo.ToDoEventHandler;
import nl.pelssers.axondemo.api.ToDoItem;
import org.axonframework.commandhandling.CommandBus;
import org.axonframework.commandhandling.SimpleCommandBus;
import org.axonframework.commandhandling.annotation.AggregateAnnotationCommandHandler;
import org.axonframework.commandhandling.gateway.CommandGateway;
import org.axonframework.commandhandling.gateway.DefaultCommandGateway;
import org.axonframework.eventhandling.EventBus;
import org.axonframework.eventhandling.SimpleEventBus;
import org.axonframework.eventhandling.annotation.AnnotationEventListenerAdapter;
import org.axonframework.eventsourcing.EventSourcingRepository;
import org.axonframework.eventstore.EventStore;
import org.axonframework.eventstore.fs.FileSystemEventStore;
import org.axonframework.eventstore.fs.SimpleEventFileResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AxonDemoConfiguration {
@Bean
public CommandBus commandBus() {
return new SimpleCommandBus();
}
@Bean
public CommandGateway commandGateway() {
return new DefaultCommandGateway(commandBus());
}
@Bean
public EventStore eventStore() {
return new FileSystemEventStore(new SimpleEventFileResolver(new File("c:/tmp/axondemo")));
}
@Bean
public EventBus eventBus() {
return new SimpleEventBus();
}
@Bean
public EventSourcingRepository<ToDoItem> todoRepository() {
EventSourcingRepository<ToDoItem> repository = new EventSourcingRepository<ToDoItem>(ToDoItem.class, eventStore());
repository.setEventBus(eventBus());
return repository;
}
@SuppressWarnings("unchecked")
@Bean
public AggregateAnnotationCommandHandler<ToDoItem> toDoItemHandler() {
return AggregateAnnotationCommandHandler.subscribe(ToDoItem.class, todoRepository(), commandBus());
}
@Bean
public AnnotationEventListenerAdapter todoEventHandler() {
return AnnotationEventListenerAdapter.subscribe(new ToDoEventHandler(), eventBus());
}
}
view raw gistfile1.java hosted with ❤ by GitHub
The demo app just issues 2 commands, mimicking what a user might do. And to make it interesting we also create an event handler for our ToDoItem events.
package nl.pelssers.axondemo;
import nl.pelssers.axondemo.api.CreateToDoItemCommand;
import nl.pelssers.axondemo.api.MarkCompletedCommand;
import nl.pelssers.axondemo.configuration.AxonDemoConfiguration;
import org.axonframework.commandhandling.gateway.CommandGateway;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class ToDoApplication {
private CommandGateway commandGateway;
public ToDoApplication(CommandGateway commandGateway) {
this.commandGateway = commandGateway;
}
/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AxonDemoConfiguration.class);
ToDoApplication todoApplication = new ToDoApplication(context.getBean(CommandGateway.class));
todoApplication.run();
}
private void run() {
final String itemId = "TODO-1";
commandGateway.send(new CreateToDoItemCommand(itemId, "Clean house"));
commandGateway.send(new MarkCompletedCommand(itemId));
}
}
view raw gistfile1.java hosted with ❤ by GitHub
package nl.pelssers.axondemo;
import org.axonframework.eventhandling.annotation.EventHandler;
import nl.pelssers.axondemo.api.ToDoItemCompletedEvent;
import nl.pelssers.axondemo.api.ToDoItemCreatedEvent;
public class ToDoEventHandler {
@EventHandler
public void handle(ToDoItemCreatedEvent event) {
System.out.println("We've got something to do: " + event.getDescription() + " (" + event.getTodoId() + ")");
}
@EventHandler
public void handle(ToDoItemCompletedEvent event) {
System.out.println("We've completed a task: " + event.getTodoId());
}
}
view raw gistfile1.java hosted with ❤ by GitHub
When we run the ToDoApplication we notice a file gets created in c:/tmp/axondemo/ for our aggregate called TODO-1.events. Also we nicely see some output appearing in the console:
We've got something to do: Clean house (TODO-1)
We've completed a task: TODO-1

Friday, January 3, 2014

Caching - the pitfall

At a current project we added some caches to our application to improve performance. However, we faced some issues I looked into and this article will demonstrate you should use caches with great precaution.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.pelssers</groupId>
<artifactId>cachingdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<spring.version>3.1.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.4.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>14.0.1</version>
</dependency>
</dependencies>
</project>
view raw gistfile1.xml hosted with ❤ by GitHub
package com.pelssers.services;
import java.util.List;
public interface PricingService {
List<Integer> getPriceHistory(Long productId);
}
view raw gistfile1.java hosted with ❤ by GitHub
package com.pelssers.services;
import java.util.List;
import org.springframework.cache.annotation.Cacheable;
import com.google.common.collect.Lists;
public class PricingServiceImpl implements PricingService {
@Cacheable(value = "services.pricing", key = "#productId")
public List<Integer> getPriceHistory(Long productId) {
System.out.println("Fetching prices from DB");
return Lists.newArrayList(2, 6, 8, 5, 9);
}
}
view raw gistfile1.java hosted with ❤ by GitHub
package com.pelssers.configuration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import com.pelssers.services.PricingService;
import com.pelssers.services.PricingServiceImpl;
@Configuration
@EnableCaching
public class DemoConfiguration {
@Bean
public PricingService pricingService() {
return new PricingServiceImpl();
}
@Bean
public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() {
EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
return ehCacheManagerFactoryBean;
}
@Bean
public CacheManager cacheManager() {
EhCacheCacheManager cacheManager = new EhCacheCacheManager();
cacheManager.setCacheManager(ehCacheManagerFactoryBean().getObject());
return cacheManager;
}
}
view raw gistfile1.java hosted with ❤ by GitHub
package com.pelssers.demo;
import java.util.Collections;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
import com.pelssers.configuration.DemoConfiguration;
import com.pelssers.services.PricingService;
@Component
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(DemoConfiguration.class);
PricingService pricingService = context.getBean(PricingService.class);
List<Integer> prices1 = pricingService.getPriceHistory(1L);
System.out.println(prices1);
Collections.reverse(prices1);
List<Integer> prices2 = pricingService.getPriceHistory(1L);
System.out.println(prices2);
}
}
view raw gistfile1.java hosted with ❤ by GitHub
<ehcache>
<diskStore path="java.io.tmpdir" />
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
statistics="true" />
<cache
name="services.pricing"
maxElementsInMemory="1000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="7200"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off"
statistics="true" />
</ehcache>
<!-- running Main will result in following output.
Fetching prices from DB
[2, 6, 8, 5, 9]
[9, 5, 8, 6, 2]
What do we see here... we only fetch the list of prices the first time.
The second time we get back the cached value.
BUT we actually modified the list of prices (even in our cache). Potential PITFALL !!
-->
view raw gistfile1.xml hosted with ❤ by GitHub
<ehcache>
<diskStore path="java.io.tmpdir" />
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
statistics="true" />
<cache
name="services.pricing"
maxElementsInMemory="1000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="7200"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off"
statistics="true" copyOnWrite="true"
copyOnRead="true" />
</ehcache>
<!-- running Main will result in following output.
Fetching prices from DB
[2, 6, 8, 5, 9]
[2, 6, 8, 5, 9]
What do we see here... we only fetch the list of prices the first time.
The second time we get back the cached value. And even although we reversed
the prices the first time it has NO effect on our cached value.
This is in most situations what you want.
-->
view raw gistfile1.xml hosted with ❤ by GitHub