Pular para o conteúdo principal

archbase-query

O módulo archbase-query fornece suporte a RSQL para criar queries dinâmicas e flexíveis via REST API.

Biblioteca Base

Este módulo é baseado no projeto rsql-jpa-specification do PerplexHub.

Instalação

<dependency>
<groupId>br.com.archbase</groupId>
<artifactId>archbase-query</artifactId>
<version>${archbase.version}</version>
</dependency>

Configuração

archbase:
rsql:
enabled: true
case-insensitive: true
page:
parameter: page
size:
parameter: size
max: 100
default: 20

O Que é RSQL?

RSQL (RESTful Service Query Language) é uma linguagem de query para parâmetros de URLs, baseada em FIQL (Feed Item Query Language).

Operadores Suportados

Operadores de Comparação

OperadorDescriçãoExemplo
==Igual astatus==NOVO
!=Diferente destatus!=CANCELADO
>=Maior ou igual adataCriacao>=2024-01-01
<=Menor ou igual aprioridade<=3
>Maior quepontuacao>50
<Menor queidade<18

Operadores de Lista

OperadorDescriçãoExemplo
=in=Está na listastatus=in=(NOVO,EM_ATENDIMENTO)
=out=Não está na listadepartamento=out=(DEPTO1)

Operadores Lógicos

OperadorDescriçãoExemplo
;E (AND)status==NOVO;prioridade==ALTA
,OU (OR)status==NOVO,status==EM_ANALISE

Operadores com Wildcards

OperadorDescriçãoExemplo
*valor*Contémdescricao==*problema*
valor*Começa comnome==Jo*
*valorTermina comemail==*@gmail.com

Implementação

Controller com RSQL

@RestController
@RequestMapping("/api/produtos")
public class ProdutoController {

private final ProdutoRepository repository;

@GetMapping
public Page<Produto> buscar(
@RequestParam(required = false) String query,
Pageable pageable) {

ArchbaseSpecification<Produto> spec = Specification.where(null);

if (query != null) {
spec = ArchbaseRSQLJPASupport.toSpecification(
query, Produto.class
);
}

return repository.findAll(spec, pageable);
}
}

Exemplos de Requisições HTTP

Filtro Simples

# Status igual a NOVO
GET /api/v1/tickets?filter=status==NOVO&page=0&size=20

# Data maior ou igual a
GET /api/v1/tickets?filter=dataAbertura>=2024-01-01&page=0&size=20

Múltiplos Filtros (AND)

# Status NOVO E prioridade ALTA
GET /api/v1/tickets?filter=status==NOVO;prioridade==ALTA&page=0&size=20

Múltiplos Filtros (OR)

# Status NOVO OU EM_ANALISE
GET /api/v1/tickets?filter=status==NOVO,status==EM_ANALISE&page=0&size=20

Lista de Valores (IN)

# Status na lista
GET /api/v1/tickets?filter=status=in=(NOVO,EM_ATENDIMENTO,RESOLVIDO)&page=0&size=20

# Departamentos na lista
GET /api/v1/tickets?filter=departamento=in=(DEPTO1,DEPTO2,DEPTO3)&page=0&size=20

Busca de Texto (Wildcard)

# Descrição contém "problema"
GET /api/v1/tickets?filter=descricao==*problema*&page=0&size=20

# E-mail termina com @gmail.com
GET /api/v1/tickets?filter=emailCliente==*@gmail.com&page=0&size=20

# Nome começa com "João"
GET /api/v1/clientes?filter=nome==João*&page=0&size=20

Com Ordenação

# Ordenar por data descendente
GET /api/v1/tickets?filter=status==NOVO&page=0&size=20&sort=dataAbertura,desc

# Ordenação múltipla
GET /api/v1/tickets?page=0&size=20&sort=prioridade,desc&sort=dataAbertura,asc

Datas e Períodos

# Criado após uma data
GET /api/v1/pedidos?filter=dataCriacao>=2024-01-01&page=0&size=20

# Criado em um período (AND)
GET /api/v1/pedidos?filter=dataCriacao>=2024-01-01;dataCriacao<=2024-12-31&page=0&size=20

Row-Level Security

O módulo suporta filtros automáticos por tenant:

@GetMapping
public Page<Produto> buscar(
@RequestParam(required = false) String query,
Pageable pageable) {

ArchbaseSpecification<Produto> spec =
ArchbaseRSQLJPASupport.toSpecification(query, Produto.class);

// Filtro de tenant aplicado automaticamente
return repository.findAll(spec, pageable);
}

Paginação

# Primeira página
GET /api/produtos?page=0&size=20

# Segunda página
GET /api/produtos?page=1&size=20

# Ordenação
GET /api/produtos?sort=nome,asc&sort=preco,desc

Validação de RSQL

Limitar Campos Permitidos

@Component
public class RSQLValidator {

private static final Set<String> CAMPOS_PERMITIDOS = Set.of(
"nome", "preco", "categoria", "estoque"
);

public void validate(String query) {
// Extrair campos da query
// Validar se estão em CAMPOS_PERMITIDOS
// Lançar exceção se inválido
}
}

Proteção contra Injeção

O framework sanitiza automaticamente queries RSQL para prevenir injeção de SQL.

Solução de Problemas

Parse Error

Erro: Could not parse query

Solução: Verifique a sintaxe RSQL

❌ nome=Notebook (deve ser == para string exata)
✅ nome=='Notebook'

Campo Não Encontrado

Erro: No property 'nomme' found for type 'Produto'

Solução: Verifique o nome do campo

❌ nomme=='Notebook'
✅ nome=='Notebook'

Próximos Passos