13 Replies Latest reply on Aug 25, 2008 5:24 PM by nimo22

    SEAM and Caused by: java.lang.NoClassDefFoundError:

    nimo22

      I use RichFaces (3.2) in SEAM (2.1).


      I can use all Tag-Libs of RichFaces without Problems.


      But when I generate a RichFaces-Component dynamically in JAVA, then I get the following error:


      Caused by: java.lang.NoClassDefFoundError: org/richfaces/component/html/HtmlDataTable



      I have used the seam-gen to setup my project and have all the libs in the WEB-INF/lib:


      commons-beanutils.jar
      commons-digester.jar
      commons-lang.jar
      commons-logging.jar
      commons-collections.jar
      richfaces-api.jar
      richfaces-ui.jar
      richfaces-impl.jar


      In relation to the RICHFACES-MANUAL chapter 3.2. Installation, I adpat the web.xml. The seam-gen does not include the these lines in the web.xml:


      Do I need this in SEAM ???


      <filter>
      <display-name>RichFaces Filter</display-name>
      <filter-name>richfaces</filter-name>
      <filter-class>org.ajax4jsf.Filter</filter-class>
      </filter>
      <filter-mapping>
      <filter-name>richfaces</filter-name>
      <servlet-name>Faces Servlet</servlet-name>
      <dispatcher>REQUEST</dispatcher>
      <dispatcher>FORWARD</dispatcher>
      <dispatcher>INCLUDE</dispatcher>
      </filter-mapping>






      In relation to SEAM-MANUAL chapter 28.1.4.5. RichFaces, I adapt the components.xml with the following lines, because seam-gen does not make it for me:


      Do I need this in SEAM ???


      <web:ajax4jsf-filter force-parser="true"
      enable-cache="true"
      log4j-init-file="custom-log4j.xml"
      url-pattern="*.seam"/>



      The seam-gen does not include these lines in the components.xml. Although, it s said:



      If RichFaces is used in your project, Seam will install the RichFaces Ajax filter for you, making sure to install it before all other built-in filters. You don't need to install the RichFaces Ajax filter in web.xml yourself.


      The error


      Caused by: java.lang.NoClassDefFoundError: org/richfaces/component/html/HtmlDataTable



      still exists and I do not know, why.



      Any ideas?






        • 1. Re: SEAM and Caused by: java.lang.NoClassDefFoundError:
          gjeudy

          Where are you programmatically building your richfaces component ? Is it in an EJB3 ? If so richfaces jar cannot be seen from ejb module. The webapp classloader is further down the classloader hierarchy.


          Try moving your richfaces creational code in a regular pojo living in your war and tell me your results.

          • 2. Re: SEAM and Caused by: java.lang.NoClassDefFoundError:
            gjeudy

            another solution would be to move up your richfaces jar in the lib dir of your EAR file though I don't recommend it, richfaces stuff should stay at the web layer.

            • 3. Re: SEAM and Caused by: java.lang.NoClassDefFoundError:
              blabno

              I've have my rich:tree creating/updating code in EJB jar, but your solution remark



              Try moving your richfaces creational code in a regular pojo living in your war

              is clever to me. I can still inject into such pojo reference to my EJB with business logic. Thanks for that hint.

              • 4. Re: SEAM and Caused by: java.lang.NoClassDefFoundError:
                nimo22

                Yes, the source of my RichFaces-Component is in an EJB3-SessionBean.


                You say richfaces stuff should stay at the web layer.


                Why? Because of keeping the MVC?


                I generate an UI-component in a SessionBean. Looking at the SEAM-Reference (7.10. Conversational components and JSF component
                bindings), there is a UI-component not embedded in a regular pojo.


                But I will do that:



                Try moving your richfaces creational code in a regular pojo living in your war

                Bernard says:



                I can still inject into such pojo reference to my EJB with business logic

                Do you inject the class with its empty constructer? What about dynamic htmlTables needing  business logic such as retrieving the values from the database and put it in the datatable. I do not want to place such code in my WAR-File..


                Can u provide an example, what is the best case to generate UI components in EJB via JAVA-CODE?


                I can not find any information about the best way.



                For example, look at this pojo:



                public class Grid implements GridLocal
                {
                    private HtmlPanelGrid htmlPanelGrid;
                
                    private HtmlOutputLabel outputLabel;
                
                // getters/setters
                
                
                public Grid() {
                
                     }
                
                public Grid(HtmlPanelGrid htmlPanelGrid, HtmlOutputLabel outputLabel) {
                          super();
                          this.htmlPanelGrid = htmlPanelGrid;
                          this.outputLabel = outputLabel;
                          
                
                List<UIComponent> children = htmlPanelGrid.getChildren();
                
                List children = htmlPanelGrid.getChildren();
                
                for (int count = 0; count < 10; count++)
                            {
                            outputLabel =  new HtmlOutputLabel(); 
                                
                htmlPanelGrid.getChildren().add(outputLabel);
                            
                
                     }
                     }
                
                }



                How I inject this component in an EJB Session Bean?
                I tried it with:


                @In (create=true)
                Grid newGrid;



                but obviously, the session-bean called the empty-constructer, therefore no components are generated.


                Another point is:


                When I do this in my SESSION-BEAN...


                @Factory("newGrid")
                public HtmlPanelGrid getGrid() {
                  for (int count = 0; count < 10; count++)
                {
                HtmlOutputLabel outputLabel =  new HtmlOutputLabel(); 
                                
                grid.getChildren().add(outputLabel);
                 return grid;
                  }



                and bind this factory in my view:


                <h:panelGrid binding="#{newGrid}"></h:panelGrid>




                ...then all works fine!


                But I have the UI-Code in my SessionBean !!!


                So what is the best-case to generate UI via JAVA-Code in SEAM ???









                • 5. Re: SEAM and Caused by: java.lang.NoClassDefFoundError:
                  gjeudy

                  I'm not saying it's not possible to use richfaces classes in EJB3, the reason why I recommend putting this in the WAR is because this is view related logic. This way you keep business methods in EJB3 which are view-agnostic allowing for better re-usability among clients. Maybe in your case the only client is the webapp but even in this case you will end up with a better architected solution.


                  You can define a seam managed pojo and store in your war file:


                  @Name("foo")
                  @Scope(ScopeType.CONVERSATION)
                  public class Foo {
                  
                    @In
                    MySessionEJBInterface mySessionEjb;
                  
                    @Factory("newGrid")
                    public HtmlPanelGrid createGrid() {
                       Data data = mySessionEjb.getData();
                       // populate grid with data
                  
                       return grid;
                    }
                  }
                  



                  When you say you can put richfaces class references in your session ejb, did you leave your richfaces jars in the WAR WEB-INF/lib and/or you moved/copied them in EAR/lib or server/lib ?  Using

                  @Factory

                  versus some other methods to instantiate your richfaces component should have no impacts on ClassLoading. ClassLoading rules are not specific to Seam but are specific to the J2EE container you are using. See JBoss ClassLoading Overview

                  • 6. Re: SEAM and Caused by: java.lang.NoClassDefFoundError:
                    nimo22

                    Hello Guillaume,


                    I tried to do it as you said as it sounds good:-)


                    Look at my view-logic, which works well:


                    @Stateful
                    @Name("dataTable")
                    @Scope(CONVERSATION)
                    public class DataTable  implements DataTableLocal {
                    
                     @In
                     private EntityManager entityManager;
                    
                     @Factory("newGrid")
                     public HtmlPanelGrid createGrid() {
                    
                     HtmlPanelGrid grid = new HtmlPanelGrid();
                     List <Entity> test = entityManager.createQuery("from Entity e").getResultList();
                    
                      for (Entity e: entity)
                         
                       {
                       HtmlOutputLabel outputLabel =  new HtmlOutputLabel();
                       outputLabel.setValue("Hello World:-) "+ e);
                       grid.getChildren().add(outputLabel);
                       }
                       return grid;
                       }
                    
                     @Destroy @Remove
                     public void destroy() {}
                    }
                    


                    Now, I want to inject my EJB-SessionBean, instead of the EntityManager to retrieve the values from there.
                    Look at my view-logic, which does NOT work:


                    @Stateful
                    @Name("dataTable")
                    @Scope(CONVERSATION)
                    public class DataTable  implements DataTableLocal {
                    
                     // now I inject my EJB-SessionBean
                     @In (create=true, required=false)
                     TestEJBBean myTestLocal;
                    
                     @Factory("newGrid")
                     public HtmlPanelGrid createGrid() {
                     
                     List <Entity> test= myTestLocal.getEntityList();
                     HtmlPanelGrid grid = new HtmlPanelGrid();
                     for (Entity e: entity)
                         
                       {
                       HtmlOutputLabel outputLabel =  new HtmlOutputLabel();
                       outputLabel.setValue("Hello World:-) "+ e);
                       grid.getChildren().add(outputLabel);
                       }
                       return grid;
                       }
                    
                      @Destroy @Remove
                      public void destroy() {}
                    }



                    In my TestEJBBean exists the method:



                    ...
                    @In (create=true)
                    private EntityManager entityManager;
                    ...
                    @Factory("entityList")
                    public List <Entity> getEntityList() {
                    
                     return entityManager.createQuery("from Entity e").getResultList();
                      }
                    



                    By injecting the TestEJBBean, the following error occurs:



                    Caused by: java.lang.NullPointerException
                         at com.DataTable.createGrid(DataTable.java:40)
                         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                         at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
                         at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                         at java.lang.reflect.Method.invoke(Unknown Source)
                         at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:112)
                         at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166)
                         at org.jboss.seam.intercept.EJBInvocationContext.proceed(EJBInvocationContext.java:44)
                         at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:5



                    I assume that my Converation-Scope in the class DataTable needs an entityManager explicitly.


                    How can I solve that?



                    • 7. Re: SEAM and Caused by: java.lang.NoClassDefFoundError:
                      gjeudy

                      Your DataTable class is also an EJB due to

                      @Stateful

                      so you are not following my recommendations here. In any case it shouldnt affect the NPE you are getting.


                      Can you post the TestEJBBean declaration and class level annotations ?

                      • 8. Re: SEAM and Caused by: java.lang.NoClassDefFoundError:
                        nimo22

                        Thanks for helping:-)


                        Okay, my TestEJBBean declaration and class level annotations:


                        @Stateful
                        @Name("userManager")
                        @Scope(CONVERSATION)
                        public class TestEJBBean implements TestEJBLocal {
                        
                        ...
                        @In (create=true)
                        private EntityManager em;
                        
                        @Factory("setup") @Begin(join = true)
                          public void myTest()
                          {
                           ...
                           }
                        
                        @Factory("entityList")
                        public List <Entity> getEntityList() {
                        
                         return entityManager.createQuery("from Entity e").getResultList();
                          }
                        
                        ....
                        
                        }



                        (I do not know, if this matters: SEAM-Manual 7.10. Conversational components and JSF component bindings)


                        Do you need more informations?


                        I tried to change the scope of TestEJBBean from conversation to session, but this did not help. I also changed my DataTable.java to a regular POJO:


                        @Name("dataTable")
                        public class DataTable {
                        ..
                        }
                        



                        but the same problem still occurs.

                        • 9. Re: SEAM and Caused by: java.lang.NoClassDefFoundError:
                          gjeudy

                          I think the injection in DataTable doesnt work:


                          @In (create=true, required=false)
                           TestEJBBean myTestLocal;



                          Seam will try to find a seam component named myTestLocal.


                          @Name("userManager")

                          is the seam component name you gave to TestEJBBean class. Either rename it to:


                          @Name("myTestLocal")

                            or rename your variable name in Datatable class to

                          @In (create=true, required=false)
                           TestEJBBean userManager;



                          You also want a reference to your EJB interface injected otherwise you will have problems so you can use this:


                          @In (create=true)
                           TestEJBLocal userManager;


                          • 10. Re: SEAM and Caused by: java.lang.NoClassDefFoundError:
                            nimo22

                            hello Guillaume,


                            great, that was my fault! Now, my View can be generated via JAVA-Code.


                            As I want to decouple my SessionBean from my view,
                            I store all view-related things in my WAR-File.


                            With the @EJB or @In,
                            I can access all the methods via Interfaces from the SessionBeans.



                            BUT:



                            What about the SCOPE of my (GUI-)POJO stored in WEB-INF ?


                            In the SEAM-Reference 7.10. Conversational components and JSF component bindings, it is shown, that I have to declare the SCOPE of my GUI-POJO as an EVENT and inject it in my SESSION-BEAN to retrieve the values from the GUI-Instance.


                            My Intention is, to search the best-practice, buildung JSF-GUIs via JAVA-Code, as JAVA-Code generated Views are faster than using JSF-Tags.


                            Should I really inject the GUI-POJO to my SessionBean to retrieve the values coming from the view? Is this best-practice?


                            Look at the following scenario:


                            My View:


                            @Name("viewRegisterUser")
                            public class DataTable  {
                            ...
                            
                            @In (create=true)
                            TestEJBLocal userManager;
                            
                            //generating the VIEW
                            List <Entity> test= myTestLocal.getEntityList();
                             HtmlPanelGrid grid = new HtmlPanelGrid();
                             for (Entity e: entity)
                                 
                               {
                               HtmlOutputLabel outputLabel =  new HtmlOutputLabel();
                               outputLabel.setValue("Hello World:-) "+ e);
                               grid.getChildren().add(outputLabel);
                               }
                               return grid;
                               }
                            HtmlInputText username = new HtmlInputText();
                            HtmlInputText password = new HtmlInputText();
                            
                            // calling the method from SessionBean
                            userManager.registerUser(username.getValue, password.getValue);
                            
                            }



                            My SessionBean:


                            @Stateful
                            @Name("userManager")
                            @Scope(CONVERSATION)
                            public class TestEJBBean implements TestEJBLocal {
                            ..
                            // I do not need the Factory-Annotation anymore !!
                            // the Values of the Query will automatically retrieved, 
                            // when the Client calls the method
                            public List <Entity> getEntityList() {
                            
                             return entityManager.createQuery("from Entity e").getResultList();
                              }
                            
                            public void registerUser(String username, String password)
                            {..}
                            }




                            You see, my View has no SCOPE, so what I am wondering is, how can I access the values from my view? Is there a better solution for all that ? (I used JSF-Tags before and retrieved the values directly from my xhtml. I know, this is common practice, but I do not want to use Tags.)


                            I think, to decouple the view from my sessionBean, I have to retrieve the values coming from the view-instance directly in my view-logic and call the business-logic via Interfaces. This is, what EJB suggests! What do you think about?






                            • 11. Re: SEAM and Caused by: java.lang.NoClassDefFoundError:
                              nimo22

                              Hmm..am I right with my assumption:
                              I have to develop an JSF-backing-bean and a SFSB and need to have an injection of the SFSB in my JSF-backing-bean.


                              And In the JSF-backing-bean, I construct my CONVERSATION-SCOPE?


                              So I have to do delete the Scope from my SFSB:


                              Stateful
                              @Name("userManager")
                              // @Scope(CONVERSATION) deleted in my SFSB
                              public class TestEJBBean implements TestEJBLocal {..}



                              and put the Scope to my JSF-backing-bean which is placed in WEB-INF/classes:



                              @Name("viewRegisterUser")
                              @Scope(CONVERSATION)
                              public class DataTable  {
                              
                              @In (create=true)
                              TestEJBLocal userManager;
                              
                              @Begin(join=true)
                              public HTMLDataTable getHtmlDataTable() {
                              //generating the VIEW
                              List <Entity> test= myTestLocal.getEntityList();
                               HtmlPanelGrid grid = new HtmlPanelGrid();
                               for (Entity e: entity)
                                   
                                 {
                                 HtmlOutputLabel outputLabel =  new HtmlOutputLabel();
                                 outputLabel.setValue("Hello World:-) "+ e);
                                 grid.getChildren().add(outputLabel);
                                 }
                                 return grid;
                                 }
                              HtmlInputText username = new HtmlInputText();
                              HtmlInputText password = new HtmlInputText();
                              
                              // calling the method from SessionBean
                              @End
                              public void end()
                                {
                              userManager.registerUser(username.getValue, password.getValue);
                               }
                              



                              SEAM does not need managedBeans, but EJB does..?!






                              • 12. Re: SEAM and Caused by: java.lang.NoClassDefFoundError:
                                gjeudy

                                nimo mayr wrote on Aug 25, 2008 14:06:


                                Hmm..am I right with my assumption:
                                I have to develop an JSF-backing-bean and a SFSB and need to have an injection of the SFSB in my JSF-backing-bean.


                                JSF-backing-bean is configured in faces-config.xml, you don't need this when using Seam. I suggest you read more Seam documentation to get familiar with the framework and it's purpose.




                                And In the JSF-backing-bean, I construct my CONVERSATION-SCOPE?


                                A scope cannot be constructed but can only be declared again, refer to Seam reference doc and examples packaged in the distribution...




                                So I have to do delete the Scope from my SFSB:

                                Stateful
                                @Name("userManager")
                                // @Scope(CONVERSATION) deleted in my SFSB
                                public class TestEJBBean implements TestEJBLocal {..}



                                and put the Scope to my JSF-backing-bean which is placed in WEB-INF/classes:


                                @Name("viewRegisterUser")
                                @Scope(CONVERSATION)
                                public class DataTable  {
                                
                                @In (create=true)
                                TestEJBLocal userManager;
                                
                                @Begin(join=true)
                                public HTMLDataTable getHtmlDataTable() {
                                //generating the VIEW
                                List <Entity> test= myTestLocal.getEntityList();
                                 HtmlPanelGrid grid = new HtmlPanelGrid();
                                 for (Entity e: entity)
                                     
                                   {
                                   HtmlOutputLabel outputLabel =  new HtmlOutputLabel();
                                   outputLabel.setValue("Hello World:-) "+ e);
                                   grid.getChildren().add(outputLabel);
                                   }
                                   return grid;
                                   }
                                HtmlInputText username = new HtmlInputText();
                                HtmlInputText password = new HtmlInputText();
                                
                                // calling the method from SessionBean
                                @End
                                public void end()
                                  {
                                userManager.registerUser(username.getValue, password.getValue);
                                 }
                                



                                SEAM does not need managedBeans, but EJB does..?!



                                I don't understand your last question. Seam is a framework that manages beans declared with the @Name or declared in components.xml files. These beans can be either POJOs or EJBs. EJBs are themselves managed by the EJB container (your J2EE application server). When you declare for example

                                @Stateless
                                @Name("myEjb")



                                you are declaring your class as an EJB and a seam component. When you inject such a component with a seam In annotation; Seam will lookup the EJB in the EJB container, perform any injections on it and set the In-annotated instance variable.

                                • 13. Re: SEAM and Caused by: java.lang.NoClassDefFoundError:
                                  nimo22

                                  Sorry, my question was a little vague but now, I understand. Thanks!


                                  It would be fine to get the opportunity to implement the GUI only via JAVA-Code in relation to SEAM and EJB. I know, I can dynamically generate the view in JAVA via JSF-API..but..


                                  Look at Wicket, GWT, jSeamless or wingsframework.


                                  I know, Seam can handle GWT or Wicket, but I do not know, if EJB can do also in an performant and reliably manner. I try.


                                  Thanks!