2013-04-09 5 views
0

Я использую Weblogic 10.3.6, Mojarra 2.0.9 и EJB3. У нас есть @ViewScoped и @SessionScoped JSF Managed beans, и мы требуем, чтобы в случае сбоя сервера все еще продолжалось. Я только что взломал его, пока не наткнулся на проблему с использованием EJB-инъекции на JSF Beans. Вот упрощенных бобы@EJB инъекции на JSF Bean после отказа

EJB Interface

@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) 

Есть ли способ получить управляемый компонент для повторной инициализации нового EJB ref, указывающего на новый сервер?

Я знаю, что могу использовать локатор сервисов с init, помещенным в метод отправки, но, если возможно, хотел бы использовать @EJB.

Заранее спасибо.

+0

Если я правильно понимаю, ваша проблема заключается в тестировании патча. Во время теста вы не можете правильно создать экземпляр своего EJB. В этом случае вы должны использовать MocKClasses, а также MockServer. Вы можете сделать это с http://arquillian.org/, или, может быть, http://code.google.com/p/mockito/. Я надеюсь, это поможет вам. –

+0

Спасибо за ответ, но это не связано с тестом. Это код в режиме ожидания. – andyfinch

ответ

0

У этого пользователя возникла проблема с решением проблемы.Когда Ян ускользнул от моего настроения, он вводил только локальное имя jndi. Для того, чтобы обеспечить возвращаемую EJB-прокси был глобальным мне нужно удалить @JNDIname аннотации из интерфейса и обеспечить mappedName к @stateless и @ejb аннотациям

@Stateless(mappedName = "MyFacadeBean") 

@EJB(mappedName = "MyFacadeBean") 
private MyFacadeBean myFacadeBean; 
0

Я родом из мира JBoss, поэтому я не совсем уверен в этом. Но можете ли вы действительно ввести удаленный интерфейс таким образом? Думаю, что должен быть определен поиск. Однако для локального интерфейса ваш звонок должен работать. И если вы используете удаленные-интерфейсы, вы должны использовать

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

и ваш DNS должен указать свою сеть на обеих машинах.

Другим возможным обходным решением может быть метод @ Produce и @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 вы можете построить хак как это:

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"); 
} 

Но оба являются только хаками

+0

Спасибо за ответ. Поверьте мне, код выше - это в основном производственный код, который работает. Я не очень разбираюсь в '@ production' и' @ inject', но кажется, что если я должен каждый раз вызывать метод, чтобы мой EJB я мог также придерживаться локатора Сервиса. – andyfinch

Смежные вопросы