0

我正在使用 Weblogic 10.3.6、Mojarra 2.0.9 和 EJB3。我们有 @ViewScoped 和 @SessionScoped JSF 托管 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 支持 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)

有没有办法让托管 Bean 重新初始化指向新服务器的新 EJB 引用?

我知道我可以使用将 init 放在提交方法中的服务定位器,但如果可能的话,我想使用 @EJB。

提前致谢。

4

2 回答 2

0

我来自 JBoss 世界,所以我对此并不完全确定。但是你真的可以用那种方式注入一个远程接口吗?我认为必须定义一个查找。但是,对于本地接口,您的呼叫应该可以工作。如果你使用远程接口,你应该使用

@EJB(lookup="jnp://wholeclustername/YourBean/remote")

并且您的 DNS 必须将您的网络指向两台机器。

另一种可能的解决方法是@Produce-method 和@Inject,您可以在其中在生产者方法中进行查找。

编辑:

是的,很不幸的。我也时不时面临这些黑客攻击:(

也许还有另一种解决方法或解决方案,我对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");
}

第二次编辑:

如果你可以使用 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");
}

但两者都只是黑客

于 2013-04-09T14:09:38.867 回答
0

经过一些试验和错误后设法解决了这个问题。由于 Jan 躲避我的设置,只注入了一个本地 jndi 名称。为了确保返回的 EJB 代理是全局的,我需要@JNDIname从接口中删除注释并为@stateless@ejb注释提供映射名称

@Stateless(mappedName = "MyFacadeBean")

@EJB(mappedName = "MyFacadeBean")
private MyFacadeBean myFacadeBean;
于 2013-05-29T13:26:44.327 回答