name: java-code-style description: Java 25 code style conventions for crypto-scout-test including naming, imports, error handling, and testing patterns license: MIT compatibility: opencode metadata: language: java version: "25" domain: style-guide
What I Do
Enforce consistent code style across the crypto-scout-test library following established Java 25 conventions.
File Structure
1-23: MIT License header
25: Package declaration
26: Blank line
27+: Imports (java.* → third-party → static, blank lines between groups)
Blank line
Class/enum/interface 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.test.Constants.DB.JDBC_URL;
import static org.junit.jupiter.api.Assertions.assertEquals;
Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Classes | PascalCase | StreamTestPublisher, MockData, AmqpTestConsumer |
| Methods | camelCase with verb | waitForDatabaseReady, deleteFromTables, canConnect |
| Constants | UPPER_SNAKE_CASE | JDBC_URL, DB_USER, BYBIT_STREAM |
| Parameters/locals | final var |
final var timeout, final var data |
| Test classes | <ClassName>Test |
MockBybitSpotDataTest, StreamConsumerPublisherTest |
| Test methods | should<Subject><Action> |
shouldSpotKline1DataReturnMap, shouldPublishPayloadToStream |
Access Modifiers
Utility Classes
final class Constants {
private Constants() {
throw new UnsupportedOperationException();
}
static final String PATH_SEPARATOR = "/";
final static class DB {
private DB() {
throw new UnsupportedOperationException();
}
static final String JDBC_URL = System.getProperty("test.db.jdbc.url", "...");
}
}
Factory Pattern
public final class StreamTestPublisher extends AbstractReactive implements ReactiveService {
private final Executor executor;
private final Environment environment;
private final String stream;
private final AtomicReference<Producer> producerRef = new AtomicReference<>();
public static StreamTestPublisher create(final NioReactor reactor, final Executor executor,
final Environment environment, final String stream) {
return new StreamTestPublisher(reactor, executor, environment, stream);
}
private StreamTestPublisher(final NioReactor reactor, final Executor executor,
final Environment environment, final String stream) {
super(reactor);
this.executor = executor;
this.environment = environment;
this.stream = stream;
}
}
Error Handling
// Unchecked exceptions for invalid state
if (is == null) {
throw new IllegalStateException("Resource not found: " + path);
}
// Try-with-resources for all closeable 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 resolve compose file URI", e);
Logging
private static final Logger LOGGER = LoggerFactory.getLogger(ClassName.class);
LOGGER.info("Connected to DB: {}", conn.getClientInfo());
LOGGER.warn("Error closing stream producer", ex);
LOGGER.error("Failed to start StreamTestPublisher", ex);
Testing (JUnit 6/Jupiter)
final class MockBybitSpotDataTest {
@BeforeAll
static void setUp() {
PodmanCompose.up();
}
@AfterAll
static void tearDown() {
PodmanCompose.down();
}
@Test
void shouldSpotKline1DataReturnMap() throws Exception {
final var data = MockData.get(MockData.Source.BYBIT_SPOT, MockData.Type.KLINE_1);
assertNotNull(data);
assertFalse(data.isEmpty());
}
}
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 Project Classes
| Class | Package | Purpose |
|---|---|---|
MockData |
com.github.akarazhev.cryptoscout.test |
Typed mock data loader with Source/Type enums |
PodmanCompose |
com.github.akarazhev.cryptoscout.test |
Container lifecycle management |
DBUtils |
com.github.akarazhev.cryptoscout.test |
Database utilities |
StreamTestPublisher |
com.github.akarazhev.cryptoscout.test |
RabbitMQ Streams publisher |
StreamTestConsumer |
com.github.akarazhev.cryptoscout.test |
RabbitMQ Streams consumer |
AmqpTestPublisher |
com.github.akarazhev.cryptoscout.test |
AMQP publisher |
AmqpTestConsumer |
com.github.akarazhev.cryptoscout.test |
AMQP consumer |
Assertions |
com.github.akarazhev.cryptoscout.test |
Test assertions |
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