12 Replies Latest reply on Mar 20, 2006 7:16 PM by erik777

    MDB extends base class: Verification of Enterprise Beans fai

    barba005

      Hi,

      I have a MDB which extends a base class. This base class implements the MessageListener and MessageDrivenBean interfaces and (among others) the onMessage method. When I try to deploy this to JBoss 3.2.6 it gives an error:

      11:51:54,934 WARN [verifier] EJB spec violation:
      Bean : VeprRekenServiceMDB
      Section: 15.7.4
      Warning: The message driven bean must declare one onMessage() method.

      11:51:54,934 ERROR [MainDeployer] could not create deployment: file:/D:/java/jboss-3.2.6/server/default/tmp/deploy/tmp26985VeprEAR.ear-contents/VeprRe
      kenEJB.jar
      org.jboss.deployment.DeploymentException: Verification of Enterprise Beans failed, see above for error messages.

      It seems to me that JBoss expects the onMessage method in the MDB, and doesn't look at the base class. Does anybody have an idea on how to fix this?

      Signature MDB:

      public class VeprRekenServiceMDBBean extends CIBaseMDBBean {
      ...
      }


      Signature base class:
      public abstract class CIBaseMDBBean implements MessageListener, MessageDrivenBean {
      ...
      public void onMessage(javax.jms.Message msg) { ... }
      ...
      }
      


        • 1. Re: MDB extends base class: Verification of Enterprise Beans
          starksm64

          The following testcase works fine for me:

          package org.jboss.test.cts.ejb;
          
          import javax.ejb.MessageDrivenBean;
          import javax.ejb.MessageDrivenContext;
          import javax.jms.MessageListener;
          import javax.jms.Message;
          import javax.jms.TextMessage;
          
          /** Test of signature validation across inheritence hiearchy
           *
           * @author Scott.Stark@jboss.org
           * @version $Revision:$
           */
          public abstract class AbstractMDB implements MessageListener, MessageDrivenBean
          {
           public void onMessage(Message message)
           {
           if( message instanceof TextMessage )
           {
           TextMessage tm = (TextMessage) message;
           onTextMessage(tm);
           }
           }
          
           public void setMessageDrivenContext(MessageDrivenContext ctx)
           {
           }
          
           public void ejbCreate()
           {
           }
          
           public void ejbRemove()
           {
           }
          
           public abstract void onTextMessage(TextMessage tm);
          }
          


          package org.jboss.test.cts.ejb;
          
          import javax.jms.TextMessage;
          
          /**
           * @author Scott.Stark@jboss.org
           * @version $Revision:$
           */
          public class ConcreteMDB extends AbstractMDB
          {
           public void onTextMessage(TextMessage tm)
           {
           System.out.println("ConcreteMDB: "+tm);
           }
          }
          


          Submit a bug report with an example that is failing to:
          http://jira.jboss.com/jira/browse/JBAS


          • 2. Re: MDB extends base class: Verification of Enterprise Beans
            markricard

            I too am having a similar problem. In the code example above, the ConcreteMDB class contains an onMessage method that takes a javax.jms.TextMessage object. In my case, I want the AbstractMDB to handle a javax.jms.ObjectMessage that contains a non-JMS system message and pass that non-jms message to the ConcreteMDB class via an abstract call. See code below:

            public abstract class AbstractMDB implements MessageListener, MessageDrivenBean
            {
            public abstract onMessage(custom.Message message);

            public void onMessage(Message message)
            {
            if( message instanceof ObjectMessage )
            {
            // convert to message
            ObjectMessage om = (ObjectMessage) message;

            // pull out our custom message
            custom.Message m = (custom.Message)om.getObject();

            // pass this message to the concrete class
            this.onMessage(m);
            }
            }

            public void setMessageDrivenContext(MessageDrivenContext ctx)
            {
            }

            public void ejbCreate()
            {
            }

            public void ejbRemove()
            {
            }

            }



            public class ConcreteMDB extends AbstractMDB
            {
            public void onMessage(custom.Message m)
            {
            System.out.println("ConcreteMDB: "+ m);
            }
            }


            when i deploy the ConcreteMDB, I get "The message driven bean must declare one onMessage() method.". But from a code perspective, I do not want to let the concrete bean know it is an mdb and do not want javax.jms.* in it at all. I want that decision to be a deployment decision.

            Ideas?

            • 3. Re: MDB extends base class: Verification of Enterprise Beans
              markricard

              Very interesting. I have found that the deployment problem has something to do with the name of the abstract method I call on the concrete class from the abstract class. In my example above, I use the onMessage(custom.Message message) signature. That fails.

              When I change the method name from onMessage to process, it deploys fine. Changing it to onMessage2 still did not work. So what is the deal? Why should the name of the method matter when the parameter is different?

              This works:

              public class ConcreteMDB extends AbstractMDB
              {
              public void process(custom.Message m)
              {
              System.out.println("ConcreteMDB: "+ m);
              }
              }

              • 4. Re: MDB extends base class: Verification of Enterprise Beans

                Bug report raised, since the poster seems incapable of following basic instructions
                and I don't want my mail filling up with guess work:
                http://jira.jboss.com/jira/browse/JBAS-1532

                • 5. Re: MDB extends base class: Verification of Enterprise Beans
                  stevenpeh

                  I believe this is what you want....

                  
                  public abstract class myBeanBase implements MessageDriverBean, MessageListener {
                  
                   public void ejbCreate() {}
                   public void ejbRemove(){}
                   public void setMessageDrivenContext(MessageDrivenContext ctx) {
                   this.ctx = ctx;
                   }
                  
                   public void onMessage(Message msg){
                   handleMessage(new myMessageWrapper(msg));
                   }
                  
                   protected abstract void handleMessage(myMessageWrapper msg);
                  
                  }
                  


                  So now you bean code dont have to import any of the javax.jms.* stuff when it extends the base class as long as your myMessageWrapper class can provide all the appropriate gettor/settor methods for processing. Cheers.

                  • 6. Re: MDB extends base class: Verification of Enterprise Beans
                    erik777

                    I'm getting this in 4.0.2, only I can't find a workaround. In my case, two conrete MDBs subclass an abstract one that contains the onMessage(), declared

                    public void onMessage(javax.jms.Message message)


                    To try to get around the validation error, I subclassed and had the conrete classes call super:

                    public void onMessage(Message message) {
                     super.onMessage(message);
                     }


                    I'm really confused why this doesn't work. I can understand a bug that can't find the method signature via the parent class; but not one that's clearly defined in the concrete classes as well.

                    Is there a fix? Is there a way I can work around this until we can upgrade? We just spent a month upgrading to 4.0.2 from 3.2.7, so 4.0.3 probably won't be an option this year.

                    Erik




                    • 7. Re: MDB extends base class: Verification of Enterprise Beans
                      genman


                      erik7777 - when JBoss has a bug in it, it's fairly easy to come up with your own patched .jar file and build a custom installation.

                      • 8. Re: MDB extends base class: Verification of Enterprise Beans
                        erik777

                        That's an option we'll consider if a patch becomes available. Until then, does anyone have any suspicion as to the cause or possible way around it?

                        • 9. Re: MDB extends base class: Verification of Enterprise Beans
                          genman


                          erik777 - it seems simple enough to create a delegate class. Basically, create an MDB class that wraps another (does not subclass).

                          if a patch becomes available


                          I suggest you write your own.

                          • 10. Re: MDB extends base class: Verification of Enterprise Beans
                            erik777

                            Right now I'd settle for understanding what's wrong and hearing either confirmation that there is a bug in 4.0.2 or an example of a workaround for it.

                            Even this doesn't work:

                            public class SubscriberTxBean
                             implements MessageDrivenBean, MessageListener
                            {
                             private static Logger logger = Logger.getLogger(SubscriberTxBean.class.getName());
                             private static final String subscriberName = "local/SubscriberTxBean";
                            
                             String getSubscriberName()
                             {
                             return subscriberName;
                             }
                            
                             public void setMessageDrivenContext(
                             MessageDrivenContext messageDrivenContext) throws EJBException { }
                            
                             public void ejbRemove() { }
                            
                             public void onMessage(Message message) {
                             logger.info("Processing message!");
                             }
                            
                             public void ejbCreate() {}
                            
                             String getBinding()
                             {
                             return "singleton-message-driven-bean";
                             }
                            


                            12:19:19,486 WARN [verifier] EJB spec violation:
                            Bean : SubscriberTxBean
                            Section: 15.7.4
                            Warning: The message driven bean must declare one onMessage() method.



                            • 11. Re: MDB extends base class: Verification of Enterprise Beans
                              caseyhelbling

                              I have a similar issue where my abstract base class doesn't have the onMessage(Message m) declaration.

                              public abstract class BaseMessageBean implements MessageDrivenBean, MessageListener
                              {
                               private MessageDrivenContext context = null;
                              
                               public void setMessageDrivenContext(MessageDrivenContext context) throws EJBException
                               {
                               this.context = context;
                               }
                              
                               public void ejbRemove() throws EJBException
                               {
                               }
                              
                               public void ejbCreate() throws EJBException
                               {
                               }
                              
                              }
                              


                              My subclass implements the BaseMessageBean and onMessage(Message m) correctly

                              public class ReportSchedulerBean extends BaseMessageBean
                               implements MessageDrivenBean, MessageListener
                              {
                               public void onMessage(Message message)
                               {
                               // stuff happens here
                               }
                              
                              }
                              


                              But I still get the spec violation stack.

                              14:56:07,578 WARN [verifier] EJB spec violation:
                              Bean : ReportSchedulerListener
                              Section: 15.7.4
                              Warning: The message driven bean must declare one onMessage() method.

                              I'm running

                              Jboss 4.0.3SP1,
                              Java 1.5.0_06-b05

                              This worked on 4.0.1sp1

                              Thoughts?

                              • 12. Re: MDB extends base class: Verification of Enterprise Beans
                                erik777

                                I barely remember this, so bare with me if I'm not correct, but I do believe that at that time we were trying to isolate the EAR and progress towards J2EE compliance. We avoided this problem by, for the time being, giving up on isolating any EAR that contained MDBs, and consequently, any other EARs they communicated with. Our only isolated EARs today in 4.0.2 are those that don't contain MDBs and don't communicate via RMI to ears containing them, or any other unisolated ear.

                                The suspicion I have, but haven't had the time to prove, yet, is that unless the container itself is configured for J2EE compliance the ears containing MDBs can have this problem. It is possibly related to a classpath issue, because during deploy I noticed that the classpath can be different than at runtime. This isn't the only issue where deployment errors were related to classpath issues that wouldn't have arisen if the EAR was isolated, or because the deployment classpath was different than the runtime classpath.

                                I know this is a vague explanation, and could be proven wrong, but it has explained our behavior and guided our decisions about which ears to isolate until we have the time to convert all our applications into a J2EE compliant state.

                                Ask yourself these questions:

                                1. Is our container configured for J2EE compliance? I forgot the exact settings, but one is jboss-service.xml/...NamingService/CallByValue.

                                2. Is your application containing the MDB isolated if your container is not? This setting is in jboss-app.xml for EARs and jboss-web.xml for WARs.

                                In our configuration, we did not get the error when both 1 and 2 were false. In the end, 1 isn't an option for us without code changes due to reliance on a hibernate2 sar, and that change isn't on the project plan yet, so we put off isolating most of our EARs for this release. I suspect that if 1 and 2 are true, you may not get the error either.