Gostaria de implementar um aplicativo java (aplicativo de servidor) que pode baixar uma nova versão (arquivo .jar) de um determinado url e, em seguida, atualizar-se em tempo de execução.
Qual é a melhor maneira de fazer isso e é possível?
Acho que o aplicativo pode baixar um novo arquivo .jar e iniciá-lo. Mas como devo fazer a transferência, por exemplo, saber quando o novo aplicativo é iniciado e depois sair. Ou há uma maneira melhor de fazer isto?
Respostas:
A estrutura básica de uma solução é a seguinte:
Existe um loop principal responsável por carregar repetidamente a versão mais recente do aplicativo (se necessário) e iniciá-la.
O aplicativo faz seu trabalho, mas verifica periodicamente a URL de download. Se detectar uma nova versão, ele volta para o inicializador.
Existem várias maneiras de implementar isso. Por exemplo:
O ativador pode ser um script de wrapper ou aplicativo binário que inicia uma nova JVM para executar o aplicativo a partir de um arquivo JAR que é substituído.
O ativador pode ser um aplicativo Java que cria um carregador de classe para o novo JAR, carrega uma classe de ponto de entrada e chama algum método nela. Se você fizer isso dessa maneira, terá que observar vazamentos de armazenamento do carregador de classe, mas isso não é difícil. (Você só precisa se certificar de que nenhum objeto com classes carregadas do JAR seja alcançável após a reinicialização.)
As vantagens da abordagem de wrapper externo são:
A segunda abordagem requer dois JARs, mas tem as seguintes vantagens:
A "melhor" maneira depende de seus requisitos específicos.
Também deve ser observado que:
Existem riscos de segurança com a atualização automática. Em geral, se o servidor que fornece as atualizações estiver comprometido ou se os mecanismos para fornecer as atualizações forem suscetíveis a ataques, a atualização automática pode comprometer o (s) cliente (s).
Enviar uma atualização a um cliente que cause danos ao cliente pode acarretar riscos legais e para a reputação da sua empresa.
Se você puder encontrar uma maneira de evitar reinventar a roda, isso seria bom. Veja as outras respostas para sugestões.
fonte
Atualmente estou desenvolvendo um JAVA Linux Daemon e também tive a necessidade de implementar um mecanismo de atualização automática. Eu queria limitar meu aplicativo a um arquivo jar e encontrei uma solução simples:
Empacote o aplicativo de atualização na própria atualização.
Aplicativo : quando o aplicativo detecta uma versão mais recente, ele faz o seguinte:
ApplicationUpdater : quando o atualizador é executado, ele faz o seguinte:
Espero que ajude alguém.
fonte
Este é um problema conhecido e eu não recomendo reinventar uma roda - não escreva seu próprio hack, apenas use o que outras pessoas já fizeram.
Duas situações que você precisa considerar:
O aplicativo precisa ser autoatualizável e continuar em execução mesmo durante a atualização (aplicativo de servidor, aplicativos incorporados). Vá com OSGi: Bundles ou Equinox p2 .
O aplicativo é um aplicativo de desktop e possui um instalador. Existem muitos instaladores com opção de atualização. Verifique a lista de instaladores .
fonte
Recentemente, criei o update4j, que é totalmente compatível com o sistema de módulos do Java 9.
Ele iniciará a nova versão perfeitamente sem reiniciar.
fonte
Eu escrevi um aplicativo Java que pode carregar plug-ins em tempo de execução e começar a usá-los imediatamente, inspirado por um mecanismo semelhante no jEdit. O jEdit é um software livre, então você tem a opção de ver como funciona.
A solução usa um ClassLoader personalizado para carregar arquivos do jar. Depois de carregados, você pode invocar algum método do novo jar que atuará como seu
main
método. Então, a parte complicada é ter certeza de se livrar de todas as referências ao código antigo para que ele possa ser coletado como lixo. Não sou um especialista nessa parte, fiz funcionar, mas não foi fácil.fonte
NetworkClassLoader
no JavaDoc para ClassLoaderfonte
Este não é necessariamente o melhor maneira, mas pode funcionar para você.
Você pode escrever um aplicativo de bootstrap (como o iniciador do World of Warcraft, se você já jogou WoW). Esse bootstrap é responsável por verificar as atualizações.
Desta forma, você não precisa se preocupar em forçar a saída de seu aplicativo.
Se o seu aplicativo for baseado na web e se for importante que eles tenham um cliente atualizado, você também pode fazer verificações de versão enquanto o aplicativo é executado. Você pode fazer isso em intervalos, durante a comunicação normal com o servidor (algumas ou todas as chamadas), ou ambos.
Para um produto em que trabalhei recentemente, fizemos verificações de versão no lançamento (sem um aplicativo de boot, mas antes que a janela principal aparecesse) e durante as chamadas para o servidor. Quando o cliente estava desatualizado, contamos com o usuário para encerrar manualmente, mas proibimos qualquer ação contra o servidor.
Observe que não sei se o Java pode invocar o código da IU antes de você abrir a janela principal. Estávamos usando C # / WPF.
fonte
Se você construir seu aplicativo usando plug-ins Equinox , poderá usar o P2 Provisioning System para obter uma solução pronta para esse problema. Isso exigirá que o servidor seja reiniciado após uma atualização.
fonte
Vejo um problema de segurança ao baixar um novo jar (etc.), por exemplo, um ataque man in the middle. Você sempre tem que assinar sua atualização para download.
No JAX2015, Adam Bien falou sobre o uso do JGit para atualizar os binários. Infelizmente, não consegui encontrar nenhum tutorial.
Fonte em alemão.
Adam Bien criou o atualizador, veja aqui
Eu fiz um fork aqui com algum frontend javaFX. Também estou trabalhando em uma assinatura automática.
fonte