Reputation: 1371
Intellij is telling me that updateTime
is of incorrect parameter type. I'm unfamiliar with this error and @EnumDateFormat
.
@DELETE
@Path("groups/{groupId}/samples/{testYear}")
@Produces(MediaType.APPLICATION_JSON)
@RolesAllowed({Profile.MP_USER_ROLE})
public Response deleteGroupSamples (@PathParam("groupId") Long groupId, @PathParam("testYear") Long testYear, @QueryParam("updateTime") @EnumDateFormat( FormatEnum.WITH_HHMMSS ) DateTime updateTime, TreatmentGroupTest sample) throws ValidationException{
manager.deleteGroupSample( this.getUser(), sample.getTestSampleId(), updateTime );
ResponseBuilder builder=null;
builder = Response.ok( );
return builder.build();
}
The error also suggests:
Checks types of parameters @PathParam, @QueryParam, etc. The type of annotated parameter, field or property must either
Be a primative type
Have a constructor that accepts a single String argument
Have a static method named valueOf or formString that accepts a single String argument (see, for example, Integer.valueOf(String))
Have a registered implementation of ParamConverterProvider JAX-RS extension SPI that returns a ParamConverter instance capable of a "form string" conversion of that type
Be List, Set or SortedSet, where T satisfies 2, 3 or 4 above. The resulting collection is read-only
Upvotes: 2
Views: 3445
Reputation: 73
I guess this is an old question, but for LocalDate
you must register an implementation of ParamConverterProvider
that returns a ParamConverter
instance that is capable of creating a LocalDate
from a String
.
If you check the javadoc for ParamConverter
, you will see that there are two methods: E fromString(String value)
and String toString(E value)
.
Also, if you see the documentation for ParamConverterProvider
you will notice that it has the following method: <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation annotations[])
.
Basically, you must create an implementation of ParamConverter<LocalDate>
that can create a LocalDate
from a String
, and then return an instance of that implementation from a registered ParamConverterProvider
.
Here is an example:
package com.example;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Optional;
/**
* The {@link ParamConverterProvider} for {@link java.time} package classes
* (i.e {@link LocalDate}, {@link LocalTime} and {@link LocalDateTime}).
*/
@Provider
public class Java8TimeParamConverterProvider implements ParamConverterProvider {
/**
* Contains a {@link DateTimeFormatter} whose pattern is "yyyy-MM-dd".
*/
public static final DateTimeFormatter CLASSIC_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
if (rawType == LocalDate.class) {
//noinspection unchecked
return (ParamConverter<T>) new Java8LocalDateClassicFormatParamConverter();
}
if (rawType == LocalTime.class) {
return null; // TODO: implement
}
if (rawType == LocalDateTime.class) {
return null; // TODO: implement
}
return null;
}
/**
* The {@link ParamConverter} for {@link LocalDate} using the {@link #CLASSIC_DATE_FORMATTER}.
*/
private static class Java8LocalDateClassicFormatParamConverter implements ParamConverter<LocalDate> {
@Override
public LocalDate fromString(String value) {
return Optional.ofNullable(value)
.map(CLASSIC_DATE_FORMATTER::parse)
.map(LocalDate::from)
.orElse(null);
}
@Override
public String toString(LocalDate value) {
return CLASSIC_DATE_FORMATTER.format(value);
}
}
}
You must register this provider. In your ResourceConfig
you must include this:
public class AppConfig extends ResourceConfig {
public AppConfig() {
register(Java8TimeParamConverterProvider.class);
}
}
Or, if you are doing package scanning:
public class AppConfig extends ResourceConfig {
public AppConfig() {
packages("com.example");
}
}
(This is why the @Provider
annotation is included in the Java8TimeParamConverterProvider
class definition). Note that this won't work if you are using spring boot, as there are issues at this moment with the final jar created by the spring boot plugin.
Another way to register your provider is by the web.xml
. In this case you must include the following:
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Include the following init-param if you want to do package scanning -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
com.example
</param-value>
</init-param>
<!-- Or use the following init-param if you want to do class register -->
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>com.example.Java8TimeParamConverterProvider</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Hope this helps you!
Upvotes: 6