我正在使用Weblogic 10.3.6,Mojarra 2.0.9和EJB3。我们有@ViewScoped和@SessionScoped JSF Managed bean,我们要求在服务器出现故障时仍然可以继续使用。我刚刚破解它,直到我在JSF Beans上使用EJB注入遇到问题。这是简化的豆
EJB接口
@JNDIName("our.ejb.jndiname")
@Remote
public interface OurEJBInterface {
some methods...
}
EJB Bean
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class ourBean implements OurEJBInterface {
the methods...
}
JSF Backing Bean
@ManagedBean
@ViewScoped
public class OurBackingBean {
@EJB
private OurBeanBeanInterface ourBeanBeanInterface ;
public void submit()
{
ourBeanBeanInterface.doSomethingFromBean();
}
}
当我们模拟故障转移时,会从新服务器正确检索会话,但是对EJB的引用仍指向旧服务器,我们收到此错误:
javax.ejb.EJBException: Could not establish a connection with -1977369784351278190S:MCPVMWLS01:[7030,7030,-1,-1,-1,-1,-1]:Destin8ShowCase:JVM01, java.rmi.ConnectException: Destination unreachable; nested exception is:
java.io.IOException: Empty server reply; No available router to destination; nested exception is:
java.rmi.ConnectException: Destination unreachable; nested exception is:
java.io.IOException: Empty server reply; No available router to destination; nested exception is: java.rmi.ConnectException: Destination unreachable; nested exception is:
java.io.IOException: Empty server reply; No available router to destination
java.rmi.ConnectException: Destination unreachable; nested exception is:
java.io.IOException: Empty server reply; No available router to destination
at weblogic.rjvm.ConnectionManager.bootstrap(ConnectionManager.java:470)
at weblogic.rjvm.ConnectionManager.bootstrap(ConnectionManager.java:402)
at weblogic.rjvm.RJVMImpl.ensureConnectionEstablished(RJVMImpl.java:306)
at weblogic.rjvm.RJVMImpl.getOutputStream(RJVMImpl.java:350)
at weblogic.rjvm.RJVMImpl.getRequestStreamInternal(RJVMImpl.java:612)
at weblogic.rjvm.RJVMImpl.getRequestStream(RJVMImpl.java:563)
at weblogic.rjvm.RJVMImpl.getOutboundRequest(RJVMImpl.java:789)
at weblogic.rmi.internal.BasicRemoteRef.getOutboundRequest(BasicRemoteRef.java:159)
at weblogic.rmi.internal.BasicRemoteRef.invoke(BasicRemoteRef.java:211)
at com.mcpplc.destin8.ejbs.manifestenquiry.ManifestEnquiryFacadeBean_qzni2o_ManifestEnquiryFacadeBeanInterfaceImpl_1036_WLStub.doMEQ02(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at weblogic.ejb.container.internal.RemoteBusinessIntfProxy.invoke(RemoteBusinessIntfProxy.java:85)
at $Proxy286.doMEQ02(Unknown Source)
at com.mcpplc.destin8.web.jsf.backingbeans.imports.Meq02BackingBean.customProcessing(Meq02BackingBean.java:49)
at com.mcpplc.destin8.web.jsf.backingbeans.BackingBean.submit(BackingBean.java:179)
有没有办法让Managed Bean重新初始化指向新服务器的新EJB ref?
我知道我可以使用一个服务定位器,并在init方法中放置init,但如果可能的话,我想使用@EJB。
提前致谢。
答案 0 :(得分:0)
我来自JBoss世界,所以我不能完全确定它。但是你真的能以这种方式注入远程接口吗?我认为必须定义一个查找。但是对于本地接口,您的呼叫应该有效。 如果您使用远程接口,则应使用
@EJB(lookup="jnp://wholeclustername/YourBean/remote")
并且您的DNS必须将您的网络指向两台计算机。
另一种可能的解决方法可以是@ Produce-method和@Inject,您可以在producer-method中进行查找。
编辑:
是的,不幸的是。我也时不时地面对这些黑客:(
也许有另一种解决方法或解决方案,我在Weblogic中不够坚定。如果你想将它与你的源分离,你也可以使用一个拦截器并在每次调用时注入一个slsb实例,也许是因为你的故障转移它也适用于@PostConstruct。我不知道:
public class LookUpEJBInterceptor {
@AroundInvoke
public Object around(InvocationContext ctx){
try {
Class<?> clazzOfEJBImplementation = ctx.getTarget().getClass();
//look for your field, I just check for the EJB annotation but that's not enough
for (Field f : clazzOfEJBImplementation.getDeclaredFields()){
if(f.isAnnotationPresent(EJB.class)){
f.setAccessible(true);
f.set(ctx.getTarget(), lookupEJB());
}
}
return ctx.proceed();
} catch (Exception e) {
e.printStackTrace();
throw new EJBException();
}
}
/**
* get your ejb
*
* @return
* @throws NamingException
*/
private Object lookupEJB() throws NamingException{
return new InitialContext().lookup("Your ejb lookup");
}
@AroundInvoke
public Object around(InvocationContext ctx){
try {
Class<?> clazzOfEJBImplementation = ctx.getTarget().getClass();
//look for your field, I just check for the EJB annotation but that's not enough
for (Field f : clazzOfEJBImplementation.getDeclaredFields()){
if(f.isAnnotationPresent(EJB.class)){
f.setAccessible(true);
f.set(ctx.getTarget(), lookupEJB());
}
}
return ctx.proceed();
} catch (Exception e) {
e.printStackTrace();
throw new EJBException();
}
}
/**
* get your ejb
*
* @return
* @throws NamingException
*/
private Object lookupEJB() throws NamingException{
return new InitialContext().lookup("Your ejb lookup");
}
第二次编辑:
如果你可以使用AspectJ,你可以像这样构建一个hack:
pointcut checkEJB(OurEJBInterface r): call(void OurEJBInterface.yourVoid()) && target(r);
void around (OurEJBInterface r) : yourVoid(r){
r = lookupYourEJB();
return proceed(r);
}
private Object lookupEJB() throws NamingException{
return new InitialContext().lookup("Your ejb lookup");
}
但两者都只是黑客
答案 1 :(得分:0)
管理以在经过一些试验和错误后解决此问题。正如Jan所说,我的设置只注入了一个当地的jndi名字。为了确保返回的EJB代理是全局的,我需要从接口中删除@JNDIname
注释,并为@stateless
和@ejb
注释提供mappedName
@Stateless(mappedName = "MyFacadeBean")
@EJB(mappedName = "MyFacadeBean")
private MyFacadeBean myFacadeBean;