Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
S

specification-arg-resolver

> 编程语言
Open source

An alternative API for filtering data with Spring MVC & Spring Data JPA

698 stars0 likes1 views
WebsiteGitHub

About

An alternative API for filtering data with Spring MVC & Spring Data JPA

specification-arg-resolver

An alternative API for filtering data with Spring MVC & Spring Data JPA.

A thorough introduction and the original rationale behind this component can be found my blog: http://blog.kaczmarzyk.net/2014/03/23/alternative-api-for-filtering-data-with-spring-mvc-and-spring-data/. In this file you can find a summary of all the current features and some API examples.

You can also take a look on working Spring Boot apps that use this library:

  • for Spring Boot 3: https://github.com/tratif/specification-arg-resolver-example-springboot3
    • this includes demonstration of Native Images for GraalVM
  • for Spring Boot 2: https://github.com/tkaczmarzyk/specification-arg-resolver-example.

Table of contents

  • Basic usage -- quick start with the lib
    • Enabling spec annotations in your Spring app
  • Simple specifications -- basic specs, such as Equal, Like, GreaterThan etc.
  • Combining specs
    • @And -- combining simple specs with and keyword
    • @Or -- combining simple specs with or keyword
    • Nested conjunctions and disjunctions
  • Join -- filtering by attributes of joined entities
  • Join fetch -- initializing lazy associations
  • Advanced HTTP parameter handling
    • Handling non-present HTTP parameters
    • Mapping HTTP parameter name to property path of an entity
  • Static parts of queries -- adding static (not bound to HTTP params) predicates such as deleted = false
  • Default value of queries -- providing a fallback value when HTTP parameter is not present
  • Annotated specification interfaces -- resolving specifications from annotated interfaces
    • Interface inheritance tree
  • Handling different field types -- handling situations when provided parameter is of different type than the field (e.g. "abc" sent against an integer field)
  • Path Variable support -- using uri fragments (resolvable with Spring's @PathVariable annotation) in specifications
  • Json Request Body support -- using json in request body to get parameters for specification
  • Type conversions for HTTP parameters -- information about supported type conversions (i.e. ability to convert HTTP parameters into Java types such as LocalDateTime, etc.) and the support of defining custom converters
  • Case insensitivity support -- information about case-insensitive strategies used for case-insensitive specifications
  • Locale support -- information about Locale configuration for case-insensitive matching
  • Character escaping support -- information about escaping special characters in LIKE-based specifications
  • SpEL support -- information about Spring Expression Language support
  • Swagger support -- information about support for generation of swagger documentation
  • Building specifications outside the web layer
  • Compatibility notes -- information about older versions compatible with previous Spring Boot and Java versions
  • Download binary releases -- Maven artifact locations

Basic usage

The following HTTP request:

GET http://myhost/api/customers?firstName=Homer

can be handled with the following controller method:

java

@RequestMapping(value = "/customers", params = "firstName")
public Iterable findByFirstName(  
      @Spec(path = "firstName", spec = Like.class) Specification spec) {

    return customerRepo.findAll(spec);
}

which will result in the following JPA query:

sql
select c from Customer c where c.firstName like '%Homer%'

Alternatively you can annotate an interface:

java
  @Spec(path="firstName", params="name", spec=Like.class)
  public interface NameSpec extends Specification {
  }

and then use it as a controller parameter without any further annotations.

Enabling spec annotations in your Spring app

All you need to do is to wire SpecificationArgumentResolver into your application. Then you can use @Spec and other annotations in your controllers. SpecificationArgumentResolver implements Spring's HandlerMethodArgumentResolver and can be plugged in as follows:

java

@Configuration
@EnableJpaRepositories
public class MyConfig implements WebMvcConfigurer {

    @Override
    public void addArgumentResolvers(List argumentResolvers) {
        argumentResolvers.add(new SpecificationArgumentResolver());
    }

    ...
}

The library converts HTTP parameters (strings) into most popular Java types such as dates, numbers, and enums. In case of a need for some additional conversion, please see how to configure specification argument resolver with If you need to use additional converters please see custom converters section.

Simple specifications

Use @Spec annotation to automatically resolve a Specification argument of your controller method. @Spec has path property that should be used to specify property path of the attribute of an entity, e.g. address.city. By default it's also the name of the expected HTTP parameter, e.g. GET http://myhost?address.city=Springfield.

Use spec attribute of the annotation to specify one of the filtering strategies listed in the subsections below (e.g. Like, Equal, In)

For multi value filters like: In.class, NotIn.class there are two ways of passing multiple arguments. The first way is passing the same HTTP parameter multiple times as follows:

GET http://myhost/customers?gender=MALE&gender=FEMALE

The second way is the use paramSeparator attribute of @Spec, which determines the argument separator (can be specified only for query parameters). For example the following controller method:

java
@RequestMapping(value = "/customers", params = "genderIn")
@ResponseBody
public Object findCustomersByGender(
	@Spec(path = "gender", params = "genderIn", paramSeparator = ",", spec = In.class) Specification spec) {
	return customerRepo.findAll(spec);
}

will handle GET http://myhost/customers?gender=MALE,FEMALE in exactly the same way as GET http://myhost/customers?gender=MALE&gender=FEMALE (as one parameter with two values ["MALE","FEMALE"]). Without specifying paramSeparator param gender=MALE,FEMALE will be processed as single value: ["MALE,FEMALE"].

Like

Filters using JPAQL like expression. It adds a wildcard % at the beginning and the end of the actual value, e.g. (..) where firstName like %Homer%.

Usage: @Spec(path="firstName", spec=Like.class).

There are also other variants which apply the wildcard only on the beginning or the ending of the provided value: StartingWith and EndingWith.

The negated version is available: NotLike which executes queries such as (..) where firstName not like %Homer%.

All Like-based specifications support character escaping.

LikeIgnoreCase

Works as Like, but the query is also case-insensitive.

Usage: @Spec(path="firstName", spec=LikeIgnoreCase.class).

There are also other variants which apply the wildcard only on the beginning or the ending of the provided value: StartingWithIgnoreCase and EndingWithIgnoreCase.

Case-insensitive comparisons are performed using the database's UPPER() function on both sides of the comparison. The results depend on your database's collation settings. Locale settings is important for case-insensitive searches. Please check the Locale support section for details.

A negation for this specification is also available: NotLikeIgnoreCase.

All Like-based specifications support character escaping.

Equal

Compares an attribute of an entity with the value of a HTTP parameter (exact match). E.g. (..) where gender = FEMALE.

Supports multiple data types: numbers, booleans, strings, dates, enums.

Usage: @Spec(path="gender", spec=Equal.class).

The default date format used for temporal fields is yyyy-MM-dd. It can be overriden with a configuration parameter (see LessThan below). If for date-time formats which store also time (LocalDateTime, OffsetDateTime, Instant, etc.) only the date is provided, then the default time value (midnight - UTC time for OffsetDateTime) will be used for checking equality. To include all results within particular date (day) use EqualDay specification.

A negation for this specification is also available: NotEqual.

EqualIgnoreCase

Works as Equal, but the query is also case-insensitive, could be used for fields of type: String, Enum.

Case-insensitive comparisons are performed using the database's UPPER() function on both sides of the comparison. The results depend on your database's collation settings. Locale settings is important for case-insensitive searches. Please check the Locale support section for details.

A negation for this specification is also available: NotEqualIgnoreCase.

In

Compares an attribute of an entity with multiple values of a HTTP parameter. E.g. (..) where gender in (MALE, FEMALE).

Supports multiple data types: numbers, booleans, strings, dates, enums.

Usage: @Spec(path="gender", spec=In.class).

HTTP request example:

GET http://myhost/customers?gender=MALE&gender=FEMALE

or if paramSeparator is specified (eg. @Spec(path="gender", paramSeparator=",", spec=In.class)):

GET http://myhost/customers?gender=MALE,FEMALE

The default date format used for temporal fields is yyyy-MM-dd. It can be overridden with a configuration parameter (see LessThan below).

A negation for this specification is also available: NotIn.

InIgnoreCase

Works as In, but the query is also case-insensitive.

Usage: @Spec(path="firstName", spec=InIgnoreCase.class).

Case-insensitive comparisons are performed using the database's UPPER() function on both sides of the comparison. The results depend on your database's collation settings. Locale settings is important for case-insensitive searches. Please check the Locale support section for details.

A negation for this specification is also available: NotInIgnoreCase.

Null

Filters using is null or is not null, depending on the value of the parameter passed in. A value of true will filter for is null, and a value of false will filter for is not null.

The data type of the field specified in path can be anything, but the HTTP parameter must be a Boolean. You should use params attribute to make it clear that the parameter is filtering for null values.

Usage: @Spec(path="activationDate", params="activationDateNull" spec=Null.class).

If you want the query to be static, i.e. not depend on any HTTP param, you can use IsNull or IsNotNull specifications. Alternatively, you can use Null with constVal attribute of Spec annotation:

For example @Spec(path="nickname", spec=Null.class, constVal="true") will always add nickname is null to the query.

NotNull

An inversion of Null d

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Java

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言