Wildfly 抛出 "Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam" 错误

Wildfly throws "Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam" error

我正在使用 wildfly 9.0 部署我的 war 文件。我的 REST GET 端点中定义了 java LocalDateTime,Java 货币类型。

当我部署 war 文件时,出现以下错误[1]。基于这个答案 [2],我已经为这两种类型编写了 "ParamConverterProvider" 实现。

它工作正常(直到现在我还没有再遇到同样的问题)现在我遇到了同样的问题。 有什么线索吗?

[1]

原因:java.lang.RuntimeException:无法在 public javax.ws.rs.core.Response com.test.rest.StockEndpoint.getItems(java.lang.Integer,java.lang.Integer,java.lang.String,java.lang.String,java.lang.Long,org.javamoney.moneta.Money ,java.util.Set,java.lang.String) 对于基本类型:org.javamoney.moneta.Money"}}}}

[2]

示例代码

package com.test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import javax.money.Monetary;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;

import org.javamoney.moneta.Money;

@Provider
public class MoneyConverterProvider  implements ParamConverterProvider {

    private final MoneyConverter converter = new MoneyConverter();

    @Override
    public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
        if (!rawType.equals(Money.class)) return null;
        return (ParamConverter<T>) converter; 
    }

    public class MoneyConverter implements ParamConverter<Money> {

        public Money fromString(String value) {
            if (value == null ||value.isEmpty()) return null; // change this for production

            return Money.of(new BigDecimal(value), Monetary.getCurrency("AUD"));
        }

        public String toString(Money value) {
            if (value == null) return "";
            return value.toString(); // change this for production
        }

    }
}

应用类

package com.test;

import javax.ws.rs.core.Application;

import com.test.autogen*;


import io.swagger.jaxrs.config.BeanConfig;

import java.util.HashSet;
import java.util.Set;

import javax.ws.rs.ApplicationPath;

@ApplicationPath("/rest")
public class RestApplication extends Application {
    public RestApplication() {
        BeanConfig beanConfig = new BeanConfig();
        //beanConfig.setVersion("1.0");
        beanConfig.setSchemes(new String[] { "http" });
        beanConfig.setTitle("My API");
        beanConfig.setBasePath("/rest");
        beanConfig.setResourcePackage("com.test.autogen");
        beanConfig.setScan(true);
    }

    @Override
    public Set<Class<?>> getClasses() {
        HashSet<Class<?>> set = new HashSet<Class<?>>();


        set.add(EmailEndpoint.class);
        set.add(StockEndpoint.class);

        set.add(io.swagger.jaxrs.listing.ApiListingResource.class);
        set.add(io.swagger.jaxrs.listing.SwaggerSerializers.class);

        return set;
    }
}

当您使用 class 路径扫描时,使用 @Path@Provider 注释的 JAX-RS 组件将被拾取并注册。有几种方法可以使用 class 路径扫描。最常见的方法是只用 empty Application class 注释 @ApplicationPath

@ApplicationPath("/api")
public class MyApplication extends Application {}

这足以加载 JAX-RS 应用程序,并使应用程序的 class 路径扫描到要注册的组件。

但是,根据规范,一旦我们重写 Application class 和 return 的任何 Set<Object> getSingletonsSet<Class> getClasses 方法 非空设置,这会自动禁用class路径扫描,因为假设我们想自己注册所有内容。

所以在之前的案例中,您可能只是在使用 class路径扫描。在这种情况下,您需要在 getClasses 方法中显式地将提供者添加到 classes 的集合中,因为您覆盖了添加其他组件 classes.[=19= 的方法]