Changelog - Cloudsupport

Versão 1.19.0

  • Webservices:
    • Agora aceita quantidade arbitrária de subpacotes em services.web.
    • As tags no Swagger (que representam grupos de endpoints) são mapeadas conforme o exemplo:

      services.web.moduleName.group.subgroup.feature.v1 -> ModuleName - Group - Subgroup

Versão 1.18.0

  • Persistência:
    • O Hibernate Interceptor registrado agora é uma cadeia (Composite Interceptor): se a aplicação precisar configurar um interceptor customizado, basta definir um bean que implemente a interface Interceptor do Hibernate. A biblioteca Cloudsupport o registrará automaticamente na cadeia, respeitando a ordenação de beans do Spring (@Order).
    • O interceptor TxGuard oferecido pela biblioteca Cloudsupport agora está funcionando corretamente: Ele protege o código-fonte impedindo operações de escrita JPA fora do escopo transacional ou dentro de transações somente-leitura.
    • O TxGuard pode ser configurado via cloudsupport.transaction.guard com os valores: off, warn ou error (padrão).
    • Testes Spring:

      Código base:

      public void handle() {
           Entity entity = em().find(/*...*/);
           entity.setField("new value");
           em().merge(entity);
           em().flush();
      }
      

      Cenários:

      “No tran” - Sem transação
      “Jakarta” - Método anotado com Jakarta @Transactional
      “Spring” - Método anotado com Spring @Transactional
      “Read only” - Método anotado com Spring @Transactional(readOnly=true)

      open-in-view Cenário Resultado do código
      (any) No tran Spring lança “No EntityManager with actual transaction” no merge().
      (any) Jakarta O BD é atualizado, como esperado.
      (any) Spring O BD é atualizado, como esperado.
      false Read only flush() silenciosamente não faz nada, sem erro. (*1)
      true Read only flush() tenta atualizar o BD, mas o TxGuard protege o código. (*1)

      (*1) Observe que o dirty checking do Hibernate é confuso: O comportamento depende de o EntityManager (session) já existir antes do escopo transacional.

  • Actuator:
    • Adicionado java.version ao endpoint Info
  • Segurança:
    • Método getSemanticLogginInCoreAttrs de SecurityUtils renomeado para getLoggedInCoreAttrs
  • Logging:
    • Para uma saída de log limpa em produção, recomendamos configurar o nível root como WARN e o pacote cloudsupport como INFO. São impressos apenas logs essenciais de inicialização e eventos gerais do ciclo de vida da aplicação (“loading”, “warming up”, “ready” e “failed”).
  • Inicialização:
    • As mensagens de log foram completamente reescritas com um novo layout
    • O banner Cloudsupport é impresso no evento ready, com informações de resumo do contexto
    • O resumo do contexto agora inclui a versão do Java e os perfis ativos do Spring Boot
  • Profile:
    • Os perfis Spring Boot cloudsupport e cloudsupport-defaults foram removidos
    • Propriedades padrão são ativadas por @EnableCloudsupport (ver abaixo)
    • Incluído logging.level.org.springdoc.core.events.SpringDocAppInitializer=error para remover warnings ruidosos quando endpoints OpenAPI são ativados. Os warnings são desnecessários, pois o padrão é false desde o springdoc-openapi v2.8.14:
      • “WARN SpringDocAppInitializer : SpringDoc /v3/api-docs endpoint is enabled by default”
      • “WARN SpringDocAppInitializer : SpringDoc /swagger-ui endpoint is enabled by default”
    • Removido logging.level.cloudsupport=info, pois o nível será herdado da aplicação
    • As propriedades padrão agora são:

      # ----------------------
      # Startup
      # ----------------------
            
      # Hide Spring banner
      spring.main.banner-mode=off
      
      # ----------------------
      # Documentation
      # ----------------------
            
      # Endpoints are disabled by default for security reasons
      springdoc.swagger-ui.enabled=false
      springdoc.api-docs.enabled=false
            
      # Springdoc tag per controller is not friendly to the Feature Service pattern
      springdoc.auto-tag-classes=false
            
      # Default is '/swagger-ui.html', but Swagger redirects to '/swagger-ui'
      springdoc.swagger-ui.path=/swagger-ui
            
      # Collapsed models
      springdoc.swagger-ui.defaultModelsExpandDepth=-1
      springdoc.swagger-ui.defaultModelExpandDepth=2
            
      # ----------------------
      # Actuator
      # ----------------------
            
      # In Kubernetes, probes should reflect the main application (web port, connection pools, framework
      # components), not the management context. To achieve this, it's a good idea to make the liveness and
      # readiness probes available on the main port. Conventional probe paths are "/livez" (liveness) and
      # "/readyz" (readiness). These are auto-activated when a Kubernetes environment is detected (presence
      # of the env vars KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT). You can force-enable them
      # regardless of environment with: "management.endpoint.health.probes.enabled=true".
      # (https://docs.spring.io/spring-boot/reference/actuator/endpoints.html section "Kubernetes Probes")
      management.endpoint.health.probes.add-additional-paths=true
            
      # ----------------------
      # Logging
      # Note: Will take effect if using Spring Boot Log Extensions (eg: log4j2-spring.xml, not log4j2.xml)
      # ----------------------
            
      # Avoids many 'WARN DefaultHandlerExceptionResolver : Resolved'.
      # Spring Boot 'spring.mvc.log-resolved-exception' does not work for all resolvers.
      # (issue https://github.com/spring-projects/spring-boot/issues/29706)
      logging.level.org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver=error
            
      # Avoid the annoying warnings:
      #   'WARN SpringDocAppInitializer: SpringDoc /v3/api-docs endpoint is enabled by default'
      #   'WARN SpringDocAppInitializer: SpringDoc /swagger-ui endpoint is enabled by default'
      # when the endpoints are explicitly enabled in a profile. Cloudsupport changes the default to disabled,
      # so these warnings are unnecessary. The default is false since springdoc-openapi v2.8.14.
      logging.level.org.springdoc.core.events.SpringDocAppInitializer=error
            
      # ----------------------
      # Persistence JPA
      # ----------------------
            
      # Hibernate naming strategy (CamelCase)
      # The default of Spring Boot is 'org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy' (snake_case)
      spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
            
      # Spring MVC defaults to creating a new JPA session per request, which can result in
      # unstable behavior of services due to potential differences in JPA sessions between service flows.
      # It is preferred to synchronize session creation with the @Transactional scope.
      spring.jpa.open-in-view=false
            
      # Format SQL output when SQL logging is enabled
      spring.jpa.properties.hibernate.format_sql=true
      
  • Configuração:
    • Pequenas melhorias de performance
    • Classes internas de configuração reescritas
    • Implementação de @EnableCloudsupport aprimorada
    • NOTA: Planejamos remover a anotação @EnableCloudsupport em futuras versões, pois a biblioteca será autoconfigurada como os starters do Spring Boot.
  • Atualmente, @EnableCloudsupport habilita:
    • Propriedades padrão aprimoradas do Boot:
      Ajuste as propriedades padrão do Spring Boot (veja acima).
    • Acesso estático ao Spring Context:
      Cria o bean SpringContext, que expõe o ApplicationContext de forma estática.
    • Códigos de rastreamento de erros:
      Cria um gerador padrão de código de rastreamento com base na propriedade cloudsupport.error.tracking-generator, caso a aplicação não forneça um. O gerador é usado em todos os módulos para registrar códigos de rastreamento em erros não tratados (webservices, jobs, etc.).
    • Health probe para HA:
      Ativa o endpoint Actuator healthreadiness, permitindo controlar estados REFUSING/ACCEPTING. Útil em cenários de Alta Disponibilidade (por exemplo, parar de receber tráfego antes de um rollout).
    • Anotações customizadas:
      Ativa as anotações @Frament, @Ws, @Job, @Remote, @Schedule.
    • Active Record e API simples de persistência:
      Ativa a API Active Record disponível em BaseEntity e BaseGenericEntity, além de métodos úteis de persistência presentes em BaseService, BaseFragment, BaseComponent e BaseJob. O bean interno PersistenceContext é criado. Consulte a documentação.
    • Auditoria JPA integrada ao JWT:
      Ativa um bean de auditoria do Spring Data que define o usuário (da trilha) a partir de um claim JWT conforme a propriedade cloudsupport.auditing.auditor-jwt-claim.
    • JPA Transaction Guard:
      Ativa um interceptor que protege o código-fonte contra operações JPA de escrita fora do escopo transacional ou dentro de transações read-only. O comportamento é definido pela propriedade cloudsupport.transaction.guard.
    • Cloudsupport Job Engine:
      Ativa o motor de rotinas, criando um bean JobRepository padrão conforme a propriedade cloudsupport.jobs.repository.
    • API de gerenciamento de Jobs:
      Cria o bean JobManager e ativa o endpoint Actuator cloudsupportjobs para gerenciamento remoto das rotinas.
    • WebClient aprimorado para webservices remotos:
      Cria o bean WebClientComponent, que fornece:
      • Uma API simples para executar GET/POST com resolução de rotas via cloudsupport.remotes.route.*.
      • Uma instância authenticatedWebClient que propaga o token OAuth2 e os headers X-Forwarded-For e X-Forwarded-Proto.
    • Resolução de rotas remotas:
      Cria o bean RemoteRouteResolver, que resolve URLs de endpoints com base nas propriedades cloudsupport.remotes.route.*, para uso em beans @Remote e no WebClientComponent. Uma solução simples para evitar URLs hardcoded.
    • Mapeamento de URLs de webservices por convenção:
      Registra um Request Mapping do Spring MVC que configura @Ws conforme as convenções do Cloudsupport (“/featureName.version”). O caminho base é definido por cloudsupport.ws.path-prefix. Veja a documentação.
    • Convenções HTTP para webservices:
      Customiza a saída de erro Whitelabel do Spring Boot conforme as convenções da arquitetura.
      • Erros de validação: HTTP 422 + campo fieldMessages (lista de {field, message}).
      • Erros de BusinessException: HTTP 422 + campo message com a mensagem de negócio.
      • Outros erros de cliente: message atualizado para <SimpleClass>: <message>;
        se for 400 e houver erro em contexto, inclui tracking e registra WARN.
      • Erros de servidor: oculta message por segurança, inclui tracking e registra ERROR.
    • Roles a partir do JWT:
      Registra um processador JWT que carrega authorities do Spring Security a partir do claim JWT definido em cloudsupport.security.jwt.authorities-claim.
    • Bypass de validação de JWT para depuração:
      Registra um decoder JWT que aceita qualquer token quando cloudsupport.security.jwt.always-trust está habilitado. Útil para desenvolvimento local ou testes unitários com JWTs não assinados.
    • Anotações de segurança:
      Ativa as anotações @IsAuthenticated, @HasAuthority, @HasAnyAuthority e o conjunto @LoggedIn* (15 no total).
    • Cadeias de segurança prontas para uso:
      Se cloudsupport.security.allow-paths estiver configurado, cria uma chain do Spring Security que libera acesso a esses caminhos.
      Se cloudsupport.security.scheme=jwt estiver definido, configura o ResourceServer OAuth2 JWT, incluindo hidratação de WebDetails, inserção de atributos JWT no MDC do Log4J, CORS/CSRF autoconfigurados e outros ajustes (ver documentação).
    • Integração da segurança com Swagger:
      Configura o requisito “JWT” no OpenAPI para endpoints @Ws quando o esquema jwt da biblioteca Cloudsupport é utilizado e as operações webservices têm @HasAuthority, @HasAnyAuthority ou @IsAuthenticated.
    • Auto-tagging no Swagger:
      Agrupa automaticamente os endpoints conforme o pacote pai das classes anotadas com @Ws, melhorando a experiência de navegação.
    • Redução de nomes de modelos no Swagger:
      Gera nomes simplificados para modelos, evitando FQNs e prevenindo colisões.
    • Proteção contra exposição de erros pelo container:
      Registra um Servlet Filter global que impede que erros não tratados cheguem ao container, evitando exposição de dados sensíveis. A biblioteca Cloudsupport redireciona esses erros para o Whitelabel do Spring Boot. Esse caso ocorre quando erros surgem antes ou fora dos mecanismos de tratamento de erro do Spring MVC.
    • Log de duração de requisições (debug):
      Registra um Servlet Filter simples para logar duração de requisições em nível DEBUG. Ignora Swagger UI, OpenAI, H2 Console e Actuator.
      Para habilitar: logging.level.cloudsupport.logging.RequestLoggingFilter=debug.
    • Múltiplos interceptadores Hibernate:
      Registra um interceptor composto que implementa uma cadeia de interceptors. Qualquer bean da aplicação que implemente Interceptor será registrado automaticamente, respeitando @Order.
    • Logging de eventos do ciclo de vida da aplicação:
      Ativa listeners que logam (em nível INFO) os principais eventos:
      • ApplicationEnvironmentPrepared (carregando)
      • ApplicationStarted (carregado e aquecendo)
      • ApplicationReady (pronto — imprime banner Cloudsupport e resumo do contexto)
      • ContextClosing (encerrando — imprime na primeira ocorrência)
      • ApplicationFailed (falha de inicialização)
    • Info Contributor para Actuator
      Adiciona informações no endpoint Info do Actuator:
      • cloudsupport.version
      • cloudsupport.jobs.scheduling
      • cloudsupport.jobs.repository
      • cloudsupport.jobs.features
      • cloudsupport.webservices.features
      • springBoot.version
      • hibernate.version
      • java.version
  • Atualização de bibliotecas:
    • bcprov-ext-jdk18on 1.78.1 removida
    • bcprov-jdk18on 1.82 importada transitivamente por bcpkix-jdk18on 1.82
    • jaxb-impl 4.0.2 removida em favor de jaxb-runtime 4.0.6
    • jakarta.xml.bind-api 4.0.2 removida
    • jakarta.xml.bind-api 4.0.4 importada transitivamente por jaxb-runtime 4.0.6
    • jaxb-api 2.3.1 removida (refere-se ao antigo namespace javax.*; não é mais usada pelo jjwt)

Versão 1.17.0

  • Segurança:
    • Propriedade cloudsupport.security.jwt.paths agora suporta o path raiz /.
    • Mantida precedência de cloudsupport.security.allow-paths sobre jwt.paths.
  • Inicialização:
    • Agora emite log com valor padrão das propriedades não declaradas na aplicação

Versão 1.16.0

  • Webservices:
    • Adicionada propriedade cloudsupport.ws.path-prefix para personalizar a URL base para endpoints webservice gerados por classes @Ws. O valor padrão é o pacote pai de services.web.
  • Persistência:
    • Corrigido método findByAttr que não propagava o fetch join para as queries
  • Inicialização:
    • Agora emite log informando se o Swagger UI está ativo ou não
    • Agora emite log informando se o endpoint OpenAPI está ativo ou não
    • Agora emite log da hora corrente, fuso e charset padrão
  • Atualização de bibliotecas:
    • log4j-jdbc-dbcp2 de 2.17.2 para 2.23.3 (Spring Boot 3.5)
    • springdoc-openapi-starter-webmvc-ui de 2.5.0 para 2.8.14
    • jjwt de 0.9.1 para 0.12.7 (CVE fixes)
    • bcpkix-jdk15on 1.70 removida em favor de bcpkix-jdk18on 1.82 (CVE fixes)
    • bcprov-ext-jdk15on 1.70 removida em favor de bcprov-ext-jdk18on 1.78.1 (CVE fixes)
    • log4j-kubernetes (log4j) removida (descontinuada) em favor d kubernetes-log4j (projeto fabric8io) 7.4.0
      Vide: https://github.com/fabric8io/kubernetes-client/blob/main/doc/KubernetesLog4j.md
    • Spring Boot de 3.3.13 para 3.5.7
      Vide: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.4-Release-Notes
      Vide: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.5-Release-Notes

Versão 1.15.0

  • Profile cloudsupport-defaults:
    • Ajustes de segurança:
      • Endpoints de OpenAPI e Swagger agora são inativos por padrão.
      • Endpoints Actuator agora seguem o padrão do Spring Boot, que expõe somente /actuator/health sem details.
    • Ajustes para Kubernetes:
      • Configurados probes Actuator de liveness e de readiness para Kubernetes nos caminhos /livez e /readyz respectivamente, ativados automaticamente pelo Spring Boot caso o ambiente K8s seja detectado. A ativação pode ser forçada via management.endpoint.health.probes.enabled=true.
    • Versão consolidada do profile:

        # ----------------------
        # Documentation
        # ----------------------
              
        # Endpoints are disabled by default for security reasons
        springdoc.swagger-ui.enabled=false
        springdoc.api-docs.enabled=false
              
        # Springdoc tag per controller is not friendly to the Feature Service pattern
        springdoc.auto-tag-classes=false
              
        # Default is '/swagger-ui.html', but Swagger redirects to '/swagger-ui'
        springdoc.swagger-ui.path=/swagger-ui
              
        # Collapsed models
        springdoc.swagger-ui.defaultModelsExpandDepth=-1
        springdoc.swagger-ui.defaultModelExpandDepth=2
              
        # ----------------------
        # Actuator
        # ----------------------
              
        # In Kubernetes, probes should reflect the main application (web port, connection pools, framework
        # components), not the management context. To achieve this,it's a good idea to make the liveness and
        # readiness probes available on the main port. Conventional probe paths are "/livez" (liveness) and
        # "/readyz" (readiness). These are auto-activated when a Kubernetes environment is detected (presence
        # of the env vars KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT). You can force-enable them
        # regardless of environment with: "management.endpoint.health.probes.enabled=true".
        # (https://docs.spring.io/spring-boot/reference/actuator/endpoints.html section "Kubernetes Probes")
        management.endpoint.health.probes.add-additional-paths=true
              
        # ----------------------
        # Logging
        # Note: Will take effect if using Spring Boot Log Extensions (eg: log4j2-spring.xml, not log4j2.xml)
        # ----------------------
              
        # Avoids many 'WARN DefaultHandlerExceptionResolver : Resolved'.
        # Spring Boot 'spring.mvc.log-resolved-exception' does not work for all resolvers.
        # (issue https://github.com/spring-projects/spring-boot/issues/29706)
        logging.level.org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver=error
              
        # Default Cloudsupport log level
        logging.level.cloudsupport.spring.AppLifecycle=info
              
        # ----------------------
        # Persistence JPA
        # ----------------------
              
        # This interceptor safeguards the source code by preventing JPA flush operations outside the
        # transaction scope or within readonly transactions. In both scenarios, the underlying database
        # operates in "auto commit mode," making erroneous flushing potentially detrimental to data integrity.
        spring.jpa.properties.hibernate.session_factory.interceptor=cloudsupport.persistence.HibernateInterceptor
              
        # Simple naming strategy
        spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
              
        # Spring MVC defaults to creating a new JPA session per request, which can result in
        # unstable behavior of services due to potential differences in JPA sessions between service flows.
        # It is preferred to synchronize session creation with the @Transactional scope.
        spring.jpa.open-in-view=false
              
        # If opting in to show SQL, format the SQL output
        spring.jpa.properties.hibernate.format_sql=true
      
  • Tratamento de URL malformado no Error Whitelabel, evitando log de erro no servidor
  • Atualização de bibliotecas:
    • Spring Boot de 3.3.1 para 3.3.13
    • log4j-jdbc-dbcp2 de 2.17.1 para 2.17.2
    • jakarta.xml.bind-api de 3.0.0 para 4.0.2 (conforme Spring Data JPA)
    • jaxb-impl de 3.0.0 para 4.0.2

Versão 1.14.0

  • Atualizada assinatura de PersistenceContext.findByAttr: parâmetro value agora aceita Object em vez de Serializable, para suporte a entidades como argumento
  • Corrigido PageableQuery quando o fetch inclui subpath
  • Corrigido PersistenceContext.getFetchJoinClauses quando o fetch inclui subpath

Versão 1.13.0

  • Adicionado método getSemanticLogginInCoreAttrs() em SecurityUtils que retorna um mapa com atributos primários do usuário autenticado:
    • Se JWT: user.sub, user.username, user.name, user.email, user.user_id, user.account_id, user.department_id
    • Para outros auth tokens do Spring Security: user.principal
  • Adicionado filtro web no Spring Security para popular o MDC do Log4j2 com os atributos do usuário autenticado (a partir do SecurityUtils)
    • Ativado por padrão no esquema de segurança ‘jwt’
  • Atributo Log4j2 MDC errorTracking renomeado para error.tracking

Versão 1.12.0

  • Melhorado WebClientComponent:
    • Cache da resolução de URL para melhor performance
    • Agora suporta bypass de resolução se o endpoint for URL completa (http:// ou https://)
    • Agora suporta endpoints com número arbitrário de níveis (ex: “/service/group/subgroup/operation”)
  • Corrigido RemoteRouteResolver quando a propriedade se referia a uma operação específica

Versão 1.11.0

  • Jobs:
    • Agora evita execução concorrente do mesmo Job com os mesmos parâmetros, com intuito de mitigar risco de inconsistência de dados
    • Adicionado concurrency() em BaseJob
      • Sobrescreva este método para configurar o nível de concorrência específico para o Job
      • É recomendado fazer isso para evitar paralelismo indesejado, caso ele possa causar inconsistência de dados
    • O parâmentro concurrency na API (JobManager e endpoints Actuator) agora é opcional
      • O valor padrão é 1 para rotinas iterativas e 2 para rotinas do tipo Produtor-Consumidor, que significa que o processo será sequencial por padrão (e não paralelo)
      • O parâmentro concurrency não pode ser informado via API caso o método concurrency() esteja implementado no Job
    • O valor padrão de queueThreshold() em rotinas do tipo Produtor-Consumidor agora é -1, que significa que o motor de rotinas irá aguardar o esvaziamento da fila bem como o términdo de todos os consumos antes de realizar nova produção
      • O valor padrão anterior implicava produção e consumo concorrentes, o que poderia causar inconsistência de dados caso o Job não faça os devidos tratamentos
    • Adicionada API jobManager.listJobSchedules() e endpoint /actuator/cloudsupportjobs/schedules que retorna a lista de definições de agendamentos de cada Job:

        {
            "jobName":  "(value)",
            "enabled":  true,
            "definitions": [ 
                {
                    "cron;": "(value)",
                    "zone;": "(value)",
                    "fixedDelay": 999,
                    "fixedDelayString;": "(value)",
                    "fixedRate;": 999,
                    "fixedRateString;": "(value)",
                    "initialDelay;": 999,
                    "initialDelayString;": "(value)",
                    "timeUnit;": "(value)"
                }
            ]
        }
      
  • Atualização de bibliotecas:
    • Spring Boot de 3.3.0 para 3.3.1

Versão 1.10.5

  • Corrigida consulta de histórico de Jobs em SQL Server, Oracle e PostgreSQL
    • Dialeto é detectado automaticamente via metadados JDBC
    • Compatibilidade: MySQL, H2, MariaDB, SQL Server 2012, Oracle 12 e PostgreSQL 8.4

Versão 1.10.4

  • Adicionada biblioteca jaxb-api necessária para jjwt

Versão 1.10.3

  • Pequenos ajustes na documentação

Versão 1.10.2

  • Correção do erro “Job Engine error while trying to persist Job instance”, devido ao uso de Blob no lugar de Clob

Versão 1.10.1

  • Pequenos ajustes na documentação

Versão 1.10.0

  • Jobs:
    • Adicionado método start(jobParams) em BaseProducerConsumerJob, executado pelo motor antes da primeira produção
    • Corrigido erro no campo errorDetails, introduzido na versão anterior
  • Segurança:
    • Adicionado SecurityUtils.isAuthenticated() equivalente a @IsAuthenticated
    • Propriedade cloudsupport.security.jwt.matches renomeada para cloudsupport.security.jwt.paths
    • Propriedade cloudsupport.security.jwt.unsigned renomeada para cloudsupport.security.jwt.always-trust (padrão é false)
      • Essa propriedade ativa um JwtDecoder que remove o bloco de assinatura de JWT (se existir)
  • Tratamento de exceções:
    • Propriedades abaixo foram substituídas pela única propriedade cloudsupport.error.conventions.enabled (padrão é true):

        cloudsupport.error.include-message-on-http-4xx
        cloudsupport.error.include-message-on-business-exception
        cloudsupport.error.hide-message-on-http-5xx
        cloudsupport.error.shorten-validation-errors
        cloudsupport.error.enable-web-tracking
        cloudsupport.jobs.save-stack-trace:false
      
    • A nova propriedade ativa os seguintes recursos (web):
      • BusinessExceptions: Será emitido o campo message no Error Whitelabel do Spring Boot, com código HTTP 422. A mensagem é projetada para ser mostrada para o usuário.
      • Jakarta/Hibernate Validations (@Valid): Será emitido o campo fieldMessages no Whitelabel contendo uma lista de {field, message}, com código HTTP 422. O frontend poderá, opcionalmente, posicionar o erro no formulário com base no campo técnico field. As mensagens são projetadas para serem mostradas para o usuário.
      • Outros erros de cliente código 400: Será emitido o campo message no Error Whitelabel contendo o nome simples da classe de erro mais a mensagem. Também será emitido o campo tracking com o código de rastreamento. O erro será logado como WARN, incluindo o rastreamento, mas sem stack trace. Preferencialmente o frontend deve mostrar o rastreamento e não a mensagem.
      • Outros erros de cliente código não 400: Será emitido o campo message no Error Whitelabel contendo o nome simples da classe de erro mais a mensagem. Não há código de rastreamento nem log. O frontend pode mostrar uma mensagem genérica conforme o código HTTP.
      • Erros de servidor: Será suprimido o campo message por motivo de segurança. Será emitido o campo tracking com o código de rastreamento. O erro será logado como ERROR, incluindo o rastreamento, e com stack trace. O frontend deve mostrar o rastreamento.
      • Um filtro de servlet é ativado para evitar que erros sejam lançados no nível do container, pois gera duplicidade de log.
      • Demais campos do Whitelabel serão emitidos conforme as configurações do Spring Boot.
      • Resumo:

        Se Código HTTP Retorno Log Interface de Usuário
        BusinessException 422 message não mostrar a mensagem
        Exceção @Valid 422 fieldMessages não mostrar as mensagens de fieldMessages
        Outros erros de cliente 400 (mesmo) message, tracking WARN, sem stack trace preferencialmente mostrar o rastreamento e não a mensagem
        Outros erros de cliente não 400 (mesmo) message não mostrar uma mensagem genérica de acordo com o código
        Erros de servidor 500 tracking ERROR, com stack trace mostrar o rastreamento
    • A nova propriedade ativa os seguintes recursos (jobs):
      • Campo exitMessage do JobExecution será populado com a mensagem no caso de BusinessException. Senão, receberá um resumo do erro incluindo o código de rastreamento, e o erro será logado como ERROR.
      • Campo errorDetails será nulo, vez que o erro constará no log.
    • Comportamento padrão se as convenções forem desativadas (web):
      • Nenhuma personalização do Whitelabel
      • Nenhuma tradução de validações Jakarta/Hibernate Validations
      • Nenhum tratamento global de erros
    • Comportamento padrão se as convenções forem desativadas (jobs):
      • Campo exitMessage receberá a mensagem da exceção, não importa qual tipo dela
      • Campo errorDetails receberá o stack trace da exceção, não importa qual tipo dela
      • Todos os erros serão logados de maneira simples, sem código de rastreamento
    • Propriedade include-binding-errors removida do perfil cloudsupport-defaults (agora é o padrão do Spring Boot)

Versão 1.9.0

  • Atualização de bibliotecas:
    • Spring Boot de 2.6.3 para 3.3.0
      • Requer Java 17 ou posterior
      • javax.persistence mudou para jakarta.persistence
      • javax.annotation mudou para jakarta.annotation
      • javax.servlet mudou para jakarta.servlet
      • javax.inject mudou para jakarta.inject
      • javax.xml mudou para jakarta.xml
      • Pacotes mantidos em javax: javax.sql.* javax.transaction.xa.* javax.xml.* javax.naming.*
    • Swagger de 1.6.5 para 2.5.0
    • SBA de 2.6.2 para 3.2.3
  • Mudanças gerais:
    • Removida anotação @EnableDefaultConfig
    • Removida classe EnumItem
    • Adicionada classe CollectorUtils com método toSingleton()
    • Classe Uid movida para cloudsuport.services
    • Pacote cloudsupport.util renomeado para cloudsupport.utils
    • Classe ResourceUtil renomeada para ResourceUtils
    • Classe ExceptionHelper renomeada para ExceptionUtils
    • Adicionado método messageFrom(throwable, tracking) em ExceptionUtils
    • Adicionado método getStackTrace(throwable) em ExceptionUtils
    • Removido método getRootSummary(throwable, lines) de ExceptionUtils
    • Método UidGenerator.get().next() movido para UidGenerator.nextLong()
    • Adicionada propriedade cloudsupport.json.default-config=false que desativa a autoconfiguração do Jackson
    • Filtro RequestLoggingFilter agora despreza requisições Actuator, H2, Swagger UI e OpenAPI
  • Jobs:
    • O motor de rotinas e suas APIs (JobManager e endpoints Actuator) agora são autoconfigurados se existirem classes com @Job
    • Removido JobExecution UID das respostas JSON dos endpoints Actuator
    • Coluna key renomeada para paramKey na tabela jobParams
    • Coluna value renomeada para paramValue na tabela jobParams
    • Exceções não Business agora são rastreadas e o código é adicionado ao MDC do Log4j2 errorTracking
    • Se cloudsupport.jobs.save-stack-trace=true (padrão é false), os stack traces de exceções não Business agora são salvos no camo errorDetails field da entidade jobExecution
  • Swagger:
    • Bean OpenAPI agora é autoconfigurado e pode ser declarado pela aplicação
    • Novo type name resolver com prevenção de colisão (collision avoidance):
      • TypeNameResolver que adiciona um contador de repetição no sufixo do nome dos models
      • Propriedade springdoc.use-fqn pode ser mantida false sem risco
  • Persistência:
    • Bean AuditorAware agora é autoconfigurado e pode ser declarado pela aplicação:
      • Implementação padrão define o auditor como sendo SecurityContextHolder.context.authentication.name ou o claim JWT se a propriedade cloudsupport.auditing.auditor-jwt-claim for definida
    • Adicionado método findByAttr com opção LockModeType em todos os estereótipos de classes de negócio
    • Adicionado método findById com opção LockModeType em todos os estereótipos de classes de negócio
    • Adicionado método findByUid com opção LockModeType em todos os estereótipos de classes de negócio
    • Os métodos de acesso à persistência em todos os estereótipos de classes de negócio agora são protected em vez de public
  • Tratamento e log de exceções:
    • Class BusinessException agora implementa ErrorResponse, em conformidade com o padrão de tratamento de exceções do Spring Web e aderente à RFC 9457
    • BusinessException agora é mapeado para o status HTTP 422 (Unprocessable Entity)
    • Adicionada interface TrackingGenerator que permite a personalização da geração de códigos de rastreamento
    • Um gerador de códigos de rastreamento é autoconfigurado com base na propriedade cloudsupport.error.tracking-generator:
      • "date" (padrão): o código terá a sintaxe "<YYMMDD>-<serviceId>-<random>", onde é os primeiros 4 dígitos do _hash_ de `spring.application.name` e é o hexa do UID de 54-bit da biblioteca Cloudsupport. Substituições são feitas para melhor legibilidade e fonética (b -> h, c -> k, d -> x, e -> w). Exemplo: `"240530-5a5w-247612h6xk280"`.
      • "uuid": o código será a versão Base64 do UUID Java (ex: "acRFQHdRSiuNW_g9vBoh3Q")
      • Ambos os geradores salvam o código no contexto MDC do Log4j2 errorTracking
    • Um bean HandlerExceptionResolver é autoconfigurado se cloudsupport.error.enable-web-tracking=true (padrão) que captura exceções web não tratadas, gera o código de rastreamento, faz o log do erro e redireciona (por dispatch) para o caminho de erro do Spring Boot (server.error.path ou error.path ou /error)
      • O código de rastreamento é adicionado ao atributo cloudsupport.error.tracking do request
    • Um bean ErrorAttributes é autoconfigurado para personalizar a página Error Whitelabel do Spring Boot:
      • Campo message será exibido em erros de cliente (4xx) se cloudsupport.error.include-message-on-http-4xx=true (padrão), tendo prioridade sobre server.error.include-message do Spring Boot. Esse recurso é útil quando se deseja não expor mensagens de erro para outros tipos de erros.
      • Campo message será exibido em exceções BusinessException se cloudsupport.error.include-message-on-business-exception=true (padrão), tendo prioridade sobre server.error.include-message do Spring Boot e sobre cloudsupport.error.include-message-on-http-4xx.
      • Campo message será ocultado em erros de servidor (5xx) se cloudsupport.error.hide-message-on-http-5xx=true (padrão), tendo prioridade sobre server.error.include-message do Spring Boot.
      • Campo (errors) é exibido de maneira mais concisa se cloudsupport.error.shorten-validation-errors=true (padrão). Afeta toda exceção que herda de BindingResult ou MethodValidationResult (ex: erros de bind ou erros de @Valid). Cada erro na lista é mapeado para {field, message} (para erros associados a campos) ou apenas {message}. O campo message também é encurtado para "Validation failed".
      • Campo tracking será ocultado em erros de servidor (5xx).
  • Segurança:
    • Adicionada anotação @IsAuthenticated como atalho para @PreAuthorize("isAuthenticated()")
    • Adicionada anotação @HasAuthority("name") como atalho para @PreAuthorize("hasAuthority('{value}')")
    • Adicionada anotação @HasAnyAuthority({"'name1'", "'name2'"}) como atalho para @PreAuthorize("hasAnyAuthority('{value}')")
    • Adicionada anotação @LoggedIn como atalho para Spring + Swagger @AuthenticationPrincipal @Parameter(hidden = true)
    • Adicionada anotação @LoggedInSubject como atalho para o claim JWT "sub" (padrão)
    • Adicionada anotação @LoggedInIssuer como atalho para o claim JWT "iss" (padrão)
    • Adicionada anotação @LoggedInAccountId como atalho para o claim JWT "account_id" (ex: tenant id, número da conta)
    • Adicionada anotação @LoggedInPersonalId como atalho para o claim JWT "personal_id" (ex: CPF, SSN, etc)
    • Adicionada anotação @LoggedInUserId como atalho para o claim JWT "user_id" (ex: matrícula, número de cadastro)
    • Adicionada anotação @LoggedInDepartmentId como atalho para o claim JWT "department_id" (ex: código da unidade organizacional)
    • Adicionada anotação @LoggedInUsername como atalho para o claim JWT "username" (ex: login)
    • Adicionada anotação @LoggedInEmail como atalho para o claim JWT "email"
    • Adicionada anotação @LoggedInPhoneNumber como atalho para o claim JWT "phone_number"
    • Adicionada anotação @LoggedInName como atalho para o claim JWT "name"
    • Adicionada anotação @LoggedInGivenName como atalho para o claim JWT "given_name"
    • Adicionada anotação @LoggedInFamilyName como atalho para o claim JWT "family_name"
    • Adicionada anotação @LoggedInNickname como atalho para o claim JWT "nickname"
    • Adicionada anotação @LoggedInPicture como atalho para o claim JWT "picture" (ex: url)
    • Anotações @LoggedIn* retornam null se o principal do token de autenticação não for um objeto Jwt
    • Adicionada propriedade cloudsupport.security.allow-paths=auto que autoconfigura endereços de acesso público, com as seguintes características:
      • Um filtro SecurityFilterChain que:
        • Permite acesso anônimo para H2 Console (dinâmico, ex: /h2-console)
        • Permite acesso anônimo para Swagger UI (dinâmico, ex: /swagger-ui)
        • Permite acesso anônimo para OpenAPI (fixado em /v3/api-docs)
        • Permite acesso anônimo para Actuator (dinâmico, ex: /actuator)
        • Desativa CSRF
        • Ativa CORS (veja abaixo o filtro autoconfigurado de CORS)
        • Permite iframe na mesma origem (requisito do H2 Console)
        • Tem Order(1)
      • Se a propriedade for diferente de auto, então o filtro será aplicado para a lista de endereços separados por vírgula
    • Adicionada propriedade cloudsupport.security.scheme=jwt que autoconfigura uma pilha de segurança então chamada de ‘jwt’, com as seguintes características:
      • Um filtro SecurityFilterChain que:
        • Ativa autorização por Oauth2 ResourceServer via JWT
        • Desativa form login (statefull)
        • Desativa BASIC login
        • Desativa CSRF
        • Ativa CORS (veja abaixo o filtro autoconfigurado de CORS)
        • Se aplica a todas as rotas (padrão) ou àquelas definidas em cloudsupport.security.jwt.matches (lista separada por vírgula)
        • Não aplica requisito de autenticação obrigatória
        • Adiciona o filtro Cloudsupport WebDetailsFilter, o qual define WebDetails como sendo o objeto de details do token de autenticação
        • Tem Order(2)
      • Suporte a hidratação de campos no WebDetails (um Map) por beans do tipo WebDetailsAttributesSource, que permite à aplicação prover dados extras
      • Ativado um WebDetailsAttributesSource padrão que injeta origin_ip, origin_proto, remote_addr e session_id no WebDetails
      • Ativada segurança de método (@PreAuthorize e @PostAuthorize)
      • Ativado templating de meta-annotation em segurança de método
      • Ativado um JwtAuthenticationConverter que carrega as permissões (authorities) a partir do claim JWT definido na propriedade cloudsupport.security.jwt.authorities-claim (por padrão "roles")
      • Ativado o security scheme no Swagger de nome "JWT" (bearer)
      • Ativado um personalizador Swagger que automaticamente configura a documentação de requisito de segurança equivalente a @SecurityRequirement(name = "JWT") nos endpoints anotados com @HasAuthority, @HasAnyAuthority ou @IsAuthenticated, em que as permissões (authorities) são inclusas como scopes do SecurityRequirement do Swagger
      • Ativado um personalizador Swagger que automaticamente adiciona os nomes da permissões na documentação dos resumos dos endpoints (summary) anotados com @HasAuthority, @HasAnyAuthority ou @IsAuthenticated, uma vez que o Swagger UI não suporta nativamente a exibição das permissões (scopes)
      • Exemplo de como o código fica simplificado:

        // Spring puro:
                       
        @PreAuthorize("hasAuthority('permission')")
        @SecurityRequirement(name = "JWT")
        @Tag(name = "group")
        public void operation(
            @AuthenticationPrincipal(expression = 
                "#this instanceof T(org.springframework.security.oauth2.jwt.Jwt) ? claims['name'] : null")
            @Parameter(hidden = true)
            String name) {
                       
        }
                       
        // Com Cloudsupport:
                       
        @HasAuthority("permission")
        public void operation(
            @LoggedInName String name) {
                       
        }
        
    • Adicionada anotação Swagger @RequiresJwt como atalho para @SecurityRequirement(name = "JWT")
    • Adicionado suporte a JWT não assinado, recurso ativado por cloudsupport.security.jwt.unsigned=true
      • Útil para testes locais da aplicação ou em ambientes confiáveis (ex: microsserviços protegidos por API Gateway)
    • Adicionado Filtro CORS autoconfigurado que permite todas as origens, todos os headers e todos os métodos registrado para todos os paths, uma vez que o microsserviço é por padrão projetado para utilização em front mobile e com requisições autenticadas
    • Class SecurityContext renomeada para SecurityUtils
    • Removido SecurityUtils.getUsername()
    • Adicionado SecurityUtils.getLogin() como atalho para SecurityContextHolder.context.authentication.name (se uso de JWT, este método retornará o claim ‘sub’)
    • Adicionado SecurityUtils.getOriginIp() como atalho para SecurityContextHolder.context.authentication.details.attributes['origin_ip']
    • Adicionado SecurityUtils.getOriginProto() como atalho para SecurityContextHolder.context.authentication.details.attributes['origin_proto']
    • Adicionado SecurityUtils.getWebDetail('key') como atalho para SecurityContextHolder.context.authentication.details.attributes['key']
    • Adicionado SecurityUtils.getWebDetails() como atalho para SecurityContextHolder.context.authentication.details
    • Adicionado SecurityUtils.getLoggedIn() equivalente a @LoggedIn
    • Adicionado SecurityUtils.getLoggedInSubject() equivalente a @LoggedInSubject
    • Adicionado SecurityUtils.getLoggedInIssuer() equivalente a @LoggedInIssuer
    • Adicionado SecurityUtils.getLoggedInAccountId() equivalente a @LoggedInAccountId
    • Adicionado SecurityUtils.getLoggedInPersonalId() equivalente a @LoggedInPersonalId
    • Adicionado SecurityUtils.getLoggedInUserId() equivalente a @LoggedInUserId
    • Adicionado SecurityUtils.getLoggedInDepartmentId() equivalente a @LoggedInDepartmentId
    • Adicionado SecurityUtils.getLoggedInUsername() equivalente a @LoggedInUsername
    • Adicionado SecurityUtils.getLoggedInPhoneNumber() equivalente a @LoggedInPhoneNumber
    • Adicionado SecurityUtils.getLoggedInEmail() equivalente a @LoggedInEmail
    • Adicionado SecurityUtils.getLoggedInName() equivalente a @LoggedInName
    • Adicionado SecurityUtils.getLoggedInGivenName() equivalente a @LoggedInGivenName
    • Adicionado SecurityUtils.getLoggedInFamilyName() equivalente a @LoggedInFamilyName
    • Adicionado SecurityUtils.getLoggedInNickname()equivalente a @LoggedInNickname
    • Adicionado SecurityUtils.getLoggedInPicture() equivalente a @LoggedInPicture
    • Adicionado SecurityUtils.hasAuthority() equivalente a @hasAuthority
    • Adicionado SecurityUtils.hasAnyAuthority() equivalente a @hasAnyAuthority
    • Adicionadas bibliotecas oauth2-resource-server e jjwt para suporte a JWT
  • Integração (remotes):
    • O Token bearer agora é propagado caso seja utilizada a API WebClientComponent.authenticated(), authenticatedGet() ou authenticatedPost(), assim como os cabeçalhos X-Forwarded-For e X-Forwarded-Proto
    • Métodos WebClientComponent.get(), post(), authenticatedGet() e authenticatedPost() resolvem a URL do endpoint via RouteResolver da biblioteca Cloudsupport
    • Se um bean do tipo WebClient.Builder for declarado na aplicação, o WebClientComponent da biblioteca Cloudsupport construirá seus clients por cima do builder provido, o que permite à aplicação adicionar regras como filtros de load balancing (ex: se @LoadBalanced for utilizado)
  • Profile:
    • O profile padrão sugerido cloudsupport-defaults.properties foi simplificado e ajustado para:

        # ----------------------
        # Documentation
        # ----------------------
        
        # Springdoc tag per controller is not friendly to the Feature Service pattern
        springdoc.auto-tag-classes=false
              
        # Default is '/swagger-ui.html', but Swagger redirects to '/swagger-ui'
        springdoc.swagger-ui.path=/swagger-ui
              
        # Collapsed models
        springdoc.swagger-ui.defaultModelsExpandDepth=-1
        springdoc.swagger-ui.defaultModelExpandDepth=2
              
        # ----------------------
        # Actuator
        # ----------------------
              
        management.endpoints.web.exposure.include=*
              
        # ----------------------
        # Error Whitelabel
        # ----------------------
        
        # Useful to the frontend, as the field name and expected type are presented in 'errors' of the Whitelabel
        server.error.include-binding-errors=ALWAYS
              
        # ----------------------
        # Logging
        # Note: Will take effect if using Spring Boot Log Extensions (eg: log4j2-spring.xml, not log4j2.xml)
        # ----------------------
              
        # Avoids many 'WARN DefaultHandlerExceptionResolver : Resolved'
        # Spring Boot 'spring.mvc.log-resolved-exception' does not work for all resolvers
        # (issue https://github.com/spring-projects/spring-boot/issues/29706)
        logging.level.org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver=error
              
        # Default Cloudsupport log level
        logging.level.cloudsupport.spring.AppLifecycle=info
              
        # ----------------------
        # Persistence JPA
        # ----------------------
              
        # This interceptor safeguards the source code by preventing JPA flush operations outside the
        # transaction scope or within readonly transactions. In both scenarios, the underlying database
        # operates in "auto commit mode," making erroneous flushing potentially detrimental to data integrity.
        spring.jpa.properties.hibernate.session_factory.interceptor=cloudsupport.persistence.HibernateInterceptor
              
        # Simple naming strategy
        spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
              
        # Spring MVC defaults to creating a new JPA session per request, which can result in
        # unstable behavior of services due to potential differences in JPA sessions between service flows.
        # It is preferred to synchronize session creation with the @Transactional scope.
        spring.jpa.open-in-view=false
              
        # If opting in to show SQL, format the SQL output
        spring.jpa.properties.hibernate.format_sql=true
      

Versão 1.8.0

  • Jobs (Motor):
    • Agora suporta ativação/desativação dos agendamentos de Job via JobConfigurations
    • JobConfigurations é persistido no banco de dados se o JobRepository JDBC for ativado
    • Adicionado método jobManager.listConfigurations() (lista as configurações)
    • Adicionado método jobManager.reloadConfigurations() (recarrega as configurações a partir do banco de dados)
    • Adicionado método jobManager.getConfiguration(jobName, key)
    • Adicionado método jobManager.setConfiguration(jobName, key, value)
    • Adicionado método jobManager.listHistory(...) (lista o histórico de execuções)
    • Alterado método jobManager.listJobNames() para listRegistryEntries()
    • Campos de data agora são salvos em UTC
    • Melhorada a performance do Producer-Consumer
    • Obs: lembre de configurar spring.task.scheduling.pool.size (limite para o total de agendamentos em execução do Spring)
    • As entidades retornadas por jobManager agora são apenas POJO
    • As entidades agora utilizam java.util.Date e status como String devido a retrocompatibilidade e aderência ao Actuator:
      • JobExecution
      • JobInstance
      • JobParams
      • JobConfigurations
      • JobHistory
      • JobRegistry
    • JobParams agora são padronizados (ordenados e com duplicidades removidas)
  • Jobs (repostiório):
    • Adicionado In-Memory JobRepository, que permite utilização do módulo de Jobs sem necessidade em banco de dados (full JVM)
    • Adicionada propriedade Spring para seleção do JobRepository: cloudsupport.jobs.repository=memory|jdbc (padrão é memory)
    • Propriedade adicional se o modo for jdbc: cloudsupport.jobs.repository.jdbc.tablePrefix (padrão é "")
  • Jobs (gerenciamento via Actuator):
    • Adicionado endpoint /actuator/cloudsupportjobs/wakeup?[jobName][instanceUid] (notifica o Job para acordar suas threads internas)
    • Adicionado endpoint /actuator/cloudsupportjobs/configurations?[reload=true] (lista as configurações de Jobs)
    • Adicionado endpoint /actuator/cloudsupportjobs/configuration?jobName&key[&value] (lê ou atualiza uma configuração, ex: "scheduling=true|false")
    • Adicionado endpoint /actuator/cloudsupportjobs/history?[jobName][&executionStatus][&exitStatus][&instanceUid][&dateFrom][&dateTo][&offset][&maxResults] (lista o histórico de execuções)
  • Para ativar o agendamento de Jobs, ambos os itens abaixo devem ser true:
    • Propriedade do Spring Boot cloudsupport.jobs.scheduling.enabled=true|false. Padrão é false.
    • Configuração do Job scheduling=true|false. Padrão é true.
    • Notas técnicas:
      • A propriedade do Spring Boot faz as anotações de classe @Schedule surtirem efeito.
      • A configuração do Job faz o método BaseSchedule.runJob surtir efeito.
      • A configuração do Job é resolvida dinamicamente a cada gatilho do @Scheduled.

Versão 1.7.0

  • Jobs (Motor):
    • Removida classe BaseBatchProducerConsumerJob em favor da nova BaseProducerConsumerJob
    • Removida classe BaseContinuousProducerConsumerJob em favor da nova BaseProducerConsumerJob
    • Adicionada classe BaseProducerConsumerJob que oferece uma API mais rica para o padrão Produtor-Consumidor:
      • Método shouldProduceMore() ativa a produção periódica
      • Método queueThreshold() configura dinamicamente o limiar do buffer que dispara nova produção
      • Método productionRetryDelay() facilmente configura uma solução robusta de atraso não blocante entre produções
      • Método wakeUp() para acordar as threads do Job, o que permite a construção de um mecanismo de produção contínua (stream processing)
    • Removido método BaseJob.elapsed(), pois poderia conduzir o dev para uma implementação ruim de backoff delay
    • Removido método BaseJob.sleep(), pois poderia conduzir o dev para uma implementação ruim de backoff delay
    • Alterado método jobManager.getRunningJobs() para listRunningJobs()
    • Adicionado método jobManager.listJobNames()
    • Adicionado método jobManager.requestStop(jobExecution|instanceUid)
    • Adicionado método jobManager.awaitTermination(jobExecution|instanceUid)
    • Adicionado método jobManager.wakeUp(jobExecution|instanceUid) (notifica o Job para acordar suas threads internas)
    • Adicionado método jobManager.wakeUpAll(jobName)
    • Removidos todos os métodos de operação da entidade jobExecution
    • Aprimoramentos menores no motor de execução
  • Jobs (gerenciamento via Actuator):
    • Adicionado endpoint /actuator/cloudsupportjobs/registry (lista os possíveis Jobs)
    • Adicionado endpoint /actuator/cloudsupportjobs/running (lista os Jobs em andamento)
    • Adicionado endpoint /actuator/cloudsupportjobs/stop?instanceUid (solicita interrupção do Job)
    • Adicionado endpoint /actuator/cloudsupportjobs/start?jobName[&jobParams]&concurrency (inicia um Job)
  • Adicionado Cloudsupport Info Actuator Contributor para enriquecer /actuator/info com dados gerais da aplicação:
    • Versões dos principais frameworks
    • Estado do agendamento de Jobs
    • Totais de funcionalidades (Jobs e webservices)
  • Actuator endpoint healthReadiness alterado para healthreadiness

Versão 1.6.0

  • Adicionada propriedade cloudsupport.jobs.scheduling.enabled=true que ativa classes @Schedule
  • Adicionado método jobManager.start(clazz, jobParams, concurrency)
  • BaseSchedule.runJob agora localiza o Job por convenção de nomes (parâmetro jobName suprimido), nova API:
    • Método BaseSchedule.runJob() para executar um Job de maneira assíncrona, com 1 thread e nenhum parâmetro
    • Método BaseSchedule.runJob(concurrency) para executar sem parâmetros
    • Método BaseSchedule.runJob(jobParams) para executar com 1 thread de trabalho
    • Método BaseSchedule.runJob(jobParams, concurrency)

Versão 1.5.0

  • Adicionados @Schedule e BaseSchedule para agendamento de Jobs via Spring Scheduled Tasks

Versão 1.4.0

  • Propriedades cloudsupport.remote.* alteradas para cloudsupport.remotes.*
  • Propriedades cloudsupport.job.* alteradas para cloudsupport.jobs.*
  • Classes Cloudsupport movidas:
    • Do pacote cloudsupport.business para cloudsupport.services
    • Do pacote cloudsupport.business.job para cloudsupport.services.jobs
    • Do pacote cloudsupport.business.ws para cloudsupport.services.web
    • Do pacote cloudsupport.remote para cloudsupport.remotes
  • Convenção de nomes de pacote para classes @Ws alterada:
    • De [...].<serviceName>.business.features.ws.<group>.<featureName>.v<num>
    • Para [...].<serviceName>.services.web.<group>.<featureName>.v<num>

Versão 1.3.0

  • Propriedades app.remote.route.* alteradas para cloudsupport.remote.route.*
  • Propriedades app.job.repositoryJdbc.* alteradas para cloudsupport.job.repositoryJdbc.*

Versão 1.2.0

  • Melhorado PageableQuery.fetch() para suportar múltiplas invocações

Versão 1.1.0

  • CORS permitido para todos os caminhos

Versão 1.0.1

  • Correção em BaseGenericEntity para reconhecer campos de ID, não apenas métodos de ID

Versão 1.0.0

  • Primeira versão
    • Spring Boot: 2.6.3
    • springdoc-openapi: 1.6.5
    • SBA: 2.6.2