9 Replies Latest reply on Feb 6, 2013 4:04 AM by sven.plath

    JBoss 7 ClassNotFound using interface implementation

    sven.plath

      Hi all,

       

      consider the following situation:

       

      Module A:

       

      * public interface Registry

      * public interface Page

      * public class RegistryImpl implements Registry

       

      Module B: depends on Module A

       

      * public class PageImpl implements Page

      * public class someAccessClass

       

       

      public class someAccessClass {
           private Registry reg;
           
           public void do() {
                Page page;
      
      
                reg = getRegistry();
                page = new PageImpl();
                reg.register(page);
           }
      }
      

       

      when the do() method is called and the reg.register() call is made, a ClassNotFoundException is thrown:

      ClassNotFoundException: foo.bar.PageImpl from [Module A]

       

      From my point of view, it should be no problem since the Module A should not care about the implementation, only the interface? How am I supposed to realize this behavior? I would have to add a new dependency to Module A each time I implement the Page in a new Module (say, C). This would look like:

       

      Module A: depends on Module B.

      Module B: depends on Module A.

       

      Do I have a serious architecture flaw? Or am I missing something. Thanks for your advice in advance!

       

      Regards,

      Sven

        • 1. Re: JBoss 7 ClassNotFound using interface implementation
          nickarls

          Would it work if you had a module like com.acme.pages which would have pages-api.jar (the Pages interface) and pages-impl.jar (Pages implementation) and a similar module for the registry concept and then a top-level app module?

          • 2. Re: JBoss 7 ClassNotFound using interface implementation
            sven.plath

            Hey,

             

            okay, let me first show you what I 'understood' (only utilizing one API for both registry and page for the sake of simplicity):

             

            Module API:

             

            public interface Registry

            public interface Page

             

            Module Impl:

             

            public class RegistryImpl implements Registry

            public class PageImpl implements Page

             

            Module App:


            public class someAccessClass

             

            I tried that approach, however the problem remains. Dependency graph is:

             

            App depends on API

            Impl depends on API


            • 3. Re: JBoss 7 ClassNotFound using interface implementation
              nickarls

              I was thinking in the lines of

               

              Page Module (com.acme.page)

                page-api.jar

                 page-impl.jar

               

              Registry Module (com.acme.registry)

                registry-api.jar

                registry-impl.jar

               

              You are always going to have a impl -> api dep but at least it will always be within a module. And the app then uses the APIs.

              • 4. Re: JBoss 7 ClassNotFound using interface implementation
                sven.plath

                Hey,

                 

                the problem is that sometimes, more than one impl exists (in fact, this is currently very common in our deployment scenarios). And because we want them to sit side by side and not in one big mega module, we need a decoupling.

                 

                Thanks,

                Sven

                • 5. Re: JBoss 7 ClassNotFound using interface implementation
                  nickarls

                  If you have multiple Page implementations, they could all live in the page-impl.jar. Or you could have page1-impl.jar, page2-impl.jar and the page module.xml would reflect that. Or is it me misunderstanding here?

                  • 6. Re: JBoss 7 ClassNotFound using interface implementation
                    nickarls

                    If you have many Page implementations, you could have page1-impl.jar, page2-impl.jar etc and have the Page module.xml include them

                    • 7. Re: JBoss 7 ClassNotFound using interface implementation
                      sven.plath

                      So you suggest that I should define circular dependencies? I also thought of that, but I feared that it is evil .

                       

                      I think I will go with that. However, it is hard to define these dependencies because normally, the Page does not know how many Impl exist, so we would have to adjust it for every different deployment scenario.

                       

                      Thanks again for your food of thought.

                      Sven

                      • 8. Re: JBoss 7 ClassNotFound using interface implementation
                        nickarls

                        One option could be to have them all in the WAR lib (appropriately split into api/impl jars) and then use CDI Instance like

                         

                        @Inject @Any Instance<Page> pages;

                         

                        and you could iterate over the implementations. It all depends on how use the various implementations. Splitting into jars is good regardless of classloading, the module approach has the backside of a deployment no longer being a "drop-in-operation".

                        It could of course be what it required (e.g. customers have different implementation modules). Not sure how CDI picks up in stuff in modules currently, though.

                         

                        BTW, what was the circular deps you mentioned? page-api, page1-impl and page2-impl would be in the same module (with no outgoing deps) and the application would depend on the module.

                        • 9. Re: JBoss 7 ClassNotFound using interface implementation
                          sven.plath

                          Hi,

                           

                          regarding the circular deps, i was thinking of splitting page-api, page1-impl and page2-impl into different deployment units. It would resemble our way of developing stuff (we do not really want top-level modules if it can be avoided). I believe we will rethink our architecture to avoid implementing Interfaces, but making the Page class configurable so that it can be used in different scenarios. For example something like this:

                           

                          Module A:

                           

                          public class PageRegistryImpl implements PageRegistry

                          public interface PageRegistry

                          public class Page

                           

                          Module B:

                           

                          public class SomeAccessClass

                           

                          public class SomeAccessClass {
                               private PageRegistry registry;
                          
                               public void do() {
                                    registry = getRegistry();
                                    registry.register(new Page(configuration));
                               }
                          }
                          

                           

                          We currently think this would be a feasible solution. We really do not want to package stuff in a WAR (all our libraries and EJBs will be deployed seperately, not inside a WAR / EAR). Think of OSGi projects with hundreds of different bundles installed side by side.

                           

                          I believe we have a design flaw here that the JBoss 7 revealed. I hope the stuff I said makes sense .

                           

                          Thanks a lot for your input.

                          Sven Plath