Alexander
Alexander

Reputation: 171

Spring data. Sort using snake case parameter

Could you tell me how to pass sort param to rest controller in snake_case format?

My entity class

@Entity
public class MyEntity extends BaseEntity{

  @Id
  private Long id;

  @Column
  private Long parentId;
}

Controller method

@GetMapping("list")
    List<MyEntity> getEntityList(
           @PageableDefault(sort = {"id"}, direction = Sort.Direction.DESC) Pageable pageable);
}

In request i want to use ?sort=parent_id

I've created Jackson2ObjectMapperBuilder and it builds correct snake_case json

But spring send me Caused by: org.springframework.data.mapping.PropertyReferenceException: No property parent found for type MyEntity! Did you mean 'parentId'? I think this is issue about parsing because spring cut everything after '_' symbol.

I've tried:

Upvotes: 3

Views: 919

Answers (1)

Alexander
Alexander

Reputation: 171

I solved the problem. For correct working with snake_case parameter values we need to create custom OncePerRequestFilter. This filter prepare params before passing to controller.

User nullptr used same way here. By the way, using filter you can prepare any other params/values but this solution may produce mistakes. All requests will go through the filter.

@Configuration
public class SnakeCaseFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        final Map<String, String[]> formattedParams = new ConcurrentHashMap<>();

        //Convert values for each parameter
        for (String param : request.getParameterMap().keySet()) {
            String[] values = request.getParameterValues(param);

            String formattedParam = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, param);

        formattedParams.put(formattedParam, values);
        }

        filterChain.doFilter(new CustomResponseWrapper(request, formattedParams), response);

    }


    /**
     * Wrapper return new formatted parameters
     */
     class CustomResponseWrapper extends HttpServletRequestWrapper {

        /**
         * Constructs a request object wrapping the given request.
         *
         * @param request the {@link HttpServletRequest} to be wrapped.
         * @throws IllegalArgumentException if the request is null
         */

        private Map<String, String[]> params;

        public CustomResponseWrapper(HttpServletRequest request, Map<String, String[]> params) {
            super(request);
            this.params = params;
        }

        @Override
        public Map<String, String[]> getParameterMap() {
            return params;
        }

        @Override
        public String[] getParameterValues(String name) {
            return params.get(name);
        }

    }
}

Upvotes: 1

Related Questions