Este documento continua relevante para a auto-configuração viva do starter, mas mistura exemplos do baseline atual com referências de compatibilidade do core legado.
Leia assim:
resource + surfaces + actions + capabilitiesAbstractCrudController são históricos ou
de compatibilidadeREADME.md, docs/index.md e
docs/architecture-overview.mdO OpenApiUiSchemaAutoConfiguration é o
“bootstrap” de todo o sistema Praxis UI Schema,
implementando o padrão “Convention over Configuration”
do Spring Boot para que desenvolvedores apenas adicionem a dependência e
todo o sistema fique automaticamente disponível.
Objetivo prático da auto-configuração: 1. adicionar a dependência no
pom.xml 2. expor controllers compatíveis com o baseline
atual do starter 3. deixar discovery, docs filtrados e infraestrutura
interna disponíveis sem boilerplate manual
| Propriedade | Padrão | Descrição |
|---|---|---|
praxis.query.by-ids.max |
200 |
Limite de IDs aceitos pelo endpoint
GET /{resource}/by-ids. Ajuda a evitar consultas excessivas
em ambientes corporativos. |
praxis.pagination.max-size |
200 |
Tamanho máximo de página aceito pelos endpoints paginados
(/filter e /options/filter). Evita requisições
muito grandes que possam degradar o sistema. |
app.openapi.internal-base-url |
vazio | Origem interna explícita para consultas server-side ao SpringDoc
(/v3/api-docs). Útil quando a URL pública difere da URL
acessível pelo processo da aplicação. |
O sistema Praxis possui duas auto-configurações que trabalham em conjunto:
| Auto-Configuração | Responsabilidade | Execução |
|---|---|---|
| PraxisMetadataAutoConfiguration | 🏗️ Infraestrutura base + Component Scan | 1º - Fundação |
| OpenApiUiSchemaAutoConfiguration | 🎨 Beans funcionais do UI Schema | 2º - Funcionalidade |
openApiUiSchemaRestTemplate)openApiUiSchemaObjectMapper)<E>),
funciona com qualquer entidade/filter dos
AbstractCrudController/schemas/filtered com resolução
automática de gruposx-ui.resource, também pode publicar
x-ui.operationExamples.<schemaType> quando a operação
OpenAPI tiver exemplos declarados/schemas/catalog com suporte à
mesma resolução de base interna do ApiDocsControllergraph TD
A[Spring Boot Startup] --> B[Detecta @AutoConfiguration]
B --> C[OpenApiUiSchemaAutoConfiguration]
C --> D[Registra 6 Beans]
D --> E[DynamicSwaggerConfig usa beans]
E --> F[Cria GroupedOpenApi dinamicamente]
F --> G[OpenApiGroupResolver recebe grupos via DI]
G --> H[ApiDocsController pronto para uso]
H --> I[Sistema funcional]
┌─────────────────────────────────────────────┐
│ PraxisMetadataAutoConfiguration │
│ 🏗️ Infraestrutura + Component Scan │
└─────────────────┬───────────────────────────┘
│ @ComponentScan detecta
▼
┌─────────────────────────────────────────────┐
│ 🔢 BigDecimal Customizer │
│ 🏗️ Grupo "praxis-metadata-infra" │
│ 🌐 Grupo "application" (fallback) │
│ 📦 @ComponentScan packages │
└─────────────────┬───────────────────────────┘
│ + registra beans específicos
▼
┌─────────────────────────────────────────────┐
│ OpenApiUiSchemaAutoConfiguration │
│ 🎨 Beans funcionais do UI Schema │
└─────────────────┬───────────────────────────┘
│ registra beans
▼
┌─────────────────────────────────────────────┐
│ 📡 RestTemplate (HTTP interno) │
│ 📝 ObjectMapper (JSON + JavaTime) │
│ 🔍 CustomOpenApiResolver (schemas + UI) │
│ 📋 GenericSpecificationsBuilder (filtros) │
│ 🎯 OpenApiGroupResolver (resolução grupos) │
│ 🌐 ApiDocsController (endpoints REST) │
└─────────────────┬───────────────────────────┘
│ componentes detectados + beans injetados
▼
┌─────────────────────────────────────────────┐
│ DynamicSwaggerConfig │
│ AbstractCrudController │
│ PraxisMetadataProvider │
│ Outros componentes detectados │
└─────────────────────────────────────────────┘
<!-- Apenas isso no pom.xml: -->
<dependency>
<groupId>io.github.codexrodrigues</groupId>
<artifactId>praxis-metadata-starter</artifactId>
</dependency>// Sem necessidade de configurar beans manualmente:
@Configuration
public class MyConfig {
// ❌ NÃO precisa disso:
// @Bean public RestTemplate restTemplate() { ... }
// @Bean public ObjectMapper objectMapper() { ... }
// @Bean public OpenApiGroupResolver resolver() { ... }
}
// ✅ Apenas use diretamente:
@ApiResource(ApiPaths.FUNCIONARIOS)
public class FuncionarioController extends AbstractCrudController<...> {
// Tudo funciona automaticamente!
}@ConditionalOnMissingBean para respeitar
configurações customizadas@Primary se necessárioPor padrão, os controllers internos de documentação tentam inferir a
base atual da aplicação com ServletUriComponentsBuilder.
Isso funciona bem quando a origem externa e a origem interna são
equivalentes, mas pode falhar em topologias com proxy reverso.
Para eliminar ambiguidade, defina:
app.openapi.internal-base-url=http://localhost:4003
Ou via ambiente:
APP_OPENAPI_INTERNAL_BASE_URL=http://localhost:4003Fluxo de resolução: 1. Se app.openapi.internal-base-url
estiver preenchida, ela é usada como base. 2. Caso contrário, a base é
inferida do contexto HTTP atual. 3. Em seguida, o starter concatena
springdoc.api-docs.path e, quando aplicável, o nome do
grupo OpenAPI.
Quando configurar explicitamente: - Render ou outras plataformas
PaaS. - Docker Compose com porta pública diferente da porta interna. -
Kubernetes com ingress/gateway. - Ambientes onde
X-Forwarded-Host e a origem interna não representam o mesmo
endpoint acessível pelo backend.
Exemplo final de URL construída:
http://localhost:4003/v3/api-docs
http://localhost:4003/v3/api-docs/api-human-resources-funcionarios
@Configuration
public class MyCustomConfig {
@Bean
@Primary // substitui o bean padrão
public ObjectMapper myObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// suas customizações específicas...
return mapper;
}
}@Bean
@Primary
public RestTemplate myRestTemplate() {
RestTemplate template = new RestTemplate();
// Configurar timeouts:
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(5000);
factory.setReadTimeout(10000);
template.setRequestFactory(factory);
return template;
}org.praxisplatform.uischema.configuration.OpenApiUiSchemaAutoConfiguration
org.praxisplatform.uischema.configuration.PraxisMetadataAutoConfiguration
# Verificar se a auto-configuração está sendo detectada:
--debug
# Buscar logs:
[INFO] OpenApiUiSchemaAutoConfiguration matched:
- @ConditionalOnMissingBean (types: org.springframework.web.client.RestTemplate)// Se houver conflito, usar @Qualifier:
@Autowired
@Qualifier("openApiUiSchemaRestTemplate")
private RestTemplate restTemplate;// No DynamicSwaggerConfig, os logs mostrarão:
[INFO] Bean GroupedOpenApi registrado: bean=funcionarios_ApiGroup, group=funcionarios, paths=/api/funcionarios/**/v3/api-docsSintomas comuns: - erro ao montar URL como
https://localhost:4003/v3/api-docs - falhas intermitentes
apenas em produção - /schemas/filtered ou
/schemas/catalog funcionando localmente, mas quebrando
atrás de proxy
Causa típica: - a aplicação inferiu a base a partir da requisição externa, mas o processo Java precisa acessar outra origem internamente
Correção: - configure app.openapi.internal-base-url para
a origem interna real do serviço - mantenha
springdoc.api-docs.path coerente com a rota publicada pelo
SpringDoc
Verificação: - a partir do ambiente da app, confirme que a URL final responde com o documento OpenAPI esperado
// 1. PraxisMetadataAutoConfiguration detecta via @ComponentScan:
@Configuration // ← Detectado pelo component scan
public class DynamicSwaggerConfig {
// 2. OpenApiUiSchemaAutoConfiguration fornece via DI:
@Autowired
private OpenApiGroupResolver resolver; // ← Injetado automaticamente
}