【问题标题】:Why we get java.lang.ClassCastException: $Proxy, in jndi lookup of a Stateless Session Bean in Glassfish 3.1.1为什么我们得到 java.lang.ClassCastException: $Proxy, in jndi lookup of a Stateless Session Bean in Glassfish 3.1.1
【发布时间】:2011-10-28 17:46:58
【问题描述】:

我们在实用程序类中查找本地状态会话 Bean 实例时遇到问题。我们总是得到一个 ClassCastException: $ProxyXYZ (XYZ 是任意数字)

我们正在使用 Glassfish 3.1.1、JPA 2、EJB 3、JSF2

所有东西都打包在一个耳朵档案中。

我们还在我们的项目中使用 Bean Validation,因此在我们的一个验证器类中,我们尝试获取一个无状态会话 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 类的实例,但无法将其强制转换为 Session 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 jndi lookup classcastexception stateless-session-bean


    【解决方案1】:

    在 glassfish 3.1.1 中获取本地或远程 ejb 引用的一种方法是通过 Bean Locator(请参阅 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
    

    最好的问候 娟

    【讨论】:

      【解决方案2】:

      作为第一个答案的摘要。出现此问题是因为您转换为 EJB 本身并且您必须转换为 EJB 的业务接口。在这里学习常见问题解答http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#POJOLocalEJB 后,我遇到了同样的麻烦。幸运的是,java.net 上的同事帮助了我。非常感谢他们。

      【讨论】:

        猜你喜欢
        • 2022-01-11
        • 1970-01-01
        • 2021-10-01
        • 2020-09-30
        • 2022-12-01
        • 2023-01-12
        • 2022-12-02
        • 2020-11-22
        • 2021-05-07
        相关资源
        最近更新 更多