I have a simple project in which I want to achieve Contract first API approach with spring boot and OpenApi Code generator.
I am getting the below exception while trying to run my application after successfully building the Api. Anyone who has an idea on how to fix this issue, I will appreciate a lot.
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'usersApiController' for bean class [com.alexdev.springopenapi.server.UsersApiController] conflicts with existing, non-compatible bean definition of same name and class [com.alexdev.springopenapi.api.UsersApiController]
Below is my Api Specification and build.gradle files
Api Specifications
openapi: 3.0.3
info:
title: User Management API
version: '1.0'
description: API for managing users
servers:
- url: https://example.com/api
paths:
/users:
get:
summary: Get all users
description: Returns a list of all users
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
post:
summary: Create a new user
description: Creates a new user
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/User'
responses:
'201':
description: Successfully created
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'400':
description: Invalid input
/users/{userId}:
get:
summary: Get user by ID
description: Returns a single user by ID
parameters:
- in: path
name: userId
description: ID of the user to return
required: true
schema:
type: integer
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
description: User not found
put:
summary: Update user
description: Updates an existing user
parameters:
- in: path
name: userId
description: ID of the user to update
required: true
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/User'
responses:
'200':
description: Successfully updated
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
description: User not found
'400':
description: Invalid input
delete:
summary: Delete user
description: Deletes a user by ID
parameters:
- in: path
name: userId
description: ID of the user to delete
required: true
schema:
type: integer
responses:
'204':
description: Successfully deleted
'404':
description: User not found
components:
schemas:
User:
type: object
properties:
id:
type: integer
format: int64
example: 1
username:
type: string
example: "john_doe"
email:
type: string
example: "[email protected]"
password:
type: string
example: "password123"
build.gradle
import org.openapitools.generator.gradle.plugin.tasks.GenerateTask
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.5'
id 'io.spring.dependency-management' version '1.1.4'
id 'org.openapi.generator' version '7.5.0' apply false
}
apply plugin: 'org.openapi.generator'
group = 'com.alexdev'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
developmentOnly 'org.springframework.boot:spring-boot-docker-compose'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0'
compileOnly 'javax.validation:validation-api:2.0.1.Final'
compileOnly 'javax.annotation:javax.annotation-api:1.3.2'
compileOnly 'com.fasterxml.jackson.core:jackson-databind:2.17.0'
compileOnly 'io.swagger.core.v3:swagger-annotations:2.2.21'
compileOnly 'org.openapitools:jackson-databind-nullable:0.2.6'
compileOnly 'javax.servlet:javax.servlet-api:4.0.1'
}
openApiGenerate {
generatorName = "spring"
library = "spring-boot"
modelNameSuffix = ""
id = "${project.name}" + "-api"
groupId = project.group
inputSpec = "${projectDir}/src/main/resources/openapi/openapi.yaml"
configFile = "${projectDir}/src/main/resources/openapi/openapi-config.yaml"
outputDir = "${buildDir}/generated/api"
modelPackage = "${group}.${project.name}.dto"
configOptions = [
apiPackage: "${group}.${project.name}.api",
serverPackage: "${group}.${project.name}.server",
]
}
tasks.register('openApiGeneratorApi', GenerateTask){
apiPackage = openApiGenerate.configOptions.get().get('apiPackage')
id = openApiGenerate.id
modelNameSuffix = openApiGenerate.modelNameSuffix
generatorName = openApiGenerate.generatorName
inputSpec = openApiGenerate.inputSpec
modelPackage = openApiGenerate.modelPackage
library = openApiGenerate.library
groupId = openApiGenerate.groupId
outputDir = openApiGenerate.outputDir
}
tasks.register('openApiGeneratorServer', GenerateTask){
apiPackage = openApiGenerate.configOptions.get().get('serverPackage')
id = openApiGenerate.id
modelNameSuffix = openApiGenerate.modelNameSuffix
generatorName = openApiGenerate.generatorName
inputSpec = openApiGenerate.inputSpec
modelPackage = openApiGenerate.modelPackage
library = openApiGenerate.library
groupId = openApiGenerate.groupId
outputDir = openApiGenerate.outputDir
}
openApiValidate {
inputSpec = openApiGenerate.inputSpec
}
sourceSets {
main{
java {
srcDir "$buildDir/generated/api/src/main/java"
}
}
}
tasks.register("buildApi", GradleBuild) {
dependsOn('openApiGeneratorApi','openApiGeneratorServer')
group = 'build'
description = "Builds the API"
}
tasks.named('test') {
useJUnitPlatform()
}