Setting Up

1. I downloaded the SDK library, but I am unsure how / where to start

From the sdk.sportradar.com you can navigate to the SDK source code GitHub repository where for each version there is an associated example project. In the example, the methods that are used to dispatch the messages to the user only log various information, but this is always a good place to see how to start using the SDK. Starting the SDK requires an access token though, which can be acquired from the Integration Manager or Sales team.

2a. I cannot build UofConfiguration - an exception is thrown on Build method

  • Check the SDK logs and look for API request failures (whoami.xml and/or producers.xml endpoints).

  • Check if the API server (telnet api.betradar.com 443) can be accessed from the machine the SDK is running on.

  • Is the token valid, has the token expired, and is the account properly configured?

  • Is the customer's IP whitelisted on our servers?

  • Are there any outbound firewall rules that might block the SDK?

  • Are there any SDK settings overridden with custom hosts and ports?

  • Is there any anti-virus software running that might block the SDK?

2b. The SDK cannot connect to the feed - an exception is thrown by the uofSdk.Open(...) method

  • Check the SDK logs and look for the connection failure reason provided by the SDK.

  • Check if the AMQP server (telnet mq.betradar.com 5671) can be accessed from the machine SDK is running on.

  • Is the token valid, has the token expired, and is the account properly configured?

  • Is the customer's IP whitelisted on our servers?

  • Are there any outbound firewall rules that might block the SDK?

  • Are there any SDK settings overridden with custom hosts and ports?

  • Is there any anti-virus software running that might block the SDK?

3. A producer never gets marked as "up"

  • Check whether the producer on the account associated with the customer's account (token) is active (Available producers endpoint on iodocs (https://iodocs.betradar.com/) page.

  • Make sure the producer is not disabled in the SDK (either via configuration file, or in-code config)

  • Verify in execution execution and rest logs that the recovery request was successful for that producer.

  • Verify within the execution or feed logs that there are messages received associated with the reovery (feed messages contain matching recovery requestId).

  • Make sure messages are being processed fast enough to "catch-up" with the producer (compare the message timestamp from the traffic logs with the time when the message was dispatched to the user from the interaction log)

4. A producer(s) is/are periodically marked as "down"

  • Does the "producer down reason" passed to callback method / event handler indicates a "processing queue delay violation"? If so, the user is processing the messages too slowly or processing of a specific message takes a long period of time (check the interaction log for duration of processing of a specific message)?

  • Does this only happen while one or more other producers are in recovery? The recovery process can generate a large number of messages in short period of time. While those messages are being processed, message created by other producers are waiting on queue to be processed. As a result, the SDK does not receive alive messages from other producers on user sessions for a longer periods of time and it marks the affected producers as "down". This can in some cases be avoided by creating multiple sessions ensuring that large number of messages from one producer do not affect another producer. Once messages generated by the recovery are processed and if the user processes messages faster than they are generated by the producers during normal operation (no recovery), the state of the producers will stabilise. (See: UOF SDK - Recovery)

5. Do I have to take care of "recovery" when using the SDK?

No, the SDK takes care of recovery for every producer which is "active" ( "available producers" endpoint on iodocs) and is not disabled in the SDK. The type of recovery made depends whether the user provided the timestamp of the last message received before starting the SDK. If no value is provided, the SDK makes a "full odds recovery" (the user will get the current odds for all matches associated with that producer) requesting as large time frame worth of messages to be recovered as a particular producer allows for; otherwise the SDK will make a "partial recovery" (the user will get the latest odds for all events which have changed and all stateful messages send after the provided timestamp).

User cannot manually start recovery process.

6. I don't want to process all messages in the same process / on the same machine to ensure better performance.

Different sessions / combinations of sessions can be created on the UofSdk object. The sessions allow to filter the messages based on their priority(hi / low priority), or based on whether the messages are associated with live, prematch and virtual events. Recommended approach is to have separate instances consuming messages from live, pre-match and virtual producers. Even though the SDK does not provide a way to subscribe messages on a per-sport basis, this can be achieved via filtering messages on the client side without excessively degrading efficiency.

7. I am using the SDK in multiple processes / machines and each time one SDK makes a recovery all SDKs get recovery messages which reduces performance.

Use the nodeId configuration property and assign it a different values in different instances. This will ensure that only the SDK instance, which requested the recovery, receives the recovery messages. The same property should be used on replay server to only receive messages replayed by a specific SDK.

8. I am a software/platform provider and/or need to access odds from different feeds belonging to multiple bookmakers in the same process

Currently SDK does not support that. The recommended approach is creating multiple SDK instances (with different configurations / tokens) and each instance will receive it's own messages.

9. How to get your first data?

You can just connect to the feed and populate the database with all the data "on-the-fly". The feed indeed gives you only IDs, however, the SDK contains methods which you can use and will get all the additional information you need from the API (e.g. marketDescriptions, fixtures, competitors, names, etc.).

However, if you would like to populate your database in advance, you can use several interfaces and their methods that are available in the SDK. Especially using the interfaces you can get on UofSdk: http://sdk.sportradar.com/content/unifiedfeedsdk/java2/javadoc/com/sportradar/unifiedodds/sdk/OddsFeed.html

JAVA - to get sport event for tomorrow

Date tomorrow = new Date();
Calendar c = Calendar.getInstance();
c.setTime(tomorrow);
c.add(Calendar.DATE, 1);
tomorrow = c.getTime();
 
List<Competition> sportEvents = sportDataProvider.getCompetitionsFor(tomorrow);
for(Competition competition: sportEvents)
{
    if (competition instanceof Match) {
        Match match = (Match) competition;
        Fixture fixture = match.getFixture();
    }  
}

JAVA - Getting sports, categories, tournaments, matches

List<Sport> sports = sportDataProvider.getSports();
for(Sport sport : sports) {
    Urn sportId = sport.getId();
    String sportName = sport.getName();
 
    List<Category> categories = sport.getCategories();
    for(Category category : categories) {
        Urn categoryId = category.getId();
        String categoryName = category.getName();
 
        List<SportEvent> tournaments = category.getTournaments();
        for(SportEvent sportEvent : tournaments) {
            if(sportEvent instanceof Tournament) {
                Tournament tournament = (Tournament)sportEvent;
                Urn tournamentId = tournament.getId();
                String tournamentName = tournament.getName();
 
                List<Competition> schedule = tournament.getCurrentSeason().getSchedule();
                for (Competition competition : schedule) {
                    Urn competitionId = competition.getId();
                    List<Competitor> competitors = competition.getCompetitors();
 
                    if(competition instanceof Match) {
                        Match match = (Match)competition;
                        Fixture fixture = match.getFixture();
                    }
                }
            }
        }
    }
}

.NET - Get all sport events for tomorrow

var sportEvents = await sportDataProvider.GetSportEventsByDateAsync(DateTime.Now.AddDays(1), CultureInfo.CurrentCulture);foreach (var sportEvent in sportEvents){ var match = sportEvent as IMatch; var matchFixture = await match?.GetFixtureAsync(); // use other methods to get other data}

.NET - Getting sports, categories, tournaments, matches

// With the SportDataProvider you can access various data about the ongoing eventsISportDataProvider sportDataProvider = oddsFeed.SportDataProvider; // get all sportsvar sports = sportDataProvider.GetSportsAsync().GetAwaiter().GetResult();// iterate through sports, get all categories, tournaments, schedule for each tournamentforeach (ISport sport in sports){ var sportName = sport.GetName(CultureInfo.CurrentCulture); var categories = sport.Categories; foreach (ICategory category in categories) { var categoryName = category.GetName(CultureInfo.CurrentCulture); var tournamets = category.Tournaments; foreach (ISportEvent sportEvent in tournamets) { var tournamentName = sportEvent.GetNameAsync(CultureInfo.CurrentCulture).GetAwaiter().GetResult(); var tournament = sportEvent as ITournament; // get schedule for current season var schedule = tournament?.GetCurrentSeasonAsync().Result.Schedule; foreach (var scheduledSportEvent in schedule) { var match = scheduledSportEvent as IMatch; var matchFixture = match?.GetFixtureAsync().GetAwaiter().GetResult(); // use other methods to get other data } } }}

10. What does SetAdjustAfterAge do?

Normally, the max window for recovery is 3-72 hours (depending on the producer).

If clients are disconnected for longer than max hours, but the SDK is still running, the SDK will then automatically have the recovery timestamp older than max hours.

If that happens, SetAdjustAfterAge then defines what should happen:

  • If false - an exception will be raised.

  • If true - maximum value for recovery timestamp will be used.

11. How to use UOF Java SDK with Java 11 or greater?

Recommended version of UOF SDK to be used is v3.x.x. It was tested to be working with java 8, java 11 and java 17.

When using UOF SDK version v2.x.x, Java 11 doesn't contain some of the libraries in its core, some of the libraries the SDK is using internally have to be added as dependencies. To do so, you should normally add the following to the pom.xml file (inside <dependencies>...</dependencies> ):

Expand source

12. How to resolve PKIX certificate exception with Java SDK

In some cases, Java SDK can raise the following exception:

 "Caused by sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target".

This is raised because of a missing certificate JVM is unable to obtain for some reason.

1. Download the certificate

openssl s_client -connect stgapi.betradar.com:443 </dev/null \| openssl x509 -out stgapi.betradar.com.cert

2. Find out which version of JDK you're running

java -version

3. Import the certificate using key tool (replace java version with your version)

keytool -import -noprompt -trustcacerts \-alias stgapi.betradar.com -file stgapi.betradar.com.cert \-keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/security/cacerts -storepass changeit

4. Check if the certificate is there (replace java version with your version)

keytool -list -v -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/security/cacerts -storepass changeit -alias stgapi.betradar.com

13. How to resolve the "Invalid char 2-3 byte order" issue in Java?

In case Java SDK raises an exception containing: ... Invalid character 2-3 bytes ... .

This issue is only present in some specific environment and circumstances and is normally caused by the client's environment (due to incorrect encoding).

To resolve this issue, the client should add "-Dfile.encoding=UTF-8" to their JVM run configuration which enforces using UTF-8 encoding to be used.

14. How to solve CultureNotFoundException in .NET SDK?

Custom CultureInfos were not supported until Windows 10. If the SDK is running on an older OS (Windows 7 or older), CultureNotFoundException (Culture is not Supported) is thrown in case a custom CultureInfo such as "srl" is created (e.g. new CultureInfo("srl")). Unfortunately, there is no other solution available than updating the OS to Windows 10 or newer.

Last updated

Was this helpful?