Reputation: 5321
I am trying to use Micronaut-servlet API for an existing microservice. Without the servlet API the following worked perfectly well
@Test
public void
saved_movies_are_returned_in_my_list() {
try (RxHttpClient client = embeddedServer.getApplicationContext()
.createBean(RxHttpClient.class, embeddedServer.getURL())) {
Movie movie = createMovie();
Response<Movie> response = client.toBlocking().retrieve(
HttpRequest.POST("/movies", movie).bearerAuth(idToken),
Argument.of(Response.class, Movie.class));
Response<List<Movie>> myMovies = client.toBlocking().retrieve(
HttpRequest.GET("/movies").bearerAuth(idToken),
Argument.of(Response.class, Argument.listOf(Movie.class)));
assertThat(myMovies.data).contains(movie);
}
}
This is the controller
@Post("/")
public Response<Movie> save(Movie movie) {
return movieService.save(movie);
}
And the service has logic where if the movie<->user mapping already exists then no data is saved and existing mapping is returned
public Response<Movie> save(Movie movie) {
Optional<Movie> byUserIdAndTmdbId = movieRepository
.findByUserIdAndTmdbId(movie.getUserId(), movie.getTmdbId());
Response<Movie> movieResponse = null;
if (!byUserIdAndTmdbId.isPresent()) {
movieResponse = new Response<>("Movie Saved Successfully",
State.SUCCESS, movieRepository.save(movie));
return movieResponse;
} else {
return new Response<>("Movie already in list",
State.SUCCESS, byUserIdAndTmdbId.get());
}
}
The repository is quite simple too
@Repository
public interface MovieRepository extends CrudRepository<Movie,Long> {
List<Movie> findByUserId(String userId);
Optional<Movie> getByUserIdAndTmdbId(String userId, Long timdbId);
}
All of this works perfectly fine until I remove
implementation "io.micronaut:micronaut-http-server-netty"
and replace it with
implementation("io.micronaut.servlet:micronaut-http-server-jetty:1.0.0.M1")
I get the following exception after this change
Failed to convert argument [Movie] for value [io.micronaut.core.convert.value.ConvertibleValuesMap@17bae1ca] due to: Cannot convert an iterable with more than 1 value to a non collection object
io.micronaut.http.client.exceptions.HttpClientResponseException: Failed to convert argument [Movie] for value [io.micronaut.core.convert.value.ConvertibleValuesMap@17bae1ca] due to: Cannot convert an iterable with more than 1 value to a non collection object
at io.micronaut.http.client.DefaultHttpClient$10.channelRead0(DefaultHttpClient.java:1831)
And if I try to keep both the dependencies then I get duplicate bean exception for the HTTPClient injection!
Upvotes: 0
Views: 768
Reputation: 863
Add the @Body
annotation to the controller method:
public Response<Movie> save(@Body Movie movie)
The default implementation (Netty runtime) does not need the annotation and thats why it works for netty, but if you use the servlet engine/implementation (jetty or tomcat etc) then the annotation is needed.
See: https://github.com/micronaut-projects/micronaut-servlet/issues/243
Upvotes: 1