0

我們在實用程序類中查找Local Stateles會話Bean實例時遇到了問題。我們總是得到一個ClassCastException:$ ProxyXYZ(XYZ爲任意數字)

我們使用的是GlassFish 3.1.1,JPA 2,EJB 3,JSF2

一切都被包裝在一個EAR歸檔。

我們也在我們的項目中使用Bean Validation,所以在我們的一個驗證器類中,我們試圖獲得一個Statateless會話bean的實例。驗證器是這樣定義的:

public class ValidadorParametroGlobal implements ConstraintValidator<ValidacionParametroGlobal, ParametroGlobal> { 

    @Override 
    public void initialize(final ValidacionParametroGlobal constraintAnnotation) { 
     try { 

      //Lookup works, jndi name is correct, but cast fails 
      ParametroGlobalBOImpl pgbo = 
        (ParametroGlobalBOImpl) new InitialContext().lookup(
        "java:global/esipren-ear/esipren-ejb/ParametroGlobalBOImpl!" + 
        "ec.gob.mf.esipren2.bo.entidad.ParametroGlobalBOLocal"); 
      LOG.info(pgbo); 
     } catch (NamingException ex) { 
      LOG.error("No se pudo recuperar el bo de parametro global en el validador"); 
      throw new IllegalStateException("No se puede ejecutar la validación", ex); 
     } 
     LOG.debug("Inicializando validador"); 
    } 
    ... MORE CODE 
} 

會話bean:

@Stateless 
@Local(ParametroGlobalBOLocal.class) 
@Remote(ParametroGlobalBORemote.class) 
public class ParametroGlobalBOImpl extends ParametroGlobalGenericBridgeImpl implements  ParametroGlobalBOLocal, 
     ParametroGlobalBORemote { 
    MORE code... 
} 

查找過程效果很好,因爲我們得到了一個Proxy類的Instancce,但不是更多鈔票丟給一個會話Bean並執行這個驗證的時候,我們得到這個異常:

java.lang.ClassCastException: $Proxy1519 
    at  ec.gob.mf.esipren2.validacion.ValidadorParametroGlobal.initialize(ValidadorParametroGlobal.java:64) 
    at ec.gob.mf.esipren2.validacion.ValidadorParametroGlobal.initialize(ValidadorParametroGlobal.java:41) 
    at org.hibernate.validator.engine.ConstraintTree.initializeConstraint(ConstraintTree.java:302) 
    at org.hibernate.validator.engine.ConstraintTree.createAndInitializeValidator(ConstraintTree.java:212) 
at org.hibernate.validator.engine.ConstraintTree.getInitializedValidator(ConstraintTree.java:189) 
    at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree|#] 

      [#|2011-10-28T11:46:10.814-0500|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=19;_ThreadName=Thread-4;|.java:135) 
    at org.hibernate.validator.metadata.MetaConstraint.validateConstraint(MetaConstraint.java:121) 
    at org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:327) 
    at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForRedefinedDefaultGroup(ValidatorImpl.java:273) 
    at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:256) 
    at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:210) 
    at org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:119) 
    at ec.gob.mf.esipren2.validacion.BeanValidationEventListener.validate(BeanValidationEventListener.java:56) 
at ec.gob.mf.esipren2.persistencia.dao.jpa.JpaGenericDAOImpl.crear(JpaGenericDAOImpl.java:113) 
    ... 95 more 
    |#] 

我們也這樣定義的驗證器類:

public class ValidadorParametroGlobal implements ConstraintValidator<ValidacionParametroGlobal, ParametroGlobal> { 

    @Override 
    public void initialize(final ValidacionParametroGlobal constraintAnnotation) { 
     try { 
      ParametroGlobalBOLocal pgbo = 
        (ParametroGlobalBOLocal) new InitialContext().lookup(
        "java:global/esipren-ear/esipren-ejb/ParametroGlobalBOImpl!" + 
        "ec.gob.mf.esipren2.bo.entidad.ParametroGlobalBOLocal"); 
      LOG.info(pgbo); 
     } catch (NamingException ex) { 
      LOG.error("No se pudo recuperar el bo de parametro global en el validador"); 
      throw new IllegalStateException("No se puede ejecutar la validación", ex); 
     } 
     LOG.debug("Inicializando validador"); 
    } 
    ... MORE CODE 
} 

但是我們得到了同樣的錯誤。

任何想法?獲得GlassFish中3.1.1本地或遠程EJB參考

回答

0

一種方式是通過一個Bean定位符(見http://www.adam-bien.com/roller/abien/entry/ejb_3_1_beanlocator_when

我Beanlocator是(見的getBean方法,它需要兩個參數:EJB組件的本地或遠程類和便攜式EJB名稱):

package ec.gob.mf.esipren2.util; 

import java.io.Serializable; 
import javax.naming.Context; 
import javax.naming.InitialContext; 
import javax.naming.NamingException; 
import javax.rmi.PortableRemoteObject; 
import org.apache.log4j.Logger; 

/** 
* Utilitario para recuperacion de instancias de Session Beans. 
* @author juan 
*/ 
public final class BeanLocator implements Serializable { 

    /** 
    * Version de la clase. 
    */ 
    private static final long serialVersionUID = 1L; 

    /** 
    * Logger de la clase. 
    */ 
    private static final Logger LOG = Logger.getLogger(BeanLocator.class); 

    /** 
    * Constructor por defecto. 
    */ 
    private BeanLocator() { 
    } 

    /** 
    * Metodo para recuperacion de Session Beans Locales usando un archivo de 
    * propiedades. 
    * @param <T> Interfaz del Tipo de Session Bean que se quiere recuperar 
    * @param clazz La clase que representa la interfaz del Session Bean 
    * @param nombreServicio 
    *  Nombre del servicio que se desea recuperar 
     * @return Una Instancia del Session Bean cuya interfaz es igual a la 
    * interfaz pasada como parametro 
    * @throws NamingException En caso de encontrarse un error al intentar 
    * recuperar la instancia del Session Bean 
    */ 
    public static <T> T getBean(final Class<T> clazz, final String nombreServicio) 
      throws NamingException { 
     LOG.trace("Recuperando servicio Local" + nombreServicio); 
     Context c = new InitialContext(); 
     Object o = c.lookup(nombreServicio); 
     LOG.trace("Se recuperó un proxy: " + o.getClass().getName()); 
     return clazz.cast(PortableRemoteObject.narrow(o, clazz)); 
    } 
} 

因此,爲了獲得一個本地EJB參考:

public String despachar() { 
    String result; 
    try { 

     ParametroGlobalBOLocal prboLocal = BeanLocator.getBean(ParametroGlobalBOLocal.class, 
       "java:global/esipren-ear/esipren-ejb/ParametroGlobalBOImpl!" + 
       "ec.gob.mf.esipren2.bo.entidad.ParametroGlobalBOLocal"); 
     prboLocal.buscarTodos(); 
     result = "Something"; 
    } catch (NamingException ex) { 
     ex.printStackTrace(); 
     result = "error"; 
    } 
    return result; 
} 

同樣的方法可以用來獲得遠程EJB引用

public String despachar1() { 
    String result; 
    try { 

     ParametroGlobalBORemote prboRemote = BeanLocator.getBean(ParametroGlobalBORemote.class, 
       "java:global/esipren-ear/esipren-ejb/ParametroGlobalBOImpl!" + 
       "ec.gob.mf.esipren2.bo.entidad.ParametroGlobalBORemote"); 
     prboRemote.buscarTodos(); 
     result = "Something"; 
    } catch (NamingException ex) { 
     ex.printStackTrace(); 
     result = "error"; 
    } 
    return result; } 

最後,這可能令您感興趣

http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#StandaloneRemoteEJB 
http://www.java.net/node/703676#comment-797861 
http://www.jguru.com/faq/view.jsp?EID=734137 

問候 胡安