Skip to content

Instantly share code, notes, and snippets.

@ArtDu
Last active June 26, 2025 14:21
Show Gist options
  • Select an option

  • Save ArtDu/ce181eed76260b057774de62d064cabb to your computer and use it in GitHub Desktop.

Select an option

Save ArtDu/ce181eed76260b057774de62d064cabb to your computer and use it in GitHub Desktop.
VK Internal Java Meetup Practice №2
  1. Install Java connector
  2. Install TDB images and tt cli
  3. Generate simple TDB application
  4. Run TDB and Redis
  5. Add TDB migration
  6. Generate simple maven project
  7. Add minimal spring application and Jshell script
  8. Build classpath to use it in Jshell
  9. Run Jshell with classpath
  10. Interact with Redis
  11. Change 3 files to use Tarantool instead of Redis
  12. Interact with Tarantool

Install java connector

Установить коннектор по инструкции.

Install TDB images and tt cli

Установить образы можно с customer_zone tarantool.io


tt cli можно установить с помощью стандартного пакетного менеджера:

# for linux with apt dep manager:
curl -L https://tarantool.io/release/3/installer.sh | bash && sudo apt-get install tt
# for macos:
brew install tt

Generate simple TDB application

tt init

# Скопируем шаблон tarantooldb
git clone git@gitlab:tarantool/tdb/tarantooldb.git
cp -r tarantooldb/templates/* templates

tt create tarantool_db --name myapp

Run TDB and Redis

Запустим tdb шаблон:

cd myapp
make up

Запустим redis server:

# macos:
brew install redis
brew services start redis
# linux with apt dep manager:
sudo apt install redis-server
sudo systemctl start redis-server

Add migration

Зайдите в TCM http://localhost:8081/cluster/migrations (admin, secret -- логин пароль по умолчанию).
Добавьте миграцию 0000002_person.lua в раздел migrations.
Спейс будет выглядит так же как в практике по синглинстанс тарантулу

local helpers = require('tt-migrations.helpers')

local function apply()    
    local space_name = 'person'
    local space = box.schema.space.create(space_name, { if_not_exists = true })
    space:format({
      {'id', 'integer'},
      {'name', 'string'},
      {'createdAt', 'datetime'},
      {'metadata', 'map', is_nullable = true},
      {'bucket_id', 'unsigned'},
    })
    space:create_index('pk', { parts = {'id'}, if_not_exists = true})
    space:create_index('bucket_id', { parts = {'bucket_id'}, unique = false, if_not_exists = true})
    helpers.register_sharding_key(space_name, {'id'})
    

    return true
end

return {
    apply = {
        scenario = apply,
    }
}

Generate simple maven project

mvn archetype:generate -DgroupId=com.example -DartifactId=my-tarantool-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Add minimal spring application and jshell script

cd my-tarantool-app

Добавить минимальное приложение можно с помощью git патча:

git init
git add . && git commit -m "Init app"
wget https://gist.githubusercontent.com/ArtDu/d6e1a927a1841e9877777844d14eecc1/raw/37534655e5625eead8448baf560ab048217c0d45/diff.patch
git apply diff.patch

Либо можно пройтись ручками добавить 4 файла и 1 поменять:

Create/modify 5 files

Add deps to pom.xml:

bash
cat > pom.xml <<EOL
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>my-tarantool-app</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>my-tarantool-app</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>3.2.12</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
      <version>3.2.12</version>
    </dependency>
<!--    <dependency>-->
<!--      <groupId>io.tarantool</groupId>-->
<!--      <artifactId>tarantool-spring-data-32</artifactId>-->
<!--      <version>1.2.1</version>-->
<!--    </dependency>-->
  </dependencies>
</project>
EOL
exit
Зачем нужна команда bash выше? Если используется zsh то он экранирует символы xml для этого скрипта, поэтому bash нужен только для создания файла pom.xml с зависимостями выше.

Add application.yaml to your redis/tarantool env

mkdir src/main/resources
cat > src/main/resources/application.yaml <<EOL
spring:
  data:
    redis:
      host: localhost
      port: 6379
    tarantool:
      host: localhost
      port: 3301

EOL

Add Person POJO:

cat > src/main/java/com/example/Person.java <<EOL
package com.example;

//import com.fasterxml.jackson.annotation.JsonFormat;
//import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.springframework.data.annotation.Id;
import org.springframework.data.keyvalue.annotation.KeySpace;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.index.Indexed;

import java.time.Instant;
import java.util.Map;

//@JsonFormat(shape = JsonFormat.Shape.ARRAY)
//@JsonIgnoreProperties(ignoreUnknown = true) // for example bucket_id
@KeySpace("person")
@RedisHash("person")
public class Person {
    @Id
    public Integer id;
    @Indexed
    public String name;
    public Instant createdAt;
    public Map metadata;

    public Person(Integer id, String name, Instant createdAt, Map metadata) {
        this.id = id;
        this.name = name;
        this.createdAt = createdAt;
        this.metadata = metadata;
    }

    public Person() {
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", createdAt=" + createdAt +
                ", metadata=" + metadata +
                '}';
    }
}

EOL

Add Person Repository:

cat > src/main/java/com/example/PersonRepository.java <<EOL
package com.example;

import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface PersonRepository extends CrudRepository<Person, Integer> {
    List<Person> findByName(String name);
}

EOL

Modify App java main Class:

cat > src/main/java/com/example/App.java <<EOL
package com.example;

//import io.tarantool.spring.data32.repository.config.EnableTarantoolRepositories;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;

@SpringBootApplication
//@EnableTarantoolRepositories
@EnableRedisRepositories
public class App {
    public static void main(String[] args) {
        App.bootstrap(args);
    }

    public static ApplicationContext bootstrap(String[] args) {
        return SpringApplication.run(App.class, args);
    }
}

EOL

Build classpath to use it in jshell

mvn clean package dependency:build-classpath -Dmdep.outputFile=classpath.txt

Run jshell with classpath

jshell --class-path $(cat classpath.txt):target/classes

Interact with redis

Загрузить зависимости и запустить spring:

import com.example.*;
import java.time.*;
var context = App.bootstrap(new String[] {}) 

Используем repository API:

var rep = context.getBean(PersonRepository.class);
rep.save(new Person(1, "art", Instant.now(), Map.of("hello", "world")));
rep.findById(1);

Change 3 files to use Tarantool instead of Redis

Поменяем приложение с помощью git патча:

rm diff.patch
wget https://gist.githubusercontent.com/ArtDu/7560100d1355efc73bf35c135f483a26/raw/c68f75c096bd0c14b19f6613b0640d8c4ffff736/diff.patch
git apply diff.patch

Либо можно пройтись ручками обновив 3 файла по diff ниже:

Update 3 files

Удалим зависимость на redis и добавим зависимость на tarantool:

diff --git a/pom.xml b/pom.xml
index 975111a..8d917f9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,15 +19,10 @@
       <artifactId>spring-boot-starter</artifactId>
       <version>3.2.12</version>
     </dependency>
-    <dependency>
-      <groupId>org.springframework.boot</groupId>
-      <artifactId>spring-boot-starter-data-redis</artifactId>
-      <version>3.2.12</version>
-    </dependency>
-<!--    <dependency>-->
-<!--      <groupId>io.tarantool</groupId>-->
-<!--      <artifactId>tarantool-spring-data-32</artifactId>-->
-<!--      <version>1.2.1</version>-->
-<!--    </dependency>-->
+   <dependency>
+     <groupId>io.tarantool</groupId>
+     <artifactId>tarantool-spring-data-32</artifactId>
+     <version>1.2.1</version>
+   </dependency>
   </dependencies>
 </project>

Добавим аннотаций над POJO Person для Tarantool и удалим аннотации нужные для Redis:

diff --git a/src/main/java/com/example/Person.java b/src/main/java/com/example/Person.java
index 645b410..f4d8b6d 100644
--- a/src/main/java/com/example/Person.java
+++ b/src/main/java/com/example/Person.java
@@ -1,23 +1,19 @@
 package com.example;

-//import com.fasterxml.jackson.annotation.JsonFormat;
-//import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import org.springframework.data.annotation.Id;
 import org.springframework.data.keyvalue.annotation.KeySpace;
-import org.springframework.data.redis.core.RedisHash;
-import org.springframework.data.redis.core.index.Indexed;

 import java.time.Instant;
 import java.util.Map;

-//@JsonFormat(shape = JsonFormat.Shape.ARRAY)
-//@JsonIgnoreProperties(ignoreUnknown = true) // for example bucket_id
+@JsonFormat(shape = JsonFormat.Shape.ARRAY)
+@JsonIgnoreProperties(ignoreUnknown = true) // for example bucket_id
 @KeySpace("person")
-@RedisHash("person")
 public class Person {
     @Id
     public Integer id;
-    @Indexed
     public String name;
     public Instant createdAt;
     public Map metadata;

В точку запуска скажем Spring чтобы использовал репозитории Tarantool вместо репозиториев Redis:

diff --git a/src/main/java/com/example/App.java b/src/main/java/com/example/App.java
index 0bfdc90..cc6a7b5 100644
--- a/src/main/java/com/example/App.java
+++ b/src/main/java/com/example/App.java
@@ -1,14 +1,12 @@
 package com.example;

-//import io.tarantool.spring.data32.repository.config.EnableTarantoolRepositories;
+import io.tarantool.spring.data32.repository.config.EnableTarantoolRepositories;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.context.ApplicationContext;
-import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;

 @SpringBootApplication
-//@EnableTarantoolRepositories
-@EnableRedisRepositories
+@EnableTarantoolRepositories
 public class App {
     public static void main(String[] args) {
         App.bootstrap(args);

Interact with Tarantool

Соберем и запустим jshell

mvn clean package dependency:build-classpath -Dmdep.outputFile=classpath.txt && jshell --class-path $(cat classpath.txt):target/classes
import com.example.*;
import java.time.*;
var context = App.bootstrap(new String[] {});

var rep = context.getBean(PersonRepository.class);
rep.save(new Person(1, "art", Instant.now(), Map.of("hello", "world")));
rep.findById(1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment