Java >> Java tutorial >  >> Java

Apache TomEE + JMS. Det har aldrig været så nemt.

Jeg husker gamle dage med J2EE (1.3 og 1.4), at det var utroligt svært at starte et projekt ved hjælp af JMS . Du skulle installere en JMS mægler , opret emner eller køer og start endelig din egen kamp med serverkonfigurationsfiler og JNDI .

Tak fra JavaEE 6 og videre ved at bruge JMS er virkelig nemt og enkelt. Men med Apache TomEE er endnu nemmere at komme i gang. I dette indlæg skal vi se, hvordan man opretter og tester en simpel applikation, som sender og modtager beskeder til/fra en JMS kø med Apache TomEE .

Apache TomEE bruger Apache Active MQ som et JMS udbyder. I dette eksempel behøver du ikke downloade eller installere noget, fordi alle elementer vil blive leveret som Maven afhængighed, men hvis du planlægger (og du bør)  brug Apache TomEE server skal du downloade Apache TomEE plus eller Apache TomEE fane. Du kan læse mere om Apache TomEE smag i http://tomee.apache.org/comparison.html.

Afhængigheder

Den første ting at gøre er at tilføje javaee-api som leveret afhængighed og junit og openejb-core som test afhængighed. Bemærk, at openejb-core afhængighed tilføjes for at have en runtime til at udføre test, vi vil se det dybt i testafsnittet.

<dependencies>
  <dependency>
    <groupId>org.apache.openejb</groupId>
    <artifactId>javaee-api</artifactId>
    <version>6.0-6</version>
    <scope>provided</scope>
  </dependency>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.apache.openejb</groupId>
    <artifactId>openejb-core</artifactId>
    <version>4.7.1</version>
    <scope>test</scope>
  </dependency>
</dependencies>

Virksomhedskode

Næste trin er at oprette forretningskoden, der er ansvarlig for at sende beskeder og modtage beskeder fra JMS . Den indeholder også en metode til at modtage beskeder fra . Til dette eksempel vil vi bruge en statsløs EJB .

import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

@Stateless
public class Messages {

  //Standard @Resource annotation is used to inject the ConnectionFactory. 
  //If no name is provided using lookup or name attribute, 
  //the fully qualified name of the class with an slash (/) and the name of the attribute is used. 
  //In this example: java:comp/env/org.superbiz.jms.Messages/connectionFactory.
  @Resource 
  private ConnectionFactory connectionFactory;

  //Standard @Resource annotation is used to inject the Queue. 
  //If no name is provided using lookup or name attribute, 
  //the fully qualified name of the class with an slash (/) and the name of the attribute is used. 
  //In this example: java:comp/env/org.superbiz.injection.jms.Messages/chatQueue.
  @Resource 
  private Queue chatQueue;


  public void sendMessage(String text) throws JMSException {

      Connection connection = null;
      Session session = null;

      try {
          connection = connectionFactory.createConnection();
          //Connection is get from ConnectionFactory instance and it is started.
          connection.start(); 

          //Creates a session to created connection.
          session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 

          //Creates a MessageProducer from Session to the Queue.
          MessageProducer producer = session.createProducer(chatQueue);
          producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); 

          TextMessage message = session.createTextMessage(text);

          //Tells the producer to send the message
          producer.send(message); 
      } finally {
          if (session != null) session.close(); 
          if (connection != null) connection.close();
      }
  }

  public String receiveMessage() throws JMSException {

      Connection connection = null;
      Session session = null;
      MessageConsumer consumer = null;

      try {
          connection = connectionFactory.createConnection();
          connection.start();

          session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

          consumer = session.createConsumer(chatQueue); 

          //Waits for a message with timeout. Note that because a TextMessage is sent, the receive method expects a TextMessage too.
          TextMessage message = (TextMessage) consumer.receive(1000); 

          return message.getText(); 
      } finally {
          if (consumer != null) consumer.close();
          if (session != null) session.close();
          if (connection != null) connection.close();
      }
  }
}

Den vigtigste del af Beskeder klasse er at bemærke, hvor let det er at injicere ConnectionFactory og
instanser inde i kode. Du behøver kun at bruge @Resource annotation og container klarer resten for dig. Bemærk endelig, at fordi vi ikke har brugt navn eller opslag attributter for at angive et navn, bruges feltets navn som ressourcenavn.

Test

Og endelig kan vi skrive en test, der bekræfter, at beskeder sendes og modtages ved hjælp af JMS kø. Vi kunne f.eks. bruge Arquilian for at skrive en test, men i dette tilfælde og på grund af enkelheden vil vi bruge en indlejret OpenEJB forekomst for at implementere JMS eksempel og kør testene.

public class MessagesTest {

  //Messages EJB is injected.
  @EJB
  private Messages messages;

  @Before
  public void setUp() throws Exception {
    Properties p = new Properties();
    //Embedded OpenEJB container is started.
    //And current test added inside created container
    //So we can use javaee annotations inside
    EJBContainer.createEJBContainer(p).getContext().bind("inject", this); 
  }

  @Test
  public void shouldSendAndReceiveMessages() throws Exception {

    //Three messages are sent.
    messages.sendMessage("Hello World!"); 
    messages.sendMessage("How are you?");
    messages.sendMessage("Still spinning?");

    //Three messages are received.
    assertThat(messages.receiveMessage(), is("Hello World!")); 
    assertThat(messages.receiveMessage(), is("How are you?"));
    assertThat(messages.receiveMessage(), is("Still spinning?"));
  }

}

Bemærk, at testen er virkelig enkel og kortfattet, du behøver kun at starte programmatisk en EJB container og bind den aktuelle test inde i den, så vi kan bruge JavaEE annoteringer inde i testen. Resten er en simpel JUnit prøve.

Og hvis du kører testen, vil du modtage en grøn kugle. Men vent, sikkert undrer du dig over, hvor JMS er mægler og dens konfiguration? Hvor er definitionen af ​​ConnectionFactory og JMS ? Og det er her OpenEJB (og Apache TomEE ) kommer i spil.

I dette tilfælde OpenEJB (og Apache TomEE ) vil bruge Apache Active MQ i indlejret tilstand, så du behøver ikke at installere Apache Active MQ på din computer for at køre testene. Desuden Apache TomEE vil oprette alle nødvendige ressourcer til dig. For eksempel vil det oprette en ConnectionFactory og en til dig med standardparametre og forventede navne (org.superbiz.Messages/ connectionFactory til ConnectionFactory og org.superbiz.Messages/chatQueue for Køen ), så du behøver ikke bekymre dig om at konfigurere JMS i testfasen. Apache TomEE er smart nok til at oprette og konfigurere dem for dig.

Du kan inspicere konsoloutput for at indse, at ressourcer er automatisk oprettet ved at læse næste logmeddelelse:INFO:Automatisk oprettelse af en ressource .

Jan 10, 2015 10:32:48 AM org.apache.openejb.config.AutoConfig processResourceRef
INFO: Auto-linking resource-ref 'java:comp/env/org.superbiz.Messages/connectionFactory' in bean Messages to Resource(id=Default JMS Connection Factory)
Jan 10, 2015 10:32:48 AM org.apache.openejb.config.ConfigurationFactory configureService
INFO: Configuring Service(id=org.superbiz.Messages/chatQueue, type=Resource, provider-id=Default Queue)
Jan 10, 2015 10:32:48 AM org.apache.openejb.config.AutoConfig logAutoCreateResource
INFO: Auto-creating a Resource with id 'org.superbiz.Messages/chatQueue' of type 'javax.jms.Queue for 'Messages'.
Jan 10, 2015 10:32:48 AM org.apache.openejb.assembler.classic.Assembler createRecipe
INFO: Creating Resource(id=org.superbiz.Messages/chatQueue)
Jan 10, 2015 10:32:48 AM org.apache.openejb.config.AutoConfig processResourceEnvRef
INFO: Auto-linking resource-env-ref 'java:comp/env/org.superbiz.Messages/chatQueue' in bean Messages to Resource(id=org.superbiz.Messages/chatQueue)
Jan 10, 2015 10:32:48 AM org.apache.openejb.config.ConfigurationFactory configureService
INFO: Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
Jan 10, 2015 10:32:48 AM org.apache.openejb.config.AutoConfig createContainer
INFO: Auto-creating a container for bean javaee.MessagesTest: Container(type=MANAGED, id=Default Managed Container)

Og det er alt, virkelig enkelt og nemt at komme i gang med JMS tak fra Java EE og TomEE . I næste indlæg skal vi se, hvordan man gør det samme, men ved at bruge en Beskeddrevne bønner (MDB).

Java tag