Version 2

    JBoss EJB 3.0 and Extensions

     

    &12488;&12524;&12452;&12523;&65301;&65306;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;Bean&65288;Message Driven Beans&65289;

     

    &12399;&12376;&12417;&12395;&65288;Introduction&65289;

     

    The Java Messaging Service (JMS) is a core service provided by J2EE application servers. It allows services to be invoked asynchronously via messages (e.g., email or IM messages). The server can re-route messages to avoid traffic peaks and respond to service requests based on service-level agreements. As a result, JMS is suitable for implementing highly scalable and reliable enterprise systems.

     

    JMS&65288;Java Messaging Service&65289;&12399;&12289;J2EE&12450;&12503;&12522;&12465;&12540;&12471;&12519;&12531;&12469;&12540;&12496;&12398;&37325;&35201;&12394;&12469;&12540;&12499;&12473;&12398;&19968;&12388;&12391;&12377;&12290;JMS&12391;&12399;&12513;&12483;&12475;&12540;&12472;&65288;&12383;&12392;&12360;&12400;&12289;&38651;&23376;&12513;&12540;&12523;&12420;&12452;&12531;&12473;&12479;&12531;&12488;&12513;&12483;&12475;&12540;&12472;&65288;IM&65289;&12394;&12393;&65289;&12434;&36890;&12375;&12390;&12469;&12540;&12499;&12473;&12434;&38750;&21516;&26399;&12395;&36215;&21205;&12391;&12365;&12414;&12377;&12290;&12469;&12540;&12496;&12399;&12289;&12488;&12521;&12501;&12451;&12483;&12463;&12398;&12500;&12540;&12463;&12434;&36991;&12369;&12390;&12513;&12483;&12475;&12540;&12472;&12398;&36865;&20449;&32076;&36335;&12434;&22793;&26356;&12375;&12383;&12426;&12289;&12469;&12540;&12499;&12473;&12524;&12505;&12523;&22865;&32004;&12395;&24540;&12376;&12383;&12522;&12463;&12456;&12473;&12488;&20966;&29702;&12434;&34892;&12387;&12383;&12426;&12377;&12427;&12371;&12392;&12364;&12391;&12365;&12414;&12377;&12290;&12388;&12414;&12426;&12289;&39640;&12356;&25313;&24373;&24615;&12392;&20449;&38972;&24615;&12434;&25345;&12388;&12456;&12531;&12479;&12540;&12503;&12521;&12452;&12474;&12471;&12473;&12486;&12512;&12434;&27083;&31689;&12377;&12427;&12398;&12395;&36969;&12375;&12390;&12356;&12427;&12398;&12391;&12377;&12290;

     

    The JMS clients send messages to message queues managed by the server (e.g., an email inbox can be a message queue). The message queues are monitored by a special kind of EJBs -- Message Driven Beans (MDBs). The MDB processes the incoming messages and perform the services requested by the message. The MDBs are the end-point for JMS service request messages.

     

    JMS&12398;&12463;&12521;&12452;&12450;&12531;&12488;&12399;&12289;&12469;&12540;&12496;&12364;&31649;&29702;&12377;&12427;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&65288;&12383;&12392;&12360;&12400;&12289;&38651;&23376;&12513;&12540;&12523;&12398;&21463;&20449;&31665;&12418;&19968;&12388;&12398;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&12391;&12377;&65289;&12395;&12513;&12483;&12475;&12540;&12472;&12434;&36865;&20449;&12375;&12414;&12377;&12290;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&12399;&29305;&21029;&12394;EJB&12289;&12377;&12394;&12431;&12385;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;Bean&65288;MDB&65289;&12364;&30435;&35222;&12375;&12414;&12377;&12290;MDB&12399;&23626;&12356;&12383;&12513;&12483;&12475;&12540;&12472;&12434;&20966;&29702;&12375;&12289;&12513;&12483;&12475;&12540;&12472;&12398;&20869;&23481;&12395;&24540;&12376;&12383;&12469;&12540;&12499;&12473;&12434;&23455;&34892;&12375;&12414;&12377;&12290;MDB&12399;JMS&12469;&12540;&12499;&12473;&12398;&35201;&27714;&12513;&12483;&12475;&12540;&12472;&12395;&23550;&12377;&12427;&32066;&31471;&12398;&24441;&30446;&12434;&26524;&12383;&12375;&12414;&12377;&12290;

     

    Developing a MDB in EJB 3.0 is very easy. You just need to implement a simple interface and specify the message queue associated with this bean using annotations.

     

    EJB 3.0&12391;MDB&12434;&38283;&30330;&12377;&12427;&12398;&12399;&38750;&24120;&12395;&31777;&21336;&12391;&12377;&12290;&12450;&12494;&12486;&12540;&12471;&12519;&12531;&12434;&20351;&12387;&12390;Bean&12395;&38306;&36899;&20184;&12369;&12427;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&12434;&25351;&23450;&12375;&12289;&21336;&32020;&12394;&12452;&12531;&12479;&12501;&12455;&12540;&12473;&12434;&23455;&35013;&12377;&12427;&12384;&12369;&12391;&12377;&12290;

     

    &12469;&12531;&12503;&12523;&12450;&12503;&12522;&12465;&12540;&12471;&12519;&12531;&65288;The Sample Application&65289;

     

    In this trail, the investment calculator application is refactored to use a Message Driven Bean. When you click on the "Calculate" button on the web form, the JSP page (calculator.jsp) sends a message containing the calculation parameters to a message queue. It then forwards to another JSP page (check.jsp) to periodically check whether the calculation result becomes available.

     

    &12371;&12398;&12488;&12524;&12452;&12523;&12391;&12399;&12289;&25237;&36039;&35336;&31639;&12450;&12503;&12522;&12465;&12540;&12471;&12519;&12531;&12434;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;Bean&12434;&20351;&12358;&12424;&12358;&12395;&25913;&22793;&12375;&12414;&12377;&12290;Web&12501;&12457;&12540;&12512;&12398;&12300;Calculate&12301;&12508;&12479;&12531;&12434;&12463;&12522;&12483;&12463;&12377;&12427;&12392;&12289;JSP&12506;&12540;&12472;&65288;calculator.jsp&65289;&12399;&35336;&31639;&29992;&12398;&24341;&25968;&12434;&25345;&12388;&12513;&12483;&12475;&12540;&12472;&12434;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&12395;&36865;&20449;&12375;&12414;&12377;&12290;&12381;&12375;&12390;&27425;&12395;&21029;&12398;JSP&12506;&12540;&12472;&65288;check.jsp&65289;&12395;&31227;&12426;&12289;&23450;&26399;&30340;&12395;&35336;&31639;&32080;&26524;&12364;&21462;&24471;&12391;&12365;&12427;&12363;&12393;&12358;&12363;&12481;&12455;&12483;&12463;&12375;&12414;&12377;&12290;

     

    The message queue is monitored by a MDB, which retrieves the incoming message, parses its contents, and performs the calculation. After the calculation is done, the MDB saves the result to an application-wide shared cache. The result is then picked up and displayed by the result-monitoring JSP page (i.e., check.jsp).

     

    MDB&12399;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&12434;&30435;&35222;&12375;&12289;&23626;&12356;&12383;&12513;&12483;&12475;&12540;&12472;&12434;&21462;&24471;&12375;&12289;&20869;&23481;&12434;&36208;&26619;&12375;&12289;&12381;&12375;&12390;&35336;&31639;&12434;&34892;&12356;&12414;&12377;&12290;&35336;&31639;&12364;&32066;&12431;&12427;&12392;&12289;&32080;&26524;&12434;&12450;&12503;&12522;&12465;&12540;&12471;&12519;&12531;&20840;&20307;&12391;&20849;&26377;&12375;&12390;&12356;&12427;&12461;&12515;&12483;&12471;&12517;&12395;&20445;&23384;&12375;&12414;&12377;&12290;&32080;&26524;&12399;&32080;&26524;&30435;&35222;JSP&12506;&12540;&12472;&65288;&12377;&12394;&12431;&12385;&12289;check.jsp&65289;&12364;&12500;&12483;&12463;&12450;&12483;&12503;&12375;&12289;&32080;&26524;&12434;&34920;&31034;&12375;&12414;&12377;&12290;

     

    &12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;Bean&65288;The Message Driven Bean&65289;

     

    In EJB 3.0, the MDB bean class is annotated with the @MessageDriven annotation, which specifies which message queue this MDB monitors (i.e., queue/mdb). If the queue does not exist, the JBoss container automatically creates it at deploy time. There is no XML configuration file needed!

     

    EJB 3.0&12391;&12399;&12289;MDB&12398;Bean&12463;&12521;&12473;&12395;@MessageDriven&12450;&12494;&12486;&12540;&12471;&12519;&12531;&12434;&20351;&29992;&12375;&12390;&12289;&12393;&12398;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&12434;&30435;&35222;&12377;&12427;&12363;&65288;&12377;&12394;&12431;&12385;&12289;queue/mdb&12394;&12393;&65289;&12434;&25351;&23450;&12375;&12414;&12377;&12290;&12461;&12517;&12540;&12364;&23384;&22312;&12375;&12394;&12356;&22580;&21512;&12399;JBoss&12467;&12531;&12486;&12490;&12364;&12487;&12503;&12525;&12452;&26178;&12395;&33258;&21205;&30340;&12395;&20316;&25104;&12375;&12414;&12377;&12290;XML&35373;&23450;&12501;&12449;&12452;&12523;&12399;&24517;&35201;&12354;&12426;&12414;&12379;&12435;&65281;

     

    The bean class needs to implement the MessageListener interface, which defines only one method onMessage(). When a message arrives in the queue monitored by this MDB, the JBoss container calls the bean class's onMessage() method and pass the incoming message in as the call parameter. In our example, the CalculatorBean.onMessage() method retrieves the message body, parses out the calculation parameters, performs the calculation, and saves the result to a static data manager class for the JSP page to pick up. The "sent" time stamp on the service request message serves as the unique ID for the calculation record (it works well for low volume web sites). A check.jsp JSP page picks up and displays the calculation record based on the message ID.

     

    Bean&12463;&12521;&12473;&12399;MessageListener&12452;&12531;&12479;&12501;&12455;&12540;&12473;&12434;&23455;&35013;&12377;&12427;&24517;&35201;&12364;&12354;&12426;&12414;&12377;&12290;MessageListener&12452;&12531;&12479;&12501;&12455;&12540;&12473;&12399;onMessage()&12513;&12477;&12483;&12489;&12434;&65297;&12388;&12384;&12369;&23450;&32681;&12375;&12390;&12356;&12414;&12377;&12290;MDB&12364;&30435;&35222;&12377;&12427;&12461;&12517;&12540;&12395;&12513;&12483;&12475;&12540;&12472;&12364;&23626;&12367;&12392;&12289;JBoss&12467;&12531;&12486;&12490;&12399;Bean&12463;&12521;&12473;&12398;onMessage()&12513;&12477;&12483;&12489;&12434;&21628;&12403;&12289;&21463;&20449;&12375;&12383;&12513;&12483;&12475;&12540;&12472;&12434;&24341;&25968;&12391;&28193;&12375;&12414;&12377;&12290;&12371;&12398;&20363;&12391;&12399;&12289;CalculatorBean.onMessage()&12513;&12477;&12483;&12489;&12399;&12289;&12513;&12483;&12475;&12540;&12472;&26412;&20307;&12434;&21462;&24471;&12375;&12289;&35336;&31639;&29992;&24341;&25968;&12434;&20999;&12426;&20986;&12375;&12289;&35336;&31639;&12434;&34892;&12356;&12289;JSP&12506;&12540;&12472;&12364;&32080;&26524;&12434;&21463;&12369;&21462;&12428;&12427;&12424;&12358;&12395;&12289;&32080;&26524;&12434;&38745;&30340;&12394;&12487;&12540;&12479;&31649;&29702;&12463;&12521;&12473;&12395;&20445;&23384;&12375;&12414;&12377;&12290;&12469;&12540;&12499;&12473;&35201;&27714;&12513;&12483;&12475;&12540;&12472;&20869;&12398;&12479;&12452;&12512;&12473;&12479;&12531;&12503;"sent"&12434;&35336;&31639;&32080;&26524;&12524;&12467;&12540;&12489;&12398;&19968;&24847;&12394;ID&12392;&12375;&12390;&20351;&29992;&12375;&12390;&12356;&12414;&12377;&65288;&20966;&29702;&37327;&12398;&23569;&12394;&12356;web&12469;&12452;&12488;&12391;&12399;&21313;&20998;&27231;&33021;&12375;&12414;&12377;&65289;&12290;JSP&12506;&12540;&12472;check.jsp&12399;&12371;&12398;&12513;&12483;&12475;&12540;&12472;ID&12434;&12418;&12392;&12395;&35336;&31639;&32080;&26524;&12524;&12467;&12540;&12489;&12434;&12500;&12483;&12463;&12450;&12483;&12503;&12375;&12289;&20869;&23481;&12434;&34920;&31034;&12375;&12414;&12377;&12290;

     

     @MessageDriven(activationConfig =
     {
       @ActivationConfigProperty(propertyName="destinationType",
         propertyValue="javax.jms.Queue"),
       @ActivationConfigProperty(propertyName="destination",
         propertyValue="queue/mdb")
     })
     public class CalculatorBean implements MessageListener {
     
       public void onMessage (Message msg) {
         try {
           TextMessage tmsg = (TextMessage) msg;
           Timestamp sent =
               new Timestamp(tmsg.getLongProperty("sent"));
           StringTokenizer st =
               new StringTokenizer(tmsg.getText(), ",");
     
           int start = Integer.parseInt(st.nextToken());
           int end = Integer.parseInt(st.nextToken());
           double growthrate = Double.parseDouble(st.nextToken());
           double saving = Double.parseDouble(st.nextToken());
     
           double result =
               calculate (start, end, growthrate, saving);
           RecordManager.addRecord (sent, result);
     
         } catch (Exception e) {
           e.printStackTrace ();
         }
       }
     
       // ... ...
     }
    

     

    Bean&12395;&12513;&12483;&12475;&12540;&12472;&12434;&36865;&20449;&12377;&12427;&65288;Send a Message to the Bean&65289;

     

    To use the message driven bean, the client (i.e, JSP page calculator.sjp in this case) use the standard JMS API to obtain the target message queue to the MDB using the queue name (queue/mdb), and then send the message to the queue.

     

    &12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;Bean&12434;&20351;&29992;&12377;&12427;&12395;&12399;&12289;&12463;&12521;&12452;&12450;&12531;&12488;&65288;&12371;&12398;&22580;&21512;&12399;JSP&12506;&12540;&12472;calculator.jsp&65289;&12391;&27161;&28310;JMS API&12434;&20351;&12387;&12390;&12289;&30446;&30340;&12398;MDB&12395;&23550;&24540;&12377;&12427;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&12434;&12461;&12517;&12540;&21517;&65288;queue/mdb&65289;&12391;&21462;&24471;&12375;&12289;&12381;&12398;&12461;&12517;&12540;&12395;&12513;&12483;&12475;&12540;&12472;&12434;&36865;&20449;&12375;&12414;&12377;&12290;

     

     try {
         InitialContext ctx = new InitialContext();
         queue = (Queue) ctx.lookup("queue/mdb");
         QueueConnectionFactory factory =
             (QueueConnectionFactory) ctx.lookup("ConnectionFactory");
         cnn = factory.createQueueConnection();
         sess = cnn.createQueueSession(false,
                 QueueSession.AUTO_ACKNOWLEDGE);
     
     } catch (Exception e) {
         e.printStackTrace ();
     }
       
     TextMessage msg = sess.createTextMessage(
         request.getParameter ("start") + "," +
         request.getParameter ("end") + "," +
         request.getParameter ("growthrate") + "," +
         request.getParameter ("saving")
     );
     
     sender = sess.createSender(queue);
     sender.send(msg);
    

     

    &12477;&12540;&12473;&12467;&12540;&12489;&21442;&29031;&65288;Complete Source Code&65289;

     

    &12469;&12540;&12496;&65288;Server&65289;

     

    • CalculatorBean.java: The message driven bean that listens at the queue/mdb queue, processes the service request message and performs the investment calculation

    • CalculationRecord.java: A data object class to store one calculation result from CalculatorBean. The object is uniquely identified by the service request message's "sent" time stamp.

    • RecordManager.java: A static class that manages system-wide CalculationRecord objects. It only keeps the last 100 records and can find a record based on its request message's "sent" time stamp.

     

    • CalculatorBean.java: queue/mdb&12461;&12517;&12540;&12434;&30435;&35222;&12375;&12289;&12469;&12540;&12499;&12473;&35201;&27714;&12513;&12483;&12475;&12540;&12472;&12434;&20966;&29702;&12375;&12289;&25237;&36039;&35336;&31639;&12434;&34892;&12358;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;Bean

    • CalculationRecord.java: CalculatorBean&12364;&34892;&12358;&21508;&35336;&31639;&32080;&26524;&12434;&20445;&23384;&12377;&12427;&12487;&12540;&12479;&12458;&12502;&12472;&12455;&12463;&12488;&12463;&12521;&12473;&12290;&12458;&12502;&12472;&12455;&12463;&12488;&12399;&12289;&12469;&12540;&12499;&12473;&35201;&27714;&12513;&12483;&12475;&12540;&12472;&12398;&12479;&12452;&12512;&12473;&12479;&12531;&12503;"sent"&12391;&19968;&24847;&12395;&35672;&21029;&12373;&12428;&12427;&12290;

    • RecordManager.java: &12471;&12473;&12486;&12512;&20840;&20307;&12391;CalculationRecord&12458;&12502;&12472;&12455;&12463;&12488;&12434;&31649;&29702;&12377;&12427;&38745;&30340;&12463;&12521;&12473;&12290;&26368;&26032;&12398;100&12524;&12467;&12540;&12489;&12398;&12415;&20445;&25345;&12375;&12289;&12524;&12467;&12540;&12489;&12399;&35201;&27714;&12513;&12483;&12475;&12540;&12472;&12398;&12479;&12452;&12512;&12473;&12479;&12531;&12503;"sent"&12434;&12418;&12392;&12395;&26908;&32034;&12391;&12365;&12427;&12290;

     

    &12463;&12521;&12452;&12450;&12531;&12488;&65288;Client&65289;

     

    • calculator.jsp: The client JSP that takes user input and sends the calculation service request message.

    • check.jsp: The client JSP that uses the RecordManager static class to check whether the CalculatorBean has finished processing a certain service request message identified by the message's "sent" time stamp.

     

    • calculator.jsp: &12518;&12540;&12470;&12363;&12425;&12398;&20837;&21147;&12434;&21463;&12369;&21462;&12426;&12289;&25237;&36039;&35336;&31639;&12398;&12469;&12540;&12499;&12473;&35201;&27714;&12513;&12483;&12475;&12540;&12472;&12434;&36865;&20449;&12377;&12427;&12463;&12521;&12452;&12450;&12531;&12488;JSP&12290;

    • check.jsp: &38745;&30340;&12463;&12521;&12473;RecordManager&12434;&20351;&29992;&12375;&12390;CalculatorBean&12398;&20966;&29702;&12364;&32066;&20102;&12377;&12427;&12398;&12434;&24453;&12388;&12463;&12521;&12452;&12450;&12531;&12488;JSP&12290;&24453;&27231;&12377;&12427;&12469;&12540;&12499;&12473;&35201;&27714;&12513;&12483;&12475;&12540;&12472;&12399;&12289;&12513;&12483;&12475;&12540;&12472;&12398;&12479;&12452;&12512;&12473;&12479;&12531;&12503;"sent"&12391;&35672;&21029;&12373;&12428;&12427;&12290;

     

    &12414;&12392;&12417;&65288;Summary&65289;

     

    In this trail, we covered how to implement a Message Driven Bean in EJB 3.0. The @MessageDriven annotation eliminated the need for complex configuration files. However, the message driven bean itself is still not a POJO -- it still need to implement the MessageListener interface. In JBoss AS, we provide another more elegant way to provide messaging services. Read on to the next trail.

     

    &12371;&12398;&12488;&12524;&12452;&12523;&12391;&12399;&12289;EJB 3.0&12395;&12362;&12369;&12427;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;Bean&12398;&23455;&35013;&26041;&27861;&12395;&12388;&12356;&12390;&23398;&12403;&12414;&12375;&12383;&12290;@MessageDriven&12450;&12494;&12486;&12540;&12471;&12519;&12531;&12434;&20351;&12358;&12371;&12392;&12395;&12424;&12426;&12289;&35079;&38609;&12394;&35373;&23450;&12501;&12449;&12452;&12523;&12399;&24517;&35201;&12394;&12367;&12394;&12426;&12414;&12377;&12290;&12375;&12363;&12375;&12289;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;Bean&12381;&12398;&12418;&12398;&12399;POJO&12391;&12399;&12394;&12367;&12289;MessageListener&12452;&12531;&12479;&12501;&12455;&12540;&12473;&12434;&23455;&35013;&12377;&12427;&24517;&35201;&12364;&12354;&12426;&12414;&12377;&12290;JBoss AS&12391;&12399;&12289;&12373;&12425;&12395;&12456;&12524;&12460;&12531;&12488;&12394;&12513;&12483;&12475;&12540;&12472;&12469;&12540;&12499;&12473;&12434;&25552;&20379;&12377;&12427;&21029;&12398;&26041;&27861;&12434;&29992;&24847;&12375;&12390;&12356;&12414;&12377;&12290;&12391;&12399;&32154;&12369;&12390;&27425;&12398;&12488;&12524;&12452;&12523;&12395;&36914;&12435;&12391;&12415;&12414;&12375;&12423;&12358;&12290;

     

    (c) 2005 JBoss, Inc. All Rights Reserved