java-ecosystem

star 0

Java 25 development patterns for the crypto-scout ecosystem including microservices, ActiveJ, and async I/O

akarazhev By akarazhev schedule Updated 2/11/2026

name: java-ecosystem description: Java 25 development patterns for the crypto-scout ecosystem including microservices, ActiveJ, and async I/O license: MIT compatibility: opencode metadata: language: java version: "25" framework: activej domain: microservices

What I Do

Provide comprehensive guidance for Java 25 development across the crypto-scout ecosystem, covering microservice patterns, ActiveJ framework usage, and async I/O operations.

Core Architecture

Launcher Pattern (ActiveJ)

public final class Service extends Launcher {

    @Override
    protected Module getModule() {
        return combine(
            JmxModule.create(),
            ServiceGraphModule.create(),
            CoreModule.create(),
            ServiceModule.create(),
            WebModule.create()
        );
    }

    @Override
    protected void onStart() throws Exception {
        ConfigValidator.validate();
    }

    @Override
    protected void run() throws Exception {
        awaitShutdown();
    }

    public static void main(String[] args) throws Exception {
        new Service().launch(args);
    }
}

Module Structure by Service

Module Purpose Services Using
CoreModule Reactor and virtual thread executor All services
WebModule HTTP server, clients, health routes All services
ClientModule AMQP publisher lifecycle crypto-scout-client
CollectorModule Repositories and services crypto-scout-collector
AnalystModule Analysis services and transformers crypto-scout-analyst
BybitSpotModule Bybit spot WebSocket consumers crypto-scout-client
BybitLinearModule Bybit linear WebSocket consumers crypto-scout-client
CmcParserModule CoinMarketCap parser crypto-scout-client

Reactive Service Pattern

public final class MyService extends AbstractReactive implements ReactiveService {
    private final Executor executor;
    private volatile Resource resource;

    public static MyService create(NioReactor reactor, Executor executor) {
        return new MyService(reactor, executor);
    }

    private MyService(NioReactor reactor, Executor executor) {
        super(reactor);
        this.executor = executor;
    }

    @Override
    public Promise<Void> start() {
        return Promise.ofBlocking(executor, () -> {
            // Initialize resources
            resource = createResource();
        });
    }

    @Override
    public Promise<Void> stop() {
        return Promise.ofBlocking(executor, () -> {
            // Cleanup resources
            closeResource(resource);
            resource = null;
        });
    }
}

Stream Transformer Pattern (Analyst)

public final class AnalystTransformer extends AbstractStreamTransformer<StreamPayload, StreamPayload> {
    @Override
    protected StreamDataAcceptor<StreamPayload> onResumed(final StreamDataAcceptor<StreamPayload> output) {
        return in -> {
            try {
                final var result = process(in);
                output.accept(result);
            } catch (final Exception ex) {
                LOGGER.error("Processing failed", ex);
                output.accept(new StreamPayload(in.stream(), in.offset(), null));
            }
        };
    }
}

Code Style Essentials

File Structure

1-23:   MIT License header
25:     Package declaration
26:     Blank line
27+:    Imports (java.* → third-party → static)
        Blank line
        Class declaration

Import Organization

import java.io.IOException;
import java.nio.file.Path;
import java.time.Duration;

import com.rabbitmq.stream.Environment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.github.akarazhev.cryptoscout.config.Constants.AmqpConfig.AMQP_RABBITMQ_HOST;

Naming Conventions

Element Convention Example
Classes PascalCase StreamService, AmqpPublisher
Methods camelCase with verb waitForDatabaseReady
Constants UPPER_SNAKE_CASE JDBC_URL, DB_USER
Locals final var final var timeout
Tests <Class>Test AmqpPublisherTest
Test methods should<Subject><Action> shouldPublishPayload

Error Handling

// Invalid state
if (resource == null) {
    throw new IllegalStateException("Resource not initialized: " + name);
}

// Try-with-resources
try (final var conn = dataSource.getConnection();
     final var stmt = conn.prepareStatement(sql)) {
    // Use resources
} catch (final SQLException e) {
    throw new IllegalStateException("Database error", e);
}

// Interrupt handling
try {
    Thread.sleep(duration.toMillis());
} catch (final InterruptedException e) {
    Thread.currentThread().interrupt();
}

Exception Hierarchy (jcryptolib)

JCryptoLibException (base)
├── ApiException
├── CmcApiException
├── StreamException
├── CircuitBreakerException
├── RateLimiterException
├── HealthCheckException
├── ResilienceException
└── ConfigurationException

Usage:

// In jcryptolib
try {
    // operation
} catch (final SomeException e) {
    throw new StreamException("Message", e);
}

// In services
} catch (final SQLException e) {
    throw new IllegalStateException("Database operation failed", e);
}

Testing Patterns

JUnit 6 (Jupiter)

final class MyServiceTest {

    @BeforeAll
    static void setUp() {
        PodmanCompose.up();
    }

    @AfterAll
    static void tearDown() {
        PodmanCompose.down();
    }

    @Test
    void shouldServiceStartSuccessfully() throws Exception {
        final var service = createTestService();
        assertTrue(service.start().isResult());
    }
}

Mock Data Usage

// Load test fixtures
final var spotKlines = MockData.get(
    MockData.Source.BYBIT_SPOT,
    MockData.Type.KLINE_1
);
final var fgi = MockData.get(
    MockData.Source.CRYPTO_SCOUT,
    MockData.Type.FGI
);

Configuration Pattern

static final String VALUE = System.getProperty("property.key", "defaultValue");
static final int PORT = Integer.parseInt(System.getProperty("port.key", "5552"));
static final Duration TIMEOUT = Duration.ofMinutes(Long.getLong("timeout.key", 3L));

Key Classes Reference

jcryptolib

Class Purpose
BybitStream WebSocket streaming with resilience
BybitParser REST API data fetching
CmcParser CoinMarketCap data parser
AnalystEngine Technical analysis indicators
Payload<T> Stream data container
CircuitBreaker Resilience pattern
RateLimiter Rate limiting
JsonUtils JSON serialization

crypto-scout-client

Class Purpose
Client Service launcher
AmqpPublisher RabbitMQ Streams publisher
AbstractBybitStreamConsumer Base for Bybit consumers
CmcParserConsumer CMC data consumer

crypto-scout-collector

Class Purpose
Collector Service launcher
StreamService Stream consumer orchestrator
BybitStreamService Bybit data processor
CryptoScoutService CMC data processor
*Repository Database access

crypto-scout-analyst

Class Purpose
Analyst Service launcher
StreamService Stream processing orchestrator
DataService Async data processing
AnalystTransformer Stream transformer
StreamPublisher Output publisher

When to Use Me

Use this skill when:

  • Writing new Java classes or services
  • Understanding ActiveJ patterns and lifecycle
  • Implementing reactive services with Promise/async
  • Organizing imports and file structure
  • Following error handling and logging conventions
  • Writing JUnit 6 tests with proper lifecycle
  • Configuring services via system properties
  • Implementing stream transformers
  • Working with jcryptolib abstractions
Install via CLI
npx skills add https://github.com/akarazhev/crypto-scout --skill java-ecosystem
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator