4 Replies Latest reply on Oct 12, 2012 9:41 AM by christoph.zuleger

    Observer method not found in local business interface if inherited

    christoph.zuleger

      Hi,

       

      it would be great if someone could explain to me why Weld complains about a missing observer method declaration in the local business interface if that method is declared in an inherited interface.

      Due to the fact that I'm not a native speaker: I attached a sample Maven project to make things clear. I tried to deploy that project on Glassfish 3.1.2.2 running Weld 1.0.8 Final.

       

      Thanks for responses!

      Christoph

        • 1. Re: Observer method not found in local business interface if inherited
          mkouba

          Hi Christoph,

           

          I think the problem is the observer methods are not business methods of you session bean (see CDI spec "10.4. Observer methods"). E.g. afterEntityCreated() is not a business method of the session bean Entity01Service. See also "4.9.7 Session Bean’s Business Interface" in EJB 3.1 spec document: "A bean class is permitted to have more than one interface. If a bean class has more than one interface—excluding the interfaces listed below—any business interface of the bean class must be explicitly designated as a business interface of the bean by means of the Local or Remote annotation on the bean class or interface or in the deployment descriptor."

           

          I would try:

          ...
          @Local({Entity01ServiceLocal.class, Service.class})
          public class Entity01Service implements Entity01ServiceLocal {
          ...
          

          or add @Local on Service.

          1 of 1 people found this helpful
          • 2. Re: Observer method not found in local business interface if inherited
            christoph.zuleger

            Thank you Martin!

             

            But I'm afraid that did not solve my problem... perhaps I should first describe my model:

             

            1) I have some kind of generic service interface (called Service with type parameter T). This interface declares the generic observer method signature (without the CDI annotations).

            2) I need service implementations for each type T: so I decided to implement pairs of local business interfaces and singleton beans for a specific entity type T (called Entity01, Entity02... they are not neccessarily JPA related).

            3) Each of these local business interfaces extends the generic service interface. That is why I thought that methods declared in the generic service interface are part of the local business interface defined in the corresponding singleton EJB.

            4) Each singleton EJB implements the concrete observer method (and adds @Observes etc. annotations to the methods).

             

            Edit: I forgot to post the stack trace...

             

            SEVERE: Exception while loading the app : WELD-000088 Observer method must be static or local business method:  [method] public de.buegmbh.bugs.weld.service.Entity02Service.afterEntityCreated(Entity02) on public@Startup @Singleton @Local class de.buegmbh.bugs.weld.service.Entity02Service

            org.jboss.weld.exceptions.DefinitionException: WELD-000088 Observer method must be static or local business method:  [method] public de.buegmbh.bugs.weld.service.Entity02Service.afterEntityCreated(Entity02) on public@Startup @Singleton @Local class de.buegmbh.bugs.weld.service.Entity02Service

                      at org.jboss.weld.bean.SessionBean.checkObserverMethods(SessionBean.java:405)

                      at org.jboss.weld.bean.SessionBean.initialize(SessionBean.java:168)

                      at org.jboss.weld.bootstrap.AbstractBeanDeployer.deploy(AbstractBeanDeployer.java:116)

                      at org.jboss.weld.bootstrap.BeanDeployment.deployBeans(BeanDeployment.java:217)

                      at org.jboss.weld.bootstrap.WeldBootstrap.deployBeans(WeldBootstrap.java:358)

                      at org.glassfish.weld.WeldDeployer.event(WeldDeployer.java:179)

                      at org.glassfish.kernel.event.EventsImpl.send(EventsImpl.java:128)

                      at org.glassfish.internal.data.ApplicationInfo.load(ApplicationInfo.java:277)

                      at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:460)

                      at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:240)

                      at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:389)

                      at com.sun.enterprise.v3.admin.CommandRunnerImpl$1.execute(CommandRunnerImpl.java:348)

                      at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:363)

                      at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1085)

                      at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1200(CommandRunnerImpl.java:95)

                      at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1291)

                      at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1259)

                      at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:461)

                      at com.sun.enterprise.v3.admin.AdminAdapter.service(AdminAdapter.java:212)

                      at com.sun.grizzly.tcp.http11.GrizzlyAdapter.service(GrizzlyAdapter.java:179)

                      at com.sun.enterprise.v3.server.HK2Dispatcher.dispath(HK2Dispatcher.java:117)

                      at com.sun.enterprise.v3.services.impl.ContainerMapper$Hk2DispatcherCallable.call(ContainerMapper.java:354)

                      at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)

                      at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)

                      at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)

                      at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)

                      at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)

                      at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)

                      at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)

                      at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)

                      at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)

                      at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)

                      at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)

                      at com.sun.grizzly.ContextTask.run(ContextTask.java:71)

                      at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)

                      at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)

                      at java.lang.Thread.run(Thread.java:722)

            • 3. Re: Observer method not found in local business interface if inherited
              mkouba

              I see. I'm not completely sure but the only way (not so elegant) is to override Service methods on extending local business interface:

              public interface Entity01ServiceLocal extends Service {
                  public void afterEntityCreated(Entity01 entity);
                  public void afterEntityUpdated(Entity01 entity);
                  public void afterEntityDeleted(Entity01 entity);
              }
              

              Imho the specs are quite vague in this area...

              1 of 1 people found this helpful
              • 4. Re: Observer method not found in local business interface if inherited
                christoph.zuleger

                Hi Martin,

                 

                yep... that's what I did to solve the problem - but it feels quite wrong, even if @Override annotations would prevent inconsistent redefinitions in the extending interface.

                 

                Correct me if I'm wrong but the EJB spec handles this differently: For example I often create a generic DAO (Data Access Object) interface for my JPA Entities that defines the default CRUD operations. Then I add entity-specific DAO-interfaces (e.g. UserDao, etc.) that extend the generic DAO and additionally define entity-specific methods like "findUserByEMail(...)". The implementing stateless EJB then just implements the entity-specific local business interface.

                 

                Some OT background: The reason why i don't want to remove the generic service interface is that I have to make sure that every implementation takes care of events. If the CDI spec would allow to implement (non-static) observer methods in abstract classes it would be perfect . This would prevent copy&paste method implementations in many usecases.

                 

                Well, thank you for your effort, I really appreciate that!