RxJava Spring Boot微服务AsyncReturnValueHandler给出404没有可用消息ERROR

时间:2017-01-30 02:47:51

标签: java spring spring-mvc spring-boot rx-java

我使用RxJava编写了一个Spring Boot微服务,你可以在这里找到project。一切都很完美。现在我正在将我的Controller / Resource类中的RxJava Observable转换为DeferredResult。我听说可以使用HandlerMethodReturnValueHandlerObservableDeferredResult的简单适配器来完成此操作。我开始实现这一点。首先,我写了HandlerMethodReturnValueHandler这样的内容。

package com.example.handlers;

public class ObservableReturnValueHandler implements AsyncHandlerMethodReturnValueHandler {
    @Override
    public boolean isAsyncReturnValue(Object returnValue, MethodParameter returnType) {
        return returnValue != null && supportsReturnType(returnType);
    }

    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        return Observable.class.isAssignableFrom(returnType.getParameterType());
    }

    @Override
    public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest) throws Exception {

        if (returnValue == null) {
            mavContainer.setRequestHandled(true);
            return;
        }

        final Observable<?> observable = Observable.class.cast(returnValue);
        WebAsyncUtils.getAsyncManager(webRequest)
                .startDeferredResultProcessing(new ObservableAdapter<>(observable), mavContainer);
    }

    public class ObservableAdapter<T> extends DeferredResult<T> {
        public ObservableAdapter(Observable<T> observable) {
            observable.subscribe(this::setResult, this::setErrorResult);
        }
    }
}

然后我编写了一个配置类,将ObservableReturnValueHandler添加到拦截器链中,以便它可以处理响应。代码如下。

package com.example.config;
@Configuration
@ComponentScan(basePackages = { "com.example.*" })
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
        returnValueHandlers.add(new ObservableReturnValueHandler());
    }
}

现在我的资源/控制器类看起来像这样。

package com.example;

@Controller
@RequestMapping("/api/currencyconverter")
public class CurrencyResource {
    private static final Logger log = LoggerFactory.getLogger(CurrencyConverter.class);

    @Autowired
    private CurrencyConverterService currencyConverterService;

    @RequestMapping(value = "/rates", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
    public Observable<CurrencyRatesDTO> getCurrencyRates(
            @RequestParam("symbol") Set<String> currencyRates) {
        log.debug("Retrieving currency rates.");
        return currencyConverterService.getCurrencyRates(currencyRates);
    }
}

下面给出了作为微服务入口点的主要类。

package com.example;

@SpringBootApplication
public class JavaRxDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(JavaRxDemoApplication.class, args);

}

问题是当我发送GET请求http://localhost:8080/api/currencyconverter/rates?symbol=USD时,我收到以下有线错误。控制台中也没有任何错误消息或异常跟踪。

{
  "timestamp": 1485742987017,
  "status": 404,
  "error": "Not Found",
  "message": "No message available",
  "path": "/api/currencyconverter/rates"
}

然后我调试了代码并发现调用了控制器方法,从控制器成功调用了REST端点。订阅Observable,收到结果并在DeferredResult内成功设置为ObservableReturnValueHandler。之后发生的事情会导致此错误。

您可以在returnvaluehandler branch of the project找到当前代码。启动和运行项目的所有必要步骤都在项目附带的自述文件中给出。我在这里失踪了什么。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

@ComponentScan(basePackages = { "com.example.*" })

应该是

@ComponentScan(basePackages = { "com.example" })

404是因为组件扫描没有拾取您的控制器。