Me gustaría implementar una aplicación java (aplicación de servidor) que pueda descargar una nueva versión (archivo .jar) de una URL determinada y luego actualizarse en tiempo de ejecución.
¿Cuál es la mejor manera de hacer esto? ¿Es posible?
Supongo que la aplicación puede descargar un nuevo archivo .jar e iniciarlo. Pero, ¿cómo debo hacer el traspaso? Por ejemplo, saber cuándo se inicia la nueva aplicación y luego salir. ¿O hay una mejor manera de hacer esto?
Respuestas:
La estructura básica de una solución es la siguiente:
Hay un bucle principal responsable de cargar repetidamente la última versión de la aplicación (si es necesario) y ejecutarla.
La aplicación hace lo suyo, pero comprueba periódicamente la URL de descarga. Si detecta una nueva versión, vuelve al lanzador.
Hay varias formas de implementar esto. Por ejemplo:
El lanzador podría ser un script contenedor o una aplicación binaria que inicia una nueva JVM para ejecutar la aplicación desde un archivo JAR que se reemplaza.
El lanzador podría ser una aplicación Java que crea un cargador de clases para el nuevo JAR, carga una clase de punto de entrada y llama a algún método en ella. Si lo hace de esta manera, debe estar atento a las fugas de almacenamiento del cargador de clases, pero eso no es difícil. (Solo debe asegurarse de que no se pueda acceder a ningún objeto con clases cargadas desde el JAR después de reiniciar).
Las ventajas del enfoque de envoltura externa son:
El segundo enfoque requiere dos JAR, pero tiene las siguientes ventajas:
La "mejor" forma depende de sus requisitos específicos.
También debe tenerse en cuenta que:
Existen riesgos de seguridad con la actualización automática. En general, si el servidor que proporciona las actualizaciones se ve comprometido, o si los mecanismos para proporcionar las actualizaciones son susceptibles de ser atacados, la actualización automática puede llevar a comprometer a los clientes.
Enviarle una actualización a un cliente que cause daño al cliente podría tener riesgos legales y riesgos para la reputación de su empresa.
Si puede encontrar una manera de evitar reinventar la rueda, sería bueno. Consulte las otras respuestas para obtener sugerencias.
fuente
Actualmente estoy desarrollando un JAVA Linux Daemon y también tuve la necesidad de implementar un mecanismo de actualización automática. Quería limitar mi aplicación a un archivo jar y se me ocurrió una solución simple:
Empaquete la aplicación de actualización en la propia actualización.
Aplicación : cuando la aplicación detecta una versión más reciente, hace lo siguiente:
ApplicationUpdater : cuando se ejecuta el actualizador, hace lo siguiente:
Espero que ayude a alguien.
fuente
Este es un problema conocido y recomiendo no reinventar una rueda: no escriba su propio truco, solo use lo que otras personas ya han hecho.
Dos situaciones que debes considerar:
La aplicación debe ser autoactualizable y seguir ejecutándose incluso durante la actualización (aplicación de servidor, aplicaciones integradas). Vaya con OSGi: Bundles o Equinox p2 .
La aplicación es una aplicación de escritorio y tiene un instalador. Hay muchos instaladores con opción de actualización. Consulte la lista de instaladores .
fuente
Recientemente he creado update4j que es totalmente compatible con el sistema de módulos de Java 9.
Iniciará sin problemas la nueva versión sin reiniciar.
fuente
Escribí una aplicación Java que puede cargar complementos en tiempo de ejecución y comenzar a usarlos de inmediato, inspirada en un mecanismo similar en jEdit. jEdit es de código abierto, por lo que tiene la opción de ver cómo funciona.
La solución utiliza un ClassLoader personalizado para cargar archivos desde el jar. Una vez que estén cargados, puede invocar algún método del nuevo jar que actuará como su
main
método. Luego, la parte complicada es asegurarse de eliminar todas las referencias al código antiguo para que pueda ser recolectado como basura. No soy un experto en esa parte, lo hice funcionar pero no fue fácil.fuente
NetworkClassLoader
en JavaDoc para ClassLoaderfuente
Esta no es necesariamente la mejor manera, pero podría funcionar para usted.
Puedes escribir una aplicación de arranque (como el lanzador de World of Warcraft, si has jugado WoW). Ese bootstrap es responsable de buscar actualizaciones.
De esta manera, no tiene que preocuparse por forzar la salida de su aplicación.
Si su aplicación está basada en la web, y si es importante que tengan un cliente actualizado, también puede verificar la versión mientras se ejecuta la aplicación. Puede hacerlo a intervalos, mientras realiza una comunicación normal con el servidor (algunas o todas las llamadas), o ambas.
Para un producto en el que trabajé recientemente, realizamos verificaciones de versión al momento del lanzamiento (sin una aplicación de arranque, pero antes de que apareciera la ventana principal) y durante las llamadas al servidor. Cuando el cliente estaba desactualizado, confiamos en que el usuario saliera manualmente, pero prohibimos cualquier acción contra el servidor.
Tenga en cuenta que no sé si Java puede invocar el código de la interfaz de usuario antes de que aparezca la ventana principal. Estábamos usando C # / WPF.
fuente
Si crea su aplicación utilizando complementos de Equinox , puede usar el sistema de aprovisionamiento P2 para obtener una solución lista para este problema. Esto requerirá que el servidor se reinicie después de una actualización.
fuente
Veo un problema de seguridad al descargar un nuevo jar (etc.), por ejemplo, un hombre en el medio del ataque. Siempre tienes que firmar tu actualización descargable.
En JAX2015, Adam Bien habló sobre el uso de JGit para actualizar los binarios. Lamentablemente no pude encontrar ningún tutorial.
Fuente en alemán.
Adam Bien creó el actualizador ver aquí
Lo bifurqué aquí con una interfaz javaFX. También estoy trabajando en una firma automática.
fuente