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
问题描述
我正在使用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> getSingletons
或Set<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屋!