JAX-RS ParamConverter with Quarkus
By Rebecca Searls | April 5, 2021
Recently RESTEasy had a request by a user who was implementing their REST service with Quarkus for support of an endpoint input parameter type java.time.Instant.
Lets look at how the user can provide support for java.time.Instant or any other data type in their REST application. The code used in this discussion can be found here.
First lets create a Quarkus getting-started app [1] to use in examining this issue.
mvn io.quarkus:quarkus-maven-plugin:1.13.0.Final:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=getting-started \
-DclassName="org.acme.getting.started.GreetingResource" \
-Dpath="/hello"
cd getting-started
Edit file ./src/main/java/org/acme/getting/started/GreetingResource.java and add the following endpoint.
@Path("time")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String helloTime(@QueryParam("name") String name, @QueryParam("time") Instant time) {
return "Hello " + name + ", " + time;
}
This is optional. You can also add a test for this endpoint. Edit file, ./src/test/java/org/acme/getting/started/GreetingResourceTest.java and add this code.
@Test
public void testHelloTimeEndpoint() {
given()
.when().get(URI.create("/hello/time?name=abc&time=2021-02-12T09:58:39Z"))
.then()
.statusCode(200)
.body(is("Hello abc, 2021-02-12T09:58:39Z"));
}
Lets run the application and call the endpoint using cURL. Build and run the application with this Quarkus command,
./mvnw compile quarkus:dev
YIKES what just happened? I get a InvocationTargetException and a stacktrace. Looking through the stacktrace I see the root cause is
Caused by: java.lang.RuntimeException: RESTEASY003875: Unable to find a
constructor that takes a String param or a valueOf() or fromString() method
for javax.ws.rs.QueryParam("time") on public java.lang.String
org.acme.getting.started.GreetingResource.helloTime(java.lang.String,java.time.Instant)
for basetype: java.time.Instant
JAX-RS enables this issue to be resolved with a ParamConverter. Interfaces ParamConverterProvider and ParamConverter are provided by the specification just for this situation. Lets create an implementation for each of these interfaces. In directory src/main/java/org/acme/getting/started create file InstantParamConverterProvider
package org.acme.getting.started;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.time.Instant;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;
@Provider
public class InstantParamConverterProvider implements ParamConverterProvider {
@SuppressWarnings("unchecked")
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType,
Type genericType,
Annotation[] annotations) {
if (rawType.isAssignableFrom(Instant.class)) {
return (ParamConverter<T>) new InstantParamConverter();
}
return null;
}
}
And file InstantParamConverter
package org.acme.getting.started;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.Provider;
import java.time.Instant;
import java.time.format.DateTimeParseException;
@Provider
public class InstantParamConverter implements ParamConverter<Instant> {
public Instant fromString(String value){
try {
String x = Instant.parse(value).toString();
return Instant.parse(value);
} catch (DateTimeParseException e) {
}
return null;
}
public String toString(Instant value){
return value.toString();
}
}
Now run the application.
./mvnw compile quarkus:dev
In a separate terminal window run cURL command.
curl -w "\n" "http://localhost:8080/hello/time?name=abc&time=2021-02-12T09:58:39Z"
Result is
Hello abc, 2021-02-12T09:58:39Z
The test can be run with this command.
./mvnw test
If you want to walk through the code with the debugger, set your debugger to port 5005 and run the application with either command
./mvnw compile quarkus:dev
or
./mvnw compile quarkus:dev -Dsuspend=true
In conclusion all elements of the JAX-RS specification still apply when writing a RESTful service with Quarkus.
References [1] Quarkus getting-started
Useful Links
YourKit supports open source projects with innovative and intelligent tools for monitoring and profiling Java and .NET applications. YourKit is the creator of YourKit Java Profiler, YourKit .NET Profiler, and YourKit YouMonitor