redimensionar icon adjust java caching jdbc java-ee

icon - resize image java jlabel



¿Cuál es la mejor manera de modernizar la aplicación J2EE de la era 2002? (6)

Tengo este amigo ...

Tengo este amigo que trabaja en una aplicación de Java ee aplicación (j2ee) comenzó a principios de los 2000. Actualmente agregan una función aquí y allá, pero tienen una gran base de código. Con los años, el equipo se ha reducido en un 70%.

[Sí, el "tengo este amigo es". Soy yo, que intento inyectar con humor la vergüenza de un consejero de secundaria en la mezcla]

Java, Vintage 2002

La aplicación utiliza EJB 2.1, struts 1.x, DAO, etc. con llamadas jdbc directas (mezcla de procedimientos almacenados y declaraciones preparadas). Sin ORM. Para el almacenamiento en caché utilizan una mezcla de OpenSymphony OSCache y una capa de caché de fabricación propia.

En los últimos años, se han esforzado por modernizar la interfaz de usuario utilizando técnicas y bibliotecas ajax. Esto en gran medida implica javascript libaries (jquery, yui, etc.).

Lado del cliente

En el lado del cliente, la falta de una ruta de actualización desde struts1 a struts2 los desanimó de migrar a struts2. Otros frameworks web se hicieron populares (wicket, spring, jsf). Struts2 no fue el "ganador claro". La migración de toda la interfaz de usuario existente de Struts1 a Struts2 / wicket / etc. no parecía ofrecer un beneficio marginal a un costo muy elevado. No querían tener un mosaico de tecnologías-du-jour (subsistema X en Struts2, subsistema Y en Wicket, etc.) para que el desarrollador escriba nuevas características usando Struts 1.

Lado del servidor

En el lado del servidor, buscaron mudarse a ejb 3, pero nunca tuvieron un gran impulso. Los desarrolladores se sienten cómodos con ejb-jar.xml, EJBHome, EJBRemote, que "ejb 2.1 as is" representa el camino de menor resistencia.

Una gran queja sobre el entorno ejb: los programadores aún pretenden que "el servidor ejb se ejecuta en jvm por separado que el motor de servlet". Ningún servidor de aplicaciones (jboss / weblogic) ha aplicado esta separación. El equipo nunca ha desplegado el servidor ejb en un cuadro separado, luego el servidor de la aplicación.

El archivo ear contiene múltiples copias del mismo archivo jar; uno para la ''capa web'' (foo.war / WEB-INF / lib) y otro para el lado del servidor (foo.ear /). El servidor de aplicaciones solo carga un jar. Las duplicaciones crean ambigüedad.

Almacenamiento en caché

En cuanto al almacenamiento en caché, utilizan varias implementaciones de caché: caché OpenSymphony y un caché de cosecha propia. Jgroups proporciona soporte para clustering

¿Ahora que?

La pregunta: ¿el equipo actualmente tiene ciclos de repuesto para invertir en la modernización de la aplicación? ¿Dónde los gastaría el inversor inteligente?

Los principales criterios:

1) ganancias de productividad. Reduciendo específicamente el tiempo para desarrollar nuevas características de subsistemas y un mantenimiento reducido. 2) rendimiento / escalabilidad.

No les importa la moda o la credibilidad tecnológica de la calle.

¿Qué recomiendan todos?

Del lado de la persistencia ¿ Cambia todo (o solo desarrollo nuevo) a JPA / JPA2?
Hibernate recta? Espere a Java EE 6?

En el lado del cliente / web-framework : ¿Migrar (algunos o todos) a struts2? ¿postigo? jsf / jsf2?

En cuanto al almacenamiento en caché: ¿terracota? ehcache? ¿coherencia? quédate con lo que tienen? ¿Cuál es la mejor forma de aprovechar los enormes tamaños de almacenamiento dinámico que ofrecen los jvms de 64 bits?

Gracias por adelantado.


Bueno, aquí está la respuesta que no exige una reescritura en un idioma diferente o primavera de aprendizaje y escribir 2000 líneas de XML. Recomiende a su amigo que intente implementar la aplicación en glassfish v3, el EJB 2.1 funcionará (y jugará bien con cualquier código EE 6 nuevo).

De ahora en adelante, ahora pueden desarrollar código nuevo en EJB 3.1 y pueden refactorizar el código anterior de EJB 2.1 cuando lo deseen.

Podrían seguir utilizando Struts o migrar lentamente el nuevo código a JSF / Wicket / ???

Lo mismo aplica para JPA, muévete a JPA 2 a su propio ritmo, aunque su modelo de dominio puede requerir que esto ocurra en un big bang o en muchos bangs más pequeños.

¿Caché? EclipseLink (JPA 2 RI) tiene un caché bastante decente a bordo. Lee mas

La mayoría de todo este pudín tiene pruebas. Acabo de implementar una aplicación heredada EJB 3 + Struts 1.3 en glassfish v3 en el trabajo, no solo fue muy simple (el pequeño esfuerzo que requirió fue moverlo de un proyecto de desarrollador a un proyecto de netbeans), pero es un gran paso para comience a refactorizar a EE 6, que tenemos la intención de hacer a medida que se soliciten errores o características.

Básicamente, esto se reduce a "Si no está roto, no lo arregles". ¿por qué cambiar código de trabajo (aunque muy viejo)? Déjalo vivir, escribe nuevas características en EE 6 y si una característica toca el código anterior, considera refaccionarlo a EE 6 mientras estás allí.

Por encima de todo, el esfuerzo involucrado en esto, sería desplegar en glassfish v3 ...


Entiendo el dolor de tu amigo :)

Sin embargo, los marcos más nuevos y brillantes no necesariamente mejorarán la vida de su usuario final, después de todo eso es lo que le pagan. Algunos problemas han existido por un tiempo, el almacenamiento en caché de datos para acelerar las cosas, los parámetros de solicitud de cableado automático a una llamada de método, la gestión de transacciones, costura de componentes relacionados juntos ... A lo largo de los años, las personas han desarrollado implementaciones "lo suficientemente buenas ".

Mi sensación es que el cambio de marco solo vale la pena el costo si trae muchas mejoras. Por ejemplo, si cambiar a otra cosa permite AJAXify su aplicación, entonces valdría la pena. Pero deberá dejar que los usuarios finales sientan la mejoría.

Mi consejo sería comenzar a desacoplar su modelo de negocio de cualquier otra cosa (DAO, UI, gestión de transacciones ...), entonces será más fácil introducir un nuevo marco (¿ORM?). Incluso si al final no funciona, probablemente habrás mejorado la calidad de la base de código desacoplando.


Es realmente difícil justificar la reingeniería de algo que "funciona" tal como está. Gastas mucho trabajo volviendo al punto de partida.

Eso dijo.

La transición de EJB 2.1 Session Beans a EJB 3 es bastante trivial. Para nosotros, cuando hicimos la transición, la mayoría de nuestros EJB se desplegaron por separado en lugar de en un EAR combinado. Pero no tienes ese problema. Incluso con EJB 3, es probable que aún tenga un archivo ejb-jar.xml (o archivos).

Pero, aún hay beneficios, creo, y el costo es muy bajo. Puedes hacerlo incrementalmente, bean por bean vs "all at once", lo cual es bueno, simplemente moviendo la mayor parte de la información en los archivos ejb-jar.xml actuales a las anotaciones dentro de la aplicación. Si nada más, trae visibilidad (como requisitos de transacción, etc.) al código y no "oculta" en los archivos ejb-jar.xml.

No hay ninguna razón para desplegar el "nivel de aplicación" en un servidor / jvm separado. ¿El nivel web está llamando beans de sesión remota? vs Local? Puede ver o no una aceleración cambiando a llamadas locales (muchas implementaciones "coubicadas" se pueden hacer de manera similar a una invocación local en algunos servidores si están configuradas correctamente, no sé si ya lo está haciendo).

El mayor riesgo de cambiar a local es que con una llamada remota, sus argumentos están "seguros" de ser cambiados, ya que están serializados a través de la red. Con la semántica local, si cambia el valor de un argumento, a propósito o no, (es decir, cambiando el valor de una propiedad en un bean), ese cambio se reflejará en la persona que llama. Eso puede o no ser un problema. Si ya están utilizando la semántica de llamadas locales, incluso para un bean "remoto", entonces ya se han encontrado con este problema.

En cuanto a JPA vs SQL, lo dejaría como está. No vale la pena rehacer todo el nivel de datos para cambiar a JPA, y si realmente desea los beneficios del tiempo de ejecución JPA (frente al tiempo de desarrollo), notablemente el almacenamiento en caché, etc., deberá convertir toda la capa de datos (o al menos trozos de partes interrelacionadas) todos a la vez. Muy arriesgado y propenso a errores.

Para el problema de "jarras duplicadas", es un artefacto de empaquetado y construcción, no de implementación. Para solucionar el problema de ambigüedad, debe trabajar en su entorno de desarrollo para usar un repositorio de jar compartido, y ser consciente del hecho de que si actualiza el jar para uno, lo actualizará para todos. La gente dice que esa es una demanda irracional, lo que obliga a la aplicación completa a actualizarse si cambia un contenedor. Para aplicaciones enormes y dispares, claro. Pero para aplicaciones en una sola JVM, no, no lo es. Por mucho que nos gustaría que todo sea un mundo aislado en la sopa que llamamos Java classloader, simplemente no es cierto. Y cuanto más podamos mantener eso simplificado, mejoraremos en términos de complejidad y mantenimiento. Para las jarras comunes, PODRÍA considerar agrupar esas jarras en el servidor de aplicaciones y fuera de la aplicación. No soy aficionado a ese enfoque, pero tiene su uso si puede hacer que funcione para usted. Ciertamente reduce el tamaño de implementación.

Del lado del cliente, no es tan difícil convertir de Struts 1 a Struts 2, ya que ambos son muy similares en el nivel superior (notablemente, ambos son marcos de acción). La clave aquí es que ambos marcos pueden vivir uno al lado del otro permitiendo, de nuevo, el cambio incremental. Puede migrar lentamente el código viejo o solo puede implementar un nuevo código en el nuevo marco. Esto es diferente de intentar mezclar y combinar un marco de acción y un marco de componentes. Esa es literalmente una situación de "perros y gatos, viviendo juntos". Si fuera por esa ruta, simplemente implementaría los componentes en su propia GUERRA y seguiría adelante. La gestión estatal de los marcos de componentes hace que la interoperación con ellos en el back end sea realmente problemática. Si decide implementar a través de una nueva GUERRA, asegúrese de pasar un poco de tiempo haciendo algún tipo de "inicio de sesión único" para que la gente "inicie sesión" en cada módulo según corresponda. Siempre que las aplicaciones no compartan ningún estado de sesión, esto es todo lo que necesita la integración. Y una vez que haya elegido agregar un nuevo subsistema a través de un nuevo WAR, puede usar cualquier tecnología que desee para el lado del cliente.

El almacenamiento en caché es un problema diferente. Las diferentes cachés resuelven diferentes problemas. Una cosa es guardar en caché y memorizar algunos pequeños bits dentro del sistema (como las representaciones JSP), o usar un caché distribuido para transferir sesiones a través de una instancia durante la conmutación por error o el equilibrio de carga. Otra cosa es tener una capa de dominio basada en caché donde la persistencia y el almacenamiento en caché están muy, muy integrados. Eso es mucho más complejo. Solo mantenerlo todo directo en tu cabeza es doloroso.

Lo primero que puedes esparcir de todas maneras por la aplicación a medida que te encuentres con una necesidad, y ese tipo de cachés pueden ser bastante independientes en lugar de ser parte de un marco de caché global y coordinado.

El último, es diferente. Allí necesita prácticamente rehacer todo su modelo de datos, incluso para las partes que no está almacenando en caché, ya que quiere asegurarse de tener un acceso consistente a los datos y a sus vistas de caché.

Esto es efectivamente lo que hace JPA, con sus dos niveles de almacenamiento en caché, y por qué lo mencioné anteriormente, no es algo que se pueda deslizar casualmente en una aplicación, excepto la mayoría de los trozos independientes de su sistema. Cuando tiene módulos distintos que tocan los mismos recursos de fondo, la coherencia y coherencia de la caché se convierte en un problema real, y es por eso que quiere que estén integrados en ambos sistemas.

Mente, se puede hacer. El truco es simplemente integrar el nivel de acceso a los datos, y luego puede comenzar el almacenamiento en caché en ese nivel. Pero si tienes gente haciendo llamadas SQL directas, esas tienen que irse.

Finalmente, creo que el término para usar es evolución, no revolución. Migrar a EJB 3 o 3.1 no creo que tenga que ser doloroso, ya que simplemente funciona con EJB 2.1, que es una bendición. PUEDE tener un entorno "mixto". La integración más dolorosa hubiera sido si hubieras usado beans de Entity, pero no lo hiciste, así que está bien. Y para todos los detractores de EJB, esta compatibilidad con versiones anteriores que se extiende a lo largo de casi 10 años de EJB, es lo que te permite mantener una gran parte de tu código y seguir adelante.


Estuve en una posición muy similar a la tuya hace unos años, con una aplicación compleja y monolítica que consistía en una mezcla de EJB 1.x y un framework MVC propio. Migrar todo al mismo tiempo nunca fue una opción, necesitaba una forma de hacerlo un poco a la vez, sin romper nada, y sin requerir la aprobación de un mega proyecto de presupuesto.

La herramienta que me permitió hacer esto fue Spring (v1.2 como era en ese momento). Cuando elimina todas las palabras de moda de Spring, lo que le queda es un marco simple para integrar componentes de aplicaciones dispares, lo que facilita intercambiar estos componentes por alternativas, modernizándose a medida que avanza.

Por ejemplo, Spring le ofrece integración con Struts 1 , lo que facilita la introducción de componentes Struts 1 en "Spring way". Sus aplicaciones Struts deberían funcionar como antes, pero ahora tienen el poder para modernizarse de abajo hacia arriba.

A continuación, las abstracciones de acceso a datos de Spring le permitirán conectar sus DAO JDBC existentes, y comenzar a presentar las abstracciones DA para facilitar su modernización. Si opta por seguir con JDBC, está bien, Spring proporciona una amplia compatibilidad con JDBC para que se sienta menos en edad de piedra. Si quieres jugar con JPA o Hibernate, entonces esos se integrarán con la aplicación administrada por Spring tan fácilmente como lo hará JDBC.

Para EJB, Spring puede envolver la capa de acceso EJB en algo menos prehistórico, haciéndolos más fáciles de tragar. Una vez que haya aislado la capa del cliente de los detalles del acceso a datos EJB, podría, si lo desea, reemplazar los EJB (uno a la vez) con componentes más simples administrados por Spring (con cualquier tipo de interacción remota, transacciones, seguridad o ninguno) de ellos), o puede retener EJB (usando EJB3, tal vez) si así lo desea.

En resumen, deje que Spring asuma el rol de "columna vertebral" de la aplicación, mientras comienza utilizando los mismos componentes heredados que ya tiene. Luego tiene una mayor libertad para modernizarse, al ritmo y al riesgo que dicta.

No será fácil, pero con algo de paciencia y perseverancia puede llegar a donde quiere ir sin demasiadas interrupciones.


Honestamente, probablemente podrías volver a hacer todo el proceso en grial y hacerlo 20 veces más rápido que el tiempo que tardó en hacerlo en 2002;)

Para proyectos en los que tengo que usar una pila de Java real, me quedo con Spring 3.0 e Hibernate 3.5. Incluso puede usar Roo para iniciar el proyecto rápidamente, y simplemente desactívelo si ya no lo desea. Use una idea como IntelliJ para hacer que la codificación sea rápida.

Lamentablemente, tengo que decir que esto ya no es productivo. Si bien es genial para Java cruda ... Java cruda solo apesta a menos que necesites absolutamente todo lo que Java ofrece.

Además, Ajax es realmente malo con Spring. Si desea utilizar la asignación de bases de datos en su MVC, debe codificar contra los deserializadores personalizados de Jackson ... por lo que debe analizar JSON sin formato. Esto es terrible, y la gente de Spring ya está consciente del problema. Buena suerte al ver una solución de alto nivel pronto.

Solía ​​reírme de la gente de Ruby on Rails ... pero tengo que dárselas, lo hicieron bien. Para proyectos pequeños y medianos, realmente funciona. Y si desea la escalabilidad de la pila de Java, Grails es una gran solución.

Si realmente, realmente, realmente no quieres ir en esa dirección, entonces simplemente usando un Spring 3.0 modernizado con Hibernate 3.5 es el camino a seguir.


Si yo fuera tú, comenzaré con medidas. Tal vez tome algunas operaciones típicas, preferiblemente aquellas que son usuarios molestos a alta carga o algo así, corte su camino en algunas fases y mida cuánto tiempo se consume en cada paso. Una vez que encuentre un paso que toma mucho tiempo, puede reducir hasta que tenga un probable culpable. Si se trata de acceso a bases de datos, tal vez el almacenamiento en caché ayude, etc. Es posible que encuentre alguna optimización simple, pero también está bien, ¿no?

Si está ejecutando una versión anterior de la aplicación. servidor, entonces yo recomendaría actualizarlo. Por lo general, tiene un mejor rendimiento / escalabilidad, y en el caso de JBoss tiene aún más sentido debido a la mejor asistencia (puede encontrar información / recursos humanos más fácil).

En cuanto a la migración de EJB2.1 a EJB3, probé la inyección de dependencias EJB3 frente a la búsqueda JNDI de EJB2.1, y fue mucho, mucho más rápido. Quizás deshacerme de las cosas de EJBHome hizo las cosas más rápidas también, aunque no estoy seguro. Una vez que migre completamente a EJB3, tendrá JPA y es muy fácil hacer que ehcache funcione, y puedo decirle que ehcache es muy eficiente. (Bueno, no sé cómo se compara con el que estás usando ahora ...)