Progettazione di un'applicazione enterprise per utilizzare il

Ci sono molte cose da considerare quando si progetta un'applicazione enterprise per utilizzare le API di Java direttamente per la messaggistica asincrona.

Procedura

  • Per le operazioni di messaggistica, è necessario scrivere programmi applicativi che utilizzano solo riferimenti alle interfacce definite nel pacchetto javax.jms .
    La Mina definisce una visione generica della messaggistica che si assota al trasporto sottostante. Un'applicazione aziendale che utilizza JMS utilizza le seguenti interfacce definite nel pacchetto javax.jms :
    Connessione
    Fornisce accesso al trasporto sottostante, e viene utilizzato per creare Sessioni.
    Sessione
    Fornisce un contesto per la creazione e l'utilizzo di messaggi, inclusi i metodi utilizzati per creare MessageProducers e MessageConsumers.
    MessageProducer
    Utilizzato per inviare messaggi.
    MessageConsumer
    Utilizzato per ricevere messaggi.
    Le interfacce Java generiche sono subclassate nelle seguenti versioni più specifiche per il funzionamento point-to-point e di pubblicazione / sottoscrizione.
    Tabella 1. Le versioni point-to-point e di pubblicazione / sottoscrizione delle interfacce comuni JMS . La prima colonna di questa tabella elenca le interfacce comuni di Java, la seconda colonna elenca le corrispondenti interfacce point-to-point e la terza colonna elenca le corrispondenti interfacce di pubblicazione / sottoscrizione.
    Interfacce comuni di Java Interfacce punto a punto Interfacce di pubblicazione / sottoscrizione
    ConnectionFactory Factory QueueConnection Factory TopicConnection
    Connessione QueueConnection TopicConnection
    Destinazione Coda Argomento
    Sessione QueueSession, TopicSession,
    MessageProducer QueueSender TopicPublisher
    MessageConsumer
    QueueReceiver,
    QueueBrowser
    TopicSubscriber

    Per ulteriori informazioni sull'utilizzo di queste interfacce JMS, consultare la documentazione Java™ Message Service Documentation e la sezione Utilizzo di Java della documentazione di IBM MQ .

    La sezione Java Message Service (Java Message Service) fornisce un elenco di metodi che non devono essere richiamati in contenitori web e EJB:
          javax.jms.Session method setMessageListener
          javax.jms.Session method getMessageListener
          javax.jms.Session method run
          javax.jms.QueueConnection method createConnectionConsumer
          javax.jms.TopicConnection method createConnectionConsumer
          javax.jms.TopicConnection method createDurableConnectionConsumer
          javax.jms.MessageConsumer method getMessageListener
          javax.jms.MessageConsumer method setMessageListener
          javax.jms.Connection setExceptionListener
          javax.jms.Connection stop
          javax.jms.Connection setClientID
    

    Questa limitazione del metodo viene applicata in WebSphere® Application Server generando un'eccezione javax.jms.IllegalStateException .

  • Le applicazioni fanno riferimento a risorse di tipo di risorse predefinite, come oggetti amministrati, a WebSphere Application Server.

    I dettagli delle risorse JMS utilizzate dalle applicazioni enterprise sono definiti in WebSphere Application Server e collegati nello spazio dei nomi JNDI dal supporto di gestione WebSphere . Un'applicazione enterprise può richiamare questi oggetti dal namespace JNDI e utilizzarli senza bisogno di sapere nulla della loro implementazione. Ciò consente di modificare l'architettura di messaggistica sottostante definita dalle risorse di JMS senza richiedere modifiche all'applicazione enterprise.

    Tabella 2. Risorse JMS per la messaggistica point-to-point e di pubblicazione / sottoscrizione . La prima colonna di questa tabella elenca le risorse di codice per la messaggistica point-to-point, e la seconda colonna elenca le risorse di gestione di quelle di pubblicazione / abbonamento.
    Point-to-point Pubblicazione/sottoscrizione
    Coda ConnectionFactory (o QueueConnectionFactory)
    ConnectionFactory (o TopicConnectionFactory)
    Argomento

    Una factory di connessione viene utilizzata per creare connessioni dal provider di gestione di Java al sistema di messaggistica ed incapsulare i parametri di configurazione necessari per creare connessioni.

  • Per migliorare le prestazioni, le connessioni e le sessioni dei pool di server delle applicazioni con il provider di dati.
    Devi configurare adeguatamente le proprietà di connessione e pool di sessione per le tue applicazioni, altrimenti potresti non ottenere il funzionamento di connessione e di sessione che desideri.
  • Le applicazioni non devono memorizzare connessioni di cache, sessioni, produttori o consumatori.
    WebSphere Application Server chiude questi oggetti quando viene completato un bean o un servlet, quindi qualsiasi tentativo di utilizzare un oggetto memorizzato nella cache avrà esito negativo con un'eccezione javax.jms.IllegalStateException .

    Per migliorare le prestazioni, le applicazioni possono memorizzare cache oggetti che sono stati guardati da JNDI. Ad esempio, un EJB o servlet deve ricercare un ConnectionFactory JMS solo una volta, ma deve richiamare il metodo createConnection su ciascuna istanza. A causa dell'effetto del pooling sulle connessioni e delle sessioni con il provider di dati, non ci dovrebbe essere alcun impatto sulle prestazioni.

  • Un sottoscrittore non durevole può essere utilizzato solo nello stesso contesto transazionale (ad esempio, una transazione globale o un contesto di transazione non specificato) che esisteva quando è stato creato l'abbonato.
  • Utilizzo di sottoscrizioni durevoli con il provider di messaggistica predefinito.
    Un abbonamento duratoso su un argomento di tipo di carattere di tipo di tipo di tipo di tipo, consente ad un abbonato di ricevere una copia di tutti i messaggi pubblicati su quell' argomento, anche dopo periodi di tempo in cui l'abbonato non è collegato al server. Pertanto, le applicazioni degli abbonati possono funzionare disconnesse dal server per lunghi periodi di tempo, per poi ricollegarsi al server e ai messaggi di processo pubblicati durante la loro assenza. Se un'applicazione crea un abbonamento durevole, viene aggiunto all'elenco di runtime che gli amministratori possono visualizzare e agire tramite la console di gestione.
    A ogni sottoscrizione durevole viene fornito un identificatore univoco, clientID##subName dove:
    clientID
    L'identificativo client utilizzato per associare una connessione e i suoi oggetti con i messaggi mantenuti per le applicazioni (come client del provider di dati). È necessario utilizzare una convenzione di denominazione che consente di identificare le applicazioni, nel caso in cui si debba correlare gli abbonamenti durevoli alle applicazioni associate per l'amministrazione di runtime.
    subName
    Il nome della sottoscrizione utilizzato per identificare univocamente un abbonamento durevole all'interno di un determinato identificativo client.

    Per gli abbonamenti durevoli creati dai fagioli guidati dai messaggi, questi valori sono impostati sulla specifica di attivazione di Java. Per altre sottoscrizioni durevoli, l'identificativo client è impostato sul factory di connessione JMS e il nome sottoscrizione è impostato dall'applicazione sull'operazione createDurableSubscriber .

    Per creare una sottoscrizione durevole ad un argomento, un'applicazione utilizza l'operazione di createDurableSubscriber definita nell'API JMS:
    public TopicSubscriber createDurableSubscriber(Topic topic,
                                java.lang.String subName,
                                java.lang.String messageSelector,
                                boolean noLocal)
                                throws JMSException
    argomento
    Il nome dell'argomento di codice a cui sottoscrivere. Questo è il nome di un oggetto che supporta le interfacce javax.jms.Topic , come ad esempio la ricerca di una voce JNDI adatta.
    subName
    Il nome utilizzato per identificare questo abbonamento.
    messageSelector
    Solo i messaggi con proprietà corrispondenti all'espressione del selettore dei messaggi vengono consegnati ai consumatori. Un valore di null o una stringa vuota indica che tutti i messaggi devono essere consegnati.
    noLocal
    Se è impostato su true, questo parametro impedisce la consegna dei messaggi pubblicati sulla stessa connessione del sottoscrittore durevole.
    Le applicazioni possono utilizzare un formato di due argomenti dell'operazione createDurableSubscriber che utilizza solo i parametri topic e subName . Questa chiamata alternativa richiama direttamente la versione a quattro argomenti come mostrato precedentemente, ma imposta messageSelector su null (in modo che tutti i messaggi vengano consegnati) e noLocal su false (in modo che i messaggi pubblicati sulla connessione vengano consegnati). Ad esempio, per creare una sottoscrizione durevole all'argomento denominato myTopic, con il nome della sottoscrizione mySubscription:
    session.createDurableSubscriber(myTopic,"mySubscription");

    Se l'operazione di sottoscrizione createDurablenon riesce, genera un'eccezione JMS che fornisce un messaggio e un'eccezione collegata per fornire ulteriori dettagli sulla causa del problema.

    Per eliminare un abbonamento durevole, un'applicazione utilizza l'operazione di annullamento sottoscrizione definita nell'API di Java

    In normali operazioni ci può essere al massimo un abbonato (connesso) attivo per un abbonamento durevole alla volta. Tuttavia, l'applicazione sottoscrittore può essere in esecuzione in un server di applicazioni clonate, per scopi di failover e di bilanciamento del carico. In questo caso la restrizione one active subscriber viene sollevata per fornire un abbonamento durevole condiviso in grado di avere più consumatori simultanei.

    Per ulteriori informazioni sull'utilizzo dell'applicazione di sottoscrizioni durevoli, consultare la sezione Utilizzo delle sottoscrizioni Durable nella specifica del sito.

  • Decidere quali selezionatori di messaggi sono necessari.
    È possibile utilizzare il meccanismo di selettore dei messaggi di tipo di tipo di messaggio per selezionare un sottoinsieme dei messaggi su una coda in modo che questo sottoinsieme venga restituito da una chiamata di ricezione. Il selettore può fare riferimento ai campi nell'intestazione del messaggio e nei campi dei messaggi presenti nelle proprietà del messaggio.
  • Recitazione sui messaggi ricevuti.
    Quando viene ricevuto un messaggio, è possibile agire su di esso come necessario dalla logica di business dell'applicazione. Alcune azioni generali di carattere di tipo Java devono controllare che il messaggio sia del tipo corretto ed estrarre il contenuto del messaggio. Per estrarre il contenuto dal corpo del messaggio, eseguire il cast dalla classe Message generica (che è il tipo di ritorno dichiarato dei metodi di ricezione) alla sottoclasse più specifica, ad esempio TextMessage. È buona norma sempre testare la classe di messaggi prima del casting, in modo che gli errori imprevisti possano essere gestiti con grazia.

    In questo caso, l'operatore instanceof viene utilizzato per controllare che il messaggio ricevuto sia del tipo TextMessage . Il contenuto del messaggio viene quindi estratto eseguendo il casting nella classe secondaria TextMessage .

           if ( inMessage instanceof TextMessage )
    
    ...
               String replyString = ((TextMessage) inMessage).getText();
    
  • Le applicazioni JMS che utilizzano il provider di messaggistica predefinito possono accedere, senza alcuna limitazione, al contenuto dei messaggi ricevuti dalla messaggistica incorporata di WebSphere Application Server Versione 5 o da IBM MQ.
  • Le applicazioni di Java possono accedere alla serie completa di proprietà JMS_IBM*.
    Queste proprietà sono di valore per le applicazioni JMS che utilizzano le risorse fornite dal provider di messaggistica predefinito, dal provider di messaggistica predefinito V5 o dal provider IBM MQ .

    Per i messaggi gestiti da IBM MQ, le proprietà JMS_IBM* sono associate a campi MQMD (Message Descriptor) IBM MQ equivalenti. Per ulteriori informazioni relative alle proprietà JMS_IBM* e ai campi MQMD, consultare la sezione Utilizzo di Java del centro informazioni di IBM MQ .

  • Le applicazioni di MQ possono utilizzare i messaggi di report come una forma di elaborazione di richiesta / risposta gestita, per dare un feedback remoto ai produttori sull'esito delle operazioni di invio e il destino dei loro messaggi.
    Le applicazioni JMS possono richiedere una gamma completa di opzioni di report utilizzando le proprietà del messaggio JMS_IBM_Report_Xxxx . Per ulteriori informazioni sull'utilizzo dei messaggi di report JMS, consultare Messaggi di report JMS.
  • Le applicazioni JMS possono utilizzare la proprietà JMS_IBM_Report_Discard_Msg per controllare il modo in cui un messaggio di richiesta viene eliminato se non può essere consegnato alla coda di destinazione.
    MQRO_Dead_Letter_Coda
    È l'impostazione predefinita. Il messaggio di richiesta deve essere scritto alla coda della lettera morta.
    MQRO_Discard
    Il messaggio di richiesta deve essere scartato. Questo di solito viene utilizzato insieme a MQRO_Exception_With_Full_Data per restituire un messaggio di richiesta indetto al suo mittente.
  • Utilizzo di un ascoltatore per ricevere i messaggi in modo asincrono.
    In un client, non in un servlet o in un bean enterprise, un'alternativa alle chiamate a QueueReceiver.receive () consiste nel registrare un metodo che viene richiamato automaticamente quando è disponibile un messaggio appropriato; ad esempio:
    ...
    MyClass listener =new MyClass();
    queueReceiver.setMessageListener(listener);
    //application continues with other application-specific behavior.
    ...
    Quando un messaggio è disponibile, viene richiamato dal metodo onMessage() sull'oggetto listener.
    import javax.jms.*;
    public class MyClass implements MessageListener
    {
    public void onMessage(Message message)
    {
    System.out.println("message is "+message);
    //application specific processing here
    ...
    
    }
    }

    Per la consegna dei messaggi asincroni, il codice delle applicazioni non può catturare eccezioni sollevate dai fallimenti per ricevere messaggi. Ciò è dovuto al fatto che il codice dell'applicazione non effettua chiamate esplicite ai metodi receive() . Per gestire questa situazione, è possibile registrare un ExceptionListener, che è un'istanza di classe che implementa il metodo onException() . Quando si verifica un errore, questo metodo viene richiamato con JMSException passato come unico parametro.

    Nota: un'alternativa allo sviluppo della classe listener JMS, è possibile utilizzare un bean basato sui messaggi, come descritto in Programmazione con bean basati sui messaggi.
  • [z/OS]Prestare attenzione quando si esegue un JMS receive() da un componente dell'applicazione lato server se il richiamo receive() è in attesa su un messaggio prodotto da un altro componente dell'applicazione distribuito nello stesso server.
    Tale JMS receive() è sincrono, quindi blocca fino a quando non viene ricevuto il messaggio di risposta.

    Questo tipo di design applicativo può portare ad un problema di consumo o di produttore dove l'intera serie di thread di lavoro può essere esaurita dal componente ricevente, che è stato bloccato in attesa di risposte, lasciando nessun thread di lavoro disponibile per il quale spedire il componente di applicazione che genererebbe il messaggio di risposta di codice. Ad esempio, un servlet e un bean basato sui messaggi vengono distribuiti nello stesso server. Quando questo servlet invia una richiesta, invia un messaggio a una coda servita dal bean basato sui messaggi (ovvero, i messaggi prodotti dal servlet vengono utilizzati dal metodo onMessage() del bean basato sui messaggi). Il servlet successivamente emette un receive(), in attesa di una risposta su una coda ReplyTo temporanea. Il metodo onMessage() del bean basato sui messaggi esegue una query del database e invia una risposta al servlet sulla coda temporanea. Se un gran numero di richieste di servlet si verificano in una volta (relativa al numero di thread di lavoro del server), allora tutti i thread di lavoro del server disponibili saranno probabilmente utilizzati per la spedizione di una richiesta di un servlet, inviare un messaggio e attendere una risposta. Il server delle applicazioni quindi entra in una condizione in cui nessun thread rimane in fase di elaborazione dei bean basati su messaggi ora in sospeso. Quindi, perché le risposte che i servi sono in attesa sono tutte bloccate, l'hangs server, che probabilmente porta al fallimento dell'applicazione.

    Le soluzioni possibili sono:

    1. Assicurarsi che il numero di thread di lavoro (# di thread per regione server * # di aree server per server) superi il numero di distribuzioni simultanee del componente dell'applicazione che esegue receive() in modo che sia sempre disponibile un thread di lavoro per inviare il componente di produzione del messaggio.
    2. Utilizzare una topologia di applicazione che pone il componente di applicazione del ricevitore in un server separato dal componente di applicazione del produttore. Anche se l'utilizzo del thread di lavoro potrebbe ancora essere attentamente considerato sotto tale scenario di distribuzione, questa separazione garantisce che ci siano sempre dei thread che non possono essere bloccati dalla componente di ricezione dei messaggi. Ci possono essere altre interazioni da considerare, come un server di applicazioni che ha più applicazioni installate.
    3. Ripercorri la tua applicazione per fare il messaggio riceve da un componente client, che non competerà con la componente produttore per i thread di lavoro. Inoltre, il componente client può fare in modo asincrono (non bloccante), che sono vietati dai server J2EE . Quindi, ad esempio, l'applicazione di esempio precedente può essere refactoring per avere un client che invia messaggi ad una coda e poi in attesa di una risposta da MDB.
  • Se si desidera utilizzare l'autenticazione con IBM MQ o con il supporto Embedded Messaging versione 5, non è possibile avere ID utente più lunghi di 12 caratteri.
    Ad esempio, l'ID utente predefinito di Windows NT, amministratore, non è valido per l'utilizzo con la messaggistica interna WebSphere , poiché contiene 13 caratteri.
  • I seguenti punti, come definiti nella specifica dell'EJB, si applicano all'utilizzo delle bandiere sulla creazione delle chiamate di sessionexxx:
    • Il flag transattivo passato sulla creazione della creazionexxxviene ignorato all'interno di una transazione globale e tutto il lavoro viene eseguito come parte della transazione. All'esterno di una transazione viene utilizzato l'indicatore di transazione e, se impostato su true, l'applicazione deve utilizzare session.commit() e session.rollback() per controllare il completamento del lavoro. In un modulo EJB2.0 , se l'indicatore di transazione è impostato su true e al di fuori di una transazione XA, la sessione è coinvolta nella transazione locale WebSphere e l'attributo dell'azione non risolta del metodo si applica al lavoro JMS se non ne è stato eseguito il commit o il rollback dall'applicazione.
    • I client non possono utilizzare Message.acknowledge() per riconoscere i messaggi. Se viene passato un valore di CLIENT_ACKNOWLEDGED sulla chiamata di creazione sessionexxx, i messaggi vengono automaticamente riconosciuti dal server delle applicazioni e Message.acknowledge() non viene utilizzato.
  • Se si desidera che l'applicazione utilizzi IBM MQ come provider JMS esterno, inviare i messaggi all'interno di una transazione gestita dal contenitore.

    Quando si utilizza IBM MQ come provider JMS esterno, i messaggi inviati in una transazione gestita dall'utente possono arrivare prima del commit della transazione. Ciò si verifica solo quando si utilizza IBM MQ come provider JMS esterno e si inviano messaggi a una coda IBM MQ all'interno di una transazione gestita dall'utente. Il messaggio arriva sulla coda di destinazione prima che la transazione commetta.

    La causa di questo problema è che il gestore risorse IBM MQ non è stato inserito nella transazione gestita dall'utente.

    La soluzione è quella di utilizzare una transazione gestita da contenitore.