Go Back   Developer Program Forum > Blogs > Java and the Betfair API

Since I mainly access the API using Java, thats what I'll be blogging about. I am most definitely not an expert java programmer, but I am getting very good at reading the Javadoc.

If I post something which is incorrect or something which could be made more efficient somehow, post a comment. I really don't have a problem with criticism of any kind. Even cruel criticism has something to be learned from and since you get a finite number of days allocated to you, any day you don't learn something is one of those days wasted.
Rate this Entry

Using properties and settings in Java

Posted 02-18-2009 at 02:26 PM by ThanksFish
Right then, sliding a little way off the Betfair API track, but with something which is still germane to writing an app which will access the API, I'm going to talk about .properties files in Java.

I know I said I generally wouldn't be talking too much about basic java stuff and I suppose to a lot of people, this stuff will seem fairly basic. However, while I was trying to find out how to do this, I visited I don't know how many web pages and got useful bits of information from each one, which was great. What I couldn't get was all of this information in one place.

You might say "have a look at the The Java Tutorials pages, and you would be right to, they are an incredibly rich resource which contain just about everything you need in order to learn how to write programs using Java. However, when you have a look at the page on that URL, you will see that in order to use the Properties class, you need to be able to write to and from files on your hard drive. This means using an object of type InputStream. Fair enough, whats one of them?

Fortunately, I have been given just enough knowledge to be dangerous, so I already had half an idea what most of this stuff was, but putting it all together was becoming a frustration for me, particularly the stuff about making sure the properties file you are reading and writing to is in the classpath - a concept of which I had only a rough grasp of before this.

A properties file is a file which generally contains key/value pairs. So a key might be "username" and the accompanying value will be <your-username>. In java, they can be used for lots of things, although the most common useage seems to be internationalisation of applications. However, the beauty of writing your own programs is that they can be used for just about anything at all.

What I've spent the past few days working out is how I can change the behaviour of the program from within the actual program. I don't know about you, but quite a lot of the time, if I'm watching what my bot is doing, I see behaviour which I want to change, but because of the situation, I don't want to stop the application and dive into the source files in order to do it. So what I needed was a way to change certain behavious of the application while the application was still running.

Which brings us back to the properties file.

Mine for example, looks a bit like this:
Code:
# Betting Configuration
divisor=3
risk_percentage=10
stake_win_percentage=2.5
stop_loss_percentage=5
#timers
account_details_timer=30
market_prices_timer=200
unmatched_bet_timer=500
What I've also done is design a form which has components related to all of those settings. For the timers, I've used JSliders, for the percentages and so on, I've used JTextFields. The idea being, that when I see something I want to alter, I can open the settings form, change the timing or percentage or whatever, write the changes to the file and have them implemented straight away. Perfect.

Lets have a look at how its done. I'm not saying this is the best way, but this is how I've done it and so far, it works. You also have to keep in mind that the properties file works only with strings. There is a capacity for it to work with XML, but I haven't got that far with it. What that means is that the values you read into and out of the properties file are strings. If you want them to be doubles or longs, you have to convert them yourself, which isn't hard.

In order to make getting and setting the settings as simple as possible, I decided to encapsulate it into a custom object, unimaginatively titled a ConfigObject.

This is what it looks like:

Code:
package me.ms.conf;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ConfigObject {
    
    private Properties conf;
    private InputStream in; 
    private int acctDetailsTimer;
    private int divisor;
    private int mPricesTimer;
    private int riskPercentage;
    private int stakeWinPercentage;
    private int stopLossPercentage;
    private int unmatchedBetTimer;
    private String username;
    private int sportID;
    private boolean valuesChanged;

    public ConfigObject()
    {
        this.conf = new Properties();
        this.in = getClass().getResourceAsStream("/me/ms/conf/MarkSmart.properties");
        try
        {
            this.conf.load(in);
        }
        catch (IOException ex)
        {
            Logger.getLogger(ConfigObject.class.getName()).log(Level.SEVERE, null, ex);
        }
        this.readProperties();
    }

    public boolean isValuesChanged()
    {
        return valuesChanged;
    }

    public void writeProperties()
    {
        if (this.isValuesChanged())
        {
            this.conf.setProperty("account_details_timer", String.valueOf(this.acctDetailsTimer));
            this.conf.setProperty("divisor", String.valueOf(this.divisor));
            this.conf.setProperty("market_prices_timer", String.valueOf(this.mPricesTimer));
            this.conf.setProperty("risk_percentage", String.valueOf(this.riskPercentage));
            this.conf.setProperty("stake_win_percentage", String.valueOf(this.stakeWinPercentage));
            this.conf.setProperty("stop_loss_percentage", String.valueOf(this.stopLossPercentage));
            this.conf.setProperty("unmatched_bet_timer", String.valueOf(this.unmatchedBetTimer));
            this.conf.setProperty("username", this.username);
        }
    }

    private void readProperties()
    {
        this.acctDetailsTimer = Integer.parseInt(this.conf.getProperty("account_details_timer"));
        this.divisor = Integer.parseInt(this.conf.getProperty("divisor"));
        this.mPricesTimer = Integer.parseInt(this.conf.getProperty("market_prices_timer"));
        this.riskPercentage = Integer.parseInt(this.conf.getProperty("risk_percentage"));
        this.stakeWinPercentage = Integer.parseInt(this.conf.getProperty("stake_win_percentage"));
        this.stopLossPercentage = Integer.parseInt(this.conf.getProperty("stop_loss_percentage"));
        this.unmatchedBetTimer = Integer.parseInt(this.conf.getProperty("unmatched_bet_timer"));
        this.username = this.conf.getProperty("username");
    }
    public int getAcctDetailsTimer()
    {
        return acctDetailsTimer;
    }

    public void setAcctDetailsTimer(int acctDetailsTimer)
    {
        this.acctDetailsTimer = acctDetailsTimer;
        this.valuesChanged = true;
    }

    public int getDivisor()
    {
        return divisor;
    }

    public void setDivisor(int divisor)
    {
        this.divisor = divisor;
        this.valuesChanged = true;
    }

    public int getMPricesTimer()
    {
        return mPricesTimer;
    }

    public void setMPricesTimer(int mPricesTimer)
    {
        this.mPricesTimer = mPricesTimer;
        this.valuesChanged = true;
    }

    public int getRiskPercentage()
    {
        return riskPercentage;
    }

    public void setRiskPercentage(int riskPercentage)
    {
        this.riskPercentage = riskPercentage;
        this.valuesChanged = true;
    }

    public int getSportID()
    {
        return sportID;
    }

    public void setSportID(int sportID)
    {
        this.sportID = sportID;
        this.valuesChanged = true;
    }

    public int getStakeWinPercentage()
    {
        return stakeWinPercentage;
    }

    public void setStakeWinPercentage(int stakeWinPercentage)
    {
        this.stakeWinPercentage = stakeWinPercentage;
        this.valuesChanged = true;
    }

    public int getStopLossPercentage()
    {
        return stopLossPercentage;
    }

    public void setStopLossPercentage(int stopLossPercentage)
    {
        this.stopLossPercentage = stopLossPercentage;
        this.valuesChanged = true;
    }

    public int getUnmatchedBetTimer()
    {
        return unmatchedBetTimer;
    }

    public void setUnmatchedBetTimer(int unmatchedBetTimer)
    {
        this.unmatchedBetTimer = unmatchedBetTimer;
        this.valuesChanged = true;
    }

    public String getUsername()
    {
        return username;
    }

    public void setUsername(String username)
    {
        this.username = username;
        this.valuesChanged = true;
    }
}
You should be able to see what it is I have done here. In the constructor, I have created a new object of the class Properties(). I have then created an InputStream and set its path to the path within my package structure (classpath) which will lead it to my created properties file. (In netbeans, you can create and edit these files by accessing the File | New File | Other sets of menus and dialogs)

Since we are performing IO, which can throw exceptions which must be caught, we have a try...catch block within the constructor, where we load the InputStream into the Properties object, allowing us to use the Properties API to access our settings.

By creating the instance variables and their associated getters and setters, I can now treat the properties file as a plain old java object, or POJO as the in crowd would have you refer to it.

Since I have created it as a custom object, I can access these settings anywhere within my code, by doing
Code:
ConfigObject con = new ConfigObject();
con.getMPricesTimer();
<etc, etc>...
Of course, this sort of thing may well be old hat to some of you guys, but it impressed the hell out of me when I got it working.

Alan
Posted in Java
Comments 0 Email Blog Entry
Total Comments 0

Comments

 

All times are GMT. The time now is 09:03 PM.


BETFAIR® and the BETFAIR LOGO are registered trade marks of The Sporting Exchange Limited. Data on Betfair website(s) (including pricing data) is protected by © and database rights. It may not be used for any purpose without a licence. © The Sporting Exchange Limited. All rights reserved.