我们在查找实用程序类中的Local Stateles会话Bean实例时遇到问题。我们总是得到一个ClassCastException:$ ProxyXYZ(XYZ是任意数字)
我们正在使用Glassfish 3.1.1,JPA 2,EJB 3,JSF2
所有内容都包装在耳档中。
我们在项目中也使用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,但将它强制转换为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
}
但是我们得到了同样的错误。
任何想法?
答案 0 :(得分:0)
在glassfish 3.1.1中获取本地或远程ejb引用的一种方法是通过Bean Locator(参见http://www.adam-bien.com/roller/abien/entry/ejb_3_1_beanlocator_when)
我的Beanlocator是(参见getBean方法,它需要两个参数:Ejb的Local或Remote类以及可移植的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
祝你好运 涓
答案 1 :(得分:0)
作为第一个答案的摘要。出现此问题的原因是您转换为EJB本身,并且必须转换为EJB的业务接口。在研究常见问题解答http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#POJOLocalEJB后,我遇到了同样的麻烦。幸运的是,java.net上的同事帮助了我。非常感谢他们。