OffsetDateTime屈服"没有找到类型为public javax.ws.rs.core.response"的参数的注入源;在GET方法中

时间:2016-10-04 10:34:34

标签: java rest jax-rs swagger

我有以下GET REST方法:

import java.time.OffsetDateTime;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import com.product.rest.api.TransactionsApi;
import com.product.rest.model.Transaction;

@Path("/transactions")

@Api(description = "the transactions API")
@Consumes({ "application/json" })
@Produces({ "application/json" })
public class TransactionsApiImpl extends TransactionsApi {

    @GET

    @Consumes({ "application/json" })
    @Produces({ "application/json" })
    @ApiOperation(value = "", notes = "Get all transactions", response =     Transaction.class, responseContainer = "List", tags = {})
    @ApiResponses(
        value = { @ApiResponse(code = 200, message = "OK", response =     Transaction.class, responseContainer = "List"),
            @ApiResponse(code = 400, message = "Bad Request", response =     Transaction.class, responseContainer = "List"),
            @ApiResponse(code = 404, message = "Not Found", response =     Transaction.class, responseContainer = "List"),
            @ApiResponse(code = 500, message = "Internal Server Error",     response = Transaction.class, responseContainer = "List") })
    @Override
    public Response transactionsGet(
        @HeaderParam("tok") String tok,
        @QueryParam("param1") Integer param1,
        @QueryParam("param2") String param2,
        @QueryParam("param3") OffsetDateTime param3,
        @QueryParam("param4") OffsetDateTime param4,
        @QueryParam("param5") Integer param5,
        @QueryParam("param6") Integer param6,
        @QueryParam("param7") String param7) {
        return Response.ok().entity("Success!").build();
    }

TransactionsApi是使用Swagger Codegen生成的实现,Transaction模型类也是如此。我在这个类中有其他几个函数,但每当我取消注释GET /transactions函数时,我都会收到以下错误:

WARN [Thread-1] (ContextHandler.java:2175) - unavailable
org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization.

[[FATAL] No injection source found for a parameter of type public javax.ws.rs.core.Response     
com.product.rest.impl.v1.TransactionsApiImpl.transactionsGet(java.lang.String,java.lang.Integer,java.lang.String,java.time.OffsetDateTime,java.time.OffsetDateTime,java.lang.Integer,java.lang.Integer,java.lang.String) at index 3.; source='ResourceMethod{httpMethod=GET, consumedTypes=[application/json], producedTypes=[application/json], suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class com.product.rest.impl.v1.TransactionsApiImpl, handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor@7df78e88]}, definitionMethod=public javax.ws.rs.core.Response

我发现的所有其他类似问题都与MultiPart Data和文件上传有关,而我正在做一个简单的GET请求。其他也使用javax.ws.rs.code.Response类的函数没有此问题,服务器正常启动。

我注意到只要OffsetDateTime类在参数中(即param3param4)就会出现问题,但我一直无法找到原因。此外,Swagger Codegen选择了OffsetDateTime,我不愿意改变它,看看每当我重新生成我的源时我将如何更改每个派生文件。

有没有人在使用REST服务和OffsetDateTime之前遇到此问题?

1 个答案:

答案 0 :(得分:10)

  

我发现的所有其他类似问题都与MultiPart数据和文件上传有关

它有关系。当Jersey无法验证资源模型时,错误是您遇到的一般错误。资源模型的一部分是方法参数。泽西岛有一个系统,可以知道它将能够处理哪些参数以及它赢得了哪些参数。在您的情况下,它不知道如何处理OffsetDateTime

您需要遵循一系列规则才能将非基本类型用作@QueryParam s(以及所有其他@XxxParams,例如@PathParam和{{1等等。):

  1. 是原始类型
  2. 拥有一个接受单个@FormParam参数的构造函数
  3. 有一个名为StringvalueOf的静态方法接受单个String参数(例如,参见fromString
  4. 具有Integer.valueOf(String) JAX-RS扩展SPI的注册实现,该实现返回一个ParamConverterProvider实例,该实例能够从字符串""转换类型。
  5. ParamConverterList<T>Set<T>,其中SortedSet<T>满足上述2,3或4。生成的集合是只读的。
  6. 所以在这个T的情况下,在列表中;它不是原始的;它没有String构造函数;它没有静态OffsetDateTimevalueOf

    所以基本上,剩下的唯一选择是为它实现fromString。基本设置看起来像

    ParamConverter/ParamConverterProvider

    泽西岛将传递查询参数的字符串值,您的工作就是创建它并将其返回。

    然后只需在应用程序中注册@Provider public class OffsetDateTimeProvider implements ParamConverterProvider { @Override public <T> ParamConverter<T> getConverter(Class<T> clazz, Type type, Annotation[] annotations) { if (clazz.getName().equals(OffsetDateTime.class.getName())) { return new ParamConverter<T>() { @SuppressWarnings("unchecked") @Override public T fromString(String value) { OffsetDateTime time = ... return (T) time; } @Override public String toString(T time) { return ...; } }; } return null; } } 即可。如果您正在使用包裹扫描,则应从OffsetDateTimeProvider注释中自动提取并注册。

    我没有使用Swagger,所以我不知道他们是否已经提供了已经实现过的这样的东西,但是他们会为你生成这个并且没有办法制作它似乎很奇怪工作。我知道泽西3队将获得Java 8支持,但谁知道什么时候会被释放。