{"id":50529166,"url":"https://github.com/gravitee-io/gravitee-archrules-maven-plugin","last_synced_at":"2026-06-03T11:01:55.084Z","repository":{"id":335308300,"uuid":"1143440370","full_name":"gravitee-io/gravitee-archrules-maven-plugin","owner":"gravitee-io","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-26T14:14:57.000Z","size":81,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-26T16:20:48.998Z","etag":null,"topics":["product-am","security-scan"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gravitee-io.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.adoc","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-27T15:29:52.000Z","updated_at":"2026-05-26T08:02:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/gravitee-io/gravitee-archrules-maven-plugin","commit_stats":null,"previous_names":["gravitee-io/gravitee-archrules-maven-plugin"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/gravitee-io/gravitee-archrules-maven-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravitee-io%2Fgravitee-archrules-maven-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravitee-io%2Fgravitee-archrules-maven-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravitee-io%2Fgravitee-archrules-maven-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravitee-io%2Fgravitee-archrules-maven-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gravitee-io","download_url":"https://codeload.github.com/gravitee-io/gravitee-archrules-maven-plugin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravitee-io%2Fgravitee-archrules-maven-plugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33860971,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["product-am","security-scan"],"created_at":"2026-06-03T11:01:54.175Z","updated_at":"2026-06-03T11:01:55.078Z","avatar_url":"https://github.com/gravitee-io.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Gravitee Architecture Rules Maven Plugin\n\n[![Gravitee.io](https://img.shields.io/static/v1?label=Available%20at\u0026message=Gravitee.io\u0026color=1EC9D2)](https://download.gravitee.io/#graviteeio-apim/plugins/policies/gravitee-archrules-maven-plugin/)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/gravitee-io/gravitee-archrules-maven-plugin/blob/master/LICENSE.txt)\n[![Releases](https://img.shields.io/badge/semantic--release-conventional%20commits-e10079?logo=semantic-release)](https://github.com/gravitee-io/gravitee-archrules-maven-plugin/releases)\n[![CircleCI](https://circleci.com/gh/gravitee-io/gravitee-archrules-maven-plugin.svg?style=svg)](https://circleci.com/gh/gravitee-io/gravitee-archrules-maven-plugin)\n\nA Maven plugin that enforces architectural rules and logging best practices across Gravitee projects using [ArchUnit](https://www.archunit.org/).\n\n## Overview\n\nThe Gravitee Architecture Rules Maven Plugin helps maintain code quality and consistency by automatically checking compliance with architectural rules during the build process. It focuses on enforcing logging best practices to ensure proper observability and traceability in distributed systems.\n\n**Key benefits:**\n- Catches architectural violations early in the development cycle\n- Enforces consistent logging patterns across the codebase\n- Improves observability by ensuring proper request context propagation\n- Reduces technical debt by preventing anti-patterns\n\n## Architecture Rules\n\nThe plugin provides two main rule checks:\n\n### 1. Global Logging Check (`global-logging-check`)\n\n**Purpose:** Prevents direct usage of SLF4J's `LoggerFactory` to enforce standardized logging patterns.\n\n**Rationale:** Direct usage of `LoggerFactory.getLogger()` can lead to inconsistent logger initialization and makes it harder to enforce organization-wide logging standards.\n\n**What it checks:**\n- No classes should depend on `org.slf4j.LoggerFactory`\n- Exceptions can be configured via allow-lists\n\n**Example violation:**\n```java\n// ❌ Violation\nimport org.slf4j.LoggerFactory;\n\npublic class MyService {\n    private static final Logger log = LoggerFactory.getLogger(MyService.class);\n}\n```\n\n### 2. Execution Context Logging Check (`execution-context-logging-check`)\n\n**Purpose:** Ensures that when an `ExecutionContext` is available as a method parameter, logging is done through the context-aware logger (`ctx.withLogger(log)`) instead of calling the logger directly.\n\n**Rationale:** In request-scoped operations, using context-aware logging automatically includes correlation IDs, API keys, and other contextual information in log entries, significantly improving traceability and debugging capabilities.\n\n**What it checks:**\n- Methods that receive an `ExecutionContext` parameter should use `ctx.withLogger(log)` for logging\n- Direct calls to `Logger.info()`, `Logger.debug()`, `Logger.error()`, `Logger.warn()`, or `Logger.trace()` are flagged as violations\n- **Internal methods (private/protected) called from a method with `ExecutionContext` are also checked** (call graph traversal)\n- Legacy `io.gravitee.gateway.api.ExecutionContext` is excluded from checks\n- Additional context classes can be configured to extend the rule beyond `ExecutionContext` types (e.g., `KafkaConnectionContext`)\n\n**Example violations:**\n```java\n// ❌ Violation - Direct call\npublic void processRequest(ExecutionContext ctx, Request request) {\n    log.info(\"Processing request\"); // Missing context information\n}\n\n//----------------------------------//\n\n// ❌ Violation - Via internal method\npublic void processRequest(ExecutionContext ctx, Request request) {\n    processInternal(request); // Calls private method\n}\n\nprivate void processInternal(Request request) {\n    log.info(\"Processing\"); // VIOLATION detected - parent has ExecutionContext\n}\n\n//----------------------------------//\n\n// ✅ Correct - Using withLogger\npublic void processRequest(ExecutionContext ctx, Request request) {\n    ctx.withLogger(log).info(\"Processing request\"); // Includes correlation ID, API key, etc.\n}\n\n//----------------------------------//\n\n// ✅ Correct - Passing ExecutionContext to internal methods\npublic void processRequest(ExecutionContext ctx, Request request) {\n    processInternal(ctx, request);\n}\n\nprivate void processInternal(ExecutionContext ctx, Request request) {\n    ctx.withLogger(log).info(\"Processing\"); // Uses contextual logger\n}\n\n//----------------------------------//\n\n// ❌ Violation - With additional context type (KafkaConnectionContext)\npublic void processKafkaMessage(KafkaConnectionContext ctx, Message msg) {\n    log.info(\"Processing message\"); // Missing Kafka context information\n}\n\n// ✅ Correct - Using withLogger with additional context type\npublic void processKafkaMessage(KafkaConnectionContext ctx, Message msg) {\n    ctx.withLogger(log).info(\"Processing message\"); // Includes Kafka connection details\n}\n```\n\n**Note:** To scan additional context types like `KafkaConnectionContext`, you must configure the `additionalContextClasses` parameter (see [Advanced Configuration](#advanced-xml-configuration)).\n\n## Configuration\n\n### Basic XML Configuration\n\nAdd the plugin to your `pom.xml`:\n\n```xml\n\u003cbuild\u003e\n    \u003cplugins\u003e\n        \u003cplugin\u003e\n            \u003cgroupId\u003eio.gravitee.maven\u003c/groupId\u003e\n            \u003cartifactId\u003egravitee-archrules-maven-plugin\u003c/artifactId\u003e\n            \u003cversion\u003e1.0.0-SNAPSHOT\u003c/version\u003e\n            \u003cexecutions\u003e\n                \u003cexecution\u003e\n                    \u003cid\u003echeck-global-logging\u003c/id\u003e\n                    \u003cgoals\u003e\n                        \u003cgoal\u003eglobal-logging-check\u003c/goal\u003e\n                    \u003c/goals\u003e\n                \u003c/execution\u003e\n                \u003cexecution\u003e\n                    \u003cid\u003echeck-execution-context-logging\u003c/id\u003e\n                    \u003cgoals\u003e\n                        \u003cgoal\u003eexecution-context-logging-check\u003c/goal\u003e\n                    \u003c/goals\u003e\n                \u003c/execution\u003e\n            \u003c/executions\u003e\n        \u003c/plugin\u003e\n    \u003c/plugins\u003e\n\u003c/build\u003e\n```\n\n### Advanced XML Configuration\n\nCustomize rule checks with allow-lists and exclusions:\n\n```xml\n\u003cplugin\u003e\n    \u003cgroupId\u003eio.gravitee.maven\u003c/groupId\u003e\n    \u003cartifactId\u003egravitee-archrules-maven-plugin\u003c/artifactId\u003e\n    \u003cversion\u003e1.0.0-SNAPSHOT\u003c/version\u003e\n    \u003cexecutions\u003e\n        \u003cexecution\u003e\n            \u003cid\u003echeck-global-logging\u003c/id\u003e\n            \u003cgoals\u003e\n                \u003cgoal\u003eglobal-logging-check\u003c/goal\u003e\n            \u003c/goals\u003e\n            \u003cconfiguration\u003e\n                \u003c!-- Exclude specific classes (useful for legacy code) --\u003e\n                \u003callowList\u003e\n                    \u003callowList\u003ecom.example.LegacyService\u003c/allowList\u003e\n                    \u003callowList\u003ecom.example.ThirdPartyAdapter\u003c/allowList\u003e\n                \u003c/allowList\u003e\n\n                \u003c!-- Exclude classes by suffix (e.g., test utilities) --\u003e\n                \u003callowListSuffixes\u003e\n                    \u003callowListSuffix\u003eTest\u003c/allowListSuffix\u003e\n                    \u003callowListSuffix\u003eTestHelper\u003c/allowListSuffix\u003e\n                \u003c/allowListSuffixes\u003e\n\n                \u003c!-- Exclude entire packages from scanning --\u003e\n                \u003cpackagesToExclude\u003e\n                    \u003cpackageToExclude\u003ecom.example.legacy..\u003c/packageToExclude\u003e\n                    \u003cpackageToExclude\u003ecom.example.generated..\u003c/packageToExclude\u003e\n                \u003c/packagesToExclude\u003e\n            \u003c/configuration\u003e\n        \u003c/execution\u003e\n\n        \u003cexecution\u003e\n            \u003cid\u003echeck-execution-context-logging\u003c/id\u003e\n            \u003cgoals\u003e\n                \u003cgoal\u003eexecution-context-logging-check\u003c/goal\u003e\n            \u003c/goals\u003e\n            \u003cconfiguration\u003e\n                \u003c!-- Same allow-list options as global-logging-check --\u003e\n                \u003callowList\u003e\n                    \u003callowList\u003ecom.example.SpecialHandler\u003c/allowList\u003e\n                \u003c/allowList\u003e\n                \u003callowListSuffixes\u003e\n                    \u003callowListSuffix\u003eConfigurationEvaluator\u003c/allowListSuffix\u003e\n                \u003c/allowListSuffixes\u003e\n                \u003cpackagesToExclude\u003e\n                    \u003cpackageToExclude\u003ecom.example.tests..\u003c/packageToExclude\u003e\n                \u003c/packagesToExclude\u003e\n\n                \u003c!-- Ignore specific ExecutionContext implementations --\u003e\n                \u003cignoreExecutionContextClasses\u003e\n                    \u003cignoreExecutionContextClass\u003ecom.example.FakeExecutionContext\u003c/ignoreExecutionContextClass\u003e\n                    \u003cignoreExecutionContextClass\u003ecom.example.MockExecutionContext\u003c/ignoreExecutionContextClass\u003e\n                \u003c/ignoreExecutionContextClasses\u003e\n\n                \u003c!-- Add additional context classes to scan (e.g., KafkaConnectionContext) --\u003e\n                \u003cadditionalContextClasses\u003e\n                    \u003cadditionalContextClass\u003eio.gravitee.node.api.kafka.KafkaConnectionContext\u003c/additionalContextClass\u003e\n                    \u003cadditionalContextClass\u003ecom.example.CustomContext\u003c/additionalContextClass\u003e\n                \u003c/additionalContextClasses\u003e\n            \u003c/configuration\u003e\n        \u003c/execution\u003e\n    \u003c/executions\u003e\n\u003c/plugin\u003e\n```\n\n### CLI Configuration with `-D` Properties\n\nAll plugin parameters can be configured via command-line properties using the `gravitee.archrules.*` prefix:\n\n```bash\n# Skip architecture checks entirely\nmvn verify -Dgravitee.archrules.skip=true\n\n# Continue build even if violations are found (warnings only)\nmvn verify -Dgravitee.archrules.failOnError=false\n\n# Global logging check with allow-lists\nmvn verify \\\n  -Dgravitee.archrules.allowList=com.example.LegacyService,com.example.ThirdPartyAdapter \\\n  -Dgravitee.archrules.allowListSuffixes=Test,TestHelper,ConfigurationEvaluator \\\n  -Dgravitee.archrules.packagesToExclude=com.example.legacy..,com.example.generated..\n\n# Execution context logging check with specific configuration\nmvn gioArchRules:execution-context-logging-check \\\n  -Dgravitee.archrules.allowList=com.example.SpecialHandler \\\n  -Dgravitee.archrules.packagesToExclude=com.example.tests.. \\\n  -Dgravitee.archrules.ignoreExecutionContextClasses=com.example.FakeExecutionContext,com.example.MockExecutionContext \\\n  -Dgravitee.archrules.additionalContextClasses=io.gravitee.node.api.kafka.KafkaConnectionContext\n\n# Run only specific goal\nmvn gioArchRules:global-logging-check\nmvn gioArchRules:execution-context-logging-check\n\n# Combine multiple parameters\nmvn verify \\\n  -Dgravitee.archrules.allowList=com.example.LegacyClass \\\n  -Dgravitee.archrules.allowListSuffixes=Test \\\n  -Dgravitee.archrules.failOnError=false\n```\n\n**Note:** When configuring lists via CLI, use comma-separated values (e.g., `class1,class2,class3`). Maven will automatically parse them into the appropriate list format.\n\n## Configuration Parameters\n\n### Common Parameters (All Goals)\n\n| Parameter | Type | Default | CLI Property | Description |\n|-----------|------|---------|--------------|-------------|\n| `skip` | `boolean` | `false` | `gravitee.archrules.skip` | Skip all architecture rule checks |\n| `failOnError` | `boolean` | `true` | `gravitee.archrules.failOnError` | Fail the build when violations are found (if false, only warnings are logged) |\n| `allowList` | `List\u003cString\u003e` | `[]` | `gravitee.archrules.allowList` | Fully qualified class names exempt from rule checks (comma-separated in CLI) |\n| `allowListSuffixes` | `List\u003cString\u003e` | `[]` | `gravitee.archrules.allowListSuffixes` | Class name suffixes exempt from rule checks (e.g., \"Test\", \"ConfigurationEvaluator\"; comma-separated in CLI) |\n| `packagesToExclude` | `List\u003cString\u003e` | `[]` | `gravitee.archrules.packagesToExclude` | Package patterns to exclude from scanning (supports ArchUnit syntax like \"com.example..\"; comma-separated in CLI) |\n\n### Execution Context Logging Check Only\n\n| Parameter | Type | Default | CLI Property | Description |\n|-----------|------|---------|--------------|-------------|\n| `ignoreExecutionContextClasses` | `List\u003cString\u003e` | `[]` | `gravitee.archrules.ignoreExecutionContextClasses` | Fully qualified class names of ExecutionContext implementations to ignore (e.g., test doubles; comma-separated in CLI) |\n| `additionalContextClasses` | `List\u003cString\u003e` | `[]` | `gravitee.archrules.additionalContextClasses` | Fully qualified class names of additional context types to scan (e.g., `io.gravitee.node.api.kafka.KafkaConnectionContext`; comma-separated in CLI) |\n\n## Execution Phase\n\nBoth goals run by default during the **`verify`** phase of the Maven lifecycle. This ensures architectural compliance is checked before integration tests and deployment.\n\n## Tips and Best Practices\n\n- **Start small:** Begin by running the checks on new modules or packages, then gradually expand coverage\n- **Use allow-lists wisely:** Allow-lists are useful for legacy code, but avoid overusing them—they can hide technical debt\n- **Leverage suffixes:** Use `allowListSuffixes` for patterns like test classes, generated code, or configuration evaluators\n- **Package exclusions:** Use ArchUnit's `..` notation (e.g., `com.example.legacy..`) to exclude entire package trees\n- **CI/CD integration:** These checks run automatically during `mvn verify` or `mvn install`, ensuring violations are caught before merge\n- **Incremental adoption:** If you have a large legacy codebase, consider creating separate executions with different configurations for new vs. legacy code\n\n## Troubleshooting\n\n**Q: The plugin fails but I don't see any violation details**\nA: Check the Maven output carefully—ArchUnit prints detailed violation reports including file locations and line numbers.\n\n**Q: Can I run the checks on test code?**\nA: By default, the plugin scans `target/classes` (main code). To scan test classes, you would need to configure `outputDirectory` to point to `target/test-classes`.\n\n**Q: How do I temporarily disable the checks?**\nA: Use `-Dgravitee.archrules.skip=true` or add `\u003cskip\u003etrue\u003c/skip\u003e` to the plugin configuration.\n\n**Q: What's the difference between `allowList` and `ignoreExecutionContextClasses`?**\nA: `allowList` exempts classes from **all** rule checks in that goal, while `ignoreExecutionContextClasses` specifically excludes certain types from being considered as \"ExecutionContext\" (useful for test doubles).\n\n## Requirements\n\n- **Java:** 21+\n- **Maven:** 3.9.6+\n- **ArchUnit:** 1.2.1\n\n## License\n\nCopyright © 2015 The Gravitee team (http://gravitee.io)\n\nLicensed under the Apache License, Version 2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgravitee-io%2Fgravitee-archrules-maven-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgravitee-io%2Fgravitee-archrules-maven-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgravitee-io%2Fgravitee-archrules-maven-plugin/lists"}