diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ada5dd74f089..a6197b347603 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -94,6 +94,9 @@ jobs:
- name: Spotless
run: ./mvnw spotless:check
+# - name: Rewrite
+# run: ./mvnw rewrite:dryRun
+
- name: Build Keycloak
uses: ./.github/actions/build-keycloak
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c0cac41469a3..542db1405e8e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -124,6 +124,20 @@ You can either use your IDE to fix these issues; or Spotless can fix them for yo
./mvnw spotless:apply
```
+### Rewrite
+
+Rewrite is used to check and apply sanity check. To check your code locally before sending a PR run:
+
+```
+./mvnw rewrite:dryRun
+```
+
+You can either use your IDE to fix these issues; or Rewrite can fix them for you by running:
+
+```
+./mvnw rewrite:run
+```
+
A good practice is to create a commit with your changes prior to running `spotless:apply` then you can see and
review what changes Spotless has applied, for example by using a diff tool. Finally, if you are happy with the changes
Spotless has applied you can amend the changes to your commit by running:
diff --git a/pom.xml b/pom.xml
index d3cabd03cb9f..0f69091a4712 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1557,9 +1557,40 @@
+
+ org.openrewrite.maven
+ rewrite-maven-plugin
+ 6.23.0
+
+ true
+ true
+
+
+
+ org.openrewrite.recipe
+ rewrite-migrate-java
+ 3.21.1
+
+
+ org.openrewrite.recipe
+ rewrite-static-analysis
+ 2.21.0
+
+
+ org.openrewrite.recipe
+ rewrite-rewrite
+ 0.15.0
+
+
+
-
+
+
+ org.openrewrite.maven
+ rewrite-maven-plugin
+
+
diff --git a/rewrite.yml b/rewrite.yml
new file mode 100644
index 000000000000..a87fad4cf658
--- /dev/null
+++ b/rewrite.yml
@@ -0,0 +1,66 @@
+---
+type: specs.openrewrite.org/v1beta/recipe
+name: org.keycloak.openrewrite.SanityCheck
+displayName: Apply all Java & Maven best practices
+description: Comprehensive code quality recipe combining modernization, security, and best practices.
+tags:
+ - java
+ - maven
+ - static-analysis
+ - cleanup
+recipeList:
+ - org.openrewrite.staticanalysis.RemoveUnusedPrivateMethods
+ # - org.openrewrite.java.RemoveUnusedImports
+ # - org.openrewrite.maven.BestPractices
+ # - org.openrewrite.java.format.NormalizeLineBreaks
+ # - org.openrewrite.java.format.RemoveTrailingWhitespace
+ # TBD
+ # - org.openrewrite.java.format.NormalizeFormat
+ # - org.openrewrite.java.migrate.UpgradeToJava17
+ # - org.openrewrite.java.migrate.lang.StringRulesRecipes
+ # - org.openrewrite.java.migrate.util.JavaLangAPIs
+ # - org.openrewrite.java.migrate.util.JavaUtilAPIs
+ # - org.openrewrite.java.migrate.util.MigrateInflaterDeflaterToClose
+ # - org.openrewrite.java.migrate.util.ReplaceStreamCollectWithToList
+ # - org.openrewrite.java.migrate.util.SequencedCollection
+ # - org.openrewrite.java.recipes.JavaRecipeBestPractices
+ # - org.openrewrite.java.recipes.RecipeTestingBestPractices
+ # - org.openrewrite.java.security.JavaSecurityBestPractices
+ # - org.openrewrite.staticanalysis.BufferedWriterCreationRecipes
+ # - org.openrewrite.staticanalysis.CommonStaticAnalysis
+ # - org.openrewrite.staticanalysis.EqualsAvoidsNull
+ # - org.openrewrite.staticanalysis.JavaApiBestPractices
+ # - org.openrewrite.staticanalysis.LowercasePackage
+ # - org.openrewrite.staticanalysis.MissingOverrideAnnotation
+ # - org.openrewrite.staticanalysis.ModifierOrder
+ # - org.openrewrite.staticanalysis.NoFinalizer
+ # - org.openrewrite.staticanalysis.NoToStringOnStringType
+ # - org.openrewrite.staticanalysis.NoValueOfOnStringType
+ # - org.openrewrite.staticanalysis.RemoveUnusedLocalVariables
+ # - org.openrewrite.staticanalysis.RemoveUnusedPrivateFields
+ # - org.openrewrite.staticanalysis.ReplaceApacheCommonsLang3ValidateNotNullWithObjectsRequireNonNull
+ # - org.openrewrite.staticanalysis.SimplifyTernaryRecipes
+ # - org.openrewrite.staticanalysis.URLEqualsHashCodeRecipes
+ # - org.openrewrite.staticanalysis.UnnecessaryCloseInTryWithResources
+ # - org.openrewrite.staticanalysis.UnnecessaryExplicitTypeArguments
+ # - org.openrewrite.staticanalysis.UnnecessaryParentheses
+ # - org.openrewrite.staticanalysis.UnnecessaryReturnAsLastStatement
+ # - tech.picnic.errorprone.refasterrules.BigDecimalRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.CharSequenceRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.ClassRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.CollectionRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.ComparatorRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.EqualityRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.FileRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.MapRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.MicrometerRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.MockitoRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.NullRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.OptionalRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.PatternRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.PreconditionsRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.PrimitiveRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.StreamRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.StringRulesRecipes
+ # - tech.picnic.errorprone.refasterrules.TimeRulesRecipes
+---