| = Getting Started with Ignite 3 Using Java API |
| |
| This guide walks you through creating a Java application that connects to an Ignite 3 cluster, demonstrating key patterns for working with data using Ignite Java API. |
| |
| == Prerequisites |
| |
| * JDK 17 or later; |
| * Maven; |
| * Up-to-date versions of Docker and Docker Compose. |
| |
| == Setting Up Ignite 3 Cluster |
| |
| Create a Docker Compose file to run a three-node Ignite cluster: |
| |
| [source, yaml] |
| ---- |
| # docker-compose.yml |
| name: ignite3 |
| |
| x-ignite-def: &ignite-def |
| image: apacheignite/ignite:3.0.0 |
| environment: |
| JVM_MAX_MEM: "4g" |
| JVM_MIN_MEM: "4g" |
| configs: |
| - source: node_config |
| target: /opt/ignite/etc/ignite-config.conf |
| |
| services: |
| node1: |
| <<: *ignite-def |
| command: --node-name node1 |
| ports: |
| - "10300:10300" # REST API port |
| - "10800:10800" # Client port |
| node2: |
| <<: *ignite-def |
| command: --node-name node2 |
| ports: |
| - "10301:10300" |
| - "10801:10800" |
| node3: |
| <<: *ignite-def |
| command: --node-name node3 |
| ports: |
| - "10302:10300" |
| - "10802:10800" |
| |
| configs: |
| node_config: |
| content: | |
| ignite { |
| network { |
| port: 3344 |
| nodeFinder.netClusterNodes = ["node1:3344", "node2:3344", "node3:3344"] |
| } |
| } |
| ---- |
| |
| === Starting and Initializing the Cluster |
| |
| 1. Start the cluster: |
| + |
| [source, bash] |
| ---- |
| docker compose up -d |
| ---- |
| + |
| 2. Run the Ignite CLI and initialize the cluster: |
| + |
| [source, bash] |
| ---- |
| docker run --rm -it --network=host -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 apacheignite/ignite:3.0.0 cli |
| ---- |
| 3. Inside the CLI, confirm the connection to the default node. |
| 4. Initialize the cluster: |
| + |
| [source, bash] |
| ---- |
| cluster init --name=ignite3 --metastorage-group=node1,node2,node3 |
| ---- |
| + |
| 5. Enter the SQL mode: |
| + |
| [source, bash] |
| ---- |
| sql |
| ---- |
| + |
| 6. Create a sample table and insert data: |
| + |
| [source, bash] |
| ---- |
| CREATE TABLE Person (id INT PRIMARY KEY, name VARCHAR); |
| INSERT INTO Person (id, name) VALUES (1, 'John'); |
| ---- |
| + |
| 7. Exit the SQL mode and CLI tool: |
| + |
| [source, bash] |
| ---- |
| exit; |
| exit |
| ---- |
| |
| == Setting Up Your Java Project |
| |
| === Create a Maven Project |
| |
| First, create a simple Maven project. Below is the example of the project we will be using: |
| |
| ``` |
| ignite3-java-demo/ |
| ├── pom.xml |
| └── src/ |
| └── main/ |
| └── java/ |
| └── com/ |
| └── example/ |
| └── Main.java |
| ``` |
| |
| === Configure Maven Dependencies |
| |
| Include the Ignite client dependency in your `pom.xml` file: |
| |
| [source, xml, subs="attributes,specialchars"] |
| ---- |
| <dependencies> |
| <!-- Ignite 3 Client --> |
| <dependency> |
| <groupId>org.apache.ignite</groupId> |
| <artifactId>ignite-client</artifactId> |
| <version>3.0.0</version> |
| </dependency> |
| </dependencies> |
| ---- |
| |
| == Building Your Java Application |
| |
| Now, let's create a Java application that connects to our Ignite cluster and performs various data operations. |
| |
| === Main Application Class |
| |
| Create a `Main.java` file with the following code: |
| |
| TIP: See the structure example above for the expected file location. This examples contains the full class file. |
| |
| [source, java] |
| ---- |
| package com.example; |
| |
| import org.apache.ignite.catalog.ColumnType; |
| import org.apache.ignite.catalog.definitions.ColumnDefinition; |
| import org.apache.ignite.catalog.definitions.TableDefinition; |
| import org.apache.ignite.client.IgniteClient; |
| import org.apache.ignite.table.KeyValueView; |
| import org.apache.ignite.table.RecordView; |
| import org.apache.ignite.table.Table; |
| import org.apache.ignite.table.Tuple; |
| |
| /** |
| * This example demonstrates connecting to an Ignite 3 cluster |
| * and working with data using different table view patterns. |
| */ |
| public class Main { |
| public static void main(String[] args) { |
| // Create an array of connection addresses for fault tolerance |
| String[] addresses = { |
| "localhost:10800", |
| "localhost:10801", |
| "localhost:10802" |
| }; |
| |
| // Connect to the Ignite cluster using the client builder pattern |
| try (IgniteClient client = IgniteClient.builder() |
| .addresses(addresses) |
| .build()) { |
| |
| System.out.println("Connected to the cluster: " + client.connections()); |
| |
| // Demonstrate querying existing data using SQL API |
| queryExistingTable(client); |
| |
| // Create a new table using Java API |
| Table table = createTable(client); |
| |
| // Demonstrate different ways to interact with tables |
| populateTableWithDifferentViews(table); |
| |
| // Query the new table using SQL API |
| queryNewTable(client); |
| } |
| } |
| |
| /** |
| * Queries the pre-created Person table using SQL |
| */ |
| private static void queryExistingTable(IgniteClient client) { |
| System.out.println("\n--- Querying Person table ---"); |
| client.sql().execute(null, "SELECT * FROM Person") |
| .forEachRemaining(row -> System.out.println("Person: " + row.stringValue("name"))); |
| } |
| |
| /** |
| * Creates a new table using the Java API |
| */ |
| private static Table createTable(IgniteClient client) { |
| System.out.println("\n--- Creating Person2 table ---"); |
| return client.catalog().createTable( |
| TableDefinition.builder("Person2") |
| .ifNotExists() |
| .columns( |
| ColumnDefinition.column("ID", ColumnType.INT32), |
| ColumnDefinition.column("NAME", ColumnType.VARCHAR)) |
| .primaryKey("ID") |
| .build()); |
| } |
| |
| /** |
| * Demonstrates different ways to interact with tables |
| */ |
| private static void populateTableWithDifferentViews(Table table) { |
| System.out.println("\n--- Populating Person2 table using different views ---"); |
| |
| // 1. Using RecordView with Tuples |
| RecordView<Tuple> recordView = table.recordView(); |
| recordView.upsert(null, Tuple.create().set("id", 2).set("name", "Jane")); |
| System.out.println("Added record using RecordView with Tuple"); |
| |
| // 2. Using RecordView with POJOs |
| RecordView<Person> pojoView = table.recordView(Person.class); |
| pojoView.upsert(null, new Person(3, "Jack")); |
| System.out.println("Added record using RecordView with POJO"); |
| |
| // 3. Using KeyValueView with Tuples |
| KeyValueView<Tuple, Tuple> keyValueView = table.keyValueView(); |
| keyValueView.put(null, Tuple.create().set("id", 4), Tuple.create().set("name", "Jill")); |
| System.out.println("Added record using KeyValueView with Tuples"); |
| |
| // 4. Using KeyValueView with Native Types |
| KeyValueView<Integer, String> keyValuePojoView = table.keyValueView(Integer.class, String.class); |
| keyValuePojoView.put(null, 5, "Joe"); |
| System.out.println("Added record using KeyValueView with Native Types"); |
| } |
| |
| /** |
| * Queries the newly created Person2 table using SQL |
| */ |
| private static void queryNewTable(IgniteClient client) { |
| System.out.println("\n--- Querying Person2 table ---"); |
| client.sql().execute(null, "SELECT * FROM Person2") |
| .forEachRemaining(row -> System.out.println("Person2: " + row.stringValue("name"))); |
| } |
| |
| /** |
| * POJO class representing a Person |
| */ |
| public static class Person { |
| // Default constructor required for serialization |
| public Person() { } |
| |
| public Person(Integer id, String name) { |
| this.id = id; |
| this.name = name; |
| } |
| |
| Integer id; |
| String name; |
| } |
| } |
| ---- |
| |
| == Running the Application |
| |
| To run your application: |
| |
| 1. Make sure your Ignite cluster is up and running; |
| 2. Compile and run your Java application: |
| |
| [source, bash] |
| ---- |
| mvn compile exec:java -Dexec.mainClass="com.example.Main" |
| ---- |
| |
| == Expected Output |
| |
| You should see output similar to this: |
| |
| [source, text] |
| ---- |
| Connected to the cluster: Connections{active=1, total=1} |
| |
| --- Querying Person table --- |
| Person: John |
| |
| --- Creating Person2 table --- |
| |
| --- Populating Person2 table using different views --- |
| Added record using RecordView with Tuple |
| Added record using RecordView with POJO |
| Added record using KeyValueView with Tuples |
| Added record using KeyValueView with Native Types |
| |
| --- Querying Person2 table --- |
| Person2: Jane |
| Person2: Jack |
| Person2: Jill |
| Person2: Joe |
| ---- |
| |
| == Understanding Table Views in Ignite 3 |
| |
| Ignite 3 provides multiple view patterns for interacting with tables on top of providing a robust SQL API. Examples below showcase how you can work with Ignite tables from your project without SQL. For examples of working with SQL, see the link:get-started/explore-sql[Getting Started with SQL] tutorial. |
| |
| === RecordView Pattern |
| |
| RecordView treats tables as a collection of records, perfect for operations that work with entire rows: |
| |
| [source, java] |
| ---- |
| // Get RecordView for Tuple objects (schema-less) |
| RecordView<Tuple> recordView = table.recordView(); |
| recordView.upsert(null, Tuple.create().set("id", 2).set("name", "Jane")); |
| |
| // Get RecordView for mapped POJO objects (type-safe) |
| RecordView<Person> pojoView = table.recordView(Person.class); |
| pojoView.upsert(null, new Person(3, "Jack")); |
| ---- |
| |
| === KeyValueView Pattern |
| |
| KeyValueView treats tables as a key-value store, ideal for simple lookups: |
| |
| [source, java] |
| ---- |
| // Get KeyValueView for Tuple objects |
| KeyValueView<Tuple, Tuple> keyValueView = table.keyValueView(); |
| keyValueView.put(null, Tuple.create().set("id", 4), Tuple.create().set("name", "Jill")); |
| |
| // Get KeyValueView for native Java types |
| KeyValueView<Integer, String> keyValuePojoView = table.keyValueView(Integer.class, String.class); |
| keyValuePojoView.put(null, 5, "Joe"); |
| ---- |
| |
| == Cleaning Up |
| |
| To stop your cluster when you are done: |
| |
| [source, bash] |
| ---- |
| docker compose down |
| ---- |
| |
| == Troubleshooting |
| |
| If you encounter connection issues: |
| |
| * Verify your Docker containers are running with `docker compose ps` command; |
| * Check if the exposed ports match those in your client configuration; |
| * Ensure that the `localhost` interface can access the Docker container network. |
| |
| == Next Steps |
| |
| Now that you've explored the basics of connecting to Ignite and interacting with data: |
| |
| * Try implementing transactions; |
| * Experiment with more complex schemas and data types; |
| * Explore data partitioning strategies; |
| * Investigate distributed computing capabilities. |