Use the Generated Code
So far we've used the OpenAPI Generator Gradle Plugin to generate the representation of the OpenAPI Specification (our contract) in Java code.

But we are not using any of that code in our application yet. Let's change that.
Implement the Generated API Interface
Let's rewrite the Controller
so it implements the generated API Interface.
-
Delete all business logic. It should look kinda empty, like this:
src/main/java/dev/pollito/users_manager/adapter/in/rest/UserController.javapackage dev.pollito.users_manager.adapter.in.rest;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
public class UserController {
} -
Implement the generated interface and select methods to override. If you are using IntelliJ IDEA, by pressing
CTRL+O
anywhere in the class, you'll see a popup asking which methods to override.We are interested in
findAll()
andfindById(id:Long)
.Now the controller should look something like this:
src/main/java/dev/pollito/users_manager/adapter/in/rest/UserController.javapackage dev.pollito.users_manager.adapter.in.rest;
import dev.pollito.users_manager.adapter.in.rest.api.UsersApi;
import dev.pollito.users_manager.adapter.in.rest.dto.User;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequiredArgsConstructor
public class UserController implements UsersApi {
@Override
public ResponseEntity<List<User>> findAll() {
return UsersApi.super.findAll();
}
@Override
public ResponseEntity<User> findById(Long id) {
return UsersApi.super.findById(id);
}
}Right-click the main class → Run. Then go to http://localhost:8080/users. You should get
501 NOT IMPLEMENTED
.Let's return a hardcoded list of Users once again.
-
Inject
Service
andMapper
again and use them infindAll()
.src/main/java/dev/pollito/users_manager/adapter/in/rest/UserController.javapackage dev.pollito.users_manager.adapter.in.rest;
import dev.pollito.users_manager.adapter.in.rest.api.UsersApi;
import dev.pollito.users_manager.adapter.in.rest.dto.User;
import dev.pollito.users_manager.adapter.in.rest.mapper.UserMapper;
import dev.pollito.users_manager.domain.port.in.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequiredArgsConstructor
public class UserController implements UsersApi {
private final UserService userService;
private final UserMapper userMapper;
@Override
public ResponseEntity<List<User>> findAll() {
return ResponseEntity.ok(userService.findAll().stream().map(userMapper::map).toList());
}
@Override
public ResponseEntity<User> findById(Long id) {
return UsersApi.super.findById(id);
}
}You'll notice that the IDE is throwing at us this error:
no instance(s) of type variable(s) exist so that List<UserResponseDTO> conforms to List<User>
inference variable T has incompatible bounds:
equality constraints: List<User>
lower bounds: List<UserResponseDTO>That is because before using OpenAPI Generator Gradle Plugin,
UserController
returnsUserResponseDTO
(the DTO we've handwritten).Other folders are omitted for simplicity.
But now with OpenAPI Generator Gradle Plugin,
UserController
is implementingUsersApi
, so it must return the generated DTO (User
).Other folders are omitted for simplicity.
-
Make
UserMapper
map to the generated DTO.package dev.pollito.users_manager.adapter.in.rest.mapper;
import static org.mapstruct.MappingConstants.ComponentModel.SPRING;
import dev.pollito.users_manager.domain.model.User;
import org.mapstruct.Mapper;
@Mapper(componentModel = SPRING)
public interface UserMapper {
dev.pollito.users_manager.adapter.in.rest.dto.User map(User u);
}-
If you get an IDE error saying
incompatible return type
, do aclean
andbuild
. -
During building, you may get a warning:
warning: Unmapped target properties: "address, company, phone, profilePictureUrl, website". dev.pollito.users_manager.adapter.in.rest.dto.User map(User u);
That's fine. We are going to map those values later down the road.
-
Right-click the main class → Run. Then go to http://localhost:8080/users. You should get the list with the hardcoded user once again.

Next Steps
Here's some homework for you:
-
Create a
User findUserById(Long id)
method inUserService
, implement it inUserServiceImpl
, and call it inUserController
ResponseEntity<User> findById(Long id)
method.-
In
UserServiceImpl
User findUserById(Long id)
method, feel free to throw aNotImplementedException
. We are going to do a proper implementation later down the road.src/main/java/dev/pollito/users_manager/domain/service/UserServiceImpl.java@Override
public User findUserById(Long id) {
throw new NotImplementedException();
}
-
-
Commit the progress so far:
git add .
git commit -m "using generated primary adapter code from an openapi specification"