java-code-style

star 0

Java 25 code style conventions for crypto-scout-client including naming, imports, error handling, and testing patterns

akarazhev By akarazhev schedule Updated 2/11/2026

name: java-code-style description: Java 25 code style conventions for crypto-scout-client including naming, imports, error handling, and testing patterns license: MIT compatibility: opencode metadata: language: java version: "25" project: crypto-scout-client domain: style-guide

What I Do

Enforce consistent code style across the crypto-scout-client microservice following established Java 25 conventions.

File Structure

1-23:   MIT License header (see below)
25:     Package declaration
26:     Blank line
27+:    Imports (java.* → third-party → static, blank lines between groups)
        Blank line
        Class/enum/interface declaration

MIT License Header

/*
 * MIT License
 *
 * Copyright (c) 2026 Andrey Karazhev
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

Import Organization

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

import com.github.akarazhev.jcryptolib.config.AppConfig;
import io.activej.inject.module.Module;
import io.activej.launcher.Launcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.github.akarazhev.cryptoscout.Constants.Module.CMC_PARSER_MODULE_ENABLED;
import static io.activej.inject.module.Modules.combine;
import static org.junit.jupiter.api.Assertions.assertEquals;

Naming Conventions

Element Convention Example
Classes PascalCase AmqpPublisher, BybitSpotBtcUsdtConsumer
Methods camelCase with verb publish, consume, validate
Constants UPPER_SNAKE_CASE AMQP_RABBITMQ_HOST, SERVER_PORT
Parameters/locals final var final var timeout, final var data
Test classes <ClassName>Test AmqpPublisherTest
Test methods should<Subject><Action> shouldPublishPayloadToStream

Access Modifiers

Utility Classes

final class Constants {
    private Constants() {
        throw new UnsupportedOperationException();
    }

    static final String PATH_SEPARATOR = "/";

    final static class AmqpConfig {
        private AmqpConfig() {
            throw new UnsupportedOperationException();
        }

        static final String AMQP_RABBITMQ_HOST = "amqp.rabbitmq.host";
        static final String AMQP_STREAM_PORT = "amqp.stream.port";
    }
}

Factory Pattern

public final class AmqpPublisher extends AbstractReactive implements ReactiveService {
    private final Executor executor;
    private volatile Producer producer;

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

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

Error Handling

Unchecked Exceptions

if (resource == null) {
    throw new IllegalStateException("Resource not found: " + path);
}

Try-with-Resources

try (final var conn = DriverManager.getConnection(JDBC_URL, DB_USER, DB_PASSWORD);
     final var st = conn.createStatement();
     final var rs = st.executeQuery(SELECT_ONE)) {
    return rs.next();
} catch (final SQLException e) {
    return false;
}

Interrupt Handling

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

Exception Chaining

throw new IllegalStateException("Failed to initialize service", e);

Logging

private static final Logger LOGGER = LoggerFactory.getLogger(ClassName.class);

LOGGER.info("Connected to stream: {}", streamName);
LOGGER.warn("Connection lost, retrying...");
LOGGER.error("Failed to start publisher", ex);

Testing (JUnit 6/Jupiter)

final class AmqpPublisherTest {

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

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

    @Test
    void shouldPublishPayloadToStream() throws Exception {
        final var publisher = createPublisher();
        final var result = publisher.publish(payload);
        assertTrue(result);
    }
}

Configuration Pattern

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

Module-Specific Patterns

Module Constants Organization

final class Constants {
    private Constants() {
        throw new UnsupportedOperationException();
    }

    final static class Module {
        private Module() {
            throw new UnsupportedOperationException();
        }

        static final String CMC_PARSER_MODULE_ENABLED = "cmc.parser.module.enabled";
        static final String BYBIT_STREAM_MODULE_ENABLED = "bybit.stream.module.enabled";
    }
}

Config Constants Organization

final class Constants {
    private Constants() {
        throw new UnsupportedOperationException();
    }

    final static class AmqpConfig {
        private AmqpConfig() {
            throw new UnsupportedOperationException();
        }

        static final String AMQP_RABBITMQ_HOST = "amqp.rabbitmq.host";
        static final String AMQP_RABBITMQ_USERNAME = "amqp.rabbitmq.username";
        static final String AMQP_RABBITMQ_PASSWORD = "amqp.rabbitmq.password";
        static final String AMQP_STREAM_PORT = "amqp.stream.port";
        static final String AMQP_BYBIT_STREAM = "amqp.bybit.stream";
        static final String AMQP_CRYPTO_SCOUT_STREAM = "amqp.crypto.scout.stream";
    }

    final static class WebConfig {
        private WebConfig() {
            throw new UnsupportedOperationException();
        }

        static final String SERVER_PORT = "server.port";
        static final String DNS_ADDRESS = "dns.address";
        static final String DNS_TIMEOUT_MS = "dns.timeout.ms";
        static final int PORT_MIN = 1;
        static final int PORT_MAX = 65535;
        static final int DNS_TIMEOUT_MIN_MS = 100;
        static final int DNS_TIMEOUT_MAX_MS = 60000;
        static final String HOSTNAME_PATTERN = "^(([0-9]{1,3}\\.){3}[0-9]{1,3})|([a-zA-Z0-9.-]+)$";
    }
}

When to Use Me

Use this skill when:

  • Writing new Java classes or methods
  • Reviewing code for style compliance
  • Understanding project conventions
  • Organizing imports and file structure
  • Implementing error handling patterns
  • Creating configuration constants
Install via CLI
npx skills add https://github.com/akarazhev/crypto-scout-client --skill java-code-style
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator