OneHP Develops

A Java development blog

Follow me on Twitter

  • Home
  • About

2012 Goals and Plans

Dec 25th

Posted by Thomas Inman in Lifestyle

No comments

Following up from my previous post on what I did in 2011 I’m going to outline what I plan to do during 2012, and say a little about how I plan to go about achieving them.

The Goals

Instead of taking on a series of focused projects one after the other next year I aim to achieve three main things during the entire period of the year.

  1. Be in the best health of my life.
  2. Learn to drive and pass my driving test.
  3. Have a secondary source source of income.

The Plan

To achieve my first goal my plan is to do a lot more exercise than I do at the moment. I intend for the main body of this to come from cycling to and from work everyday. I’ve done a little bit of planning for this and found a route from my house to my workplace that is mainly off road. It’s a 10 mile route each way so it should be quite challenging to start off with but provide enough exercise so that I have to spend little of the rest of my time doing any more.

The second goal doesn’t really require any planning, simply find an instructor and learn.

For the third goal I’m going to be taking part in the development of a mobile game with a couple of friends of mine. We’ve already started the planning and prototyping stages of this and I expect this project to take up a significant amount of my free time in 2011. Hopefully our game will be successful and provide me with a secondary income source. I may also explore other avenues towards this goal as well.

Extras

I recently read an article by Russell Davies titled ‘How to be Interesting’. The main gist of the article is that to be interesting you should produce content (photos, blog posts, audio interviews and even physical objects) and share it with other people. It’s quite an old article but it’s a good read and I’d like to have a go at some if not all of the 10 ideas that Russell came up with.

Doing all this should keep me busy and productive through 2012 and I’ve also got maintenance and improvements to make on Trickle as well as a project for another family member. Hopefully I can fit everything in.

cycling, driving, exercise, game development, income, project

2011 Post Mortem – Project Year

Dec 8th

Posted by Thomas Inman in Lifestyle

1 comment

The Idea

Sometime at the end of last year I decided that I wanted to force myself to get a bit more out of life than just my daily routine. Inspired by Matt Cutts’ 30 day projects I decided that during 2011 I was going to undertake a series of projects. I opted for projects lasting 36 days as I felt that it would give me a bit more scope in what I could achieve, and it would divide the year roughly into tenths. I would complete nine projects and then take the last tenth off for relaxation and Christmas.

The projects I ended up undertaking, in order, were:

  1. No alcohol
  2. Develop Betfair Trickle into a usable product
  3. Listen to an album I’ve not listened to before everyday
  4. Achieve 555 visits to this blog
  5. Produce an EP
  6. Code
  7. No ready meals
  8. Do some exercise everyday
  9. Grow a moustache

Out of of the nine projects I failed numbers three and five and I would say that number six was a bit of an unfocussed cop-out as I couldn’t think of anything good to do.

1. No Alcohol

Picking this project was a bit of a no brainer, I’d had a very heavy December and it’s a classic new year’s resolution to stop drinking. I found it fairly difficult to stick to this project and it probably helped that people are pretty spent up after Christmas and don’t go out as much, I tested my resolve a couple of times going out but stuck to the soft drinks. After three or four weeks I could feel a physical benefit from staying off alcohol, I slept much better and generally felt much more alert and fit, a detox like this is something I might repeat in the future.

2. Develop Betfair Trickle into a Usable Product

Trickle is pretty much the reason for this blog’s existence and it was an ideal second project, the system I was providing at the time just wasn’t cutting it and I wanted to use some of the skills I had learnt in my day job for a personal project. Most of the posts on this site are about Trickle but here is the post I made after I did my 36 days on it.

3. Listen to an album I’ve not listened to before every day

This one was surprisingly difficult and in the end I decided to fail the project and stop after about 20 days. Finding about an hour out of everyday became a chore and I stopped enjoying the challenge. With the previous project I could put in 5 hours work for a couple of nights and then do no work for a couple of days. The commitment of having to do something everyday even when I wasn’t in the mood ultimately killed this one and for the next few projects I tried to focus on something I could achieve across the 36 days instead of something I could do once everyday for 36 days.

4. Achieve 555 Visits to this Blog

I went for this project as a way to spur myself into writing more blog posts and to develop my technical writing. For the first three quarters of the project the increase in traffic was pretty low and I wasn’t on target to reach my goal but luckily I managed to produce a blog post that gained me over 1200 views alone in the last nine days of the project. The post in question is this one about using Dropbox to share save files in the game Terraria, this was something I came up with to solve a problem my friends and I had encountered. Terraria had just come out on Steam and by tweeting a couple of times and posting a thread in the largest forum for the game I picked up quite a few hits. I ended up smashing my target ending the 36 days with 1,525 visits.

5. Produce an EP

I had just bought an iPad and figured that with a bit of messing around with Garage Band I could at least come up with something semi-listenable. It turns out that I underestimated my lack of musical talent. This coupled with Garage Band having some horrible quirks that caused me massive amounts of frustration lead to failure number two, after 36 days I didn’t have a single song let alone the three or four I had hoped for. Maybe I should start a bit slower and learn an instrument at some point, I’d quite like to be able to play a brass instrument and these plastic cast Trombones look quite interesting and fairly cheap too.

6. Code

As I said in the intro this one was a bit of a cop-out, I did write more code than I usually would but there was no discernible product at the end of it all, bit of a poor show on my part.

7. No Ready Meals

I quite enjoyed this one, other than missing pizza a bit I actually found it a bit easier than I was expecting. Pasta took over a large part of my diet with various home-made sauces but I did have a go at a couple of more adventurous meals like a seafood potato bake and some home-made soup. I felt some benefit to my health from this project, but not really on par with the no alcohol project. I think the biggest change this project made was on my wallet, it was definitely cheaper to produce my own meals rather than buying pre-made stuff, I guess the trade off here comes in the time spent preparing the meal though. I found the cooking quite satisfying though and I don’t think it’s a bad way to spend 30-45 minutes. I’ve just moved into a new house where I’ve finally got a freezer so I might try to do some more proper cooking now that I can save the leftovers instead of eating bolognese for four days in a row.

8. Do Some Exercise Everyday

In this project I ignored my previous issue with attempting to repeat something everyday for the project timeline, but this time it worked out and I stuck to performing some exercise everyday. My routine generally consisted of lifting low weight barbells for quite a few repetitions, a couple of times a day. I would keep lifting until it was mildly discomforting to do so, then rest and do another set a little while later. When I didn’t have access to weights I would either do press-ups or go cycling. I didn’t really feel any healthier while doing this project but I guess weight training isn’t the kind of cardiovascular/fat-burning activity that would have that effect, I did see a noticeable change in upper body muscle definition thought which I was fairly pleased with considering no-one who knows me would ever use anything near the word muscular to describe me. Due to certain rules around my final project I wasn’t going to be able to start until November and as I was enjoying this one I extended it out to 50 days, this project was an unexpected success all round I think.

9. Grow a Moustache

For my final project the idea fell right in my lap, a friend suggested it back in August and I’d seen people doing Movember for a couple of years now. I knew another couple of friends were already thinking about having a go and with no important social engagements coming up I thought why not. This one ended up being fairly easy really, although it got a bit annoying for the last week when it descended onto my top lip. So after a month of looking slightly foolish it turned out something like this, not great I know and I was glad to see it gone as soon as December rolled around. One friend is keeping his till Christmas for some reason, though I concede his was a little better than mine.

Wrap Up

I feel it was well worth taking on these projects for the year as it gave me areas of focus to try improve my life. I think I could have perhaps done a better job of picking my projects though and I’m disappointed about the couple that I failed. I also think I could have been more adventurous with some of my choices, looking at some of Matt Cutts’ projects he’s really taking on really challenging things like writing a 50 thousand word novel or going vegan for 30 days. I’m not going to to be repeating this format for 2012 but I do have something else planned and I might do a couple of more challenging 30 day projects if I can think of something really worthwhile. I’ll be following up with another post for my plans for 2012 soon.

alcohol, betfair, dropbox, exercise, food, moustache, music, project, terraria, trickle

Vaadin Helpers – Part Two – Value Backed ComboBox and TwinColSelect

Sep 19th

Posted by Thomas Inman in Vaadin

2 comments

In part one I talked about the ViewUtils class I use to create basic fields for Vaadin forms. In this part I’ll talk about the ComboBox and TwinColSelect components, both useful for getting a user to pick from a contained set of options.

The difference between the TextField and ComboBox or TwinColSelect inputs is that what you want to display is often different to the value you want backing the field, with the TextField you’re generally dealing with strings so this isn’t really an issue. A common use of the ComboBox is for a person’s title, you could represent this just as a string but it might be useful to have a title object containing information on the gender related to the title or if the title is a professional one. You only want to display the base title string when picking from a combo box though, and be able to retrieve the entire object once the user has made their choice.

Both the TwinColSelect and ComboBox are backed by the Container object, which makes it pretty easy to achieve a list of labelled items backed by the whole object. To start I made an Interface that I add to any POJO that I need to be able to pick in a ComboBox.

public interface ComboBoxAware {
	String getComboBoxLabel();
}

I use the enforced method to get the label for the ComboBox when I’m adding entries to the Container, as below.

private static void addItemToComboBoxContainer(Container container, ComboBoxAware addition) {
	Object id = container.addItem();
	container.getContainerProperty(id, "Label").setValue(addition.getComboBoxLabel());
	container.getContainerProperty(id, "Value").setValue(addition);
}

This gets called for every entry to populate the container.

private static Container createComboBoxContainer(List<ComboBoxAware> items){
	Container container = new IndexedContainer();
	container.addContainerProperty("Label", String.class, "");
	container.addContainerProperty("Value", ComboBoxAware.class, null);
	for(ComboBoxAware item : items){
		addItemToComboBoxContainer(container, item);
	}
	return container;
}

Then the container is used to back a ComboBox.

public static ComboBox smallCombo(String label, boolean required, List<ComboBoxAware> items){
	ComboBox comboBox = new ComboBox();
	applyFormat(comboBox, label, required, ViewConstants.COMMON_FIELD_WIDTH);
	comboBox.setContainerDataSource(createComboBoxContainer(items));
	comboBox.setItemCaptionPropertyId("Label");
	return comboBox;
}

To retrieve the backing object once the user has made a selection I have another method that the ComboBox is passed to.

public static Object getComboBoxValue(ComboBox comboBox){
	if (null == comboBox.getValue()){
		return null;
	}
	return comboBox.getContainerProperty(comboBox.getValue(), "Value").getValue();
}

The code for creating TwinColSelect inputs is essentially identical to above, but to retrieve the backing objects is a little different as the component allows multiple selections.

public static List<? extends TwinColAware> selections(TwinColSelect twinColSelect){
	Set<Object> selectedIds = (Set<Object>) twinColSelect.getValue();
	List<TwinColAware> selections = Lists.newArrayList();
	for(Object id : selectedIds){
		selections.add((TwinColAware) twinColSelect.getContainerDataSource().getItem(id).getItemProperty("Value").getValue());
	}
	return selections;
}
ComboBox, Container, java, TwinColSelect, Vaadin

Vaadin Helpers – Part One – Simple Text Fields

Sep 17th

Posted by Thomas Inman in Vaadin

1 comment

I’m using Vaadin again in my latest project and I knew this one was going to be fairly form heavy so I made a concious effort to put together a small framework so I can throw together forms a bit quicker and have them more readable as well.

I have a ViewUtils class that has static methods for constructing lots of basic input fields for forms. Most fields have three things that need setting every time, the label preceding the field, if the field is mandatory or not and the width the field will take on screen. I use the following method in most my field setups.

private static void applyFormat(Field field ,String label, boolean required, String width){
	field.setCaption(label);
	field.setRequired(required);
	field.setWidth(width);
}

I then have a couple of methods for each type of field in various sizes. Basic text fields for example have these two methods.

public static TextField smallText(String label, boolean required){
	TextField textField = new TextField();
	applyFormat(textField, label, required, ViewConstants.COMMON_FIELD_WIDTH);
	return textField;
}

public static TextField mediumText(String label, boolean required){
	TextField textField = new TextField();
	applyFormat(textField, label, required, ViewConstants.DOUBLE_FIELD_WIDTH);
	return textField;
}

For numerical fields I use the following methods.

public static TextField smallNumerical(String label, boolean required, String lower, String upper){
	TextField textField = new TextField();
	applyFormat(textField, label, required, ViewConstants.COMMON_FIELD_WIDTH);
	applyNumericalValidation(textField, required, lower, upper);
	return textField;
}

public static TextField mediumNumberical(String label, boolean required, String lower, String upper){
	TextField textField = new TextField();
	applyFormat(textField, label, required, ViewConstants.DOUBLE_FIELD_WIDTH);
	applyNumericalValidation(textField, required, lower, upper);
	return textField;
}

private static void applyNumericalValidation(Field field, boolean required, String lower, String upper){
	field.addValidator(new RegexpValidator("[1-9][0-9]*(\\.[0-9]{1,2}){0,1}", "Field must be numberical, with up to two decimal places"));
	field.addValidator(new RangeValidator(lower, upper, required));
}

This is the custom RangeValidator used within those methods.

import java.math.BigDecimal;

import org.apache.commons.lang.StringUtils;

import com.vaadin.data.validator.AbstractStringValidator;

@SuppressWarnings("serial")
public class RangeValidator extends AbstractStringValidator {

	private final BigDecimal lower;
	private final BigDecimal upper;
	private final boolean required;

	public RangeValidator(String lower, String upper, boolean required) {
		super("");
		this.lower = StringUtils.isBlank(lower) ? new BigDecimal("0.00") : new BigDecimal(lower);
		this.upper = StringUtils.isBlank(upper) ? new BigDecimal("1000000000.00") : new BigDecimal(upper);
		this.required = required;
	}

	@Override
	protected boolean isValidString(String value) {
		if(StringUtils.isBlank(value)){
			if(!this.required){
				return true;
			}else{
				super.setErrorMessage("This is a required field");
				return false;
			}
		}
		BigDecimal bigDecimal = new BigDecimal(value);
		if(bigDecimal.compareTo(this.lower) < 0){
			super.setErrorMessage("Value is too small, must be larger than " + this.lower);
			return false;
		}
		if(bigDecimal.compareTo(this.upper) > 0){
			super.setErrorMessage("Value is too large, must be smaller than " + this.upper);
			return false;
		}
		return true;
	}
}

Using these few methods makes it easy to define the fields for a form in a few lines, if you import static ViewUtils you get a nice concise block of code describing the fields as well. Here’s an example.

private void buildView(){
	this.mainLayout = new VerticalLayout();
	this.forename = smallText("Forename", true);
	this.surname = smallText("Surname", true);
	this.addressLine1 = mediumText("Address Line 1", true);
	this.addressLine2 = mediumText("Address Line 2", false);
	this.addressLine3 = mediumText("Town", false);
	this.minBudget = smallNumerical("Min Budget", true, "0", "100000");
	this.maxBudget = smallNumerical("Max Budget", true, "100000", "500000");

	this.mainLayout.addComponent(this.forename);
	this.mainLayout.addComponent(this.surname);
	this.mainLayout.addComponent(this.addressLine1);
	this.mainLayout.addComponent(this.addressLine2);
	this.mainLayout.addComponent(this.addressLine3);
	this.mainLayout.addComponent(this.minBudget);
	this.mainLayout.addComponent(this.maxBudget);
}

In my next post I’ll be looking at using the ComboBox and TwinColSelect input fields.

Update : Part two is now up

java, text field, Vaadin

Mini Bitcoin Project – realcoin.net

Jul 17th

Posted by Thomas Inman in Experiments

No comments

Over the past couple of weeks I’ve been putting together a small site to promote the Bitcoin virtual currency. I’m pretty interested in the technical and economic side of trying to introduce a new peer-to-peer currency, and I’ve learnt a lot more about web security by reading about the teething issues Bitcoin service providers are having. The site I’ve made is called Real Coin and the idea behind it is to show people the amount of money already moving in the Bitcoin network by equating transactions to what you could buy with the corresponding amount of dollars.

Underneath the application is a very basic single controller web-app on the Spring-MVC framework, I’ve used this framework briefly in my job but this is the first personal project I’ve tried it out on and I’m pretty happy with how it’s turned out. I wanted it to be a really simple app so I decided to eschew any database persistence for storing the item data in favour of a static store just in the Java. I don’t expect to be altering my list of items very frequently so a database layer would have been a bit of a waste of resources I think.

I’ve got a couple of improvements I’d like to make but I’ve got another project I need to get on with at the moment and one of the improvements will rely on me finding a suitable API or putting in a lot of work to build it myself.

bitcoin, java, real coin, spring

Sharing Terraria Worlds Using Dropbox

May 19th

Posted by Thomas Inman in Gaming

No comments

I’ve been playing Terraria multiplayer over the past couple of days and was thinking of how to share hosting the game as well as play when your friends aren’t online. In short using a shared Dropbox folder you can each have a copy of your multiplayer world on your own computer so you can host or play alone.

1.
All persons should complete this step
Get set up with a Dropbox account from http://www.dropbox.com/ and install the Dropbox software.
If you’re using Windows 7 the default Dropbox folder is at C:\Users\username\Dropbox

2.
One person should complete this step
Start a Terraria world using the game as normal and then quit out of the game, this will be the world you are going to share among friends.

3.
One person should complete this step
Rename the world storage file to something unique
The file will be inside C:\Users\username\Documents\My Games\Terraria\Worlds\
Look for the highest numbered .wld file, the modified time should be within the last couple of minutes.
(For this guide presume we have renamed the world to sharedworld.wld)
Worlds folder before rename and after rename

4.
One person should complete this step
Create a new ‘Worlds’ folder inside your Dropbox folder
New folder

5.
One person should complete this step
Copy C:\Users\username\Documents\My Games\Terraria\Worlds\sharedworld.wld into your new C:\Users\username\Dropbox\Worlds folder.
Copied file

6.
One person should complete this step
Warning: Be careful in this step, only delete the file you renamed then copied.
Once copied to the Dropbox folder delete ’sharedworld.wld’ from C:\Users\username\Documents\My Games\Terraria\Worlds
Deleting world

7.
One person should complete this step
Right click on the C:\Users\username\Dropbox\Worlds folder and from the Dropbox menu select ‘Share this Folder’. Share the folder with all the friends you are playing with who have Dropbox accounts.
Share folder

8.
All persons should complete this step
Accept the sharing request from Dropbox

9.
All persons should complete this step
Everybody should now have a C:\Users\username\Dropbox\Worlds folder.
Open a command prompt as administrator. (Windows Button -> All Programs -> Accessories -> Command Prompt -> Right Click -> Run as Administrator)
Type this command
mklink "C:\Users\username\Documents\My Games\Terraria\Worlds\sharedworld.wld" C:\Users\username\Dropbox\Worlds\sharedworld.wld
and hit enter
Command line

10.
Now when anyone starts up Terraria they can host or play the world in single player.

Note: Two or more people should not host or play single player at the same time, this will cause multiple versions of the world and you’ll only end up with one version linked with everyone.

dropbox, terraria

Dynamically Scheduled Jobs with Quartz

May 14th

Posted by Thomas Inman in Betfair Trickle

3 comments

Over the past few weeks I’ve been experiencing problems with the application when it is placed under heavy load. Due to the low processing power of my EC2 micro instance when there are lots of bets waiting to be placed then the app is performing very slowly and some bets are being placed too late. The existing scheduling solution of checking every second for bets that need placing was eating up far too much processing power and hammering the database as well. Changing the scheduling solution has been high on my list for a while and I’ve some experience of using Quartz in my day job so I thought I’d move the bet placement scheduling over to use it.

I have two jobs for placing bets, one that updates the prices five seconds before the bet is evaluated and the another to evaluate and place the bet if necessary. Under Quartz each of these actions are set-up inside a class that extends QuartzJobBean, each of these are then mapped onto a JobDetailBean in the Spring configuration so we can attach triggers to them. The class and config for my bet placement job is shown below.

package uk.co.onehp.trickle.services.betfair;

import java.util.List;

import org.joda.time.LocalDateTime;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.scheduling.quartz.QuartzJobBean;

import uk.co.onehp.trickle.domain.Bet;
import uk.co.onehp.trickle.services.domain.DomainService;

@Configurable(preConstruction=true)
public class PlaceBetsJob extends QuartzJobBean{

	@Autowired
	BetfairService betfairService;

	@Autowired
	DomainService domainService;

	@Override
	protected void executeInternal(JobExecutionContext arg0)
	throws JobExecutionException {
		List<Bet> bets = this.domainService.getBetsToPlace();
		final LocalDateTime now = new LocalDateTime();
		for(Bet bet : bets){
			for(Integer secondsBeforeOff : bet.getUnprocessedTimings()){
				if(now.isAfter(bet.getHorse().getRace().getStartTime().minusSeconds(secondsBeforeOff))){
					bet.markTimingProcessed(secondsBeforeOff);
					this.domainService.updateBet(bet);
					this.betfairService.placeBet(bet);
				}
			}
		}
	}
}
<bean id="placeBetsJob" class="org.springframework.scheduling.quartz.JobDetailBean">
	<property name="jobClass" value="uk.co.onehp.trickle.services.betfair.PlaceBetsJob"/>
</bean>

Then we can configure a trigger for the job in the Spring xml, as I want the job to fire as a one off at a specific time I’m using a CronTriggerBean as the trigger. The cron expression I initially set is just an arbitrary point in the distant future, I don’t intend the job to fire until I have set it programmatically later on. The trigger is then mapped to the quartz scheduler which I’ve defined as a SchedulerFactoryBean.

<bean id="placeBetsTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
	<property name="jobDetail" ref="placeBetsJob"/>
	<property name="cronExpression" value="0 0 0 1 1 ? 2222"/>
</bean>

<bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
	<property name="triggers">
		<list>
	        	<ref bean="placeBetsTrigger"/>
		</list>
	</property>
</bean>

To dynamically reschedule the job I autowire the scheduler and the the trigger into my service class and use the rescheduleJob method on the scheduler.

@Service("scheduledService")
public class ScheduledServiceImpl implements ScheduledService {
	@Autowired
	SchedulerFactoryBean quartzScheduler;

	@Autowired
	CronTriggerBean placeBetsTrigger;

	@Override
	public void scheduleNextBet() throws ParseException, SchedulerException {
		Scheduler scheduler = this.quartzScheduler.getObject();
		this.placeBetsTrigger.setCronExpression(nextBetSchedule());
		scheduler.rescheduleJob(this.placeBetsTrigger.getName(),this.placeBetsTrigger.getGroup(),this.placeBetsTrigger);
	}

	private String nextBetSchedule() {
		LocalDateTime nextBetTime = this.domainService.getNextBetTime();
		String cron = String.format("%s %s %s %s %s ?", nextBetTime.getSecondOfMinute(), nextBetTime.getMinuteOfHour()
				, nextBetTime.getHourOfDay(), nextBetTime.getDayOfMonth(), nextBetTime.getMonthOfYear());
		return cron;
	}
}

This service method is called each time a write is made to my bets table, so whenever a bet is added, deleted or placed we schedule the job to fire for the next bet. The method is also called once when we start the app, another Quartz job is used for this.

package uk.co.onehp.trickle.services.betfair;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.scheduling.quartz.QuartzJobBean;

@Configurable(preConstruction=true)
public class StartupJob extends QuartzJobBean {

	@Autowired
	ScheduledService scheduledService;

	@Override
	protected void executeInternal(JobExecutionContext arg0)
	throws JobExecutionException {
		this.scheduledService.scheduleNextBet();
	}
}
<bean id="startupJob" class="org.springframework.scheduling.quartz.JobDetailBean">
	<property name="jobClass" value="uk.co.onehp.trickle.services.betfair.StartupJob"/>
</bean>

The trigger for this job is a SimpleTriggerBean that fires once as soon as the application context configuration is loaded.

<bean id="startupTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
	<property name="jobDetail" ref="startupJob"/>
	<property name="repeatCount" value="0"></property>
</bean>

With this setup I’m only checking for bets to place at the time they should be placed and the application should run a lot smoother as a result. I’m going to do a sizeable test tomorrow to ensure no business logic has been affected by the changes and then once I’ve put the app onto my EC2 I hope to see just how much performance increase I’ve gained.

betfair, ec2, java, quartz, scheduled, spring, trickle

Bidirectional Hibernate Relationships and Eager Loading

May 1st

Posted by Thomas Inman in Betfair Trickle

No comments

From the very start of using Hibernate for data persistence in Trickle I’ve been using eager loading as more often than not the child objects are required for some amount of processing, this led to some performance issues when I came to add bidirectional relationships into my persistent objects.

I initially added bidirectional mapping between all four layers of my race data objects (Market, Meeting, Race, Horse) as I needed data from parent objects in some situations, for example having the meeting name for a race so I could display it when listing bets. After a few test runs on my local machine it became clear that adding in these mappings had completely crippled the performance of the application and after thinking it through it was pretty obvious why. The application contains a timer that ticks every second to check for bets it needs to place at that time, this is second on my list currently to replace with something better, and every time this timer ticked it was retrieving the test bet I had set-up. This Bet object referenced a Horse object, which referenced a Race object, which referenced both all the Horses in that race as well as a Meeting object. The Meeting in turn referenced all the Races for that meeting as well as the object for the UK market. Every time I hit the database I was pulling back the entire UK market all the way down to the prices for each horse. Whoops.

At this point I decided to trade off being able to grab all the data of the parent objects at will for performance and chose a few key fields that I would copy onto the child objects on creation instead. I left in only the lowest level mapping as a bidirectional one as it was acceptable to get back the race data, including other runners, for the horse I had pulled from the database. This cleared up the performance issues immediately.

hibernate, java, trickle

Ludum Dare: Postmortem

Apr 27th

Posted by Thomas Inman in Experiments

No comments

With Ludum Dare 20 coming up this and weekend and it landing in the middle of a four day weekend here in the UK I’m considering having another punt at making something. Looking back at the notes I made during the last LD and the scores I received for my game Sprawl I’ve come up with a few things I would do differently this time.

Use Tools You Already Know (Or Spend Some Time Learning)

I stuck to this as far as the language I was using was concerned but was forced to use a different IDE to my regular Eclipse set-up as I wasn’t going to buy a copy of FlashBuilder. I believe not knowing keyboard shortcuts or handy features of the IDE cost me quite a bit of time. As I didn’t do any preparation for LD19 I spent couple of hours downloading, installing and debugging development toolkit issues, I also wasted some time trying to connect my netbook to a printer trying to print out a cheat-sheet for the IDE I’d chosen to use (IntelliJ IDEA). Making time to prep and better learn the tools I was going to use could have saved me a lot of time.

Don’t Neglect Sound and Graphics

My game scored pretty badly overall but my lowest scoring category was graphics and it’s pretty easy to see why. I should have made an effort to put at least some visual style into the game rather than simple colour blocks, even some gradients or shading would have been better than nothing and some simple animation could have made a big difference. I added on a few sounds towards the end of development but I think to make any headway in the audio scoring I would have needed to add in some music.

(Find a Way to) Use All the Time You’ve Got

I cut the final release of my game about eight hours before the competition finished, that’s time I could have spent addressing my previous point or adding more features. I stopped because I got bored/burnt-out and I think I wanted to go to the pub as well. There’s two ways I can think of to overcome this point, either magically come up with some more willpower from somewhere, or put yourself in an environment where it’s going to be difficult to stop developing early. I think the best way to do this would be to get together with other developers taking part in LD, the more the better I reckon for support and peer pressure, for example this looks great http://starfruitgames.com/blog/?p=312.


Well that’s the improvements I’d make, so I’ll quickly mention some things I think I got right.

Take a Walk

I went for a walk early evening on the first day and came back with loads of great ideas and a good picture of how to code some of it in my mind. Not quite sure why this works but I think it’s something to do with the brain having something else to do and letting the ideas stew as you can’t just start coding them immediately. I found 10-15 minutes was a good amount of time to get out for.

Do a Little Bit of Planning

I spent the first hour or so working on paper to come up with a bit of a mind map of concepts I was interested in using, and then a bit of hashing out how my engine was going to work.

Keep Writing Notes

I kept my notebook at hand for keeping track of what I was doing and for drawing/working out anything I’m needed clarifying in my head, I pretty sure I’ve ended up drawing out some trigonometry sketches in every project I’ve ever done.


I’m not sure I’ll manage to participate in LD20 but if I do, or when I do my next LD, I’m going to try keep improving my process and taking notes so I can learn what works and what I can do better next time.

Ludum Dare

Apache CXF and the Betfair API

Apr 24th

Posted by Thomas Inman in Betfair Trickle

No comments

In my previous Betfair application I used Netbeans’ WSDL to Java generation tools in order to generate the classes required for interfacing with the Betfair API and when I moved over to Trickle I simply copied the generated code over. I realised this could cause issues if Betfair made significant changes to the API and my generated classes became out of date so after seeing a colleague of mine using Apache CXF to do generation from a web-service I thought I’d give it a go.

I initially made the mistake of downloading the WSDL files, including them in my project and having CXF point at them locally for generation, but this caused two issues. Firstly I would still have the problem of out of date classes if I didn’t keep an eye out for updates to the API and re-download the WSDLs, and secondly I encountered an issue where sometimes the application would fail when run on my EC2 instance as it was trying to find the WSDLs based on the path on my local machine. At this point I made the move to have CXF look directly at the WSDLs on the Betfair developers website.

The CXF Maven plugin is very easy to use and re-generates the classes as part of the generate-sources phase of the Maven lifecycle. I have the following set-up to generate the Betfair classes in their own ’src/main/generated’ package.

<build>
	<plugins>
		<plugin>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-codegen-plugin</artifactId>
			<version>2.2.6</version>
			<executions>
				<execution>
					<id>generate-sources</id>
					<phase>generate-sources</phase>
					<configuration>
						<sourceRoot> ${basedir}/src/main/generated/java</sourceRoot>
						<wsdlOptions>
							<wsdlOption>
								<wsdl> https://api.betfair.com/global/v3/BFGlobalService.wsdl </wsdl>
								<wsdl> https://api.betfair.com/exchange/v5/BFExchangeService.wsdl </wsdl>
							</wsdlOption>
						</wsdlOptions>
					</configuration>
					<goals>
						<goal>wsdl2java</goal>
					</goals>
				</execution>
			</executions>
		</plugin>
	</plugins>
</build>

With the generated classes I can then hit the Betfair API. For example to login.

final BFGlobalService_Service service = new BFGlobalService_Service();
final BFGlobalService port = service.getBFGlobalService();
LoginReq request = new LoginReq();
request.setUsername("username");
request.setPassword("password");
request.setProductId(82);
final LoginResp result = port.login(request);
apache, betfair, cxf, java, maven, trickle
123»
  • Twitter

    Loading tweets...
    Follow me on Twitter!
  • Categories

    • Android
    • Betfair Trickle
    • Experiments
    • Gaming
    • Lifestyle
    • Vaadin
  • Archive

    • December 2011
    • September 2011
    • July 2011
    • May 2011
    • April 2011
    • March 2011
    • December 2010
    • September 2010
    • June 2010
    • May 2010
    • April 2010
    • March 2010
Top