Wildfly抛出“无法找到采用javax.ws.rs.QueryParam的String参数或valueOf()或fromString()方法的构造函数".错误 [英] Wildfly throws "Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam" error

查看:205
本文介绍了Wildfly抛出“无法找到采用javax.ws.rs.QueryParam的String参数或valueOf()或fromString()方法的构造函数".错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Im using wildfly 9.0 to deploy my war file. I have java LocalDateTime, Java Money types defined in my REST GET endpoints.

部署战争文件时,出现以下错误[1].基于此答案[2],我为两种类型都编写了"ParamConverterProvider"实现.

When i deploy my war file, i get following error[1]. Based on this answer [2] I have written "ParamConverterProvider" implementations for both types.

工作正常(到目前为止,我再也没有见过相同的问题),现在我遇到了相同的问题. 有任何线索吗?

It was working fine( I haven't seen same issue again till now) and now i get same issue. Any clue?

[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)的基本类型:org.javamoney.moneta.Money}}}}

Caused by: java.lang.RuntimeException: Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam(\"totalMoneyVolumeForPeriod\") on 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) for basetype: org.javamoney.moneta.Money"}}}}

[2]

jaxrs找不到我的joda.money类型的自定义(反)序列化器

示例代码

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

推荐答案

使用类路径扫描时,将拾取并注册带有@Path@Provider注释的JAX-RS组件.有两种使用类路径扫描的方法.最常见的方法是只给一个 empty Application类加上@ApplicationPath

When you are using classpath scanning, JAX-RS components annotated with @Path or @Provider will get picked up and registered. There are a couple way to use classpath scanning. The most common way is to just have an empty Application class annotated with @ApplicationPath

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

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

This is enough for a JAX-RS application to be loaded, and to have the application's classpath scanned to components to register.

但是,按照规范,一旦我们覆盖了Application类的任何Set<Object> getSingletonsSet<Class> getClasses方法,并返回了 non-empty 设置,这将自动禁用类路径扫描,因为我们假设要自己注册所有内容.

But, per the specification, once we override any of the Set<Object> getSingletons or Set<Class> getClasses methods of the Application class, and return a non-empty set, this automatically disables classpath scanning, as it is assumed we want to register everything ourselves.

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

So in previous cases, you were probably just using classpath scanning. In this case, you need to explicitly add the provider to the set of classes in your getClasses method, since you overrode the method to add other component classes.

这篇关于Wildfly抛出“无法找到采用javax.ws.rs.QueryParam的String参数或valueOf()或fromString()方法的构造函数".错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆