2013-02-18 13 views
12

Ho un progetto Java EE 5 che utilizza JBoss 5.1 e un problema come questo. Devo fare una specie di ricerca run-time per alcuni EJB in MDB utilizzando una stringa risultante dal contenuto del messaggio. È solo una specie di modello di localizzazione del servizio utilizzato negli MDB. Ora, poiché gli MDB iniziano a consumare subito dopo l'implementazione, ho un sacco di NameNotFoundException poiché l'ordine di implementazione implicito non funziona bene qui (ricerca in fase di esecuzione). Cosa ne pensi? È possibile farlo davvero bene usando EJB 3.0? È anche accettabile per me utilizzare qualsiasi materiale specifico del fornitore (JBoss 5.1) se risolve il problema.Ricerca run-time per EJB in MDB che consuma subito dopo la distribuzione

Alcuni frammento di codice per visualizzare la situazione:

@MessageDriven(mappedName="jms/Queue") 
public class MessageBean implements MessageListener { 

    @Resource 
    private MessageDrivenContext mdc; 

    public void onMessage(Message msg) { 

     final String beanName = // extract somehow the bean's name from 'msg' 
     final Context ctx = new InitialContext(); 
     final Object obj = ctx.lookup(beanName); // NameNotFoundException 
     // do something with 'obj' 
    } 
} 
+0

Idea veloce: se il consumo è transazionale, è possibile rifiutare il tx su "NameNotFoundException", avere un ragionevole criterio di riprova e sperare che gli EJB siano stati distribuiti la prossima volta? –

+0

È qualcosa, ma si noti che se avrò milioni di messaggi in attesa in coda (che è il mio caso in realtà), ognuno verrà inizialmente elaborato per rifiutare semplicemente tx. Il database probabilmente si inginocchierà. Ad ogni modo ottiene un carico enorme all'avvio dell'applicazione. –

+0

Puoi incollare qui uno snippet di codice .. come stai effettuando la ricerca. qual è la tua definizione della classe MDB? – user1428716

risposta

4

Utilizzare uno di questi quattro diversi approcci.

  1. dipendenze Declare EJB (riferimenti EJB) con l'annotazione "@EJB" (non usare ricerca JNDI). Per i riferimenti del bean di entità, è necessario fare riferimento all'interfaccia home del bean di entità. Contenitore deve garantire tutte le dipendenze vengono iniettati prima di metodi/messaggio-ascoltatori sono trattati:

    MessageDriven (mappedName = "JMS/queue")
    public class MessageBean implementa MessageListener {

    @EJB private EntityBeanHomeA entityBeanHomeA;  
    
    @EJB private EntityBeanHomeB entityBeanHomeB;  
    
    @EJB private EntityBeanHomeC entityBeanHomeC;  
    
    @EJB private SessionBeanD sessionBeanD;  
    
    @Resource 
    private MessageDrivenContext mdc; 
    
    public void onMessage(Message msg) { 
    
        final String beanName = // extract somehow the bean's name from 'msg' 
        final Object obj = getDependentEJB(beanName); 
        // do something with 'obj' 
    } 
    
    private Object getDependentEJB(String beanName) { 
        Object result = null; 
        if ("EntityBeanHomeA".equals(beanName)) { 
         result = entityBeanHomeA; 
        else if ("EntityBeanHomeB".equals(beanName)) { 
         result = entityBeanHomeB; 
        else ("EntityBeanHomeC".equals(beanName)) { 
         result = entityBeanHomeC; 
        else ("SessionBeanD".equals(beanName)) { 
         result = sessionBeanD; 
        } 
        return result; 
    } 
    

    }

  2. Utilizzare la ricerca JNDI, ma dichiarare dipendenze EJB tramite descrittori di distribuzione EJB. Anche in questo caso, il contenitore deve assicurare garantire tutte le dipendenze sono installati prima di metodi/messaggi vengono elaborati:

    @MessageDriven (mappedName = "jms/Queue") public class MessageBean implementa MessageListener {

    // as given in the original Question... 
    

    }

    descrittore

    distribuzione: ricerca

    <enterprise-beans> 
        <message-driven> 
         ... 
         <ejb-name>MessageBean</ejb-name> 
         <ejb-class>com.company.pkg.MessageBean</ejb-class> 
         <messaging-type>javax.jms.MessageListener</messaging-type> 
         <message-destination-type>javax.jms.Queue</message-destination-type> 
         <message-destination-link>ExpenseProcessingQueue</message-destination-link> 
         <ejb-ref> 
          <description> This is a reference to an EJB 2.1 entity bean 
           that encapsulates access to employee records. 
          </description> 
          <ejb-ref-name>ejb/EmplRecord</ejb-ref-name> 
          <ejb-ref-type>Entity</ejb-ref-type> 
          <home>com.wombat.empl.EmployeeRecordHome</home> 
          <remote>com.wombat.empl.EmployeeRecord</remote> 
          <ejb-link>EmployeeRecord</ejb-link> <-- if in same EJB jar --> 
             <-- ../emp/emp.jar#EmployeeRecord if in diff EJB jar --> 
         </ejb-ref> 
         <ejb-local-ref> 
          <description> This is a reference to the local business interface 
           of an EJB 3.0 session bean that provides a payroll service. 
          </description> 
          <ejb-ref-name>ejb/Payroll</ejb-ref-name> 
          <local>com.aardvark.payroll.Payroll</local> 
          <ejb-link>Payroll</ejb-link> 
         </ejb-local-ref> 
         <ejb-local-ref> 
          <description> This is a reference to the local business interface of an 
           EJB 3.0 session bean that provides a pension plan service. 
          </description> 
          <ejb-ref-name>ejb/PensionPlan</ejb-ref-name> 
          <local>com.wombat.empl.PensionPlan</local> 
          <ejb-link>PensionPlan</ejb-link> <-- if in same EJB jar --> 
         </ejb-local-ref> 
         ... 
        </message-driven> 
        ... 
    </enterprise-beans> 
    
  3. Usa JNDI ma non dichiarare le dipendenze all'USI ng annotazioni @EJB o distribuzione EJB: gestisci interamente con la tua logica, senza che il contenitore aiuti. Utilizzare ritardi/gestione degli errori.

  4. Usa JBoss configurazione proprietaria per controllare l'ordine di distribuzione:

    http://texnoblog.wordpress.com/2010/09/16/depends-in-jboss/

    How to order deployment of EJBs and JMS queue config in JBoss 5?

+0

Glen, grazie per la risposta. Ciò conferma che non esiste alcuna soluzione rigida ed elegante che utilizza queste tecnologie. In ogni caso, è necessario un tipo di hacking. Probabilmente proverò con l'opzione 3 o 4. –

2

Un modo potrebbe essere quello di creare un manichino-EJB che si inietta nel vostro MDB, in questo modo il vostro mdb non sarebbe iniziare a consumare fino a che l'iniezione può effettivamente prendere posto.

Se il manichino-EJB è fornito in bundle con l'EJB si intendeva fare lookup dinamico su, questo dovrebbe funzionare

La mia risposta here risolve un caso d'uso simile.

1

si potrebbe implementare un ciclo con backoff intorno alla chiamata di ricerca.

Problemi correlati