Changelog do Cloudsupport

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
  • Adicioando 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 suporte 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 do 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 do Cloudsupport
    • Se um bean do tipo WebClient.Builder for declarado na aplicação, o WebClientComponent do 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:

      # ----------------------
      # 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
    • SpringBoot: 2.6.3
    • springdoc-openapi: 1.6.5
    • SBA: 2.6.2