Persistence

Persistence enables data to be saved for the server, rooms and clients.

Configuration

With the default configuration Union is already persistence enabled using
an embedded Derby database. To disable persistence remove the following
line from the union.xml:

<datasource id="union"/>

You can change the default database and add additional datasources to
persist specific attributes or even replace the built in persistence
entirely. See Advanced Configuration below.

Persistent Attributes

Server, room, and account attributes can be persisted using Union's built-in database or any other custom data source. To persist an attribute, include the Attribute.PERSISTENT flag setting.

For example, the following code sets the shared account attribute “hobby” and also makes it persistent.

1
2
client.getAccount().setAttribute("hobby", "chess", Attribute.SCOPE_GLOBAL,
                    Attribute.FLAG_SHARED | Attribute.FLAG_PERSISTENT);

To stop persisting an attribute remove the Attribute.PERSISTENT flag.
Omitting the Attribute.PERSISTENT flag will remove the attribute from the database.

To set the shared attribute “hobby” and also stop making it persistent, use:

1
2
client.getAccount().setAttribute("hobby", "chess", Attribute.SCOPE_GLOBAL,
                    Attribute.FLAG_SHARED);

Increasing the Length Limit for Persisted Attribute Values

By default, the maximum length of a persisted attribute value is 768 characters. To increase that limit, follow these steps:

  1. Make a backup copy of /UNION_HOME/libs/union.jar.
  2. Unzip /UNION_HOME/libs/union.jar. A folder named /union/ will be created. (Note: not all decompression utilities support unzipping .jar files. If your decompression utility does not recognize .jar files, first rename union.jar to union.zip, then unzip union.zip.)
  3. In the /union/ folder, edit one (or more) of the following files:
    • AccountAttribute.hbm.xml (for account attributes)
    • RoomAttribute.hbm.xml (for room attributes)
    • ServerAttribute.hbm.xml (for server attributes)
  4. In the following line:
    <property name="value" column="VALUE"/>
    

    add a length attribute that specifies the desired character limit. For example, the following code increases the character limit to 1024:

    <property name="value" column="VALUE"  length="1024"/>
    
  5. Save the edited .xml file(s).
  6. Re-zip the /union/ folder.
  7. Change the resulting .zip file's name from union.zip to union.jar.
  8. Restart Union Server.

Accounts

An account is a persistent identity for a specific user of Union. An account is identified by a userID and protected by a password.

To create an account on the server with a userID of "carmack" and a password of "quake".

1
server.createAccount("carmack", "quake");

To log in an account. If another client is currently connected to the server they will be disconnected.

1
client.login("carmack", "quake");

To log off an account. When an account is logged off the client is disconnected from the server.

1
client.logoff("carmack", "quake");

To remove an account from the server. If a client with the userID is currently logged in to the server they will be disconnected.

1
server.removeAccount("carmack", "quake");

Advanced Configuration

Persistence is configured in the persistence section of the union.xml. The persistence section defines the datasources that are deployed with the server. A datasource saves and retrieves persistent information. Union comes configured with a datasource that uses Hibernate to talk to a database. By default this database is an embedded version of Derby. You can change the database Union connects to by editting the file UNION_HOME/lib/uhibernate.cfg.xml and replacing the hibernate.connection.* properties with those for the database of your choice.

Union can support multiple, concurrent datasources. Each datasource is configured to handle specific attributes in a chain according to the order they appear in the union.xml. If no datasource handler is found the default datasource (the last datasource specified) is used.

When specifying room id or scope id you can use:

** to specify all scopes.
* to specify the unnamed qualifier.

When specifying name you can use:

* to specify all attributes

Server Attributes

Example:

1
2
3
4
     <server-attributes>
         <name>environment</name>
         <name>version</name>
     </server-attributes>

The datasource will handle all server attributes named "environment" or "version".

Room Attributes

Example:

1
2
3
     <room id="**">
         <name>welcomeMsg</name>
     </room>

The datasource will handle the room attribute "welcomeMsg" in any room on the server.

Example:

1
2
3
4
    <room id="games.*">
        <name>highScoreDay</name>
        <name>highScoreWeek</name>
    </room>

The datasource will handle the room attribute "highScoreDay" and "highScoreWeek" in any room in the "games.*" qualifier (eg. games.Chess1, games.Chess2, games.Hockey).

Example:

1
2
3
    <room id="*">
        <name>dailyReport</name>
    </room>

The datasource will handle the room attribute "dailyReport" in any room in the unnamed qualifer (eg. ChatRoom, Lobby).

Example:

1
2
3
    <room id="games.Lobby">
        <name>*</name>
    </room>

The datasource will handle any room attribute in the room "games.Lobby".

Account Attributes

Example:

1
2
3
     <scope id="**">
         <name>score</name>
     </scope>

The datasource will handle any account attribute named "score" in any scope.

Example:

1
2
3
     <scope id="">
         <name>username</name>
     </scope>

The datasource will handle the global scope account attribute "username".

Example:

1
2
3
     <scope id="chat.*">
         <name>avatar</name>
     </scope>

The datasource will handle the account attribute "avatar" when scoped to any room in the "chat.*" qualifier (eg. chat.Hobbies, chat.Sports).

Example:

1
2
3
4
5
     <scope id="games.WeeklyContest*">
         <name>team</name>
         <name>points</name>
         <name>games</name>
     </scope>

The datasource will handle the account attributes "team", "points" and "games" when scoped to the room "games.WeeklyContest".

Complete Example

The following example shows how to deploy a second datasource to the server while still keeping the embedded Union database as the default. Note: when specifying the default Union embedded database you can use the reserved id union and omit the class element.

The datasource "secondDS" will be loaded as the class MyDatasource which must implement the interface net.user1.union.api.Datasource. Any attribute not handled by the datasource "secondDS" will be handled by the Union database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    <persistence>
       <datasource id="secondDS">
            <attributes>
                <attribute name="debug">true</attribute>
            </attributes>
            <class>com.mycompany.MyDatasource</class>
            <server-attributes>
                <server-attributes>
                    <name>environment</name>
                    <name>version</name>
                </server-attributes>
            </server-attributes>
            <room-attributes>
                <room id="**">
                    <name>welcomeMsg</name>
                </room>
                <room id="games.*">
                    <name>highScoreDay</name>
                    <name>highScoreWeek</name>
                </room>
                <room id="*">
                    <name>dailyReport</name>
                </room>
                <room id="games.Lobby">
                    <name>*</name>
                </room>
            </room-attributes>
            <account-attributes>
                <scope id="**">
                    <name>score</name>
                </scope>
                <scope id="">
                    <name>username</name>
                </scope>
                <scope id="chat.*">
                    <name>avatar</name>
                </scope>
                <scope id="games.WeeklyContest*">
                    <name>team</name>
                    <name>points</name>
                    <name>games</name>
                </scope>
            </account-attributes>
        </datasource>    
        <datasource id="union"/>
    </persistence>