Por defecto WebLongi 10.3.4 viene con JSF 1.2 (que no soporta anotaciones para inyección de dependencias, etc – i.e. vale hongo). Sin embargo, supuestamente ésta es la primera versión que puede soportar JSF 2, junto con otros features de JEE6 como vimos haciendo el proyecto base >>.

instalación

Después de harto luchar tratando de encontrar una versión de JSF en maven que pudiera deployar junto con mi aplicación a cada servidor – con lo que se tiraba un lindo

java.lang.UnsupportedOperationException 	at
javax.faces.application.Application.getResourceHandler(Application.java:286) 	at
javax.faces.webapp.FacesServlet.service(FacesServlet.java:307) 	at
weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
...

en tiempo de ejecución – pude aceptar que si queremos usar JSF 2, tenemos que usar la versión proveída por WebLogic.

La susodicha se encuentra en wlserver_10.3/common/deployable-libraries y responde al nombre de jsf-2.0.war (si es que quiere).

Para deployarlo, los buenos de Oracle nos ofrecen dos maneras >>:

  1. Usando el comando de consola weblogic.Deployer, lo cual, adivine ud., no funciona… bueno, funciona si le pasamos la ruta a weblogic.jar – pero éso no lo dice la documentación.
    java -cp ~/ruta/a/weblogic.war weblogic.Deployer -adminurl t3://localhost:7001 -user weblogic -password welcome1 -deploy -library ~/ruta/a/WL/common/deployable-libraries/jsf-2.0.war
  2. Desde la consola de administración (más fácil, pero muy manual para ser serio) en Dependencias > Instalar:

    aquí se selecciona

Pero éso no es todo amigos. Además hay que decirle al servidor que esta app usa esa versión de JSF. Ésto se hace creando un archivo WEB-INF/weblogic.xml

<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.2/weblogic-web-app.xsd">
<wls:weblogic-version>10.3.4</wls:weblogic-version>
<wls:library-ref>
<wls:library-name>jsf</wls:library-name>
<wls:specification-version>2.0</wls:specification-version>
<wls:implementation-version>1.0.0.0_2-0-2</wls:implementation-version><!--ojo-->
<wls:exact-match>true</wls:exact-match>
</wls:library-ref>
</wls:weblogic-web-app>

Éso es lo particular.

Como en todo .WAR, también hay que crear el WEB-INF/web.xml donde le especificamos que el Servlet de JSF tiene que interpretar los archivos .xhtml

<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>

y, bueno, darle la dependencia de jsf 2 a maven para que pueda compilar javax.faces.bean… en el pom.xml

<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.0</version>
<scope>provided</scope><!--ojo-->
</dependency>

ojo que tiene scope provided justamente porque usamos el de WLS, no queremos que empaquete uno.

Con éso podemos conectar una vista con un ManagedBean, por ejemplo:

<h:outputText value="#{miBean.prop}">
@ManagedBean
public class MiBean{
public string prop;
}

inyección

En teoría, ésto también debiera permitir inyectar EJBs en el ManagedBean (según la sintaxis de EJB 3)

@Remote
public interface EJB{
public void metodo();
}
@Stateless
public class EJBBean implements EJB{
public void metodo(){}
}

así

@ManagedBean
public class MiBean{
@EJB EJB elEjb;
//...
}

pero ésto no funciona.

Siempre queda null.

En teoría, ésto debiera pasar justamente si no usamos la implementación de JSF de WebLogic >> ya que ésta trae un JAR (propietario) wls.jsf.di.jar que trae una única clase com.sun.faces.spi.InjectionProvider que es la encargada de efectuar la inyección de dependencia.

Intenté también aislando este jar y poniéndolo en el WEB-INF/lib… pero nada.

¿Habrá algo que estoy haciendo mal?

En efecto, si miro dentro del WAR tengo jsf-api en WEB-INF/lib

Ésto porque me falta hacer un mvn clean package para que tome el scope provided de jsf-api. Con ésto ya no está la librería y parece que ya estamos usando JSF 2 ya que al deployar el servidor tira este error

JavaServer Faces 2.0 requires Dynamic Web Module 2.5 or newer

Para solucionar ésto, hay que hacer un web.xml conforme a la versión de Servlet 2.5 en vez de 3.0 >>

<?xml version="1.0" encoding="UTF-8"?>
<web-app     xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!--servlet, como arriba -->
</web-app>

Parece que ahora sí está haciendo la inyección de dependencia pues al deployar se cae con

java.lang.ClassNotFoundException: com.numerica.test.interfaces.EJB
weblogic.utils.classloaders.GenericClassLoader.findLocalClass(GenericClassLoader.java:297)
	at weblogic.utils.classloaders.GenericClassLoader.findClass(GenericClassLoader.java:270)
	at weblogic.utils.classloaders.ChangeAwareClassLoader.findClass(ChangeAwareClassLoader.java:64)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Truncated. see log file for complete stacktrace

Ésto significa que no está pudiendo inyectar en ejb remoto porque no tiene ni la librería en WEB-INF/lib ni su declaración en el MANIFEST.MF >>.

Como quiero que el JAR corra por separado, necesito lo segundo, para lo cual puedo usar el maven-war-plugin >>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>

entonces, si declaro la dependencia al jar como opcional

<groupId>com.numerica.test</groupId>
<artifactId>miJAR</artifactId>
<version>1.0</version>
<type>ejb</type>
<optional>true</optional><!--ojo-->
</dependency>

queda en el MANIFEST.MF

Manifest-Version: 1.0
Built-By: numerico
Build-Jdk: 1.6.0_24
Class-Path: miJAR-1.0.jar
Created-By: Apache Maven 3.0.4
Archiver-Version: Plexus Archiver
.

pero sigue el mismo error.

En el fondo el asunto es que, pese a que al compilar sí tengo la interfaz disponible – y por éso el compilador no se cae en el import – probablemente la clase que efectúa la inyección de la dependencia la necesita en tiempo de deploy.

Entonces el jar (o parte de él) sí tiene que estar disponible en WEB-INF/lib.

Aquí es donde nos va a ser útil el maven-ejb-plugin. Éste puede generar un jar cliente (que tiene sólo las interfaces) >> :

En el pom.xml del JAR

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.3</version>
<configuration>
<generateClient>true</generateClient><!--false por defecto-->
</configuration>
</plugin>

El cual luego  referenciamos desde el del WAR como ejb-client

<dependency>
<groupId>com.numerica.test</groupId>
<artifactId>MiJAR</artifactId>
<version>1.0-SNAPSHOT</version>
<type>ejb-client</type><!--ojo-->
</dependency>

y ahora sí funciona.

Es decir, intenta hacer la inyección de la interfaz, pero no encuentra el bean

[J2EE:160200]Error resolving ejb-ref 'com.numerica.test.MiBean/EJB' from module 'MiWAR' of application '_auto_generated_ear_'. The ejb-ref does not have an ejb-link and the JNDI name of the target bean has not been specified. Attempts to automatically link the ejb-ref to its target bean failed because no EJBs in the application were found to implement the 'com.numerica.test.interfaces.EJB' interface. Please link or map this ejb-ref to its target EJB and ensure the interfaces declared in the ejb-ref are correct.

at weblogic.deployment.BaseEnvironmentBuilder.autowireEJBRef(BaseEnvironmentBuilder.java:427)

Ésto es porque, como es un ejb remoto, hay que especificarle el nombre JNDI del bean para que lo encuentre.
En EJB 3 no hay una manera portable de hacerlo >> – cada contenedor tiene la suya – y la de WebLogic es con la propiedad mappedName de la anotación @EJB

@EJB(mappedName="nombre") private EJB ejb;

Éste debe coincidir con el del EJB, el cual también podemos especificar en la anotación @Stateless del EJB referenciado

@Stateless(mappedName="nombre")

y ahí tenemos la bendita inyección de dependencias funcionando…

Este sitio utiliza cookies.    Leer más
Privacidad