Apache Camel e Kotlin: Extension functions na prática

Use AdviceWith de uma maneira simplificada

Willian Antunes
Juntos Somos Mais
3 min readDec 31, 2018

--

Quando escrevemos rotas no Apache Camel, vários meios de integração podem ser utilizados para trafegar uma mensagem de uma ponta a outra, como por exemplo SOAP, REST, Socket TCP, Stomp, e tantos outros. Tudo depende de sua necessidade de negócio.

Testes unitários ou de integração não são uma preocupação. Como utilizo Spring Boot nos projetos, existe uma seção dedicada no projeto explicando como realizar testes usando o framework. Uma prática muito comum é alterar os consumers e producers (DSLs from e to, respectivamente) das rotas (expliquei um pouco na postagem Telão Interativo SPTV com Apache Camel). O problema disso é que acontece muita repetição de código, por mais abstraído que seja. Sem contar que AdviceWithRouteBuilder não é uma interface funcional, então sempre temos que instanciar anonimamente.

Veja no link abaixo um exemplo de uso com Java:

E com Kotlin? Como poderíamos mudar o jogo? Uma abordagem é com extension functions.

Tem dúvidas em relação ao Kotlin? Experimente!

Entendendo o padrão e chegando na definição

Para implementar, como ainda desconheço o poder bélico total da linguagem (minha linguagem core ainda é Java), fui entendendo a partir de exemplos. A primeira coisa que fiz foi isolar a situação pontuando necessidades/comportamentos:

  1. ModelCamelContext é injetado.
  2. Antes de cada método de teste, é necessário preparar o ambiente.
  3. A preparação só é possível anotando a classe com @UseAdviceWith, prevenindo que o Apache Camel inicie automaticamente.
  4. É necessário verificar se o contexto não foi iniciado, caso positivo é possível executar o método getRouteDefinition a partir de uma rota e aplicar adviceWith.
  5. O método adviceWith exige receber o contexto do Apache Camel que será aplicado e uma instância de uma classe que implemente AdviceWithRouteBuilder.
  6. Já dentro do método configure do AdviceWithRouteBuilder, a partir da instância anônima, é possível usar vários métodos para alterar a rota, como replaceFromWith, interceptSendToEndpoint, weaveByToUri e outros.

A partir daí pude visualizar o uso de extension functions dentro da classe ModelCamelContext, já que dependemos dela para verificar se já foi iniciada ou não e também de passa-la como argumento pro método adviceWith.

Exemplos do próprio Kotlin como base para criar o nosso

Toda classe em Kotlin tem as funções also, apply, let, run e outros. Então acessei o código-fonte para entendê-los, como foram abstraídos e tals. Como o this (instância anônima da classe abstrata) é obrigatório, um dos parâmetros da função estendida deve ser do tipo AdviceWithRouteBuilder.() -> Unit (na documentação do Kotlin ele chama isso de function type with receiver), e o outro o ID da rota, para obtermos a sua definição.

Finalizando com regras finais

A rota só pode ser alterada antes de ser iniciada, então podemos usar takeIf para verificar.

Seu retorno pode ser nulo caso o predicado retorne falso, para garantirmos que teremos a instância podemos usar ?. seguida da função apply, que terá o this contendo ModelCamelContext.

Basta agora executarmos o método getRouteDefinition, usando o ID da rota que definimos no parâmetro da função, seguido do adviceWith, recebendo this e a instância anônima do AdviceWithRouteBuilder.

É agora que devemos executar a função que recebemos via parâmetro. Veja o que a IDE informa ao colocarmos:

O valor do this, que no caso é da instância anônima, dentro da função configure(), é capturado pela closure (mais detalhes aqui). Para finalizar, só falta iniciarmos o contexto do Apache Camel com as definições passadas. Podemos usar a função also para encadear e então finalizar nossa abstração:

Agora veja o ANTES no teste unitário:

E o DEPOIS:

Um pequeno comentário

Embora ainda minha linguagem principal seja Java, fico super animado programando em Kotlin por ser uma tecnologia moderna, com vários recursos frutos de lições aprendidas de outras linguagens (Java, Scala, Python, Groovy e C#, até onde eu sei) e com suporte fantástico de grande duas empresas (JetBrains e Google).

Recomendo seu uso não só em projetos Android, mas também para back-end.

Ao som de DataDyne Central: Defection, Perfect Dark.

--

--