Version 3

    JBoss EJB 3.0 and Extensions

     

    &12488;&12524;&12452;&12523;&65302;&65306;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&65288;Message Driven POJOs&65289;

     

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

     

    While message driven bean is very powerful and flexible, it is perhaps too flexible for many messaging-based remote procedure call (RPC) applications. The client and the bean must agree on the message queue to use and the exact message exchange format. That is a bit of hassle for developers who just want to make reliable asynchronous RPCs over message channels. It is also a source of potential runtime errors as the coupling between the client and the message end point is not checked by the compiler. In addition, the EJB 3.0 message driven bean is still a "component" that has to implement the MessageListener interface -- it is not a POJO.

     

    &12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;Bean&12399;&38750;&24120;&12395;&24375;&21147;&12391;&26580;&36575;&12391;&12377;&12364;&12289;&12513;&12483;&12475;&12540;&12472;&22411;&12398;&36960;&38548;&25163;&32154;&12365;&21628;&12403;&20986;&12375;&65288;RPC&65289;{FOOTNOTE DEF 1 1}&12391;&12399;&26580;&36575;&12377;&12366;&12390;&12375;&12414;&12358;&22580;&21512;&12418;&22810;&12356;&12391;&12375;&12423;&12358;&12290;&12463;&12521;&12452;&12450;&12531;&12488;&12392;Bean&12392;&12398;&38291;&12391;&12289;&20351;&29992;&12377;&12427;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&12392;&27491;&30906;&12394;&12513;&12483;&12475;&12540;&12472;&20132;&25563;&24418;&24335;&12434;&20107;&21069;&12395;&21462;&12426;&27770;&12417;&12390;&12362;&12367;&24517;&35201;&12364;&12354;&12426;&12414;&12377;&12290;&21336;&12395;&12513;&12483;&12475;&12540;&12472;&12481;&12515;&12493;&12523;&12434;&21033;&29992;&12375;&12390;&20449;&38972;&24615;&12398;&39640;&12356;&38750;&21516;&26399;RPC&12434;&34892;&12356;&12383;&12356;&12384;&12369;&12398;&38283;&30330;&32773;&12395;&12392;&12387;&12390;&12399;&12289;&12371;&12428;&12399;&23569;&12375;&38754;&20498;&12394;&12371;&12392;&12391;&12377;&12290;&12414;&12383;&12289;&12463;&12521;&12452;&12450;&12531;&12488;&12392;&12513;&12483;&12475;&12540;&12472;&12398;&32066;&31471;&12392;&12398;&38291;&12398;&30456;&24615;&12399;&12467;&12531;&12497;&12452;&12523;&26178;&12395;&12399;&26908;&26619;&12373;&12428;&12394;&12356;&12383;&12417;&12289;&23455;&34892;&26178;&12456;&12521;&12540;&12398;&21407;&22240;&12392;&12394;&12427;&21487;&33021;&24615;&12364;&12354;&12426;&12414;&12377;&12290;&12373;&12425;&12395;&12289;EJB 3.0&12398;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;Bean&12399;MessageListener&12452;&12531;&12479;&12501;&12455;&12540;&12473;&12434;&23455;&35013;&12375;&12394;&12369;&12428;&12400;&12394;&12425;&12394;&12356;&12300;&12467;&12531;&12509;&12540;&12493;&12531;&12488;&12301;&12398;&12414;&12414;&12391;&12377;&12290;&12388;&12414;&12426;&12289;POJO&12391;&12399;&12394;&12356;&12398;&12391;&12377;&12290;

     

    {FOOTNOTE RED #1 1} &12371;&12371;&12395;&12300;&12450;&12503;&12522;&12465;&12540;&12471;&12519;&12531;&12301;&12364;&27442;&12375;&12356; -tokobayashi

     

    In JBoss's EJB 3.0 application server, there is an easier way to implement message driven RPCs. You can use POJOs as message end-points (message driven POJO). The RPC caller retrieves a automatically generated stub of the POJO and make regular calls against the POJO methods. The JBoss message driven POJO works very much like an EJB 3.0 session bean, except that all calls are tunneled via a message queue. In this trail, we will discuss how message driven POJOs are used in JBoss.

     

    JBoss EJB 3.0&12450;&12503;&12522;&12465;&12540;&12471;&12519;&12531;&12469;&12540;&12496;&12391;&12399;&12289;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;&12398;RPC&12434;&23455;&35013;&12377;&12427;&12383;&12417;&12398;&12289;&12424;&12426;&31777;&21336;&12394;&26041;&27861;&12434;&25552;&20379;&12375;&12390;&12356;&12414;&12377;&12290;&12513;&12483;&12475;&12540;&12472;&12398;&32066;&31471;&12392;&12375;&12390;POJO&12434;&20351;&29992;&12391;&12365;&12414;&12377;&65288;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&65289;&12290;RPC&12398;&21628;&12403;&20986;&12375;&20596;&12399;&33258;&21205;&29983;&25104;&12373;&12428;&12383;POJO&12398;&12473;&12479;&12502;&12434;&21462;&24471;&12375;&12289;POJO&12513;&12477;&12483;&12489;&12395;&23550;&12375;&12390;&36890;&24120;&36890;&12426;&12398;&21628;&12403;&20986;&12375;&12434;&34892;&12356;&12414;&12377;&12290;JBoss&12398;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&12399;EJB 3.0&12398;&12475;&12483;&12471;&12519;&12531;Bean&12392;&12411;&12392;&12435;&12393;&21516;&12376;&12424;&12358;&12395;&21205;&20316;&12375;&12414;&12377;&12290;&36949;&12356;&12399;&12289;&12377;&12409;&12390;&12398;&21628;&12403;&20986;&12375;&12364;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&12434;&32076;&30001;&12377;&12427;&12371;&12392;&12391;&12377;&12290;&12371;&12398;&12488;&12524;&12452;&12523;&12391;&12399;&12289;JBoss&12398;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&12398;&20351;&12356;&26041;&12395;&12388;&12356;&12390;&35696;&35542;&12375;&12414;&12377;&12290;

     

    &12469;&12531;&12503;&12523;&12450;&12503;&12522;&12465;&12540;&12471;&12519;&12531;&65288;The sample application&65289;

     

    In this sample application, the JSP page calculator.jsp asynchronously invokes the calculation method on a message driven POJO over a message queue. After the message driven POJO finishes the calculation, it saves the result in a server wide cache manager. The check.jsp page checks the result in the cache and displays the result when it becomes available. It works similar to the sample application in the message driven bean trail.

     

    &12371;&12398;&12488;&12524;&12452;&12523;&12398;&12469;&12531;&12503;&12523;&12450;&12503;&12522;&12465;&12540;&12471;&12519;&12531;&12391;&12399;&12289;JSP&12506;&12540;&12472;calculator.jsp&12364;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&12434;&36890;&12375;&12390;&12289;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&12398;&35336;&31639;&12513;&12477;&12483;&12489;&12434;&38750;&21516;&26399;&12395;&21628;&12403;&20986;&12375;&12414;&12377;&12290;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&12399;&35336;&31639;&12434;&32066;&12360;&12427;&12392;&12289;&32080;&26524;&12434;&12471;&12473;&12486;&12512;&12398;&12461;&12515;&12483;&12471;&12517;&12510;&12493;&12540;&12472;&12515;&12395;&20445;&23384;&12375;&12414;&12377;&12290;check.jsp&12506;&12540;&12472;&12364;&12461;&12515;&12483;&12471;&12517;&20869;&12398;&32080;&26524;&12434;&12481;&12455;&12483;&12463;&12375;&12289;&32080;&26524;&12434;&21462;&24471;&12391;&12365;&12383;&12425;&34920;&31034;&12375;&12414;&12377;&12290;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;Bean&12398;&12488;&12524;&12452;&12523;&12391;&29992;&12356;&12383;&12469;&12531;&12503;&12523;&12450;&12503;&12522;&12465;&12540;&12471;&12519;&12531;&12392;&21516;&12376;&12424;&12358;&12394;&21205;&12365;&12434;&12375;&12414;&12377;&12290;

     

    POJO&12499;&12472;&12493;&12473;&12452;&12531;&12479;&12501;&12455;&12540;&12473;&65288;The POJO business interface&65289;

     

    To define a message driven POJO, you first have to define a business interface for it. The business interface is marked with the @Producer annotation. Note that the methods declared in this interface cannot return values. The method call against a message driven POJO is asynchronous and the caller does not block to wait for return values.

     

    &12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&12434;&23450;&32681;&12377;&12427;&12395;&12399;&12289;&12414;&12378;&12499;&12472;&12493;&12473;&12452;&12531;&12479;&12501;&12455;&12540;&12473;&12434;&23450;&32681;&12375;&12414;&12377;&12290;&12499;&12472;&12493;&12473;&12452;&12531;&12479;&12501;&12455;&12540;&12473;&12395;&12399;@Producer&12450;&12494;&12486;&12540;&12471;&12519;&12531;&12434;&25351;&23450;&12375;&12414;&12377;&12290;&12371;&12398;&12452;&12531;&12479;&12501;&12455;&12540;&12473;&12391;&23450;&32681;&12377;&12427;&12513;&12477;&12483;&12489;&12399;&32080;&26524;&12434;&36820;&12379;&12394;&12356;&12371;&12392;&12395;&27880;&24847;&12375;&12390;&12367;&12384;&12373;&12356;&12290;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&12395;&23550;&12377;&12427;&12513;&12477;&12483;&12489;&21628;&12403;&20986;&12375;&12399;&38750;&21516;&26399;&12395;&34892;&12431;&12428;&12289;&21628;&12403;&20986;&12375;&20596;&12399;&32080;&26524;&12434;&24453;&12385;&12414;&12379;&12435;&12290;

     

     @Producer
     public interface Calculator {
     
       public void doCalculation (long sent, int start, int end,
                                  double growthrate,
                                  double saving);
     }
    

     

    &12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&12398;&23455;&35013;&65288;The message driven POJO implementation&65289;

     

    The implementation of the message driven POJO is tagged with the @Consumer annotation. You can specify the message queue property in the annotation attribute. Again, if a message queue is un-defined, JBoss will create one for you at server start-up.

     

    &12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&12398;&23455;&35013;&12395;&12399;@Consumer&12450;&12494;&12486;&12540;&12471;&12519;&12531;&12434;&20351;&29992;&12375;&12414;&12377;&12290;&12450;&12494;&12486;&12540;&12471;&12519;&12531;&12398;&23646;&24615;&12395;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&12398;&12503;&12525;&12497;&12486;&12451;&12434;&25351;&23450;&12391;&12365;&12414;&12377;&12290;&12371;&12371;&12391;&12418;&21516;&27096;&12395;&12289;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&12364;&26410;&23450;&32681;&12398;&22580;&21512;&12399;JBoss&12364;&12469;&12540;&12496;&36215;&21205;&26178;&12395;&20316;&25104;&12375;&12414;&12377;&12290;

     

     @Consumer(activationConfig =
     {
       @ActivationConfigProperty(propertyName="destinationType",
         propertyValue="javax.jms.Queue"),
       @ActivationConfigProperty(propertyName="destination",
         propertyValue="queue/mdpojo")
     })
     public class CalculatorBean implements Calculator {
     
       public void doCalculation (long sent, int start, int end,
                                  double growthrate, double saving) {
     
         double result = calculate (start, end, growthrate, saving);
     
         // Save in the system's results cache
         RecordManager.addRecord (new Timestamp(sent), result);
       }
     
       private double calculate (int start, int end,
                                 double growthrate, double saving) {
         // ... ...
       }
     
     }
    

     

    &12463;&12521;&12452;&12450;&12531;&12488;&65288;The client&65289;

     

    To use the message driven POJO on the client side, you have to lookup a stub object of the @Producer interface from the JNDI. The auto-generated stub object not only implements the @Producer interface but also a component interface named ProducerObject. Using the ProducerObject.getProducerManager() method, you can get a ProducerManager object, which is used to make JMS connections. After a JMS connection is established, you can call any method in the @Producer stub object and the method is actually invoked over the pre-defined message queue. The following code snippet shows how the message driven POJO client works.

     

    &12463;&12521;&12452;&12450;&12531;&12488;&20596;&12391;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&12434;&20351;&29992;&12377;&12427;&12395;&12399;&12289;JNDI&12434;&20351;&12387;&12390;@Producer&12452;&12531;&12479;&12501;&12455;&12540;&12473;&12398;&12473;&12479;&12502;&12458;&12502;&12472;&12455;&12463;&12488;&12434;&12523;&12483;&12463;&12450;&12483;&12503;&12375;&12414;&12377;&12290;&33258;&21205;&29983;&25104;&12373;&12428;&12427;&12473;&12479;&12502;&12458;&12502;&12472;&12455;&12463;&12488;&12399;&12289;@Producer&12452;&12531;&12479;&12501;&12455;&12540;&12473;&12398;&23455;&35013;&12384;&12369;&12391;&12399;&12394;&12367;&12289;ProducerObject&12392;&12356;&12358;&12467;&12531;&12509;&12540;&12493;&12531;&12488;&12452;&12531;&12479;&12501;&12455;&12540;&12473;&12418;&23455;&35013;&12375;&12390;&12356;&12414;&12377;&12290;ProducerObject.getProducerManager()&12513;&12477;&12483;&12489;&12434;&20351;&12387;&12390;ProducerManager&12458;&12502;&12472;&12455;&12463;&12488;&12434;&21462;&24471;&12375;&12289;&12371;&12398;&12458;&12502;&12472;&12455;&12463;&12488;&12434;&20351;&12387;&12390;JMS&12467;&12493;&12463;&12471;&12519;&12531;&12434;&20316;&25104;&12375;&12414;&12377;&12290;JMS&12467;&12493;&12463;&12471;&12519;&12531;&12364;&30906;&31435;&12373;&12428;&12427;&12392;&12289;@Producer&12473;&12479;&12502;&12458;&12502;&12472;&12455;&12463;&12488;&12398;&12393;&12398;&12513;&12477;&12483;&12489;&12418;&21628;&12409;&12427;&12424;&12358;&12395;&12394;&12426;&12289;&20107;&21069;&12395;&23450;&32681;&12375;&12383;&12513;&12483;&12475;&12540;&12472;&12461;&12517;&12540;&12434;&36890;&12375;&12390;&12513;&12477;&12483;&12489;&12364;&21628;&12400;&12428;&12414;&12377;&12290;&27425;&12395;&31034;&12377;&12467;&12540;&12489;&12398;&25244;&31883;&12399;&12289;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&12398;&12463;&12521;&12452;&12450;&12531;&12488;&12391;&12377;&12290;

     

     InitialContext ctx = new InitialContext();
     Calculator cal = (Calculator) ctx.lookup(
                     Calculator.class.getName());
     ProducerObject po = (ProducerObject) cal;
     ProducerManager manager = po.getProducerManager();
     
     manager.connect(); // internally create a JMS connection
     try {
       result = nf.format(cal.calculate(start, end, growthrate, saving));
     } finally {
       manager.close(); // clean up the JMS connection
     }
    

     

    &12477;&12540;&12473;&12467;&12540;&12489;&21442;&29031;&65288;Complete source code&65289;

     

    &12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&65288;Message driven POJO&65289;

     

    • Calculator.java: The message driven POJO's business interface

    • MdpojoCalculatorBean.java: The message driven POJO's implementation

     

    • Calculator.java: &12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&12398;&12499;&12472;&12493;&12473;&12452;&12531;&12479;&12501;&12455;&12540;&12473;

    • MdpojoCalculatorBean.java: &12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&12398;&23455;&35013;

     

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

     

    • calculator.jsp: The JSP page for the client UI

     

    • calculator.jsp: &12463;&12521;&12452;&12450;&12531;&12488;&12518;&12540;&12470;&12452;&12531;&12479;&12501;&12455;&12540;&12473;&12398;JSP&12506;&12540;&12472;

     

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

     

    In this trail, you learned how message driven POJOs work in JBoss application server. In the next trail, we will focus on efficient ways to obtain and make use of service objects from within an EJB 3.0 application.

     

    &12371;&12398;&12488;&12524;&12452;&12523;&12391;&12399;&12289;JBoss&12450;&12503;&12522;&12465;&12540;&12471;&12519;&12531;&12469;&12540;&12496;&12398;&12513;&12483;&12475;&12540;&12472;&39366;&21205;&22411;POJO&12395;&12388;&12356;&12390;&23398;&12403;&12414;&12375;&12383;&12290;&27425;&12398;&12488;&12524;&12452;&12523;&12391;&12399;&12289;EJB 3.0&12450;&12503;&12522;&12465;&12540;&12471;&12519;&12531;&20869;&12391;&12398;&12469;&12540;&12499;&12473;&12458;&12502;&12472;&12455;&12463;&12488;&12398;&21177;&26524;&30340;&12394;{FOOTNOTE DEF 2 2}&20351;&29992;&26041;&27861;&12395;&12388;&12356;&12390;&23398;&12403;&12414;&12377;&12290;

     

    {FOOTNOTE RED #2 2} obtain &12364;&25244;&12369;&12390;&12356;&12427;&12290;&24847;&22259;&30340;&12394;&12425;&12356;&12356;&12391;&12377;&12364;� -tokobayashi

     

    (c) 2005 JBoss, Inc. All Rights Reserved