Tips: WELD-001400 Normal scoped bean is not proxyable

Este error ocurre cuando por algún motivo Weld (la implementación para CDI) no es capaz modificar alguno de nuestros beans para inyectarle comportamiento.

En la práctica la solución a este problema es muy sencilla, es suficiente con revisar la clase (o la jerarquia de clases afectada) buscando algún método, atributo o clase interna marcada como final. Ya que si cualquiera de nuestros métodos está marcado como final la “mágia” CDI no podrá modificar nuestra clase.

Con esto el problema lo tendremos resuelto en la práctica, pero ahora nos queda una lavor mucho más difícil, convencer a  “los responsables de calidad” de lo absurdo que resulta que una de las reglas de validación de código sea “Design For Extension” que obliga a que todos los métodos no preparados para ser extendidos sean finales. Y es que estamos trabajando muy duro para mejorar nuestra calidad de código, pero nos estamos encontrando con que muchas reglas y pautas no encajan nada bien con el nuevo estándar JEE 6. Y que para conseguir que la arquitectura de una aplicación JEE 6 tenga una excelentes puntuaciones tenemos nos toca hacer un poco de código “espaqueti”.

Comentarios

  1. Definir cuándo una clase o método ha sido definido para ser derivada es importante.

    El problema de que Weld no sea capaz de generar un proxy en algunos casos es otro problema, pero eso no justifica no utilizar ‘final’. Aún así, la documentación debería dejar claro que tal o cual método puede o no ser derivado.

    Llamar a esas buenas prácticas “absurdas reglas de calidad” es temerario. Es posible que en tu organización sean innecesarias, pero no creo que sea correcto extender esa afirmación a todo proyecto de software. En Java, la palabra ‘final’ puede y debe ser usada en clases y métodos salvo cuando, como en tu caso, es imposible.

  2. Hola
    He de reconocer que usar la palabra “absurda” quizas es demasiado. Pero en general si que causan más problemas de los que pretenden prevenir. El post realmente no era un ataque al uso de final en métodos, y desde luego no estoy en contra de su uso.
    Aunque ya que estamos te enumero algunas de mis experiencias negativas:
    – Hace muy complicados los test unitarios ya que casi cualquier mock chocará con el final (ejemplo Mockito o más elaborados como Jboss Arquillian).

    – No solo choca con Weld, sino con cualquier cosa que requiera manipulación de la clase o injección como Hibernate, EclipseLink, Seam, IoC, JSF, JAX-WS, etc…

    – En los métodos y clases no mejora el rendimiento, el compilador JIT sabe deducirlo.

    – No usarlo evita programadores desconcertados con errores extraños producidos por parámetros que extrañamente no llegaron.

    – Busca esos final obligatorios en cualquier proyecto Java realmente importante: Eclipse, Tomcat, Glassfish, Jboss, Netbeans, etc…

    – Quizas esto es mas subjetivo, pero su uso obligatorio rompe la filosofía de la herencia, en lugar de marcar una clase como final a no ser que sea imposible, lo logico es marcarla solo cuando sea necesario que nadie la pueda modificar.

    Y en definitiva, aunque no era la intención del artículo debo confesar un fuerte prejuicio en contra de la moda de la calidad de código estricta. Para mí, “el código re-editable/reutilizable” bien estructurado es mucho, mucho mejor que una caja negra intocable.

  3. El nuevo modelo de programación que proponen frameworks como Spring, Guice, CDI con uso de inyecciones, AOP, proxys y mucha magia hace que sea necesrio una revisión de las métricas de calidad relacionadas con el código estático. Si programas desde cero, usando sólo POJOs, sin ningún tipo de framework o contenedor sí que son aplicables, pero en el mundo real esto nunca se da.

  4. Si entramos en http://sonar.apache.org podemos ver los informes de los proyectos de Apache. Si cogemos tres proyectos de envergadura como pueden ser Struts 2 o Camel vemos que de 15443 y 17323 violaciones, 5892 y 11325 (respectivamente) son de Design for Extension, o lo que es lo lo mismo: el 38.17% y el 65.3% del total de violaciones.

    Creo que ambos proyectos son lo suficientemente representativos y conocidos como para hacerse una idea del por qué de la violación de esta regla.

    Hoy por hoy, muchísimos frameworks usan intercepción en tiempo de ejecución y beneficiarse de las bondades de esta técnica es incompatible con ponerlo “todo a final”, por ejemplo.

Deja un comentario