【问题标题】:Wildfly throws "Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam" errorWildfly 抛出“无法找到采用 String 参数或 valueOf() 或 fromString() 方法用于 javax.ws.rs.QueryParam 的构造函数”错误
【发布时间】:2016-09-23 18:40:42
【问题描述】:

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

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

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

[1]

原因:java.lang.RuntimeException:无法找到一个构造函数,该构造函数采用公共 javax 上的 javax.ws.rs.QueryParam(\"totalMoneyVolumeForPeriod\") 的 String 参数或 valueOf() 或 fromString() 方法.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) for basetype: org.javamoney.moneta.Money"}}}}

[2]

jaxrs could not find my custom (de)serializers for joda.money type

示例代码

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;
    }
}

【问题讨论】:

  • 确保已注册。除此之外,请展示一些我们可以测试的代码。
  • @peeskillet 如何,我应该在哪里注册?
  • @peeskillet 我已经提供了我的示例代码..除此之外我没有做任何事情
  • 如果你使用类路径扫描,它应该被@Provider注解注册。否则,您需要在 Application 类中注册它

标签: rest jax-rs wildfly wildfly-9


【解决方案1】:

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

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

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

但是,根据规范,一旦我们覆盖 Application 类的任何 Set&lt;Object&gt; getSingletonsSet&lt;Class&gt; getClasses 方法,并返回一个 非空 集,这会自动禁用类路径扫描,因为假设我们想自己注册所有内容。

所以在以前的情况下,您可能只是使用类路径扫描。在这种情况下,您需要在 getClasses 方法中将提供程序显式添加到类集,因为您覆盖了该方法以添加其他组件类。

【讨论】:

    猜你喜欢
    • 2016-02-04
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    • 2022-08-15
    相关资源
    最近更新 更多