8 Replies Latest reply on Dec 24, 2009 8:59 AM by Prathamesh Gaddam

    Programmatically view generation

    Prathamesh Gaddam Novice

      Dear Team,


      Towards programmatic view generation, when multiple components are added to panel components, only the last added one is rendeed.


      What m'i missing? Anything I need to take care further? Following is the code snippet where the only text rendered is 'Catch you later!' and no other message.



           public Collection<? extends UIComponent> buildView() {
                List <UIComponent> components = new ArrayList<UIComponent>();
                
                HtmlOutputText text = new HtmlOutputText();
                     text.setId("idHello");
                     text.setValue("Test Successful!");
                components.add(text);
                
                HtmlOutputText bye = new HtmlOutputText();
                     text.setId("idBye");
                     text.setValue("Good bye!");
                components.add(bye);
                
                HtmlOutputText msg = new HtmlOutputText();
                     text.setValue("Catch you later!");
                components.add(msg);
      
                return components;
           }



           @Override
           @Factory("TestMyView")
           public HtmlAjaxOutputPanel initView(){
                try {
                     htmlAjaxOutputPanel = new HtmlAjaxOutputPanel(); 
                     htmlAjaxOutputPanel.getChildren().addAll(buildView());
      
                     System.out.println("Components: count-"+htmlAjaxOutputPanel.getChildCount()+", "+htmlAjaxOutputPanel.getChildren());
      
                } catch (Exception e) {
                     log.debug("FAILED: View Initialzation", e);
                }
                return htmlAjaxOutputPanel;
           }
      
      

        • 1. Re: Programmatically view generation
          Tim Evers Master

          So, does your debug line


          System.out.println("Components: count-"+htmlAjaxOutputPanel.getChildCount()+", "+htmlAjaxOutputPanel.getChildren());
          



          print what you'd expect it to?

          • 2. Re: Programmatically view generation
            Prathamesh Gaddam Novice

            Hi Tim,


                    Thank you for reply.


            1. Yes, I get expected result on console, the components count and the list's values.


            2. Further for command component HtmlCommandButton the MethodExpression binded is invoked only if the seam-component is in session-scope and not for the default event-scope. What I need to do? Any code snippet?

            • 3. Re: Programmatically view generation
              Tim Evers Master

              Interesting....


              I had a similar problem the other day. I basically ended up thinking that the order I thought things happened wasn't true and so I changed how I was doing this to make it work.


              I'm really not sure why what you are doing isn't working but try this and see if it works. This way is not right and is terrible for performance but I want to see if it is related to the same problem I was having. If so, then maybe I need to spend a bit more time understanding what's going on so I can fix my problem and you can fix yours :)


              Basically, instead of binding to a @Factory or @Out variable bind directly to a getter in an EVENT scoped bean.


              @Name("BindingBean")
              @Scope(ScopeType.EVENT)
              public class BindingBean {
              
                  private HtmlPanelGrid grid = new HtmlPanelGrid();
              
                  public HtmlPanelGrid getGrid() {
                      grid.getChildren.clear();
                      HtmlOutputText text = new HtmlOutputText();
                      text.setId("idHello");
                      text.setValue("Test Successful!");
                      grid.getChildren().add(text);
                        
                      HtmlOutputText bye = new HtmlOutputText();
                      text.setId("idBye");
                      text.setValue("Good bye!");
                      grid.getChildren().add(bye);
                        
                      HtmlOutputText msg = new HtmlOutputText();
                      text.setValue("Catch you later!");
                      grid.getChildren().add(msg);
              
                      return grid;
                   }
                  }
              
                  public void setGrid(HtmlPanelGrid grid) {
                      this.grid = grid;
                  }
              }
              



              So, your xhtml would just be.


              <h:panelGrid binding="#{BindingBean.grid}"
              



              Obviously this is not a viable solution, but I think the event scoped bean causes some weird behaviour in certain circumstances. I gota read a bit more :)


              So, let me know if this works for you and I'll take another look at this problem at my end if I get a few spare mins today :)

              • 4. Re: Programmatically view generation
                Prathamesh Gaddam Novice

                Tim,


                Admire your efforts.


                In the following code the components works (and even method invocation if placed in htmlForm). Now need to check whether any abstract class can be extracted. Any way worked out?


                @Name("test")
                public class Test {
                
                     @In(required = false, create = true)
                     @Out(required = false, scope=ScopeType.CONVERSATION)
                     HtmlPanel pnlContainer;
                
                     @In
                     FacesMessages facesMessages;
                     
                     public void renderComponents() {
                //          HtmlForm htmlForm = new HtmlForm();
                               
                          HtmlOutputText text = new HtmlOutputText();
                               text.setId("idHello");
                               text.setValue("Test Successful!");
                          pnlContainer.getChildren().add(text);
                //          htmlForm.getChildren().add(text);
                          
                          HtmlOutputText done = new HtmlOutputText();
                               done.setId("idDone");
                               done.setValue("Done!  ");
                          pnlContainer.getChildren().add(done);
                //          htmlForm.getChildren().add(done);
                          
                          FacesContext facesContext = FacesContext.getCurrentInstance();
                          ExpressionFactory expressionFactory = facesContext.getApplication().getExpressionFactory();
                          ELContext elContext = facesContext.getELContext();
                          MethodExpression methodExpression = 
                               expressionFactory.createMethodExpression(elContext, "#{test.display}", String.class, new Class<?>[]{});
                
                          HtmlCommandButton commandButton = new HtmlCommandButton();
                               commandButton.setId("idGo");
                               commandButton.setValue("Go!");
                               commandButton.setActionExpression(methodExpression);
                          pnlContainer.getChildren().add(commandButton);
                //          htmlForm.getChildren().add(commandButton);
                          
                //          pnlContainer.getChildren().add(htmlForm);
                               
                     }
                
                     @End
                     public void display(){
                          facesMessages.add("Method Binding Successful!"); 
                          System.out.println("Method Binding Successful!");
                     }
                     
                     @Factory("container")
                     @Begin(join=true)
                     public HtmlPanel start() {
                          pnlContainer = new HtmlPanel();
                          renderComponents();
                          return pnlContainer;
                     }
                }
                

                • 5. Re: Programmatically view generation
                  Prathamesh Gaddam Novice

                  Regret, my bad!


                  The setValue() was used for the same components. Rectified and now working fine!


                  Tim, thank you for your time.

                  • 6. Re: Programmatically view generation
                    Prathamesh Gaddam Novice

                    Dear Team,


                    Tried to abstract the class and bind the view using getter/setter methods. However it failed. with the reason as No conversation context active. Why? What m'I missing?


                    Following is the code snippet. If instead of getter/setter method if I use the @Factory(viewName) to bind it with the tags it works. However need to make manual context search and set the modified value.


                    @Name("testBaseView")
                    public class TestBaseView extends BaseView {
                    
                         public Collection<? extends UIComponent> buildView() {
                              List <UIComponent> components = new ArrayList<UIComponent>();
                              
                              HtmlCommandButton commandButton = new HtmlCommandButton();
                                   commandButton.setId("idGo");
                                   commandButton.setValue("Go!");
                                   commandButton.setActionExpression(createMethodExpression("#{testBaseView.updateView}"));
                              components.add(commandButton);
                              
                              return components;
                         }
                         
                         public void updateView(){
                    //          Object object = Contexts.getEventContext().get("baseView");
                    //          if(object instanceof HtmlAjaxOutputPanel){ 
                    //               HtmlAjaxOutputPanel panel = (HtmlAjaxOutputPanel) object;
                    //                    panel.getChildren().clear();
                                        getView().getChildren().clear();
                                        HtmlOutputText click = new HtmlOutputText();
                                             click.setId("idClick");
                                             click.setValue("Clicked!");
                    //                    panel.getChildren().add(click);
                                             getView().getChildren().add(click);
                    //               Contexts.getEventContext().set("baseView", panel);
                                   
                                   facesMessages.add("Button Clicked");
                    //          }else{
                    //               facesMessages.add("Unable to update the view!");
                    //          }
                         }
                         
                          @In(required=false, value="baseView")
                          public void setView(UIPanel panel){
                               super.setView(panel);
                          }
                          
                          @Out(required=false, value="baseView")
                          public UIPanel getView(){
                               return super.getView();
                          }
                    }
                    



                    public abstract class BaseView implements Viewable {
                    
                         HtmlAjaxOutputPanel htmlAjaxOutputPanel;
                    
                         @In
                         protected FacesMessages facesMessages;
                    
                         @Logger
                         protected Log log;
                    
                         public UIPanel getView() {
                              return htmlAjaxOutputPanel;
                         }
                    
                         public void setView(UIPanel panel) {
                              if (panel instanceof HtmlAjaxOutputPanel) {
                                   htmlAjaxOutputPanel = (HtmlAjaxOutputPanel) panel;
                              } else {
                                   log.error("Needed HtmlAjaxOutputPanel");
                              }
                         }
                         
                          //* Needs to implement buildView() in its concrete sub-class.
                         @Create
                         public HtmlAjaxOutputPanel initView() {
                              try {
                                   htmlAjaxOutputPanel = new HtmlAjaxOutputPanel();
                                   htmlAjaxOutputPanel.getChildren().addAll(buildView());           //TODO: Validate buildView()
                                   log.debug("Initialized View"); 
                              } catch (Exception e) {
                                   log.error("View Initialzation", e);
                              }
                              return htmlAjaxOutputPanel;
                         }
                    
                          //* Creates a method expression to bind with the UIComponent action.
                         protected MethodExpression createMethodExpression(String expression) {..}
                    }
                    

                    • 7. Re: Programmatically view generation
                      Tim Evers Master

                      Take a look at the Seam doco regarding binding and conversations.


                      http://docs.jboss.org/seam/latest/reference/en-US/html_single/#d0e6504


                      Go to section '7.11. Conversational components and JSF component bindings
                      ' if the link doesn't work properly.


                      I haven't had time to really investigate this properly. When I tried to do things they way they explain in the doco it didn't work for me, but I think I might know why.


                      But, take the time to read the info from that link and see if this solves your problem. From the error message you have given it looks like you have bound to a Seam bean that is conversation scoped or the event scoped bean is trying to access a Conversation scoped bean. This wont work because the Conversation context hasn't been restored at the time the binding getter/setter methods get called.


                      I hope this helps.

                      • 8. Re: Programmatically view generation
                        Prathamesh Gaddam Novice

                        Thank you TIM, you made my day! Now i got the near to the reason of my quertion-'why?'


                        Merry Christmas!