Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 15 di 68
  • livello ninja
Indice lezioni

MDB: la classe del Connector

Portiamo a conclusione la parte dedicata ai Message Driven Bean con implementazione della classe del Connector e l'escuzione del JUnit test per l'MDB.
Portiamo a conclusione la parte dedicata ai Message Driven Bean con implementazione della classe del Connector e l'escuzione del JUnit test per l'MDB.
Link copiato negli appunti

La classe del Connector

Implementiamo adesso la classe del Connector. Prima di procedere nell'analisi del codice, definiamo le seguenti Queue in standalone-full.xml:

<jms-queue name="ShippingQueue2">
                        <entry name="java:jboss/exported/jms/queue/ShippingQueue2"/>
                    </jms-queue>
                    <jms-queue name="ShippingQueue3">
                        <entry name="java:jboss/exported/jms/queue/ShippingQueue3"/>
                    </jms-queue>

La classe del connettore JCA deve implementare l'interfaccia javax.resource.spi.ResourceAdapter ed essere annotata con @Connector:

@Connector(
        description = "This is a MDB sample resource adapter",
        eisType = "MDB Connector",
        vendorName = "JBoss Wildfly",
        version = "1.0"
)
public class MdbEventConnector implements ResourceAdapter { ... }

L'interfaccia prevede diversi metodi da implementare, nel nostro caso possiamo lasciar vuoti tutti i metodi tranne endPointActivation() per il quale forniamo la seguente implementazione:

@Override
	public void endpointActivation(MessageEndpointFactory messageEndpointFactory, ActivationSpec activationSpec)
			throws ResourceException {
		Class<?> beanClass = messageEndpointFactory.getEndpointClass();
		try {
			InitialContext namingContext = new InitialContext();
			ConnectionFactory connectionFactory = (ConnectionFactory) namingContext
					.lookup(JMS_CONNECTION_FACTORY_JNDI_NAME);
			Queue shippingQueue1 = (Queue) namingContext.lookup(JMS_QUEUE_JNDI_NAME1);
			Queue shippingQueue2 = (Queue) namingContext.lookup(JMS_QUEUE_JNDI_NAME2);	
			JMSContext  jmsContext1 = connectionFactory.createContext();
			JMSContext  jmsContext2 = connectionFactory.createContext();
			JMSConsumer jmsConsumer1= jmsContext1.createConsumer(shippingQueue1);
			JMSConsumer jmsConsumer2= jmsContext2.createConsumer(shippingQueue2);
			jmsConsumer1.setMessageListener(createMdbEventListener(messageEndpointFactory, beanClass, "order1"));
			jmsConsumer2.setMessageListener(createMdbEventListener(messageEndpointFactory, beanClass, "order2"));
			jmsContext1.start();
			jmsContext2.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

Il metodo inizia con il recupero della classe dell'MDB collegata al Connettore attraverso messageEndpointFactory.getEndpointClass() e successivamente ottiene una ConnectionFactory JMS e i riferimenti alle Queue già definite. Sulla ConnectionFactory recuperiamo due JMSContext che consentono di creare due consumer di messaggi, uno per ogni Queue. Sui consumer impostiamo un event listener per il recupero del messaggio e l'invocazione del metodo target dell'MDB:

private MessageListener createMdbEventListener(MessageEndpointFactory messageEndpointFactory, Class<?> beanClass,
			String destinationMethod) {
		for (Method method : beanClass.getMethods()) {
			if (method.getName().equals(destinationMethod)) {
				return new MessageListener() {
					@Override
					public void onMessage(Message msg) {
						MessageEndpoint endpoint = null;
						try {
							String message = ((TextMessage) msg).getText();
							endpoint = messageEndpointFactory.createEndpoint(null);
							endpoint.beforeDelivery(method);
							method.invoke(endpoint, message);
							endpoint.afterDelivery();
						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							if (endpoint != null) {
								endpoint.release();
							}
						}
					}
				};
			}
		}
		return null;
	}

Il metodo costruisce un MessageListener il cui evento onMessage() produce l'invocazione del metodo target dell'MDB (blocco try). Se analizziamo il log prodotto da JBoss Wildfly in fase di deploy troviamo due righe che ci mostrano come gli MDB ShippingProcessor e ShippingProcessor2 stiano utilizzando rispettivamente gli adapter Hornet ed MdbEventConnector:

INFO  [org.jboss.as.ejb3] (MSC service thread 1-5) WFLYEJB0042: Started message driven bean 'ShippingProcessor' with 'hornetq-ra.rar' resource adapter
INFO  [org.jboss.as.ejb3] (MSC service thread 1-6) WFLYEJB0042: Started message driven bean 'ShippingProcessor2' with 'Progetto1Ear.ear#Progetto1Connector.rar' resource adapter

JUnit test per l'MDB

Concludiamo con il JUnit test per l'MDB ShippingProcessor2:

....
    private static final String JMS_QUEUE_JNDI_NAME2="/jms/queue/ShippingQueue2";
    private static final String JMS_QUEUE_JNDI_NAME3="/jms/queue/ShippingQueue3";
    ....
    @Test
    public void testShippingMDBNotInt() throws NamingException, JMSException {
        ConnectionFactory  connectionFactory = (ConnectionFactory)
        namingContext.lookup(JMS_CONNECTION_FACTORY_JNDI_NAME);
        Queue shippingQueue2 = (Queue)namingContext.lookup(JMS_QUEUE_JNDI_NAME2);
        Queue shippingQueue3 = (Queue)namingContext.lookup(JMS_QUEUE_JNDI_NAME3);
        Connection connect = connectionFactory.createConnection();
        Session session = connect.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageProducer producer2 = session.createProducer(shippingQueue2);
        MessageProducer producer3 = session.createProducer(shippingQueue3);
        TextMessage textMsg = session.createTextMessage();
        textMsg.setText("Order message for MDB no interface");
        producer2.send(textMsg);
        producer3.send(textMsg);
        connect.close();
    }
    ....

Da notare il recupero dei riferimenti alle Queue, la costruzione di due producer e l'invio del messaggio sulle code. Alla ricezione dei messaggi, grazie al Connector, vengono invocati i metodi order1() e order2() di ShippingProcessor2.

Ti consigliamo anche