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> getSingletons
或 Set<Class> getClasses
方法 非空设置,这会自动禁用class路径扫描,因为假设我们想自己注册所有内容。
所以在之前的案例中,您可能只是在使用 class路径扫描。在这种情况下,您需要在 getClasses
方法中显式地将提供者添加到 classes 的集合中,因为您覆盖了添加其他组件 classes.[=19= 的方法]
我正在使用 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> getSingletons
或 Set<Class> getClasses
方法 非空设置,这会自动禁用class路径扫描,因为假设我们想自己注册所有内容。
所以在之前的案例中,您可能只是在使用 class路径扫描。在这种情况下,您需要在 getClasses
方法中显式地将提供者添加到 classes 的集合中,因为您覆盖了添加其他组件 classes.[=19= 的方法]