Skip to content

Instantly share code, notes, and snippets.

@ghahramani
Created June 6, 2018 22:13
Show Gist options
  • Save ghahramani/12694474d300b72bb5c7f8bd6e61beb8 to your computer and use it in GitHub Desktop.
Save ghahramani/12694474d300b72bb5c7f8bd6e61beb8 to your computer and use it in GitHub Desktop.
Support Pageable and Sort type in Webflux
package com.navid.webflux.serializer
import org.springframework.core.MethodParameter
import org.springframework.core.ReactiveAdapterRegistry
import org.springframework.data.web.PageableHandlerMethodArgumentResolver
import org.springframework.stereotype.Component
import org.springframework.util.MultiValueMap
import org.springframework.web.context.request.NativeWebRequest
import org.springframework.web.reactive.BindingContext
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono
import java.security.Principal
import java.util.*
/**
* Developed by Navid Ghahremani (ghahramani.navid@gmail.com)
**/
//TODO: Feel free to give me hint to imporve this file
@Component
class PageableResolver(registry: ReactiveAdapterRegistry, private val resolver: PageableHandlerMethodArgumentResolver) : HandlerMethodArgumentResolverSupport(registry) {
override fun resolveArgument(parameter: MethodParameter, bindingContext: BindingContext, exchange: ServerWebExchange): Mono<Any> {
return Mono.just(resolver.resolveArgument(parameter, null, MockNative(exchange.request.queryParams), null))
}
override fun supportsParameter(parameter: MethodParameter): Boolean {
return this.resolver.supportsParameter(parameter)
}
private class MockNative(private val parameters: MultiValueMap<String, String>) : NativeWebRequest {
override fun getParameter(paramName: String): String? {
return this.parameters.getFirst(paramName)
}
override fun getParameterValues(paramName: String): Array<String>? {
return this.parameters[paramName]?.toTypedArray()
}
override fun isUserInRole(role: String): Boolean {
return false
}
override fun getRemoteUser(): String? {
return null
}
override fun getLocale(): Locale {
return Locale.getDefault()
}
override fun getParameterMap(): MutableMap<String, Array<String>> {
return mutableMapOf()
}
override fun getSessionId(): String {
return ""
}
override fun getAttributeNames(scope: Int): Array<String> {
return arrayOf()
}
override fun registerDestructionCallback(name: String, callback: Runnable, scope: Int) {
}
override fun resolveReference(key: String): Any? {
return null
}
override fun getHeaderValues(headerName: String): Array<String>? {
return null
}
override fun getUserPrincipal(): Principal? {
return null
}
override fun getDescription(includeClientInfo: Boolean): String {
return ""
}
override fun getSessionMutex(): Any {
return ""
}
override fun getNativeResponse(): Any? {
return null
}
override fun <T : Any?> getNativeResponse(requiredType: Class<T>?): T? {
return null
}
override fun getParameterNames(): MutableIterator<String> {
return mutableListOf<String>().iterator()
}
override fun getNativeRequest(): Any {
return ""
}
override fun <T : Any?> getNativeRequest(requiredType: Class<T>?): T? {
return null
}
override fun removeAttribute(name: String, scope: Int) {
}
override fun getHeader(headerName: String): String? {
return null
}
override fun getContextPath(): String {
return ""
}
override fun checkNotModified(lastModifiedTimestamp: Long): Boolean {
return false
}
override fun checkNotModified(etag: String): Boolean {
return false
}
override fun checkNotModified(etag: String?, lastModifiedTimestamp: Long): Boolean {
return false
}
override fun getHeaderNames(): MutableIterator<String> {
return mutableListOf<String>().iterator()
}
override fun getAttribute(name: String, scope: Int): Any? {
return null
}
override fun setAttribute(name: String, value: Any, scope: Int) {
}
override fun isSecure(): Boolean {
return false
}
}
}
package com.navid.webflux.serializer
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.ReactiveAdapterRegistry
import org.springframework.data.domain.PageRequest
import org.springframework.data.web.PageableHandlerMethodArgumentResolver
import org.springframework.data.web.SortHandlerMethodArgumentResolver
import org.springframework.data.web.config.PageableHandlerMethodArgumentResolverCustomizer
import org.springframework.data.web.config.SortHandlerMethodArgumentResolverCustomizer
import java.util.*
/**
* Developed by Navid Ghahremani (ghahramani.navid@gmail.com)
**/
@Configuration
class PageableSerializer {
@Bean
@ConditionalOnMissingBean
fun pageableCustomizer(properties: SpringDataWebProperties): PageableHandlerMethodArgumentResolverCustomizer {
return PageableHandlerMethodArgumentResolverCustomizer { resolver ->
val pageable = properties.pageable
resolver.setPageParameterName(pageable.pageParameter)
resolver.setSizeParameterName(pageable.sizeParameter)
resolver.setOneIndexedParameters(pageable.isOneIndexedParameters)
resolver.setPrefix(pageable.prefix)
resolver.setQualifierDelimiter(pageable.qualifierDelimiter)
resolver.setFallbackPageable(PageRequest.of(0, pageable.defaultPageSize))
resolver.setMaxPageSize(pageable.maxPageSize)
}
}
@Bean
@ConditionalOnMissingBean
fun sortCustomizer(properties: SpringDataWebProperties): SortHandlerMethodArgumentResolverCustomizer {
return SortHandlerMethodArgumentResolverCustomizer { resolver ->
resolver.setSortParameter(properties.sort.sortParameter)
}
}
@Bean
fun pageableHandler(pageableResolver: Optional<PageableHandlerMethodArgumentResolverCustomizer>, sortHandler: SortHandlerMethodArgumentResolver, reactiveAdapterRegistry: ReactiveAdapterRegistry): PageableHandlerMethodArgumentResolver {
val handler = PageableHandlerMethodArgumentResolver(sortHandler)
pageableResolver.ifPresent { c -> c.customize(handler) }
return handler
}
@Bean
fun sortHandler(sortResolver: Optional<SortHandlerMethodArgumentResolverCustomizer>): SortHandlerMethodArgumentResolver {
val handler = SortHandlerMethodArgumentResolver()
sortResolver.ifPresent { c -> c.customize(handler) }
return handler
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment