-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: @RestResource annotation and source generation #97
base: master
Are you sure you want to change the base?
Conversation
This PR adds the @RestResource annotation and a visitor. the idea is to generate to combine the annotation with a Micronaut Data CrudRepository to generate a REST controller. For example, for a Book entity: ```java import io.micronaut.core.annotation.Nullable; import io.micronaut.data.annotation.GeneratedValue; import io.micronaut.data.annotation.Id; import io.micronaut.data.annotation.MappedEntity; import io.micronaut.serde.annotation.Serdeable; @Serdeable @MappedEntity public record Book(@GeneratedValue @id @nullable Long id, String title) { } ``` and a JDBC repository: ```java import io.micronaut.data.jdbc.annotation.JdbcRepository; import io.micronaut.data.model.query.builder.sql.Dialect; import io.micronaut.data.repository.CrudRepository; @JdbcRepository(dialect = Dialect.H2) public interface BookRepository extends CrudRepository<Book, Long> { } ``` And a class annotated with `@RestResource`: ```java import io.micronaut.sourcegen.annotations.RestResource; @RestResource(repository = BookRepository.class, rolesAllowed = { "isAnonymous()" }) class BookRestResource { } ``` Generates the following controller: ```java @controller("/books") @RolesAllowed("isAnonymous()") class BookController { @Inject BookRepository repository; @get Iterable<Book> findAll() { return this.repository.findAll(); } @get("/{id}") Optional<Book> findById(Long id) { return this.repository.findById(id); } @delete("/{id}") @Status(HttpStatus.NO_CONTENT) void deleteById(Long id) { this.repository.deleteById(id); } @Status(HttpStatus.CREATED) @post void save(@Body Book entity) { this.repository.save(entity); } @put @Status(HttpStatus.NO_CONTENT) void update(@Body Book entity) { this.repository.update(entity); } } ```
I used field injection because I did not see in the api how to generate a constructor and use constructor injection. |
looks useful but would be good to have meta annotations for create/read/update/delete and have That said this could also be achieved with an interface with default methods which may be more natural/easier to extend. |
Quality Gate failedFailed conditions |
It might be good to generate some DTOs and allow to make some fields hidden, readonly etc |
interface CrudResource<E, I> {
CrudRepository<E, I> repository();
@Get
default Iterable<Book> findAll() {
return repository().findAll();
}
@Get("/{id}")
default Optional<Book> findById(Long id) {
return repository().findById(id);
}
@Delete("/{id}")
@Status(HttpStatus.NO_CONTENT)
default void deleteById(Long id) {
repository().deleteById(id);
}
@Status(HttpStatus.CREATED)
@Post
default void save(@Body Book entity) {
repository().save(entity);
}
@Put
@Status(HttpStatus.NO_CONTENT)
default void update(@Body Book entity) {
repository().update(entity);
}
}
@Controller("/books")
@RolesAllowed("isAnonymous()")
record BookResource(BookRepository repository) implements CrudResource<Book, Long> {
}
The code generation approach has limitations in terms of how you can customise the output. |
but such an api will be in Micronaut Data not here right? |
probably |
This PR adds the
@RestResource
annotation and a visitor. The idea is to generate to controller given Micronaut Data CrudRepository.For example, for a Book entity:
and a JDBC repository:
And a class annotated with
@RestResource
:Generates the following controller:
I would prefer to generate
instead of
but not sure how to do this with the api.
Also, the
save
method should probably be: but that was challenging with the current API as well.thoughts ?