https://a.storyblok.com/f/270183/515089/e3fc869db2/java-version-4.png

A versão 4 da biblioteca de clientes Java da Nexmo já está disponível

Publicado em May 4, 2021

Tempo de leitura: 5 minutos

Hoje lançamos a versão 4.0.0 da nossa Biblioteca Cliente Java da Nexmo. Embora estivéssemos muito satisfeitos com as versões 3.x da biblioteca, percebemos que havia alguns aspectos que a impediam de oferecer a experiência ideal ao usuário.

Uma nova versão principal traz algumas quebras de compatibilidade com versões anteriores, mas também uma série de novos recursos incríveis. Gostaria de dar algumas dicas de migração e explicar por que escolhemos esse caminho.

Para ver a lista completa de alterações, você pode consultar nosso registro de alterações na página de lançamento

Suporte ao Java 7

Foi uma decisão difícil, mas decidimos que era hora de encerrar o suporte oficial ao Java 7. Escolher a próxima versão do Java a ser adotada também foi um desafio, mas atualizamos a versão alvo para o Java 8.

Fim do suporte da Oracle

A Oracle encerrou as atualizações públicas do Java 7 em abril de 2015. Embora ainda ofereça suporte estendido até julho de 2020, a empresa vem incentivando os usuários a atualizarem o software há bastante tempo.

Wikipedia Java Version TableWiki Java Version

É verdade que outros JDKs ainda recebem atualizações para o Java 7, mas acreditamos que isso seja um dos fatores limitantes que nos impedem de avançar com o desenvolvimento.

Recentemente, nós encerramos o suporte aos protocolos TLS legados. Além disso, o Maven Central deixou de oferecer suporte em maio de 2018. Isso complica o processo de integração contínua e torna a manutenção da biblioteca com suporte ao Java 7 ainda mais desafiadora.

Versões futuras do Java

Não tomamos essa decisão de ânimo leve e, com os novos lançamentos passando a ter uma ciclo de lançamento de seis meses, não acreditamos que as futuras versões trarão mudanças tão drásticas. Donald Smith, da Oracle, afirma:

A transição do Java 9 para o 10 e depois para o 11 se assemelha mais à transição do 8 para o 8u20 e depois para o 8u40 do que à transição do 7 para o 8 e depois para o 9. É assustador ver isso à primeira vista, quando se está acostumado a lançamentos principais a cada três anos e se tem uma percepção do enorme impacto dessas grandes mudanças. O ciclo de seis meses não é assim.

Queremos ser o mais inclusivos possível e, por isso, adicionamos alguns recursos ao cliente para ajudar a determinar qual é a melhor versão do Java a ser utilizada daqui para frente.

Instanciação do cliente

Ao instanciar o NexmoClient objeto não exige mais que você se preocupe com como fazer a autenticação. Em vez disso, agora você conta com um Builder para auxiliar na construção do cliente por meio de várias opções de configuração.

Antigo

Veja como o NexmoClient costumava ser instanciado para uso tanto com a SMS API quanto com a Voice API:

AuthMethod tokenAuth = new TokenAuthMethod(NEXMO_API_KEY, NEXMO_API_SECRET);
AuthMethod applicationAuth = new JWTAuthMethod(NEXMO_APPLICATION_ID,
        FileSystems.getDefault().getPath(NEXMO_APPLICATION_PRIVATE_KEY_PATH)
);

NexmoClient client = new NexmoClient(tokenAuth, applicationAuth);

Esse processo exigia que você compreendesse como o esquema de autenticação funciona. Também achamos que usar nomes como TokenAuthMethod e JWTAuthMethod não fossem intuitivos o suficiente.

Novo

Com a nova versão, veja como você pode instanciar NexmoClient para uso tanto com a SMS API quanto com a Voice API:

NexmoClient client = new NexmoClient.Builder()
        .apiKey(NEXMO_API_KEY)
        .apiSecret(NEXMO_API_SECRET)
        .applicationId(NEXMO_APPLICATION_ID)
        .privateKeyPath(NEXMO_PRIVATE_KEY_PATH)
        .build();

Você também pode fornecer o conteúdo do seu arquivo de chave privada, caso esteja carregando-o de outra fonte:

NexmoClient client = new NexmoClient.Builder()
        .apiKey(NEXMO_API_KEY)
        .apiSecret(NEXMO_API_SECRET)
        .applicationId(NEXMO_APPLICATION_ID)
        .privateKeyContents(NEXMO_PRIVATE_KEY_CONTENTS)
        .build();

Como usuário, você só precisa se preocupar com as credenciais que possui. Não é necessário se preocupar com qual AuthMethod usar com sua chave e seu segredo de API; basta fornecer Builder todas as credenciais que você possui.

Há algumas ressalvas ao fornecer essas informações dessa maneira. Se você fornecer uma chave de API, também deverá fornecer um segredo ou um segredo de assinatura. Caso contrário, o build método a lançar uma NexmoClientCreationException.

O objeto de controle de chamadas da Nexmo

O Objeto de Controle de Chamadas da Nexmo (NCCO) passaram por uma grande reformulação nesta atualização. Originalmente, chamávamos nossos serializadores de classes NCCO com nomes como TalkNcco, InputNcco, ConnectNcco. No entanto, isso não corresponde à convenção de nomenclatura atual.

Nosso Guia da NCCO diz que

Um Objeto de Controle de Chamada da Nexmo (NCCO) é um array JSON de ações utilizado para controlar o fluxo de uma chamada da Voice API.

Então, renomeamos essas classes para “classes de ação”, com nomes como TalkAction, InputAction, e ConnectAction. Além disso, criamos um wrapper de coleção especial chamado Ncco para integrá-las todas e cuidar da construção da estrutura JSON.

Antigo

Veja a seguir como você poderia proceder para criar um NCCO que permita a um usuário registrar uma mensagem:

Route answerRoute = (req, res) -> {
    String recordingUrl = String.format("%s://%s/webhooks/recordings", req.scheme(), req.host());

    TalkNcco intro = new TalkNcco("Please leave a message after the tone, then press #.");

    RecordNcco record = new RecordNcco();
    record.setEventUrl(recordingUrl);
    record.setEndOnSilence(3);
    record.setEndOnKey('#');
    record.setBeepStart(true);

    TalkNcco outro = new TalkNcco("Thank you for your message. Goodbye");

    Ncco[] nccos = new Ncco[]{intro, record, outro};

    res.type("application/json");

    return new ObjectMapper().writer().writeValueAsString(nccos);
};

Novo

Agora, você pode fazer algo assim:

Route answerRoute = (req, res) -> {
    String recordingUrl = String.format("%s://%s/webhooks/recordings", req.scheme(), req.host());

    TalkAction intro = new TalkAction.Builder("Please leave a message after the tone, then press #.").build();

    RecordAction record = new RecordAction.Builder()
            .eventUrl(recordingUrl)
            .endOnSilence(3)
            .endOnKey('#')
            .beepStart(true)
            .build();

    TalkAction outro = new TalkAction.Builder("Thank you for your message. Goodbye").build();

    res.type("application/json");

    return new Ncco(intro, record, outro).toJson();
};

Ou então, você poderia criar os objetos e envolvê-los em um Ncco sem criar variáveis locais adicionais:

return new Ncco(
        new TalkAction.Builder("Please leave a message after the tone, then press #.").build(),
        new RecordAction.Builder()
                .eventUrl(recordingUrl)
                .endOnSilence(3)
                .endOnKey('#')
                .beepStart(true)
                .build(),
        new TalkAction.Builder("Thank you for your message. Goodbye").build()
).toJson();

O objetivo dessa mudança foi criar uma experiência mais intuitiva para a criação de objetos com muitas propriedades.

Para alguns itens, como TalkAction com apenas uma text propriedade, parece que dá mais código. No entanto, a vantagem fica totalmente evidente quando suas ações se tornam um pouco mais complexas.

Queremos explorar outras maneiras de ajudar nessa questão, talvez utilizando métodos de fábrica para oferecer alguns atalhos práticos.

Número de solicitações de análise de dados

Nosso InsightClient continha vários métodos com diversas combinações de parâmetros. À medida que o número de opções para a análise de números aumenta, a lista de parâmetros também tende a crescer.

Há uma tendência comum na maioria dessas atualizações e, mais uma vez, optamos pelo padrão “builder”.

Antigo

Para realizar uma solicitação padrão de informações sobre números com dados de identificação de chamadas (CNAM), você faria algo assim:

StandardInsightResponse response = client.getInsightClient()
        .getStandardNumberInsight(INSIGHT_NUMBER, null, true);

Observe que é necessário usar null no segundo parâmetro para ter acesso ao cnam parâmetro. Isso parece errado.

Novo

Agora, você pode fazer o seguinte:

StandardInsightRequest request = new StandardInsightRequest.Builder(INSIGHT_NUMBER)
        .cnam(true)
        .build();

StandardInsightResponse response = client.getInsightClient()
        .getStandardNumberInsight(request);

Não eliminamos o método existente, mas decidimos considerá-lo obsoleto, recomendando o uso dos construtores de solicitação, com sua remoção prevista para a próxima versão principal.

Falei sobre como o padrão Builder pode aumentar a verbosidade do código. Por isso, para os objetos de solicitação de insights numéricos, também incluímos alguns métodos de fábrica estáticos para casos de uso comuns.

Embora seja possível criar objetos de solicitação desta forma:

AdvancedInsightRequest request = new AdvancedInsightRequest.Builder(INSIGHT_NUMBER).build();

Você também pode usar um método de fábrica estático fornecido, desta forma:

AdvancedInsightRequest request = AdvancedInsightRequest.withNumber(INSIGHT_NUMBER);

Queremos explorar um pouco mais esses métodos de fábrica, especialmente para nossas novas classes de ação.

Limitação do escopo

O fluxo de trabalho padrão nas versões 3.x sempre consistiu em passar por NexmoClient para obter acesso a outros clientes que fornecem acesso à API. Isso continua sendo o caso. No entanto, a maioria de nossos Endpoint e Method foram declaradas como públicas. Isso tornou o fornecimento de atualizações um desafio, pois não queremos quebrar a interface pública que criamos, já que isso exigiria uma atualização de versão principal.

Lembre-se de que você deve sempre usar NexmoClient para obter instâncias de outros clientes e acessar a API:

NexmoClient client = new NexmoClient.Builder()
        .apiKey(NEXMO_API_KEY)
        .apiSecret(NEXMO_API_SECRET)
        .build();

SmsClient smsClient = client.getSmsClient();

TextMessage message = new TextMessage("Acme Inc", TO_NUMBER, "Hello World!");

SmsSubmissionResponse response = smsClient.submitMessage(message);

Não deveria ser necessário instanciar um novo Endpoint ou Method classe, já que elas são usadas internamente e estão sujeitas a alterações.

Atualizamos o escopo da maioria das classes internas para o escopo padrão do pacote. Embora isso não garanta um verdadeiro encapsulamento, estamos fazendo isso para desencorajar o uso direto dessas classes, a fim de podermos atualizá-las com mais facilidade. Isso também exigiu algumas alterações nos pacotes; você poderá notar que alguns pacotes foram removidos ou renomeados.

Conclusão

Antes de mais nada, desculpem-nos pelos transtornos causados! Mas esperamos que essas mudanças nos coloquem em uma posição melhor para oferecer atualizações no futuro.

Se você tiver algum problema durante o processo de migração ou perceber alguma anomalia na biblioteca da versão 4, não hesite em Enviar um ticket e nos informar!

Não se esqueça de conferir nossos módulos atualizados no Nexmo Developer.

Compartilhar:

https://a.storyblok.com/f/270183/150x150/a3d03a85fd/placeholder.svg
Steve CrowEx-funcionários da Vonage

Steve se autodenomina “Mathlete” e “Rei da Ironia”. Ele também é apaixonado por galgos, quebra-cabeças de torção e jogos de tabuleiro europeus. Quando não está falando de matemática para quem não entende de matemática, nem de Java para quem não entende de Java, ele pode ser encontrado tomando café e programando.