├── .detekt └── config.yml ├── .github ├── CODEOWNERS ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── question.md ├── dependabot.yml ├── issue_template.md ├── pull_request_template.md └── workflows │ ├── build.yml │ ├── deploy.yml │ └── release.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── SECURITY.md ├── examples ├── simple-java │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── example │ │ ├── Application.java │ │ ├── PersonDestination.java │ │ ├── PersonMapping.java │ │ └── PersonSource.java └── simple-kotlin │ ├── pom.xml │ └── src │ └── main │ └── kotlin │ └── example │ ├── Application.kt │ ├── PersonDestination.kt │ ├── PersonMapping.kt │ └── PersonSource.kt ├── pom.xml └── src ├── main ├── kotlin │ └── dev │ │ └── akkinoc │ │ └── spring │ │ └── boot │ │ └── orika │ │ ├── OrikaAutoConfiguration.kt │ │ ├── OrikaMapperFactoryBuilderConfigurer.kt │ │ ├── OrikaMapperFactoryConfigurer.kt │ │ ├── OrikaProperties.kt │ │ ├── module.md │ │ └── package.md └── resources │ └── META-INF │ ├── spring-configuration-metadata.json │ └── spring │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports └── test ├── kotlin └── dev │ └── akkinoc │ └── spring │ └── boot │ └── orika │ ├── BasicTest.kt │ ├── DisabledTest.kt │ ├── MapperFactoryBuilderConfigurationTest.kt │ ├── MapperFactoryConfigurationTest.kt │ ├── PropertiesConfigurationTest.kt │ ├── TestContextConfiguration.kt │ └── test │ └── mock │ ├── MockOrikaMapperFactoryBuilderConfigurer.kt │ └── MockOrikaMapperFactoryConfigurer.kt └── resources └── application.yml /.detekt/config.yml: -------------------------------------------------------------------------------- 1 | comments: 2 | UndocumentedPublicClass: 3 | active: true 4 | searchInInnerObject: false 5 | UndocumentedPublicFunction: 6 | active: true 7 | UndocumentedPublicProperty: 8 | active: true 9 | complexity: 10 | TooManyFunctions: 11 | ignoreDeprecated: true 12 | ignoreOverridden: true 13 | ignorePrivate: true 14 | formatting: 15 | ImportOrdering: 16 | active: true 17 | NoBlankLineBeforeRbrace: 18 | active: false 19 | ParameterListWrapping: 20 | active: false 21 | performance: 22 | SpreadOperator: 23 | active: false 24 | style: 25 | ClassOrdering: 26 | active: true 27 | ForbiddenComment: 28 | active: false 29 | FunctionOnlyReturningConstant: 30 | active: false 31 | NoTabs: 32 | active: true 33 | ReturnCount: 34 | excludeLabeled: true 35 | excludeGuardClauses: true 36 | SerialVersionUIDInSerializableClass: 37 | active: false 38 | UnusedPrivateMember: 39 | allowedNames: (readObject|readObjectNoData|readResolve|serialVersionUID|writeObject|writeReplace) 40 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @akkinoc 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: akkinoc 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug report 3 | about: Create a bug report. 4 | labels: type:bug 5 | --- 6 | 7 | ## Describe the bug 8 | 9 | 12 | 13 | ## To Reproduce 14 | 15 | 18 | 19 | ## Expected behavior 20 | 21 | 24 | 25 | ### Environment 26 | 27 | 30 | 31 | * **Version of this library used**: 32 | * **Version of Java used**: 33 | * **Version of Spring Boot used**: 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 💡 Feature request 3 | about: Suggest an idea or a feature. 4 | labels: type:enhancement 5 | --- 6 | 7 | ## Describe the problem you'd like to have solved 8 | 9 | 12 | 13 | ## Describe the solution you'd like 14 | 15 | 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: ❓ Question 3 | about: Ask a question about usage, support, internal behavior, etc. 4 | labels: type:question 5 | --- 6 | 7 | ## Question 8 | 9 | 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: cron 7 | cronjob: 0 12 * * * 8 | assignees: 9 | - akkinoc 10 | labels: 11 | - type:dependencies 12 | milestone: 3 13 | - package-ecosystem: maven 14 | directories: 15 | - / 16 | - /examples/simple-java 17 | - /examples/simple-kotlin 18 | schedule: 19 | interval: cron 20 | cronjob: 0 12 * * * 21 | assignees: 22 | - akkinoc 23 | labels: 24 | - type:dependencies 25 | milestone: 3 26 | groups: 27 | spring-boot: 28 | patterns: 29 | - org.springframework.boot:* 30 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | ## Describe the issue 2 | 3 | 6 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Describe the changes 2 | 3 | 6 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | push: 4 | pull_request: 5 | workflow_dispatch: 6 | jobs: 7 | build: 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | java: [17, 21] 12 | name: Build with Java ${{ matrix.java }} 13 | runs-on: ubuntu-24.04 14 | env: 15 | MAVEN_ARGS: -B --color always 16 | steps: 17 | - name: Checkout the Git repository 18 | uses: actions/checkout@v4.2.2 19 | - name: Setup Java 20 | uses: actions/setup-java@v4.7.1 21 | with: 22 | distribution: temurin 23 | java-version: ${{ matrix.java }} 24 | cache: maven 25 | - name: Export the project version 26 | run: echo PROJECT_VERSION=$(mvn -Dexpression=project.version -q help:evaluate) | tee -a $GITHUB_ENV 27 | - name: Build the project 28 | run: mvn clean install 29 | - name: Build the "examples/simple-java" project 30 | run: mvn -Dorika-spring-boot-starter.version=$PROJECT_VERSION clean install 31 | working-directory: examples/simple-java 32 | - name: Build the "examples/simple-kotlin" project 33 | run: mvn -Dorika-spring-boot-starter.version=$PROJECT_VERSION clean install 34 | working-directory: examples/simple-kotlin 35 | - name: Upload the coverage report to Codecov 36 | uses: codecov/codecov-action@v5.4.3 37 | with: 38 | token: ${{ secrets.CODECOV_TOKEN }} 39 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | on: 3 | push: 4 | tags: 5 | - v* 6 | schedule: 7 | - cron: 0 12 * * 5 8 | workflow_dispatch: 9 | jobs: 10 | deploy: 11 | name: Deploy 12 | runs-on: ubuntu-24.04 13 | env: 14 | MAVEN_ARGS: -B --color always 15 | steps: 16 | - name: Checkout the Git repository 17 | uses: actions/checkout@v4.2.2 18 | - name: Setup Java 19 | uses: actions/setup-java@v4.7.1 20 | with: 21 | distribution: temurin 22 | java-version: 21 23 | cache: maven 24 | server-id: central 25 | server-username: MAVEN_CENTRAL_USERNAME 26 | server-password: MAVEN_CENTRAL_PASSWORD 27 | - name: Import GPG key 28 | uses: crazy-max/ghaction-import-gpg@v6.3.0 29 | with: 30 | gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} 31 | passphrase: ${{ secrets.GPG_PASSPHRASE }} 32 | - name: Export the project version 33 | run: echo PROJECT_VERSION=$(mvn -Dexpression=project.version -q help:evaluate) | tee -a $GITHUB_ENV 34 | - name: Deploy the project 35 | run: mvn clean deploy 36 | if: ${{ startsWith(github.ref, 'refs/tags/') || endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }} 37 | env: 38 | MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} 39 | MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} 40 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | version: 6 | description: Version 7 | type: string 8 | required: true 9 | jobs: 10 | release: 11 | name: Release 12 | runs-on: ubuntu-24.04 13 | env: 14 | MAVEN_ARGS: -B --color always 15 | steps: 16 | - name: Checkout the Git repository 17 | uses: actions/checkout@v4.2.2 18 | with: 19 | ssh-key: ${{ secrets.GIT_PRIVATE_KEY }} 20 | - name: Setup Java 21 | uses: actions/setup-java@v4.7.1 22 | with: 23 | distribution: temurin 24 | java-version: 21 25 | cache: maven 26 | server-id: central 27 | server-username: MAVEN_CENTRAL_USERNAME 28 | server-password: MAVEN_CENTRAL_PASSWORD 29 | - name: Import GPG key 30 | uses: crazy-max/ghaction-import-gpg@v6.3.0 31 | with: 32 | gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} 33 | passphrase: ${{ secrets.GPG_PASSPHRASE }} 34 | git_user_signingkey: true 35 | git_commit_gpgsign: true 36 | git_tag_gpgsign: true 37 | - name: Release the project 38 | run: mvn -DreleaseVersion=${{ inputs.version }} release:clean release:prepare 39 | env: 40 | MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} 41 | MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/eclipse,intellij+all,intellij+iml,java,kotlin,linux,macos,maven,netbeans,vim,visualstudiocode,windows 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=eclipse,intellij+all,intellij+iml,java,kotlin,linux,macos,maven,netbeans,vim,visualstudiocode,windows 3 | 4 | ### Eclipse ### 5 | .metadata 6 | bin/ 7 | tmp/ 8 | *.tmp 9 | *.bak 10 | *.swp 11 | *~.nib 12 | local.properties 13 | .settings/ 14 | .loadpath 15 | .recommenders 16 | 17 | # External tool builders 18 | .externalToolBuilders/ 19 | 20 | # Locally stored "Eclipse launch configurations" 21 | *.launch 22 | 23 | # PyDev specific (Python IDE for Eclipse) 24 | *.pydevproject 25 | 26 | # CDT-specific (C/C++ Development Tooling) 27 | .cproject 28 | 29 | # CDT- autotools 30 | .autotools 31 | 32 | # Java annotation processor (APT) 33 | .factorypath 34 | 35 | # PDT-specific (PHP Development Tools) 36 | .buildpath 37 | 38 | # sbteclipse plugin 39 | .target 40 | 41 | # Tern plugin 42 | .tern-project 43 | 44 | # TeXlipse plugin 45 | .texlipse 46 | 47 | # STS (Spring Tool Suite) 48 | .springBeans 49 | 50 | # Code Recommenders 51 | .recommenders/ 52 | 53 | # Annotation Processing 54 | .apt_generated/ 55 | .apt_generated_test/ 56 | 57 | # Scala IDE specific (Scala & Java development for Eclipse) 58 | .cache-main 59 | .scala_dependencies 60 | .worksheet 61 | 62 | # Uncomment this line if you wish to ignore the project description file. 63 | # Typically, this file would be tracked if it contains build/dependency configurations: 64 | #.project 65 | 66 | ### Eclipse Patch ### 67 | # Spring Boot Tooling 68 | .sts4-cache/ 69 | 70 | ### Intellij+all ### 71 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 72 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 73 | 74 | # User-specific stuff 75 | .idea/**/workspace.xml 76 | .idea/**/tasks.xml 77 | .idea/**/usage.statistics.xml 78 | .idea/**/dictionaries 79 | .idea/**/shelf 80 | 81 | # AWS User-specific 82 | .idea/**/aws.xml 83 | 84 | # Generated files 85 | .idea/**/contentModel.xml 86 | 87 | # Sensitive or high-churn files 88 | .idea/**/dataSources/ 89 | .idea/**/dataSources.ids 90 | .idea/**/dataSources.local.xml 91 | .idea/**/sqlDataSources.xml 92 | .idea/**/dynamic.xml 93 | .idea/**/uiDesigner.xml 94 | .idea/**/dbnavigator.xml 95 | 96 | # Gradle 97 | .idea/**/gradle.xml 98 | .idea/**/libraries 99 | 100 | # Gradle and Maven with auto-import 101 | # When using Gradle or Maven with auto-import, you should exclude module files, 102 | # since they will be recreated, and may cause churn. Uncomment if using 103 | # auto-import. 104 | # .idea/artifacts 105 | # .idea/compiler.xml 106 | # .idea/jarRepositories.xml 107 | # .idea/modules.xml 108 | # .idea/*.iml 109 | # .idea/modules 110 | # *.iml 111 | # *.ipr 112 | 113 | # CMake 114 | cmake-build-*/ 115 | 116 | # Mongo Explorer plugin 117 | .idea/**/mongoSettings.xml 118 | 119 | # File-based project format 120 | *.iws 121 | 122 | # IntelliJ 123 | out/ 124 | 125 | # mpeltonen/sbt-idea plugin 126 | .idea_modules/ 127 | 128 | # JIRA plugin 129 | atlassian-ide-plugin.xml 130 | 131 | # Cursive Clojure plugin 132 | .idea/replstate.xml 133 | 134 | # SonarLint plugin 135 | .idea/sonarlint/ 136 | 137 | # Crashlytics plugin (for Android Studio and IntelliJ) 138 | com_crashlytics_export_strings.xml 139 | crashlytics.properties 140 | crashlytics-build.properties 141 | fabric.properties 142 | 143 | # Editor-based Rest Client 144 | .idea/httpRequests 145 | 146 | # Android studio 3.1+ serialized cache file 147 | .idea/caches/build_file_checksums.ser 148 | 149 | ### Intellij+all Patch ### 150 | # Ignore everything but code style settings and run configurations 151 | # that are supposed to be shared within teams. 152 | 153 | .idea/* 154 | 155 | !.idea/codeStyles 156 | !.idea/runConfigurations 157 | 158 | ### Intellij+iml ### 159 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 160 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 161 | 162 | # User-specific stuff 163 | 164 | # AWS User-specific 165 | 166 | # Generated files 167 | 168 | # Sensitive or high-churn files 169 | 170 | # Gradle 171 | 172 | # Gradle and Maven with auto-import 173 | # When using Gradle or Maven with auto-import, you should exclude module files, 174 | # since they will be recreated, and may cause churn. Uncomment if using 175 | # auto-import. 176 | # .idea/artifacts 177 | # .idea/compiler.xml 178 | # .idea/jarRepositories.xml 179 | # .idea/modules.xml 180 | # .idea/*.iml 181 | # .idea/modules 182 | # *.iml 183 | # *.ipr 184 | 185 | # CMake 186 | 187 | # Mongo Explorer plugin 188 | 189 | # File-based project format 190 | 191 | # IntelliJ 192 | 193 | # mpeltonen/sbt-idea plugin 194 | 195 | # JIRA plugin 196 | 197 | # Cursive Clojure plugin 198 | 199 | # SonarLint plugin 200 | 201 | # Crashlytics plugin (for Android Studio and IntelliJ) 202 | 203 | # Editor-based Rest Client 204 | 205 | # Android studio 3.1+ serialized cache file 206 | 207 | ### Intellij+iml Patch ### 208 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 209 | 210 | *.iml 211 | modules.xml 212 | .idea/misc.xml 213 | *.ipr 214 | 215 | ### Java ### 216 | # Compiled class file 217 | *.class 218 | 219 | # Log file 220 | *.log 221 | 222 | # BlueJ files 223 | *.ctxt 224 | 225 | # Mobile Tools for Java (J2ME) 226 | .mtj.tmp/ 227 | 228 | # Package Files # 229 | *.jar 230 | *.war 231 | *.nar 232 | *.ear 233 | *.zip 234 | *.tar.gz 235 | *.rar 236 | 237 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 238 | hs_err_pid* 239 | replay_pid* 240 | 241 | ### Kotlin ### 242 | # Compiled class file 243 | 244 | # Log file 245 | 246 | # BlueJ files 247 | 248 | # Mobile Tools for Java (J2ME) 249 | 250 | # Package Files # 251 | 252 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 253 | 254 | ### Linux ### 255 | *~ 256 | 257 | # temporary files which can be created if a process still has a handle open of a deleted file 258 | .fuse_hidden* 259 | 260 | # KDE directory preferences 261 | .directory 262 | 263 | # Linux trash folder which might appear on any partition or disk 264 | .Trash-* 265 | 266 | # .nfs files are created when an open file is removed but is still being accessed 267 | .nfs* 268 | 269 | ### macOS ### 270 | # General 271 | .DS_Store 272 | .AppleDouble 273 | .LSOverride 274 | 275 | # Icon must end with two \r 276 | Icon 277 | 278 | # Thumbnails 279 | ._* 280 | 281 | # Files that might appear in the root of a volume 282 | .DocumentRevisions-V100 283 | .fseventsd 284 | .Spotlight-V100 285 | .TemporaryItems 286 | .Trashes 287 | .VolumeIcon.icns 288 | .com.apple.timemachine.donotpresent 289 | 290 | # Directories potentially created on remote AFP share 291 | .AppleDB 292 | .AppleDesktop 293 | Network Trash Folder 294 | Temporary Items 295 | .apdisk 296 | 297 | ### macOS Patch ### 298 | # iCloud generated files 299 | *.icloud 300 | 301 | ### Maven ### 302 | target/ 303 | pom.xml.tag 304 | pom.xml.releaseBackup 305 | pom.xml.versionsBackup 306 | pom.xml.next 307 | release.properties 308 | dependency-reduced-pom.xml 309 | buildNumber.properties 310 | .mvn/timing.properties 311 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 312 | .mvn/wrapper/maven-wrapper.jar 313 | 314 | # Eclipse m2e generated files 315 | # Eclipse Core 316 | .project 317 | # JDT-specific (Eclipse Java Development Tools) 318 | .classpath 319 | 320 | ### NetBeans ### 321 | **/nbproject/private/ 322 | **/nbproject/Makefile-*.mk 323 | **/nbproject/Package-*.bash 324 | build/ 325 | nbbuild/ 326 | dist/ 327 | nbdist/ 328 | .nb-gradle/ 329 | 330 | ### Vim ### 331 | # Swap 332 | [._]*.s[a-v][a-z] 333 | !*.svg # comment out if you don't need vector files 334 | [._]*.sw[a-p] 335 | [._]s[a-rt-v][a-z] 336 | [._]ss[a-gi-z] 337 | [._]sw[a-p] 338 | 339 | # Session 340 | Session.vim 341 | Sessionx.vim 342 | 343 | # Temporary 344 | .netrwhist 345 | # Auto-generated tag files 346 | tags 347 | # Persistent undo 348 | [._]*.un~ 349 | 350 | ### VisualStudioCode ### 351 | .vscode/* 352 | !.vscode/settings.json 353 | !.vscode/tasks.json 354 | !.vscode/launch.json 355 | !.vscode/extensions.json 356 | !.vscode/*.code-snippets 357 | 358 | # Local History for Visual Studio Code 359 | .history/ 360 | 361 | # Built Visual Studio Code Extensions 362 | *.vsix 363 | 364 | ### VisualStudioCode Patch ### 365 | # Ignore all local history of files 366 | .history 367 | .ionide 368 | 369 | ### Windows ### 370 | # Windows thumbnail cache files 371 | Thumbs.db 372 | Thumbs.db:encryptable 373 | ehthumbs.db 374 | ehthumbs_vista.db 375 | 376 | # Dump file 377 | *.stackdump 378 | 379 | # Folder config file 380 | [Dd]esktop.ini 381 | 382 | # Recycle Bin used on file shares 383 | $RECYCLE.BIN/ 384 | 385 | # Windows Installer files 386 | *.cab 387 | *.msi 388 | *.msix 389 | *.msm 390 | *.msp 391 | 392 | # Windows shortcuts 393 | *.lnk 394 | 395 | # End of https://www.toptal.com/developers/gitignore/api/eclipse,intellij+all,intellij+iml,java,kotlin,linux,macos,maven,netbeans,vim,visualstudiocode,windows 396 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, caste, color, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | . 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.1, available at 119 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 120 | 121 | Community Impact Guidelines were inspired by 122 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 123 | 124 | For answers to common questions about this code of conduct, see the FAQ at 125 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available 126 | at [https://www.contributor-covenant.org/translations][translations]. 127 | 128 | [homepage]: https://www.contributor-covenant.org 129 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 130 | [Mozilla CoC]: https://github.com/mozilla/diversity 131 | [FAQ]: https://www.contributor-covenant.org/faq 132 | [translations]: https://www.contributor-covenant.org/translations 133 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | [![issues badge]][issues] 4 | [![pulls badge]][pulls] 5 | [![license badge]][license] 6 | 7 | [issues]: https://github.com/akkinoc/orika-spring-boot-starter/issues 8 | [issues badge]: https://img.shields.io/github/issues/akkinoc/orika-spring-boot-starter 9 | [pulls]: https://github.com/akkinoc/orika-spring-boot-starter/pulls 10 | [pulls badge]: https://img.shields.io/github/issues-pr/akkinoc/orika-spring-boot-starter 11 | [license]: LICENSE.txt 12 | [license badge]: https://img.shields.io/github/license/akkinoc/orika-spring-boot-starter?color=blue 13 | 14 | [Bug reports][issues] and [pull requests][pulls] are welcome :) 15 | 16 | ## Setup 17 | 18 | To set up, run: 19 | 20 | ```console 21 | $ git clone https://github.com/akkinoc/orika-spring-boot-starter.git 22 | $ cd orika-spring-boot-starter 23 | ``` 24 | 25 | ## Building and Testing 26 | 27 | To build and test, run: 28 | 29 | ```console 30 | $ mvn clean install 31 | ``` 32 | 33 | ## License 34 | 35 | By contributing, you agree that your contributions will be licensed under the [Apache License, Version 2.0][license]. 36 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # orika-spring-boot-starter 2 | 3 | [![maven central badge]][maven central] 4 | [![javadoc badge]][javadoc] 5 | [![release badge]][release] 6 | [![build badge]][build] 7 | [![codecov badge]][codecov] 8 | [![license badge]][license] 9 | [![sponsor badge]][sponsor] 10 | 11 | [maven central]: https://maven-badges.herokuapp.com/maven-central/dev.akkinoc.spring.boot/orika-spring-boot-starter 12 | [maven central badge]: https://maven-badges.herokuapp.com/maven-central/dev.akkinoc.spring.boot/orika-spring-boot-starter/badge.svg 13 | [javadoc]: https://javadoc.io/doc/dev.akkinoc.spring.boot/orika-spring-boot-starter 14 | [javadoc badge]: https://javadoc.io/badge2/dev.akkinoc.spring.boot/orika-spring-boot-starter/javadoc.svg 15 | [release]: https://github.com/akkinoc/orika-spring-boot-starter/releases 16 | [release badge]: https://img.shields.io/github/v/release/akkinoc/orika-spring-boot-starter?color=brightgreen&sort=semver 17 | [build]: https://github.com/akkinoc/orika-spring-boot-starter/actions/workflows/build.yml 18 | [build badge]: https://github.com/akkinoc/orika-spring-boot-starter/actions/workflows/build.yml/badge.svg 19 | [codecov]: https://codecov.io/gh/akkinoc/orika-spring-boot-starter 20 | [codecov badge]: https://codecov.io/gh/akkinoc/orika-spring-boot-starter/branch/main/graph/badge.svg 21 | [license]: LICENSE.txt 22 | [license badge]: https://img.shields.io/github/license/akkinoc/orika-spring-boot-starter?color=blue 23 | [sponsor]: https://github.com/sponsors/akkinoc 24 | [sponsor badge]: https://img.shields.io/static/v1?logo=github&label=sponsor&message=%E2%9D%A4&color=db61a2 25 | 26 | [Spring Boot] Starter for [Orika]. 27 | 28 | [Spring Boot]: https://spring.io/projects/spring-boot 29 | [Orika]: https://orika-mapper.github.io/orika-docs 30 | 31 | ⚠️ Please note that [Orika] has not been maintained for a long time ([orika-mapper/orika#372]). 32 | 33 | [orika-mapper/orika#372]: https://github.com/orika-mapper/orika/issues/372 34 | 35 | ## Features 36 | 37 | * Manages MapperFacade in the application context and makes it injectable into your code. 38 | * Provides an interface to configure MapperFactory. 39 | * Provides an interface to configure MapperFactoryBuilder. 40 | * Provides configuration properties to configure MapperFactoryBuilder. 41 | 42 | ## Dependencies 43 | 44 | Depends on: 45 | 46 | * Java 17 or 21 47 | * Kotlin 1.9 48 | * Spring Boot 3.5 49 | * Orika 1.5 50 | 51 | The following JVM option is required ([orika-mapper/orika#377]). 52 | 53 | [orika-mapper/orika#377]: https://github.com/orika-mapper/orika/issues/377 54 | 55 | ```console 56 | --add-opens java.base/java.lang=ALL-UNNAMED 57 | ``` 58 | 59 | ## Usage 60 | 61 | ### Adding the Dependency 62 | 63 | The artifact is published on [Maven Central Repository][maven central]. 64 | If you are using Maven, add the following dependency. 65 | 66 | ```xml 67 | 68 | dev.akkinoc.spring.boot 69 | orika-spring-boot-starter 70 | ${orika-spring-boot-starter.version} 71 | 72 | ``` 73 | 74 | ### Injecting the MapperFacade 75 | 76 | The MapperFacade is managed in the application context. 77 | Inject the MapperFacade into your code. 78 | 79 | For example in Java: 80 | 81 | ```java 82 | import ma.glasnost.orika.MapperFacade; 83 | ``` 84 | 85 | ```java 86 | @Autowired 87 | private MapperFacade orikaMapperFacade; 88 | ``` 89 | 90 | ### Mapping Your Beans 91 | 92 | Map your beans using the MapperFacade. 93 | 94 | For example in Java: 95 | 96 | ```java 97 | // Maps from PersonSource to PersonDestination 98 | PersonSource src = new PersonSource("John", "Smith", 23); 99 | System.out.println(src); // => "PersonSource(firstName=John, lastName=Smith, age=23)" 100 | PersonDestination dest = orikaMapperFacade.map(src, PersonDestination.class); 101 | System.out.println(dest); // => "PersonDestination(givenName=John, sirName=Smith, age=23)" 102 | ``` 103 | 104 | ## MapperFactory Configuration 105 | 106 | If you need to configure the MapperFactory, 107 | create an instance of OrikaMapperFactoryConfigurer in the application context. 108 | The OrikaMapperFactoryConfigurer components are auto-detected and the "configure" method is called. 109 | 110 | For example in Java: 111 | 112 | ```java 113 | import dev.akkinoc.spring.boot.orika.OrikaMapperFactoryConfigurer; 114 | import ma.glasnost.orika.MapperFactory; 115 | 116 | @Component 117 | public class PersonMapping implements OrikaMapperFactoryConfigurer { 118 | @Override 119 | public void configure(MapperFactory orikaMapperFactory) { 120 | orikaMapperFactory.classMap(PersonSource.class, PersonDestination.class) 121 | .field("firstName", "givenName") 122 | .field("lastName", "sirName") 123 | .byDefault() 124 | .register(); 125 | } 126 | } 127 | ``` 128 | 129 | See also the Orika User Guide: 130 | 131 | * [Declarative Mapping Configuration](https://orika-mapper.github.io/orika-docs/mappings-via-classmapbuilder.html) 132 | * [Advanced Mapping Configurations](https://orika-mapper.github.io/orika-docs/advanced-mappings.html) 133 | 134 | ## MapperFactoryBuilder Configuration 135 | 136 | If you need to configure the MapperFactoryBuilder, 137 | create an instance of OrikaMapperFactoryBuilderConfigurer in the application context. 138 | The OrikaMapperFactoryBuilderConfigurer components are auto-detected and the "configure" method is called. 139 | 140 | For example in Java: 141 | 142 | ```java 143 | import dev.akkinoc.spring.boot.orika.OrikaMapperFactoryBuilderConfigurer; 144 | import ma.glasnost.orika.impl.DefaultMapperFactory.MapperFactoryBuilder; 145 | 146 | @Component 147 | public class OrikaConfiguration implements OrikaMapperFactoryBuilderConfigurer { 148 | @Override 149 | public void configure(MapperFactoryBuilder orikaMapperFactoryBuilder) { 150 | // Your configuration codes. 151 | } 152 | } 153 | ``` 154 | 155 | See also the Orika User Guide: 156 | 157 | * [MapperFactory Configuration](https://orika-mapper.github.io/orika-docs/mapper-factory.html) 158 | 159 | ## Configuration Properties 160 | 161 | Provides the following configuration properties. 162 | These can be configured by your "application.yml", "application.properties", etc. 163 | 164 | ```yaml 165 | # The configuration properties for Orika. 166 | orika: 167 | # Whether to enable auto-configuration. 168 | # Defaults to true. 169 | enabled: true 170 | # Whether to use built-in converters. 171 | # See also MapperFactoryBuilder.useBuiltinConverters. 172 | # By default, follows Orika's behavior. 173 | use-builtin-converters: true 174 | # Whether to use auto-mapping. 175 | # See also MapperFactoryBuilder.useAutoMapping. 176 | # By default, follows Orika's behavior. 177 | use-auto-mapping: true 178 | # Whether to map nulls. 179 | # See also MapperFactoryBuilder.mapNulls. 180 | # By default, follows Orika's behavior. 181 | map-nulls: true 182 | # Whether to dump the current state of the mapping infrastructure objects 183 | # upon occurrence of an exception while mapping. 184 | # See also MapperFactoryBuilder.dumpStateOnException. 185 | # By default, follows Orika's behavior. 186 | dump-state-on-exception: false 187 | # Whether to favor extension by default in registered class-maps. 188 | # See also MapperFactoryBuilder.favorExtension. 189 | # By default, follows Orika's behavior. 190 | favor-extension: false 191 | # Whether full field context should be captured. 192 | # See also MapperFactoryBuilder.captureFieldContext. 193 | # By default, follows Orika's behavior. 194 | capture-field-context: false 195 | ``` 196 | 197 | ## API Reference 198 | 199 | Please refer to the [Javadoc][javadoc]. 200 | 201 | ## Release Notes 202 | 203 | Please refer to the [Releases][release] page. 204 | 205 | ## License 206 | 207 | Licensed under the [Apache License, Version 2.0][license]. 208 | 209 | ## Support the Project 210 | 211 | If this project is useful to you, I appreciate giving a ⭐ star to this repository. 212 | I would also appreciate if you would consider 💖 [sponsoring][sponsor] as well. 213 | Your support is my biggest motive force. Thanks ✨ 214 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Only the latest stable release is supported. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | To report a vulnerability, please email . 10 | -------------------------------------------------------------------------------- /examples/simple-java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | dev.akkinoc.spring.boot 7 | orika-spring-boot-starter.examples.simple-java 8 | 1.0.0-SNAPSHOT 9 | 10 | 11 | org.springframework.boot 12 | spring-boot-starter-parent 13 | 3.5.0 14 | 15 | 16 | 17 | [3.0.0,) 18 | 19 | 20 | 21 | 22 | org.projectlombok 23 | lombok 24 | provided 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter 29 | 30 | 31 | dev.akkinoc.spring.boot 32 | orika-spring-boot-starter 33 | ${orika-spring-boot-starter.version} 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /examples/simple-java/src/main/java/example/Application.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import ma.glasnost.orika.MapperFacade; 5 | import org.springframework.boot.ApplicationArguments; 6 | import org.springframework.boot.ApplicationRunner; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | 10 | @RequiredArgsConstructor 11 | @SpringBootApplication 12 | public class Application implements ApplicationRunner { 13 | 14 | private final MapperFacade orikaMapperFacade; 15 | 16 | @Override 17 | public void run(ApplicationArguments args) { 18 | 19 | // Maps from PersonSource to PersonDestination 20 | PersonSource src = new PersonSource("John", "Smith", 23); 21 | System.out.println(src); // => "PersonSource(firstName=John, lastName=Smith, age=23)" 22 | PersonDestination dest = orikaMapperFacade.map(src, PersonDestination.class); 23 | System.out.println(dest); // => "PersonDestination(givenName=John, sirName=Smith, age=23)" 24 | 25 | } 26 | 27 | public static void main(String... args) { 28 | SpringApplication.run(Application.class, args); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /examples/simple-java/src/main/java/example/PersonDestination.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class PersonDestination { 11 | private String givenName = ""; 12 | private String sirName = ""; 13 | private int age = 0; 14 | } 15 | -------------------------------------------------------------------------------- /examples/simple-java/src/main/java/example/PersonMapping.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | import dev.akkinoc.spring.boot.orika.OrikaMapperFactoryConfigurer; 4 | import ma.glasnost.orika.MapperFactory; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class PersonMapping implements OrikaMapperFactoryConfigurer { 9 | 10 | @Override 11 | public void configure(MapperFactory orikaMapperFactory) { 12 | orikaMapperFactory.classMap(PersonSource.class, PersonDestination.class) 13 | .field("firstName", "givenName") 14 | .field("lastName", "sirName") 15 | .byDefault() 16 | .register(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /examples/simple-java/src/main/java/example/PersonSource.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class PersonSource { 11 | private String firstName = ""; 12 | private String lastName = ""; 13 | private int age = 0; 14 | } 15 | -------------------------------------------------------------------------------- /examples/simple-kotlin/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | dev.akkinoc.spring.boot 7 | orika-spring-boot-starter.examples.simple-kotlin 8 | 1.0.0-SNAPSHOT 9 | 10 | 11 | org.springframework.boot 12 | spring-boot-starter-parent 13 | 3.5.0 14 | 15 | 16 | 17 | [3.0.0,) 18 | 19 | 20 | 21 | 22 | org.jetbrains.kotlin 23 | kotlin-stdlib-jdk8 24 | 25 | 26 | org.jetbrains.kotlin 27 | kotlin-reflect 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter 32 | 33 | 34 | dev.akkinoc.spring.boot 35 | orika-spring-boot-starter 36 | ${orika-spring-boot-starter.version} 37 | 38 | 39 | 40 | 41 | src/main/kotlin 42 | src/test/kotlin 43 | 44 | 45 | org.jetbrains.kotlin 46 | kotlin-maven-plugin 47 | 48 | 49 | org.jetbrains.kotlin 50 | kotlin-maven-allopen 51 | ${kotlin.version} 52 | 53 | 54 | 55 | 56 | spring 57 | 58 | 59 | 60 | 61 | maven-compiler-plugin 62 | 63 | 64 | default-compile 65 | none 66 | 67 | 68 | default-testCompile 69 | none 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /examples/simple-kotlin/src/main/kotlin/example/Application.kt: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | import ma.glasnost.orika.MapperFacade 4 | import org.springframework.boot.ApplicationArguments 5 | import org.springframework.boot.ApplicationRunner 6 | import org.springframework.boot.autoconfigure.SpringBootApplication 7 | import org.springframework.boot.runApplication 8 | 9 | @SpringBootApplication 10 | class Application(private val orikaMapperFacade: MapperFacade) : ApplicationRunner { 11 | 12 | override fun run(args: ApplicationArguments) { 13 | 14 | // Maps from PersonSource to PersonDestination 15 | val src = PersonSource("John", "Smith", 23) 16 | println(src) // => "PersonSource(firstName=John, lastName=Smith, age=23)" 17 | val dest = orikaMapperFacade.map(src, PersonDestination::class.java) 18 | println(dest) // => "PersonDestination(givenName=John, sirName=Smith, age=23)" 19 | 20 | } 21 | 22 | } 23 | 24 | fun main(vararg args: String) { 25 | runApplication(*args) 26 | } 27 | -------------------------------------------------------------------------------- /examples/simple-kotlin/src/main/kotlin/example/PersonDestination.kt: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | data class PersonDestination( 4 | var givenName: String = "", 5 | var sirName: String = "", 6 | var age: Int = 0, 7 | ) 8 | -------------------------------------------------------------------------------- /examples/simple-kotlin/src/main/kotlin/example/PersonMapping.kt: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | import dev.akkinoc.spring.boot.orika.OrikaMapperFactoryConfigurer 4 | import ma.glasnost.orika.MapperFactory 5 | import org.springframework.stereotype.Component 6 | 7 | @Component 8 | class PersonMapping : OrikaMapperFactoryConfigurer { 9 | 10 | override fun configure(orikaMapperFactory: MapperFactory) { 11 | orikaMapperFactory.classMap(PersonSource::class.java, PersonDestination::class.java) 12 | .field("firstName", "givenName") 13 | .field("lastName", "sirName") 14 | .byDefault() 15 | .register() 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /examples/simple-kotlin/src/main/kotlin/example/PersonSource.kt: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | data class PersonSource( 4 | var firstName: String = "", 5 | var lastName: String = "", 6 | var age: Int = 0, 7 | ) 8 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | dev.akkinoc.spring.boot 7 | orika-spring-boot-starter 8 | 3.6.1-SNAPSHOT 9 | 10 | orika-spring-boot-starter 11 | Spring Boot Starter for Orika. 12 | https://github.com/akkinoc/orika-spring-boot-starter 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 3.5.0 18 | 19 | 20 | 21 | akkinoc.dev 22 | https://akkinoc.dev 23 | 24 | 25 | 26 | 27 | akkinoc 28 | Akihiro Kondo 29 | akkinoc@gmail.com 30 | https://akkinoc.dev 31 | 32 | 33 | 34 | 35 | 36 | Apache License, Version 2.0 37 | https://www.apache.org/licenses/LICENSE-2.0.txt 38 | 39 | 40 | 41 | 42 | https://github.com/akkinoc/orika-spring-boot-starter 43 | scm:git:https://github.com/akkinoc/orika-spring-boot-starter.git 44 | scm:git:git@github.com:akkinoc/orika-spring-boot-starter.git 45 | HEAD 46 | 47 | 48 | 49 | GitHub Issues 50 | https://github.com/akkinoc/orika-spring-boot-starter/issues 51 | 52 | 53 | 54 | GitHub Actions 55 | https://github.com/akkinoc/orika-spring-boot-starter/actions 56 | 57 | 58 | 59 | 60 | org.jetbrains.kotlin 61 | kotlin-stdlib 62 | 63 | 64 | org.jetbrains.kotlin 65 | kotlin-reflect 66 | 67 | 68 | org.springframework.boot 69 | spring-boot-starter 70 | 71 | 72 | ma.glasnost.orika 73 | orika-core 74 | 1.5.4 75 | 76 | 77 | org.springframework.boot 78 | spring-boot-starter-test 79 | test 80 | 81 | 82 | io.kotest 83 | kotest-assertions-core-jvm 84 | 5.9.1 85 | test 86 | 87 | 88 | 89 | 90 | src/main/kotlin 91 | src/test/kotlin 92 | 93 | 94 | maven-help-plugin 95 | 96 | true 97 | 98 | 99 | 100 | maven-clean-plugin 101 | 102 | 103 | maven-enforcer-plugin 104 | 105 | 106 | 107 | [${java.version},) 108 | 109 | 110 | [3.9,) 111 | 112 | 113 | 114 | 115 | 116 | enforce 117 | 118 | enforce 119 | 120 | 121 | 122 | 123 | 124 | org.jacoco 125 | jacoco-maven-plugin 126 | 0.8.13 127 | 128 | 129 | prepare-agent 130 | 131 | prepare-agent 132 | 133 | 134 | 135 | report 136 | 137 | report 138 | 139 | 140 | 141 | 142 | 143 | maven-resources-plugin 144 | 145 | 146 | org.jetbrains.kotlin 147 | kotlin-maven-plugin 148 | 149 | 150 | org.jetbrains.kotlin 151 | kotlin-maven-allopen 152 | ${kotlin.version} 153 | 154 | 155 | 156 | 157 | spring 158 | 159 | 160 | 161 | 162 | maven-compiler-plugin 163 | 164 | 165 | default-compile 166 | none 167 | 168 | 169 | default-testCompile 170 | none 171 | 172 | 173 | 174 | 175 | maven-surefire-plugin 176 | 177 | --add-opens java.base/java.lang=ALL-UNNAMED 178 | 179 | 180 | 181 | maven-jar-plugin 182 | 183 | 184 | 185 | true 186 | true 187 | true 188 | 189 | 190 | 191 | 192 | 193 | maven-source-plugin 194 | 195 | 196 | jar 197 | 198 | jar 199 | 200 | 201 | 202 | 203 | 204 | org.jetbrains.dokka 205 | dokka-maven-plugin 206 | 2.0.0 207 | 208 | 209 | src/main/kotlin/dev/akkinoc/spring/boot/orika/module.md 210 | src/main/kotlin/dev/akkinoc/spring/boot/orika/package.md 211 | 212 | 213 | 214 | 215 | javadocJar 216 | package 217 | 218 | javadocJar 219 | 220 | 221 | 222 | 223 | 224 | com.github.ozsie 225 | detekt-maven-plugin 226 | 1.23.8 227 | 228 | 229 | io.gitlab.arturbosch.detekt 230 | detekt-cli 231 | 1.23.8 232 | 233 | 234 | io.gitlab.arturbosch.detekt 235 | detekt-formatting 236 | 1.23.8 237 | 238 | 239 | 240 | true 241 | .detekt/config.yml 242 | 243 | 244 | 245 | check 246 | 247 | check 248 | 249 | 250 | 251 | 252 | 253 | maven-install-plugin 254 | 255 | 256 | maven-gpg-plugin 257 | 3.2.7 258 | 259 | true 260 | 261 | 262 | 263 | sign 264 | deploy 265 | 266 | sign 267 | 268 | 269 | 270 | 271 | 272 | org.sonatype.central 273 | central-publishing-maven-plugin 274 | 0.7.0 275 | true 276 | 277 | true 278 | central 279 | 280 | 281 | 282 | maven-release-plugin 283 | 3.1.1 284 | 285 | v@{project.version} 286 | 287 | 288 | 289 | 290 | 291 | 292 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/akkinoc/spring/boot/orika/OrikaAutoConfiguration.kt: -------------------------------------------------------------------------------- 1 | package dev.akkinoc.spring.boot.orika 2 | 3 | import ma.glasnost.orika.MapperFacade 4 | import ma.glasnost.orika.MapperFactory 5 | import ma.glasnost.orika.impl.DefaultMapperFactory 6 | import ma.glasnost.orika.impl.DefaultMapperFactory.MapperFactoryBuilder 7 | import org.slf4j.Logger 8 | import org.slf4j.LoggerFactory.getLogger 9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean 10 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty 11 | import org.springframework.boot.context.properties.EnableConfigurationProperties 12 | import org.springframework.context.annotation.Bean 13 | import org.springframework.context.annotation.Configuration 14 | 15 | /** 16 | * The auto-configuration for Orika. 17 | */ 18 | @Configuration(proxyBeanMethods = false) 19 | @ConditionalOnProperty(prefix = "orika", name = ["enabled"], havingValue = "true", matchIfMissing = true) 20 | @EnableConfigurationProperties(OrikaProperties::class) 21 | class OrikaAutoConfiguration { 22 | 23 | /** 24 | * Provides the [MapperFactoryBuilder]. 25 | * 26 | * @param orikaProperties The configuration properties for Orika. 27 | * @param orikaMapperFactoryBuilderConfigurers The configurers for [MapperFactoryBuilder]. 28 | * @return The [MapperFactoryBuilder]. 29 | */ 30 | @Bean 31 | @ConditionalOnMissingBean 32 | fun orikaMapperFactoryBuilder( 33 | orikaProperties: OrikaProperties, 34 | orikaMapperFactoryBuilderConfigurers: List, 35 | ): MapperFactoryBuilder<*, *> { 36 | val orikaMapperFactoryBuilder = DefaultMapperFactory.Builder() 37 | orikaProperties.useBuiltinConverters?.also { orikaMapperFactoryBuilder.useBuiltinConverters(it) } 38 | orikaProperties.useAutoMapping?.also { orikaMapperFactoryBuilder.useAutoMapping(it) } 39 | orikaProperties.mapNulls?.also { orikaMapperFactoryBuilder.mapNulls(it) } 40 | orikaProperties.dumpStateOnException?.also { orikaMapperFactoryBuilder.dumpStateOnException(it) } 41 | orikaProperties.favorExtension?.also { orikaMapperFactoryBuilder.favorExtension(it) } 42 | orikaProperties.captureFieldContext?.also { orikaMapperFactoryBuilder.captureFieldContext(it) } 43 | orikaMapperFactoryBuilderConfigurers.forEach { it.configure(orikaMapperFactoryBuilder) } 44 | log.debug("Providing the {}: {}", MapperFactoryBuilder::class.simpleName, orikaMapperFactoryBuilder) 45 | return orikaMapperFactoryBuilder 46 | } 47 | 48 | /** 49 | * Provides the [MapperFactory]. 50 | * 51 | * @param orikaMapperFactoryBuilder The [MapperFactoryBuilder]. 52 | * @param orikaMapperFactoryConfigurers The configurers for [MapperFactory]. 53 | * @return The [MapperFactory]. 54 | */ 55 | @Bean 56 | @ConditionalOnMissingBean 57 | fun orikaMapperFactory( 58 | orikaMapperFactoryBuilder: MapperFactoryBuilder<*, *>, 59 | orikaMapperFactoryConfigurers: List, 60 | ): MapperFactory { 61 | val orikaMapperFactory = orikaMapperFactoryBuilder.build() 62 | orikaMapperFactoryConfigurers.forEach { it.configure(orikaMapperFactory) } 63 | log.debug("Providing the {}: {}", MapperFactory::class.simpleName, orikaMapperFactory) 64 | return orikaMapperFactory 65 | } 66 | 67 | /** 68 | * Provides the [MapperFacade]. 69 | * 70 | * @param orikaMapperFactory The [MapperFactory]. 71 | * @return The [MapperFacade]. 72 | */ 73 | @Bean 74 | @ConditionalOnMissingBean 75 | fun orikaMapperFacade(orikaMapperFactory: MapperFactory): MapperFacade { 76 | val orikaMapperFacade = orikaMapperFactory.mapperFacade 77 | log.debug("Providing the {}: {}", MapperFacade::class.simpleName, orikaMapperFacade) 78 | return orikaMapperFacade 79 | } 80 | 81 | companion object { 82 | 83 | /** 84 | * The logger. 85 | */ 86 | private val log: Logger = getLogger(OrikaAutoConfiguration::class.java) 87 | 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/akkinoc/spring/boot/orika/OrikaMapperFactoryBuilderConfigurer.kt: -------------------------------------------------------------------------------- 1 | package dev.akkinoc.spring.boot.orika 2 | 3 | import ma.glasnost.orika.impl.DefaultMapperFactory.MapperFactoryBuilder 4 | 5 | /** 6 | * The interface to configure [MapperFactoryBuilder]. 7 | */ 8 | interface OrikaMapperFactoryBuilderConfigurer { 9 | 10 | /** 11 | * Configures the [MapperFactoryBuilder]. 12 | * 13 | * @param orikaMapperFactoryBuilder The [MapperFactoryBuilder]. 14 | */ 15 | fun configure(orikaMapperFactoryBuilder: MapperFactoryBuilder<*, *>) 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/akkinoc/spring/boot/orika/OrikaMapperFactoryConfigurer.kt: -------------------------------------------------------------------------------- 1 | package dev.akkinoc.spring.boot.orika 2 | 3 | import ma.glasnost.orika.MapperFactory 4 | 5 | /** 6 | * The interface to configure [MapperFactory]. 7 | */ 8 | interface OrikaMapperFactoryConfigurer { 9 | 10 | /** 11 | * Configures the [MapperFactory]. 12 | * 13 | * @param orikaMapperFactory The [MapperFactory]. 14 | */ 15 | fun configure(orikaMapperFactory: MapperFactory) 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/akkinoc/spring/boot/orika/OrikaProperties.kt: -------------------------------------------------------------------------------- 1 | package dev.akkinoc.spring.boot.orika 2 | 3 | import ma.glasnost.orika.impl.DefaultMapperFactory.MapperFactoryBuilder 4 | import org.springframework.boot.context.properties.ConfigurationProperties 5 | 6 | /** 7 | * The configuration properties for Orika. 8 | * 9 | * @property enabled 10 | * Whether to enable auto-configuration. 11 | * @property useBuiltinConverters 12 | * Whether to use built-in converters. 13 | * See also [MapperFactoryBuilder.useBuiltinConverters]. 14 | * By default, follows Orika's behavior. 15 | * @property useAutoMapping 16 | * Whether to use auto-mapping. 17 | * See also [MapperFactoryBuilder.useAutoMapping]. 18 | * By default, follows Orika's behavior. 19 | * @property mapNulls 20 | * Whether to map nulls. 21 | * See also [MapperFactoryBuilder.mapNulls]. 22 | * By default, follows Orika's behavior. 23 | * @property dumpStateOnException 24 | * Whether to dump the current state of the mapping infrastructure objects 25 | * upon occurrence of an exception while mapping. 26 | * See also [MapperFactoryBuilder.dumpStateOnException]. 27 | * By default, follows Orika's behavior. 28 | * @property favorExtension 29 | * Whether to favor extension by default in registered class-maps. 30 | * See also [MapperFactoryBuilder.favorExtension]. 31 | * By default, follows Orika's behavior. 32 | * @property captureFieldContext 33 | * Whether full field context should be captured. 34 | * See also [MapperFactoryBuilder.captureFieldContext]. 35 | * By default, follows Orika's behavior. 36 | */ 37 | @ConfigurationProperties("orika") 38 | data class OrikaProperties 39 | @JvmOverloads 40 | constructor( 41 | val enabled: Boolean = true, 42 | val useBuiltinConverters: Boolean? = null, 43 | val useAutoMapping: Boolean? = null, 44 | val mapNulls: Boolean? = null, 45 | val dumpStateOnException: Boolean? = null, 46 | val favorExtension: Boolean? = null, 47 | val captureFieldContext: Boolean? = null, 48 | ) 49 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/akkinoc/spring/boot/orika/module.md: -------------------------------------------------------------------------------- 1 | # Module orika-spring-boot-starter 2 | 3 | [Spring Boot] Starter for [Orika]. 4 | 5 | [Spring Boot]: https://spring.io/projects/spring-boot 6 | [Orika]: https://orika-mapper.github.io/orika-docs 7 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/akkinoc/spring/boot/orika/package.md: -------------------------------------------------------------------------------- 1 | # Package dev.akkinoc.spring.boot.orika 2 | 3 | [Spring Boot] Starter for [Orika]. 4 | 5 | [Spring Boot]: https://spring.io/projects/spring-boot 6 | [Orika]: https://orika-mapper.github.io/orika-docs 7 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": [ 3 | { 4 | "name": "orika", 5 | "type": "dev.akkinoc.spring.boot.orika.OrikaProperties", 6 | "sourceType": "dev.akkinoc.spring.boot.orika.OrikaProperties", 7 | "description": "The configuration properties for Orika." 8 | } 9 | ], 10 | "properties": [ 11 | { 12 | "name": "orika.enabled", 13 | "type": "java.lang.Boolean", 14 | "sourceType": "dev.akkinoc.spring.boot.orika.OrikaProperties", 15 | "description": "Whether to enable auto-configuration.", 16 | "defaultValue": true 17 | }, 18 | { 19 | "name": "orika.use-builtin-converters", 20 | "type": "java.lang.Boolean", 21 | "sourceType": "dev.akkinoc.spring.boot.orika.OrikaProperties", 22 | "description": "Whether to use built-in converters. See also MapperFactoryBuilder.useBuiltinConverters. By default, follows Orika's behavior." 23 | }, 24 | { 25 | "name": "orika.use-auto-mapping", 26 | "type": "java.lang.Boolean", 27 | "sourceType": "dev.akkinoc.spring.boot.orika.OrikaProperties", 28 | "description": "Whether to use auto-mapping. See also MapperFactoryBuilder.useAutoMapping. By default, follows Orika's behavior." 29 | }, 30 | { 31 | "name": "orika.map-nulls", 32 | "type": "java.lang.Boolean", 33 | "sourceType": "dev.akkinoc.spring.boot.orika.OrikaProperties", 34 | "description": "Whether to map nulls. See also MapperFactoryBuilder.mapNulls. By default, follows Orika's behavior." 35 | }, 36 | { 37 | "name": "orika.dump-state-on-exception", 38 | "type": "java.lang.Boolean", 39 | "sourceType": "dev.akkinoc.spring.boot.orika.OrikaProperties", 40 | "description": "Whether to dump the current state of the mapping infrastructure objects upon occurrence of an exception while mapping. See also MapperFactoryBuilder.dumpStateOnException. By default, follows Orika's behavior." 41 | }, 42 | { 43 | "name": "orika.favor-extension", 44 | "type": "java.lang.Boolean", 45 | "sourceType": "dev.akkinoc.spring.boot.orika.OrikaProperties", 46 | "description": "Whether to favor extension by default in registered class-maps. See also MapperFactoryBuilder.favorExtension. By default, follows Orika's behavior." 47 | }, 48 | { 49 | "name": "orika.capture-field-context", 50 | "type": "java.lang.Boolean", 51 | "sourceType": "dev.akkinoc.spring.boot.orika.OrikaProperties", 52 | "description": "Whether full field context should be captured. See also MapperFactoryBuilder.captureFieldContext. By default, follows Orika's behavior." 53 | } 54 | ], 55 | "hints": [ 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | dev.akkinoc.spring.boot.orika.OrikaAutoConfiguration 2 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/akkinoc/spring/boot/orika/BasicTest.kt: -------------------------------------------------------------------------------- 1 | package dev.akkinoc.spring.boot.orika 2 | 3 | import io.kotest.matchers.nulls.shouldBeNull 4 | import io.kotest.matchers.nulls.shouldNotBeNull 5 | import io.kotest.matchers.shouldBe 6 | import ma.glasnost.orika.MapperFacade 7 | import ma.glasnost.orika.MapperFactory 8 | import ma.glasnost.orika.impl.DefaultMapperFactory.MapperFactoryBuilder 9 | import org.junit.jupiter.api.Test 10 | import org.springframework.beans.factory.annotation.Autowired 11 | import org.springframework.boot.test.context.SpringBootTest 12 | import org.springframework.test.util.ReflectionTestUtils.getField 13 | 14 | /** 15 | * Tests the case where the configuration is the default. 16 | */ 17 | @SpringBootTest 18 | class BasicTest { 19 | 20 | @Test 21 | fun `Provides the configuration properties for Orika`(@Autowired orikaProperties: OrikaProperties?) { 22 | orikaProperties.shouldNotBeNull() 23 | orikaProperties.enabled.shouldBe(true) 24 | orikaProperties.useBuiltinConverters.shouldBeNull() 25 | orikaProperties.useAutoMapping.shouldBeNull() 26 | orikaProperties.mapNulls.shouldBeNull() 27 | orikaProperties.dumpStateOnException.shouldBeNull() 28 | orikaProperties.favorExtension.shouldBeNull() 29 | orikaProperties.captureFieldContext.shouldBeNull() 30 | } 31 | 32 | @Test 33 | fun `Provides the MapperFactoryBuilder`(@Autowired orikaMapperFactoryBuilder: MapperFactoryBuilder<*, *>?) { 34 | orikaMapperFactoryBuilder.shouldNotBeNull() 35 | getField(orikaMapperFactoryBuilder, "useBuiltinConverters").shouldBe(true) 36 | getField(orikaMapperFactoryBuilder, "useAutoMapping").shouldBe(true) 37 | getField(orikaMapperFactoryBuilder, "mapNulls").shouldBe(true) 38 | getField(orikaMapperFactoryBuilder, "dumpStateOnException").shouldBe(false) 39 | getField(orikaMapperFactoryBuilder, "favorExtension").shouldBe(false) 40 | getField(orikaMapperFactoryBuilder, "captureFieldContext").shouldBe(false) 41 | } 42 | 43 | @Test 44 | fun `Provides the MapperFactory`(@Autowired orikaMapperFactory: MapperFactory?) { 45 | orikaMapperFactory.shouldNotBeNull() 46 | } 47 | 48 | @Test 49 | fun `Provides the MapperFacade`(@Autowired orikaMapperFacade: MapperFacade?) { 50 | orikaMapperFacade.shouldNotBeNull() 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/akkinoc/spring/boot/orika/DisabledTest.kt: -------------------------------------------------------------------------------- 1 | package dev.akkinoc.spring.boot.orika 2 | 3 | import io.kotest.matchers.nulls.shouldBeNull 4 | import ma.glasnost.orika.MapperFacade 5 | import ma.glasnost.orika.MapperFactory 6 | import ma.glasnost.orika.impl.DefaultMapperFactory.MapperFactoryBuilder 7 | import org.junit.jupiter.api.Test 8 | import org.springframework.beans.factory.annotation.Autowired 9 | import org.springframework.boot.test.context.SpringBootTest 10 | 11 | /** 12 | * Tests the case where auto-configuration is disabled. 13 | */ 14 | @SpringBootTest(properties = ["orika.enabled=false"]) 15 | class DisabledTest { 16 | 17 | @Test 18 | fun `Does not provide the configuration properties for Orika`(@Autowired orikaProperties: OrikaProperties?) { 19 | orikaProperties.shouldBeNull() 20 | } 21 | 22 | @Test 23 | fun `Does not provide the MapperFactoryBuilder`(@Autowired orikaMapperFactoryBuilder: MapperFactoryBuilder<*, *>?) { 24 | orikaMapperFactoryBuilder.shouldBeNull() 25 | } 26 | 27 | @Test 28 | fun `Does not provide the MapperFactory`(@Autowired orikaMapperFactory: MapperFactory?) { 29 | orikaMapperFactory.shouldBeNull() 30 | } 31 | 32 | @Test 33 | fun `Does not provide the MapperFacade`(@Autowired orikaMapperFacade: MapperFacade?) { 34 | orikaMapperFacade.shouldBeNull() 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/akkinoc/spring/boot/orika/MapperFactoryBuilderConfigurationTest.kt: -------------------------------------------------------------------------------- 1 | package dev.akkinoc.spring.boot.orika 2 | 3 | import dev.akkinoc.spring.boot.orika.test.mock.MockOrikaMapperFactoryBuilderConfigurer 4 | import io.kotest.matchers.types.shouldBeSameInstanceAs 5 | import ma.glasnost.orika.impl.DefaultMapperFactory.MapperFactoryBuilder 6 | import org.junit.jupiter.api.Test 7 | import org.springframework.beans.factory.annotation.Autowired 8 | import org.springframework.boot.test.context.SpringBootTest 9 | import org.springframework.boot.test.context.TestConfiguration 10 | import org.springframework.context.annotation.Bean 11 | 12 | /** 13 | * Tests the case where the [MapperFactoryBuilder] is configured. 14 | */ 15 | @SpringBootTest 16 | class MapperFactoryBuilderConfigurationTest { 17 | 18 | @Test 19 | fun `Configures the MapperFactoryBuilder`( 20 | @Autowired orikaMapperFactoryBuilder: MapperFactoryBuilder<*, *>, 21 | @Autowired mockOrikaMapperFactoryBuilderConfigurer1: MockOrikaMapperFactoryBuilderConfigurer, 22 | @Autowired mockOrikaMapperFactoryBuilderConfigurer2: MockOrikaMapperFactoryBuilderConfigurer, 23 | ) { 24 | mockOrikaMapperFactoryBuilderConfigurer1.configured.shouldBeSameInstanceAs(orikaMapperFactoryBuilder) 25 | mockOrikaMapperFactoryBuilderConfigurer2.configured.shouldBeSameInstanceAs(orikaMapperFactoryBuilder) 26 | } 27 | 28 | /** 29 | * The additional test context configuration. 30 | */ 31 | @TestConfiguration(proxyBeanMethods = false) 32 | class AdditionalTestContextConfiguration { 33 | 34 | /** 35 | * Provides the first [MockOrikaMapperFactoryBuilderConfigurer]. 36 | * 37 | * @return The first [MockOrikaMapperFactoryBuilderConfigurer]. 38 | */ 39 | @Bean 40 | fun mockOrikaMapperFactoryBuilderConfigurer1(): MockOrikaMapperFactoryBuilderConfigurer { 41 | return MockOrikaMapperFactoryBuilderConfigurer() 42 | } 43 | 44 | /** 45 | * Provides the second [MockOrikaMapperFactoryBuilderConfigurer]. 46 | * 47 | * @return The second [MockOrikaMapperFactoryBuilderConfigurer]. 48 | */ 49 | @Bean 50 | fun mockOrikaMapperFactoryBuilderConfigurer2(): MockOrikaMapperFactoryBuilderConfigurer { 51 | return MockOrikaMapperFactoryBuilderConfigurer() 52 | } 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/akkinoc/spring/boot/orika/MapperFactoryConfigurationTest.kt: -------------------------------------------------------------------------------- 1 | package dev.akkinoc.spring.boot.orika 2 | 3 | import dev.akkinoc.spring.boot.orika.test.mock.MockOrikaMapperFactoryConfigurer 4 | import io.kotest.matchers.types.shouldBeSameInstanceAs 5 | import ma.glasnost.orika.MapperFactory 6 | import org.junit.jupiter.api.Test 7 | import org.springframework.beans.factory.annotation.Autowired 8 | import org.springframework.boot.test.context.SpringBootTest 9 | import org.springframework.boot.test.context.TestConfiguration 10 | import org.springframework.context.annotation.Bean 11 | 12 | /** 13 | * Tests the case where the [MapperFactory] is configured. 14 | */ 15 | @SpringBootTest 16 | class MapperFactoryConfigurationTest { 17 | 18 | @Test 19 | fun `Configures the MapperFactory`( 20 | @Autowired orikaMapperFactory: MapperFactory, 21 | @Autowired mockOrikaMapperFactoryConfigurer1: MockOrikaMapperFactoryConfigurer, 22 | @Autowired mockOrikaMapperFactoryConfigurer2: MockOrikaMapperFactoryConfigurer, 23 | ) { 24 | mockOrikaMapperFactoryConfigurer1.configured.shouldBeSameInstanceAs(orikaMapperFactory) 25 | mockOrikaMapperFactoryConfigurer2.configured.shouldBeSameInstanceAs(orikaMapperFactory) 26 | } 27 | 28 | /** 29 | * The additional test context configuration. 30 | */ 31 | @TestConfiguration(proxyBeanMethods = false) 32 | class AdditionalTestContextConfiguration { 33 | 34 | /** 35 | * Provides the first [MockOrikaMapperFactoryConfigurer]. 36 | * 37 | * @return The first [MockOrikaMapperFactoryConfigurer]. 38 | */ 39 | @Bean 40 | fun mockOrikaMapperFactoryConfigurer1(): MockOrikaMapperFactoryConfigurer { 41 | return MockOrikaMapperFactoryConfigurer() 42 | } 43 | 44 | /** 45 | * Provides the second [MockOrikaMapperFactoryConfigurer]. 46 | * 47 | * @return The second [MockOrikaMapperFactoryConfigurer]. 48 | */ 49 | @Bean 50 | fun mockOrikaMapperFactoryConfigurer2(): MockOrikaMapperFactoryConfigurer { 51 | return MockOrikaMapperFactoryConfigurer() 52 | } 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/akkinoc/spring/boot/orika/PropertiesConfigurationTest.kt: -------------------------------------------------------------------------------- 1 | package dev.akkinoc.spring.boot.orika 2 | 3 | import io.kotest.matchers.shouldBe 4 | import ma.glasnost.orika.impl.DefaultMapperFactory.MapperFactoryBuilder 5 | import org.junit.jupiter.api.Test 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.boot.test.context.SpringBootTest 8 | import org.springframework.test.util.ReflectionTestUtils.getField 9 | 10 | /** 11 | * Tests the case where the configuration properties are configured. 12 | */ 13 | @SpringBootTest( 14 | properties = [ 15 | "orika.enabled=true", 16 | "orika.use-builtin-converters=false", 17 | "orika.use-auto-mapping=false", 18 | "orika.map-nulls=false", 19 | "orika.dump-state-on-exception=true", 20 | "orika.favor-extension=true", 21 | "orika.capture-field-context=true", 22 | ] 23 | ) 24 | class PropertiesConfigurationTest { 25 | 26 | @Test 27 | fun `Configures the MapperFactoryBuilder`(@Autowired orikaMapperFactoryBuilder: MapperFactoryBuilder<*, *>) { 28 | getField(orikaMapperFactoryBuilder, "useBuiltinConverters").shouldBe(false) 29 | getField(orikaMapperFactoryBuilder, "useAutoMapping").shouldBe(false) 30 | getField(orikaMapperFactoryBuilder, "mapNulls").shouldBe(false) 31 | getField(orikaMapperFactoryBuilder, "dumpStateOnException").shouldBe(true) 32 | getField(orikaMapperFactoryBuilder, "favorExtension").shouldBe(true) 33 | getField(orikaMapperFactoryBuilder, "captureFieldContext").shouldBe(true) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/akkinoc/spring/boot/orika/TestContextConfiguration.kt: -------------------------------------------------------------------------------- 1 | package dev.akkinoc.spring.boot.orika 2 | 3 | import org.springframework.boot.SpringBootConfiguration 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration 5 | 6 | /** 7 | * The test context configuration. 8 | */ 9 | @SpringBootConfiguration(proxyBeanMethods = false) 10 | @EnableAutoConfiguration 11 | class TestContextConfiguration 12 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/akkinoc/spring/boot/orika/test/mock/MockOrikaMapperFactoryBuilderConfigurer.kt: -------------------------------------------------------------------------------- 1 | package dev.akkinoc.spring.boot.orika.test.mock 2 | 3 | import dev.akkinoc.spring.boot.orika.OrikaMapperFactoryBuilderConfigurer 4 | import ma.glasnost.orika.impl.DefaultMapperFactory.MapperFactoryBuilder 5 | 6 | /** 7 | * The mock configurer for [MapperFactoryBuilder]. 8 | */ 9 | class MockOrikaMapperFactoryBuilderConfigurer : OrikaMapperFactoryBuilderConfigurer { 10 | 11 | /** 12 | * The configured [MapperFactoryBuilder]. 13 | */ 14 | var configured: MapperFactoryBuilder<*, *>? = null 15 | private set 16 | 17 | override fun configure(orikaMapperFactoryBuilder: MapperFactoryBuilder<*, *>) { 18 | check(configured == null) { "The MockOrikaMapperFactoryBuilderConfigurer is already configured: $this" } 19 | configured = orikaMapperFactoryBuilder 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/akkinoc/spring/boot/orika/test/mock/MockOrikaMapperFactoryConfigurer.kt: -------------------------------------------------------------------------------- 1 | package dev.akkinoc.spring.boot.orika.test.mock 2 | 3 | import dev.akkinoc.spring.boot.orika.OrikaMapperFactoryConfigurer 4 | import ma.glasnost.orika.MapperFactory 5 | 6 | /** 7 | * The mock configurer for [MapperFactory]. 8 | */ 9 | class MockOrikaMapperFactoryConfigurer : OrikaMapperFactoryConfigurer { 10 | 11 | /** 12 | * The configured [MapperFactory]. 13 | */ 14 | var configured: MapperFactory? = null 15 | private set 16 | 17 | override fun configure(orikaMapperFactory: MapperFactory) { 18 | check(configured == null) { "The MockOrikaMapperFactoryConfigurer is already configured: $this" } 19 | configured = orikaMapperFactory 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | main: 3 | banner-mode: off 4 | logging: 5 | level: 6 | root: info 7 | dev.akkinoc.spring.boot.orika: debug 8 | --------------------------------------------------------------------------------