Linter for DSF (Data Sharing Framework) process plugins. Validates BPMN processes, FHIR resources, and plugin configurations from JAR files.
For more information, see the DSF Linter Tool documentation.
Download the latest linter-cli-<version>.jar from the Releases page and run it directly — no build step required.
# Run on local JAR file
java -jar linter-cli-0.1.3.jar --path your-plugin.jar --html
# Run on remote JAR file
java -jar linter-cli-0.1.3.jar \
--path https://github.com/datasharingframework/dsf-process-ping-pong/releases/download/v2.0.0.1/dsf-process-ping-pong-2.0.0.1.jar --html
# View report at: /tmp/dsf-linter-report-<name>/dsf-linter-report/index.htmlOnly necessary if you want to modify or develop the linter itself.
# Clone and build inside the dsf-linter project root
git clone https://github.com/datasharingframework/dsf-linter.git
cd dsf-linter
mvn clean package
# Then run the freshly built JAR
java -jar linter-cli/target/linter-cli-0.1.3.jar --path your-plugin.jar --htmlmvn clean package # Full build with tests
mvn clean package -DskipTests # Skip tests (faster)
mvn clean package -X # Verbose outputThe linter accepts only JAR files as input:
| Input Type | Example | Description |
|---|---|---|
| Local JAR | --path C:\path\to\plugin.jar |
JAR file in local filesystem |
| Remote JAR | --path https://example.com/plugin.jar |
JAR file via HTTP/HTTPS URL |
Note: Maven projects must first be built with mvn clean package before the resulting JAR file can be linted.
Expected structure in the JAR file:
META-INF/services/- Plugin registrationbpe/- BPMN process definitionsfhir/- FHIR resources
# Local JAR file
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path C:\path\to\plugin.jar --html
# Remote JAR file
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path https://github.com/datasharingframework/dsf-process-ping-pong/releases/download/v2.0.0.1/dsf-process-ping-pong-2.0.0.1.jar --html# Multiple reports with custom path
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path plugin.jar --html --json --report-path ./reports
# Verbose output (colors enabled by default, use --no-color to disable)
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path plugin.jar --html --verbose
# Lint Maven project
# Step 1: Build project
cd /path/to/project && mvn clean package
# Step 2: Lint resulting JAR
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path /path/to/project/target/my-plugin-1.0.0.jar --html# GitHub Actions / GitLab CI
FORCE_COLOR=1 java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path plugin.jar --html --json --verbose
# Jenkins (fail on errors)
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path plugin.jar --html
# Exit code: 0 = success, 1 = errors
# Don't fail build (gradual adoption)
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path plugin.jar --html --no-fail| Option | Description |
|---|---|
--path <input> |
Path to JAR file (local or URL) |
--html |
Generate HTML report |
--json |
Generate JSON report |
--report-path <dir> |
Custom report directory |
--exclusions <file> |
Path to a JSON exclusion config (see Excluding Issues) |
--verbose |
Verbose logging |
--no-color |
Disable colored output (default: enabled) |
--no-fail |
Exit 0 even on errors |
| Variable | Effect |
|---|---|
NO_COLOR |
Disables colored output |
FORCE_COLOR |
Forces colored output (CI) |
TERM=dumb |
Disables colored output |
WT_SESSION, ANSICON |
Windows color detection |
Users often encounter known, intentional, or external findings that clutter reports and make triage harder. The exclusion system lets you suppress specific lint items from HTML and JSON reports without modifying the plugin source.
Create a file named dsf-linter-exclusions.json in the project root (auto-discovered) or point to it explicitly with --exclusions:
{
"affectsExitStatus": false,
"rules": [
{ "type": "BPMN_PROCESS_HISTORY_TIME_TO_LIVE_MISSING" },
{ "severity": "WARN", "file": "update-allow-list.bpmn" },
{ "messageContains": "optional field" }
]
}Each rule is an AND combination of its non-null fields. Multiple rules are OR-combined — an item is excluded when any rule matches.
| Field | Match type | Example |
|---|---|---|
type |
Exact (case-insensitive) match against the LintingType enum name |
"BPMN_PROCESS_HISTORY_TIME_TO_LIVE_MISSING" |
severity |
Exact (case-insensitive) match against the severity level | "WARN", "ERROR", "INFO" |
file |
Case-insensitive substring match against the file name | "update-allow-list" |
messageContains |
Case-insensitive substring match against the issue description | "optional field" |
Every rule must specify at least one field — a rule with no criteria is rejected on load.
affectsExitStatus |
Behaviour |
|---|---|
false (default) |
Excluded items are fully suppressed — they do not appear in reports and do not count towards the exit code |
true |
Excluded items are hidden from reports, but their error count still contributes to the exit code (non-zero exit on errors) |
# Explicit exclusion file
java -jar linter-cli-0.1.3.jar \
--path plugin.jar --html \
--exclusions /path/to/my-exclusions.json
# Exclude only from reports, but still fail on excluded errorsExclusion file with affectsExitStatus: true:
{
"affectsExitStatus": true,
"rules": [
{ "type": "BPMN_PROCESS_HISTORY_TIME_TO_LIVE_MISSING" }
]
}All available type names are defined in LintingType.java. A few common examples:
| Type | Description |
|---|---|
BPMN_PROCESS_HISTORY_TIME_TO_LIVE_MISSING |
historyTimeToLive not set on process |
BPMN_PROCESS_NOT_EXECUTABLE |
Process isExecutable not set to true |
STRUCTURE_DEFINITION_SNAPSHOT_PRESENT |
StructureDefinition should not contain a snapshot |
FHIR_TASK_STATUS_NOT_DRAFT |
Task status is not draft |
PLUGIN_DEFINITION_MISSING_SERVICE_LOADER_REGISTRATION |
Plugin missing ServiceLoader registration |
See linter-core/src/main/java/dev/dsf/linter/output/LintingType.java for the full list.
dsf-linter/
├── pom.xml # Parent Maven POM
├── dsf-linter-exclusions.json # Example exclusion config (optional)
├── .github/ # CI workflows & issue templates
├── linter-core/ # Core linting logic
│ ├── src/main/java/dev/dsf/linter/
│ │ ├── DsfLinter.java # Main orchestrator
│ │ ├── analysis/ # Leftover resource detection
│ │ ├── bpmn/ # BPMN model & element linters
│ │ ├── classloading/ # Dynamic class loading
│ │ ├── constants/ # Constants & configuration
│ │ ├── exception/ # Custom exceptions
│ │ ├── exclusion/ # Exclusion rules & filtering
│ │ ├── fhir/ # FHIR resource linters
│ │ ├── input/ # Input handling & JAR processing
│ │ ├── logger/ # Logging infrastructure
│ │ ├── output/ # Lint item definitions
│ │ │ └── item/ # Specific lint items
│ │ ├── plugin/ # Plugin definition discovery
│ │ ├── report/ # HTML, JSON & console reporting
│ │ ├── service/ # Linting services & orchestration
│ │ ├── setup/ # Project setup & building
│ │ └── util/ # Shared utilities
│ │ ├── api/ # API version detection
│ │ ├── bpmn/ # BPMN helpers
│ │ │ └── linters/ # Event, message & timer linters
│ │ ├── cache/ # Caching utilities
│ │ ├── converter/ # Format converters (JSON/XML)
│ │ ├── linting/ # Linting helpers
│ │ ├── loader/ # Class/service loading
│ │ └── resource/ # Resource discovery & resolution
│ ├── src/main/resources/
│ │ ├── templates/ # HTML report templates
│ │ └── logback*.xml # Logging configuration
│ └── src/test/
│ ├── java/ # Unit & integration tests
│ │ ├── bpmn/
│ │ ├── exclusion/
│ │ ├── fhir/
│ │ ├── service/
│ │ └── util/
│ └── resources/ # Test fixtures
│ ├── bpmn/
│ ├── dsf-multi-plugin-test/
│ └── fhir/examples/ # Sample FHIR resources
│ ├── pingPongProcess/
│ ├── dashBoardReport/
│ └── feasibility/
└── linter-cli/ # CLI interface
└── src/main/java/dev/dsf/linter/
├── Main.java # Entry point & argument parsing
├── LinterExecutor.java # Runs the linting pipeline
└── ResultPrinter.java # Console output formatting
Requirements:
- Java 25+
- Maven 3.6+
IDE Setup:
- Import as Maven project
- Set JDK to 25+
mvn test # All tests
mvn test -Dtest=BpmnLoadingTest # Specific test
mvn test -Dtest=ExclusionFilterTest # Exclusion filter tests
mvn test -X # Verbose
mvn clean package -DskipTests # Build without tests# 1. Make changes
vim linter-core/src/main/java/dev/dsf/linter/service/BpmnLintingService.java
# 2. Build
mvn clean package -DskipTests
# 3. Test
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path test-plugin.jar --html --verbose
# 4. Check report
open /tmp/dsf-linter-report-test-plugin/dsf-linter-report/index.html
# 5. Run tests
mvn test# Start with debugger
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 \
-jar linter-cli/target/linter-cli-0.1.3.jar \
--path plugin.jar --html --verbose
# Attach debugger to localhost:5005| Component | Purpose |
|---|---|
DsfLinter |
Main orchestrator |
ProjectSetupHandler |
Maven build execution |
ResourceDiscoveryService |
Plugin & resource discovery |
BpmnLintingService |
BPMN validation |
FhirLintingService |
FHIR validation |
PluginLintingService |
Plugin validation |
LintingReportGenerator |
Report generation |
ExclusionFilter |
Suppresses lint items matched by exclusion rules |
ExclusionConfigLoader |
Loads dsf-linter-exclusions.json |
/tmp/dsf-linter-report-<name>/dsf-linter-report/
├── index.html # Summary
├── plugin-name.html # Plugin details
└── plugin-name.json # JSON (if --json)
DSF Linter v1.0.0
=================================================================
Project: /path/to/plugin.jar
Report: /tmp/dsf-linter-report-plugin/dsf-linter-report
=================================================================
Phase 1: Project Setup
✓ JAR file validated
✓ Resources extracted
Phase 2: Resource Discovery
✓ Found 1 plugin(s)
✓ Plugin: my-process-plugin
- BPMN: 2 files
- FHIR: 15 resources
Phase 3: Linting
✓ BPMN validation: 0 errors, 1 warning
✓ FHIR validation: 0 errors, 0 warnings
✓ Plugin validation: 0 errors
Phase 4: Report Generation
✓ HTML report generated
Summary
=================================================================
✓ SUCCESS - No errors found
Plugins: 1
Errors: 0
Warnings: 1
Execution time: 2.3s
=================================================================
The linter accepts only JAR files as input:
# Wrong - Maven project directly
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path /path/to/project --html
# Correct - Build first, then lint JAR
cd /path/to/project && mvn clean package
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path /path/to/project/target/my-plugin-1.0.0.jar --htmlVerify the path:
# Windows
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path "C:\Users\Username\project\target\plugin.jar" --html
# Linux/Mac
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path /home/username/project/target/plugin.jar --html# Check Maven settings
ls ~/.m2/settings.xml
# Use verbose mode
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path plugin.jar --html --verbose# --html flag must be set
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path plugin.jar --html # ← Required
# Use absolute path
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path plugin.jar --html --report-path $(pwd)/reportsCheck the URL and network connection:
# Test download separately
curl -L -o test.jar https://example.com/plugin.jar
# Then use the local file
java -jar linter-cli/target/linter-cli-0.1.3.jar \
--path test.jar --htmlFor questions or support, you can reach the developer via Zulip:
If you encounter a bug, please create an issue on GitHub: