# Getting started: LiveObjects in Java
This guide shows how to integrate Ably LiveObjects into your Java application.
You will learn how to:
* Create an Ably account and get an API key for authentication.
* Install the Ably Pub/Sub SDK.
* Create a channel with LiveObjects functionality enabled.
* Create, update and subscribe to changes on LiveObjects data structures: [LiveMap](https://ably.com/docs/liveobjects/map.md) and [LiveCounter](https://ably.com/docs/liveobjects/counter.md).
## Authentication
An [API key](https://ably.com/docs/auth.md#api-keys) is required to authenticate with Ably. API keys are used either to authenticate directly with Ably using [basic authentication](https://ably.com/docs/auth/basic.md), or to generate tokens for untrusted clients using [token authentication](https://ably.com/docs/auth/token.md).
[Sign up](https://ably.com/sign-up) for a free account and create your own API key in the [dashboard](https://ably.com/dashboard) or use the [Control API](https://ably.com/docs/platform/account/control-api.md) to create an API key programmatically.
API keys and tokens have a set of [capabilities](https://ably.com/docs/auth/capabilities.md) assigned to them that specify which operations can be performed on which resources. The following capabilities are available for LiveObjects:
* `object-subscribe` - grants clients read access to LiveObjects, allowing them to get the root object and subscribe to updates.
* `object-publish` - grants clients write access to LiveObjects, allowing them to perform mutation operations on objects.
To use LiveObjects, an API key must have at least the `object-subscribe` capability. With only this capability, clients will have read-only access, preventing them from calling mutation methods on LiveObjects.
For the purposes of this guide, make sure your API key includes both `object-subscribe` and `object-publish` [capabilities](https://ably.com/docs/auth/capabilities.md) to allow full read and write access.
## Install Ably Pub/Sub SDK
LiveObjects is available as part of the Ably Pub/Sub SDK via the dedicated Objects plugin.
### Install for Maven:
```xml
io.ablyably-java1.3.0io.ablyliveobjects1.3.0
```
### Install for Gradle:
```java
implementation 'io.ably:ably-java:1.3.0'
implementation 'io.ably:liveobjects:1.3.0'
```
For `Android` platform, use `ably-android` instead of `ably-java`
```java
implementation 'io.ably:ably-android:1.3.0'
```
## Instantiate a client
Instantiate an Ably Realtime client from the Pub/Sub SDK, providing the Objects plugin:
```java
AblyRealtime realtime = new AblyRealtime(new ClientOptions("ABLY_KEY"));
```
A [`ClientOptions`](https://ably.com/docs/api/realtime-sdk.md#client-options) object may be passed to the Pub/Sub SDK instance to further customize the connection, however at a minimum you must set an API key and provide an `Objects` plugin so that the client can use LiveObjects functionality.
## Create a channel
LiveObjects is managed and persisted on [channels](https://ably.com/docs/channels.md). To use LiveObjects, you must first create a channel with the correct [channel mode flags](https://ably.com/docs/channels/options.md#modes):
* `OBJECT_SUBSCRIBE` - required to access objects on a channel.
* `OBJECT_PUBLISH` - required to create and modify objects on a channel.
```java
ChannelOptions opts = new ChannelOptions();
opts.modes = new ChannelMode[] {
ChannelMode.object_publish,
ChannelMode.object_subscribe
};
ChannelBase channel = realtime.channels.get("test-channel", opts);
```
## Get root object
The [`channel.getObjects`](https://ably.com/docs/api/realtime-sdk/channels.md#objects) method gives access to the LiveObjects API for a channel.
Use it to get the root object, which is the entry point for accessing and persisting objects on a channel. The root object is a [`LiveMap`](https://ably.com/docs/liveobjects/map.md) instance that always exists on a channel and acts as the top-level node in your object tree. You can get the root object using the `getRoot()` method of LiveObjects:
```java
// The root is returned once the LiveObjects state is synchronized with the Ably system.
// `getRoot` Implicitly attaches channel if it's in a INITIALIZED state
RealtimeObjects objects = channel.getObjects();
LiveMap root = objects.getRoot(); // blocks current thread till result is returned
```
The above `getRoot()` method is blocking in nature so it's recommended to use `getRootAsync()` instead
```java
RealtimeObjects objects = channel.getObjects();
objects.getRootAsync(new ObjectsCallback() {
@Override
public void onSuccess(LiveMap root) {
// Successfully retrieved the root LiveMap
System.out.println("Root object retrieved: " + root);
// You can now use the root object to create and manage other objects
}
@Override
public void onError(AblyException exception) {
// Handle errors (network issues, authentication failures, etc.)
System.err.println("Failed to get root object: " + exception.getMessage());
}
});
```
| Blocking Method | Async Method |
| --------------- | ------------ |
| `RealtimeObjects.getRoot()` | `RealtimeObjects.getRootAsync()` |
| `RealtimeObjects.createMap()` | `RealtimeObjects.createMapAsync()` |
| `RealtimeObjects.createCounter()` | `RealtimeObjects.createCounterAsync()` |
| `LiveMap.set()` | `LiveMap.setAsync()` |
| `LiveMap.remove()` | `LiveMap.removeAsync()` |
| `LiveCounter.increment()` | `LiveCounter.incrementAsync()` |
| `LiveCounter.decrement()` | `LiveCounter.decrementAsync()` |
## Create objects
You can create new objects using dedicated methods of the LiveObjects API at [`channel.getObjects()`](https://ably.com/docs/api/realtime-sdk/channels.md#objects). To persist them on a channel and share them between clients, you must assign objects to a parent `LiveMap` instance connected to the root object. The root object itself is a `LiveMap` instance, so you can assign objects to the root and start building your object tree from there.
```java
LiveCounter visitsCounter = objects.createCounter();
LiveMap reactionsMap = objects.createMap();
root.set("visits", LiveMapValue.of(visitsCounter));
root.set("reactions", LiveMapValue.of(reactionsMap));
```
## Subscribe to updates
Subscribe to realtime updates to objects on a channel. You will be notified when an object is updated by other clients or by you.
```java
visitsCounter.subscribe((counterUpdate) ->
System.out.println("Visits counter updated: " +
counterUpdate.getUpdate().getAmount());
);
reactionsMap.subscribe((mapUpdate) -> {
System.out.println("Reactions map updated: " + mapUpdate.getUpdate());
System.out.println("Reactions map updated: " + reactionsMap.entries());
});
```
## Update objects
Update objects using mutation methods. All subscribers (including you) will be notified of the changes when you update an object:
```java
visitsCounter.increment(5); // counter updated: 5
visitsCounter.decrement(2); // counter updated: 3
reactionsMap.set("like", LiveMapValue.of(10)); // {"like": 10}
reactionsMap.set("love", LiveMapValue.of(5)); // {"like": 10}, {"love": 5}
reactionsMap.remove("like"); // {"love": 5}
```
## Next steps
This quickstart introduced the basic concepts of LiveObjects and demonstrated how it works. The next steps are to:
* Read more about [LiveCounter](https://ably.com/docs/liveobjects/counter.md) and [LiveMap](https://ably.com/docs/liveobjects/map.md).
* Learn about [Batching Operations](https://ably.com/docs/liveobjects/batch.md).
* Learn about [Objects Lifecycle Events](https://ably.com/docs/liveobjects/lifecycle.md).
* Add [Typings](https://ably.com/docs/liveobjects/typing.md) for your LiveObjects.