Skip to main content

server-arch-gates

Check Artemis server code against the architectural rules the build enforces, before pushing. Use when writing or changing Java under src/main/java, adding a service, repository, REST resource, DTO, cache, or cross-node state, or when an ArchUnit test fails and the message does not make the rule obvious. Gives the rule, the reason, and the exact local command that proves it.

インストールへ移動

ソース情報

リポジトリ
ls1intum/Artemis
ソースの最終更新活動
2026年9月15日 11:49
検出された SKILL.md の言語
英語
スター
811
フォーク
394

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

ファイルエクスプローラー
2 ファイル

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
server-arch-gates
description
Check Artemis server code against the architectural rules the build enforces, before pushing. Use when writing or changing Java under src/main/java, adding a service, repository, REST resource, DTO, cache, or cross-node state, or when an ArchUnit test fails and the message does not make the rule obvious. Gives the rule, the reason, and the exact local command that proves it.
# Server architecture gates Artemis enforces its server conventions with a large ArchUnit suite under `src/test/java`, most of it module-scoped subclasses of a handful of abstract rule bases. They are not style preferences. Each one exists because the pattern it forbids produced a production bug. The failure messages are often terse, so this skill maps a change to the rules it is subject to and to the reason behind each. ## Run them locally The whole architecture suite, which is what the Server Code Style job runs: ```bash ./gradlew test -DincludeTags='ArchitectureTest' -x webapp ``` This is much faster than the full server test suite. Run it before pushing any change to `src/main/java`. A violation fails both Server Code Style and Server Tests, so it is worth catching locally. A single class while iterating: ```bash ./gradlew test --tests ArchitectureTest -x webapp ``` ## Which rules apply to what you changed | You changed | Read | | -------------------------------------- | --------------------------------------------------- | | A service or REST resource | Transactions, persistence access, module boundaries | | A repository | Transactions, raw JDBC | | A DTO record | DTO conventions | | Anything holding state across requests | Caching, distributed data | | An entity or an association | Caching, entity conventions | | Anything at all in a large file | Counted gates | | Anything that lowercases or uppercases | Case conversion | | Anything that serializes JSON | Jackson version | The detail for each, with the reason and the failing rule name, is in `reference/gates.md`. Read it rather than guessing; several of these rules forbid something that looks completely reasonable. **Jackson 2 must not appear in production code.** Artemis serializes with Jackson 3, whose packages are `tools.jackson`. Jackson 2 stays on the runtime classpath for third-party libraries that carry their own mapper, so a `com.fasterxml.jackson.databind`, `.core`, `.dataformat`, `.datatype`, `.module`, `.jr` or `.jaxrs` import still compiles — `testNoJackson2InProductionCode` in `ArchitectureTest` is what rejects it. The one exception is `com.fasterxml.jackson.annotation`: `jackson-annotations` never moved to the `tools.jackson` group, so `@JsonInclude`, `@JsonProperty` and `@JsonTypeInfo` stay where they are and must not be "fixed". Mappers are immutable in Jackson 3 — derive one with `JsonMapper.builder()` or `rebuild()`, never `configure()` or `registerModule()` on a built instance — and its exceptions are unchecked, so a `catch (IOException)` no longer catches a parse failure. ## The rules most often broken **No transaction boundaries in services or controllers.** `@Transactional`, `TransactionTemplate`, and `PlatformTransactionManager` belong in repositories, typically on modifying queries, and `TransactionSynchronizationManager` is banned outright. Enforced globally by `testTransactionBoundariesOnlyInRepositories`, `testNoProgrammaticTransactionManagement` and `testNoTransactionSynchronization` in `src/test/java/de/tum/cit/aet/artemis/shared/architecture/ArchitectureTest.java`. The replacements are a check in the `WHERE` clause of a `@Modifying` query, or explicit compensation in a `catch` block. **No direct persistence access.** No injected `EntityManager` or `EntityManagerFactory`, and no `JdbcClient`, `JdbcTemplate`, or `DataSource`. Write the statement as a `@Query` on a repository, with `nativeQuery = true` where there is no entity to name. Enforced by `shouldNotUseEntityManagerDirectly` and `shouldNotUseRawJdbcDirectly` in `src/test/java/de/tum/cit/aet/artemis/shared/architecture/ArchitectureTest.java`. Three classes sit on that rule's exception list, carrying a TODO to refactor them away. One of them is `TitleCacheEvictionService`, which holds an `EntityManagerFactory` purely to reach the Hibernate `EventListenerRegistry` and register itself as a listener. So when the caching section below calls it the canonical eviction pattern, copy its eviction logic, not its constructor: a new class doing the same thing fails the rule, because the list is grandfathering rather than permission. Raw JDBC has no per-class exceptions at all; only `core.config` may hold a `DataSource`. **Never touch Hazelcast or Redis directly.** All cross-node state goes through `DistributedDataProvider` in `src/main/java/de/tum/cit/aet/artemis/core/service/distributed/`. Enforced by `src/test/java/de/tum/cit/aet/artemis/shared/architecture/DistributedDataProviderArchitectureTest.java`. The provider is configurable, so direct usage does not fail loudly, it silently loses the state. **No Hibernate second-level cache.** No `@Cache` on entities or associations. Enforced by `testNoHibernateSecondLevelCacheAnnotation` in `ArchitectureTest.java`. For DTO and projection caching use Spring `@Cacheable`, always paired with explicit eviction. **Reach optional modules through their API.** Use `Optional<*Api>`, never another module's repository directly. **Never fold case without a locale.** `String.toLowerCase()` and `String.toUpperCase()` use the JVM default locale, so the same input gives a different answer depending on where the server runs. Pass `Locale.ROOT` for machine-facing values and `Locale.ENGLISH` only where the surrounding code already does for that kind of value. Enforced by `testNoLocaleLessCaseConversion` in `ArchitectureTest.java`, over production and test classes both. ## Before adding a cache The default answer is not to. The bar is a measured performance gain that justifies the eviction-correctness work, because there is no service-level transaction boundary to coordinate eviction within a request. See `documentation/docs/developer/guidelines/caching.mdx` for the full rationale, and `reference/gates.md` for the pattern if you do proceed. ## Adding a capability to the distributed data layer If `DistributedDataProvider` lacks what you need, add it there, implement it for all three providers (Hazelcast, Redis, Local), and add a case to `AbstractDistributedDataTest`. That suite is what keeps the providers in agreement. Request entry lifetimes at the call site with `getExpiringMap(name, ttl)`; `getMap(name)` rejects a per-entry TTL deliberately, because a provider map configuration only applies to that one provider. Full guidance: `documentation/docs/developer/guidelines/distributed-data.mdx`.
GitHubで見る