Hlavní navigace

Glassfish v2 9.1_02 + ActiveMQ 5.2.0 + Example

23. 1. 2009 19:43 (aktualizováno) bardolf

Tento zapisek zcela vychazi z http://weblogs.java.net/blog/ram­psarathy/archive/2007/03/glas­sfish_v2_an.html, kde se snazim celou situaci namapovat na uvedene verze s tim, ze opravim male drobnosti, pripadne uvest nekde doplnujici info. Uvedeny priklad bude v EJB3 (kombinace anotaci a xml descriptoru), prestoze v prvotnim testovani je volani JNDI nejlepsi zpusob debugovani. Cilem je pouzit Active MQ jako JMS providera v AS Glassfish a schopnost poslat/prijmout zpravu pomoci tohoto providera.

  1. Instalace Glassfish a ActiveMQ. Spustime oba servery.
  2. Zmena classpath v Glassfish. Nakopirujeme soubory activemq-core-5.2.0.jar a commons-logging-1.1.1.jar do ${GLASSFISH_HOME}/lib/ a nastaveni Application Server → JVM Settings → Path Settings → Classpath Suffix na hodnotu:activemq-core-5.2.0.jar, commons-logging-1.1.1.jar. AS je potreba restartovat.
  3. Vytvoreni pozadovanych front. V jednoduche Java aplikaci vytvorime instance ActiveMQQueue a ActiveMQXAConnectionFactory (a dalsi pro nas nedulezite) a ulozime je do JNDI stromu, ktery bude ulozen na filesystemu.

    public static void main(String[] args) {
     try {
      Properties props = new Properties();
      props.put(„java.naming.fac­tory.initial“, „com.sun.jndi.fscontext.Ref­FSContextFactory“);
      props.put(„java.naming.provider.url“, „file:/home/nemecm/activemqobjects“);
      InitialContext jndiContext = new InitialContext(props);
      ActiveMQQueue mq = new ActiveMQQueue(„Send“);
      ActiveMQQueue outmq = new ActiveMQQueue(„Receive“);

      ActiveMQTopic top = new ActiveMQTopic(„ReceiveTopic“);
      ActiveMQXAConnectionFactory confac = new ActiveMQXAConnectionFactory();
      ActiveMQConnectionFactory confac1 = new ActiveMQConnectionFactory();
      jndiContext.rebind(„Send“, mq);
      jndiContext.rebind(„Receive“, outmq);
      jndiContext.rebind(„ReceiveTopic“, top);
      jndiContext.rebind(„acti­vemqconnectionfactory“, confac);
      jndiContext.rebind(„acti­vemqnonxaconnectionfactory“, confac1);
     }catch (Exception e) {
      System.out.println("Could not create JNDI " + "context: "+ e.toString());
      e.printStackTrace();
      System.exit(1);
     }
    }

    Jen upozornim ze knihovnu fscontext.jar je mozno nalezt v ${GLASSFISH_HOME}/imq/lib, dale posledni element v ceste (zde activemqobjects) je adresar a musi existovat pred spustenim programu.

  4. Konfigurace AS Glassfish. Vsechny konfiguracni kroky predpokladaji existenci souboru ~/.aspasswd obsahujici heslo k AS (defaultne adminadmin) a prikazy jsou spousteny v ${GLASSFISH_HOME}/bin.
  5. Konfigurace modulu konektoru.

    ./asadmin create-resource-adapter-config –user admin –passwordfile ~/.aspasswd
    –property SupportsXA=true:ProviderIn­tegrationMode=jndi:RMPoli­cy=OnePerPhysicalConnecti­on: JndiProperties=java.namin­g.factory.initial\\=com.sun­.jndi.fscontext.RefFSContex­tFactory, java.naming.provider.url\\=fi­le\\:/home/nemecm/activem­qobjects:LogLevel=FINEST genericra

  6. Deploy resource adapteru

    ./asadmin deploy –user admin –passwordfile ~/.aspasswd ~/servers/glassfish/lib/ad­dons/resourceadapters/gene­ricjmsra/genericra.rar

  7. Vytvoreni 2 connection poolu a jejich nasmerovani na instanci ActiveMQConnectionFactory ulozenou v JNDI.

    ./asadmin create-connector-connection-pool –raname genericra –connectiondefinition javax.jms.QueueConnectionFactory –transactionsupport XATransaction –property ConnectionFactoryJndiName=ac­tivemqconnectionfactory in­pool

    ./asadmin create-connector-connection-pool –raname genericra –connectiondefinition javax.jms.QueueConnectionFactory –transactionsupport XATransaction –property ConnectionFactoryJndiName=ac­tivemqconnectionfactory outpool

  8. Vytvoreni kontektor resourcu

    ./asadmin create-connector-resource –poolname inpool jms/inboundXAQCF

    ./asadmin create-connector-resource –poolname outpool jms/outboundXAQCF

  9. Vytvoreni JMS resourcu.

    ./asadmin create-admin-object –raname genericra –restype javax.jms.Queue –property DestinationJndiName=Receive jms/inqueue

    ./asadmin create-admin-object –raname genericra –restype javax.jms.Queue –property DestinationJndiName=Send jms/outqueue

  10. Priklad. Slibovana ukazka bude zasilat message do fronty, ktere je mozno snadno prohlizet v administracnim rozhrani ActiveMQ. Cteni teto zpravy, tedy vytvoreni Message Driven Beany by uz nemel byt zadny problem. Protoze od zacatku pracujeme s transakcnimi verzemi implementaci (zde XA) je nutno volat samotne odeslani v ramci transakce. Neni tedy mozno poslat message jednoduse napr. ze servletu, ale bude vytvorena session beana s BMT. V pripade, ze bychom se presto pokusili poslat message ze netransakcniho prostredi dostaneme podobnou vyjimku

    Session's XAResource has not been enlisted in a distributed transaction.

    Bussines interface

    public interface ExchangeRateProducer {
     void sendExchangeRate(String xml);
    }

    a jeho implementace

    public class ExchangeRateProducerBean implements ExchangeRateProducer {
     private static Log log = LogFactory.getLog(Exchange­RateProducerBean.class);
     @Resource(name=„connectionFactory“)
     private ConnectionFactory connectionFactory;
     @Resource(name=„queue“)
     private Queue queue;
     @Resource
     private SessionContext context;

     public void sendExchangeRate(String xml) {
      UserTransaction transaction = context.getUserTransaction();
      try {
       try {
        transaction.begin();
        Connection connection = connectionFactory.createConnection();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageProducer producer = session.createProducer(queue);
        TextMessage msg = session.createTextMessage();
        msg.setText(xml);
        producer.send(msg);
        session.close();
        connection.close();
        transaction.commit();
       } catch (JMSException e) {
        log.error(„JMSException catched.“, e);
        transaction.rollback();
       }
       } catch (Exception e) {
        log.error(„Exception occured.“, e);
       }
      }
     }
    }

    Male intermezzo: this blog engine SUCKS! Nenasel jsem jednoduchy zpusob (popravde nemam moc chut neco zkoumat) jak vlozit xml text, zalamovani je tragicke. Asi to neni urceno k zamerum jake jsem jsou mnou ocekavany. Asi budu muset postovat podobne zapisky jinam ;-(

    Urcite jsou potreba ejb-jar.xml a sub-ejb-jar.xml, ale zvyse uvedenych duvodu nemam silu to ted resit. Takze ne zcela spravne nejprve ejb-jar.xml

    [enterprise-beans]
     [session]
      [ejb-name]ExchangeRateProducer[/ejb-name]
      [business-remote]com.ness.csa.vhoz.tes­t.services.ExchangeRatePro­ducer[/business-remote]
      [ejb-class]com.ness.csa.vhoz.tes­t.services.ExchangeRatePro­ducerBean[/ejb-class]
      [session-type]Stateless[/session-type]
      [transaction-type]Bean[/transaction-type]
      [resource-ref]
        [res-ref-name]connectionFactory[/res-ref-name]
        [res-auth]Container[/res-auth]
        [mapped-name]jms/outboundXAQCF[/mapped-name]
      [/resource-ref]
      [resource-ref]
        [res-ref-name]queue[/res-ref-name]
        [res-type]javax.jms.Queue[/res-type]
        [mapped-name]jms/outqueue[/mapped-name]
      [/resource-ref]
      [/session]
     [/enterprise-beans]

    a sun-ejb-jar.xml

    [sun-ejb-jar]
     [enterprise-beans]
      [ejb]
        [ejb-name]ExchangeRateProducer[/ejb-name]
        [jndi-name]ejb/ExchangeRateProducer[/jndi-name]
      [/ejb]
     [/enterprise-beans]
    [/sun-ejb-jar]

    Po zavolani metody sendExchangeRate(„ahoj“) je mozno prohlednout ziskat tento vysledek v browseru

Tak to je snad vse, mozna nejsou dobre mapovany fronty Receive a Send v obrazich a v kodu, ale to je jen vysledek ruznych testovani ;-).

Bardolf