private RequestMappingHandlerAdapter createAdapter(ApplicationContext context) throws Exception { RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter(); adapter.setApplicationContext(context); adapter.afterPropertiesSet(); return adapter; }
@Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter(); adapter.setMessageReaders(serverCodecConfigurer().getReaders()); adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer()); adapter.setReactiveAdapterRegistry(webFluxAdapterRegistry()); ArgumentResolverConfigurer configurer = new ArgumentResolverConfigurer(); configureArgumentResolvers(configurer); adapter.setArgumentResolverConfigurer(configurer); return adapter; }
@Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter(); adapter.setMessageReaders(getMessageReaders()); adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer()); adapter.setReactiveAdapterRegistry(webReactiveAdapterRegistry()); List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(); addArgumentResolvers(resolvers); if (!resolvers.isEmpty()) { adapter.setCustomArgumentResolvers(resolvers); } return adapter; }
@Override public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) { HandlerMethod handlerMethod = (HandlerMethod) handler; Assert.state(this.methodResolver != null && this.modelInitializer != null, "Not initialized"); InitBinderBindingContext bindingContext = new InitBinderBindingContext( getWebBindingInitializer(), this.methodResolver.getInitBinderMethods(handlerMethod)); InvocableHandlerMethod invocableMethod = this.methodResolver.getRequestMappingMethod(handlerMethod); Function<Throwable, Mono<HandlerResult>> exceptionHandler = ex -> handleException(ex, handlerMethod, bindingContext, exchange); return this.modelInitializer .initModel(handlerMethod, bindingContext, exchange) .then(Mono.defer(() -> invocableMethod.invoke(exchange, bindingContext))) .doOnNext(result -> result.setExceptionHandler(exceptionHandler)) .doOnNext(result -> bindingContext.saveModel()) .onErrorResume(exceptionHandler); }
/** * Override to plug a sub-class of {@link RequestMappingHandlerAdapter}. */ protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() { return new RequestMappingHandlerAdapter(); }
@Test public void requestMappingHandlerAdapter() throws Exception { ApplicationContext context = loadConfig(WebFluxConfig.class); String name = "requestMappingHandlerAdapter"; RequestMappingHandlerAdapter adapter = context.getBean(name, RequestMappingHandlerAdapter.class); assertNotNull(adapter); List<HttpMessageReader<?>> readers = adapter.getMessageReaders(); assertEquals(13, readers.size()); ResolvableType multiValueMapType = forClassWithGenerics(MultiValueMap.class, String.class, String.class); assertHasMessageReader(readers, forClass(byte[].class), APPLICATION_OCTET_STREAM); assertHasMessageReader(readers, forClass(ByteBuffer.class), APPLICATION_OCTET_STREAM); assertHasMessageReader(readers, forClass(String.class), TEXT_PLAIN); assertHasMessageReader(readers, forClass(Resource.class), IMAGE_PNG); assertHasMessageReader(readers, forClass(Message.class), new MediaType("application", "x-protobuf")); assertHasMessageReader(readers, multiValueMapType, APPLICATION_FORM_URLENCODED); assertHasMessageReader(readers, forClass(TestBean.class), APPLICATION_XML); assertHasMessageReader(readers, forClass(TestBean.class), APPLICATION_JSON); assertHasMessageReader(readers, forClass(TestBean.class), new MediaType("application", "x-jackson-smile")); assertHasMessageReader(readers, forClass(TestBean.class), null); WebBindingInitializer bindingInitializer = adapter.getWebBindingInitializer(); assertNotNull(bindingInitializer); WebExchangeDataBinder binder = new WebExchangeDataBinder(new Object()); bindingInitializer.initBinder(binder); name = "webFluxConversionService"; ConversionService service = context.getBean(name, ConversionService.class); assertSame(service, binder.getConversionService()); name = "webFluxValidator"; Validator validator = context.getBean(name, Validator.class); assertSame(validator, binder.getValidator()); }
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory())); resolvers.add(new RequestParamMapMethodArgumentResolver()); resolvers.add(new PathVariableMethodArgumentResolver(getBeanFactory())); resolvers.add(new PathVariableMapMethodArgumentResolver()); resolvers.add(new RequestBodyArgumentResolver(getMessageReaders(), getReactiveAdapterRegistry())); resolvers.add(new ModelAttributeMethodArgumentResolver(getReactiveAdapterRegistry())); resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory())); resolvers.add(new RequestHeaderMapMethodArgumentResolver()); resolvers.add(new CookieValueMethodArgumentResolver(getBeanFactory())); resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory())); resolvers.add(new SessionAttributeMethodArgumentResolver(getBeanFactory())); resolvers.add(new RequestAttributeMethodArgumentResolver(getBeanFactory())); resolvers.add(new HttpEntityArgumentResolver(getMessageReaders(), getReactiveAdapterRegistry())); resolvers.add(new ModelArgumentResolver()); resolvers.add(new ErrorsMethodArgumentResolver(getReactiveAdapterRegistry())); resolvers.add(new ServerWebExchangeArgumentResolver()); resolvers.add(new PrincipalArgumentResolver()); if (getCustomArgumentResolvers() != null) { resolvers.addAll(getCustomArgumentResolvers()); resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true)); resolvers.add(new ModelAttributeMethodArgumentResolver(getReactiveAdapterRegistry(), true)); return resolvers;
@Test public void requestMappingHandlerAdapter() throws Exception { delegatingConfig.setConfigurers(Collections.singletonList(webFluxConfigurer)); ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) this.delegatingConfig.requestMappingHandlerAdapter().getWebBindingInitializer(); verify(webFluxConfigurer).configureHttpMessageCodecs(codecsConfigurer.capture()); verify(webFluxConfigurer).getValidator(); verify(webFluxConfigurer).getMessageCodesResolver(); verify(webFluxConfigurer).addFormatters(formatterRegistry.capture()); verify(webFluxConfigurer).configureArgumentResolvers(any()); assertNotNull(initializer); assertTrue(initializer.getValidator() instanceof LocalValidatorFactoryBean); assertSame(formatterRegistry.getValue(), initializer.getConversionService()); assertEquals(13, codecsConfigurer.getValue().getReaders().size()); }
@Override public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) { HandlerMethod handlerMethod = (HandlerMethod) handler; InvocableHandlerMethod invocable = new InvocableHandlerMethod(handlerMethod); invocable.setArgumentResolvers(getArgumentResolvers()); Mono<BindingContext> bindingContextMono = this.bindingContextFactory.createBindingContext(handlerMethod, exchange); return bindingContextMono.then(bindingContext -> invocable.invoke(exchange, bindingContext) .doOnNext(result -> result.setExceptionHandler( ex -> handleException(ex, handlerMethod, bindingContext, exchange))) .otherwise(ex -> handleException( ex, handlerMethod, bindingContext, exchange))); }
@Test public void customMessageConverterConfig() throws Exception { ApplicationContext context = loadConfig(CustomMessageConverterConfig.class); String name = "requestMappingHandlerAdapter"; RequestMappingHandlerAdapter adapter = context.getBean(name, RequestMappingHandlerAdapter.class); assertNotNull(adapter); List<HttpMessageReader<?>> messageReaders = adapter.getMessageReaders(); assertEquals(2, messageReaders.size()); assertHasMessageReader(messageReaders, forClass(String.class), TEXT_PLAIN); assertHasMessageReader(messageReaders, forClass(TestBean.class), APPLICATION_XML); }
private Mono<HandlerResult> handleException(Throwable ex, HandlerMethod handlerMethod, BindingContext bindingContext, ServerWebExchange exchange) { InvocableHandlerMethod invocable = findExceptionHandler(handlerMethod, ex); if (invocable != null) { try { if (logger.isDebugEnabled()) { logger.debug("Invoking @ExceptionHandler method: " + invocable.getMethod()); } invocable.setArgumentResolvers(getArgumentResolvers()); bindingContext.getModel().asMap().clear(); return invocable.invoke(exchange, bindingContext, ex); } catch (Throwable invocationEx) { if (logger.isWarnEnabled()) { logger.warn("Failed to invoke @ExceptionHandler method: " + invocable.getMethod(), invocationEx); } } } return Mono.error(ex); }
@Bean public RequestMappingHandlerAdapter handlerAdapter() { return new RequestMappingHandlerAdapter(); }
private WebBindingInitializer getBindingInitializer() { return getAdapter().getWebBindingInitializer(); }
/** * Override to plug a sub-class of {@link RequestMappingHandlerAdapter}. */ protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() { return new RequestMappingHandlerAdapter(); }