1 2 Previous Next 23 Replies Latest reply on Aug 31, 2009 1:29 AM by kragoth

    Crazy Idea?: Programmatic Navigation (Static or Dynamic)

      Hi!


      I while ago I wrote a post in my blog about navigation the way WebObjects use to do it. So far I have not found a framework with such a simple and at the same powerful way for dealing with navigation and exchange of data between pages (sadly webobjects didn't support the concept of Long running conversations, but I think its navigational API could evolve to become a really good fit for Seam conversational model). Lately I have been having some doubts about the way navigation works in Seam, specially when dealing with nested conversations combined with @PerNestedConversation.


      The other day Tim Evers wrote that he would also like to have some kind of programmatic navigation, and it seemed similar to what I been thinking about, but he was unable to visit my blog due to firewall restrictions.


      Therefore I am posting here part of my blog post because I would like to discuss this different way of doing navigation in a more programmatic way:


      Here is a pseudo code example (In WebObjects, both pages and reusable fragments are WOComponents):


      public WOComponent gotoProfilePage(){
      ProfilePage profilePage = new ProfilePage();
      
      profilePage.setUser(this.getSelectedUser());
      return profilePage;
      
      }
      



      I think it is pretty self explanatory, it is an action that navigates to the ProfilePage, but it has all the advantage of static typing and object orientation, or course we could make it more dynamic if we need to:


      public WOComponent gotoProfilePage(){
      WOComponent profilePage = this.getPageWithName("ProfilePage");
      
      profilePage.takeValueForKey(this.getSelectedUser(),"user");
      return profilePage;
      
      }
      



      Therefore, using an API similar to this one as a basis we could have a programmatic and object oriented way of navigating that can work in a dynamic way if needed.


      Here is example of how this could look like if altered to be more Seam/RESTEasy like:


      
      @Path('/profile.xhtml')
      @Scope(ScopeType.PAGE)
      public class ProfilePage{
      
         //Other stuff in ProfilePage controller
         public void setUser(User user){...};
      
      }
      
      @Path('/home.xhtml')
      @Scope(ScopeType.PAGE)
      public class HomePage{
      
         //This is an action linked to a JSF control
         public ProfilePage gotoProfilePage(){
           ProfilePage profilePage = new ProfilePage();
           profilePage.setUser(this.getSelectedUser());
           return profilePage;
        }
      
         //Other Stuff in ProfilePage
         public User getSelectedUser(){...};
      
      
      }
      



      A Seam interceptor could detect that the action returned an object annotated with @Path('/home.xhtml') and redirect to that page sending the currently selected user in HomePage to the ProfilePage using a Temporary Conversation.


      What do you guys think? Would it work? Do you notice any major flaws with this model?

        • 1. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)

          Francisco Peredo wrote on Oct 16, 2008 18:56:



          A Seam interceptor could detect that the action returned an object annotated with @Path('/home.xhtml') and redirect to that page sending the currently selected user in HomePage to the ProfilePage using a Temporary Conversation.


          Should have written:

          A Seam interceptor could detect that the action returned an object annotated with @Path('/profile.xhtml') and redirect to that page sending the currently selected user in HomePage to the ProfilePage using a Temporary Conversation.




          What do you guys think? Would it work? Do you notice any major flaws with this model?


          • 2. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)

            And the dynamic way (with help from DynaBean) of dealing with this would be:


            @Path("/profile.xhtml")
            @Name("profilePage)
            @Scope(ScopeType.PAGE)
            public class ProfilePage{
            
               //Other stuff in ProfilePage controller
               public void setUser(User user){...};
            
            }
            
            @Path("/home.xhtml")
            @Name("homePage")
            @Scope(ScopeType.PAGE)
            public class HomePage{
            
               //This is an action linked to a JSF control
               public DynaBean gotoProfilePage(){
                   DynaBean profilePage=new WrapDynaBean (Component.getInstance("profilePage"));
                   profilePage.set("user",this.getSelectedUser());
                   return profilePage;
              }
            
               //Other Stuff in HomePage
               public User getSelectedUser(){...};
            
            
            }
            
            



            I think this proposal (both in its static and dynamic forms) also has the advantage of being more respectful of encapsulation than @Out/@In

            • 3. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)
              pmuir

              This is the way Wicket doesn navigation, and is very very nice, I agree.


              However I think it is a (very) bad fit with JSF as you have to introduce this layer of  Page orientated controller components which are orthogonal to component architecture in Seam (which are Entity/use case orientated) and basically redundant. If you want this layer, then use Wicket, not JSF!


              Using pages.xml with <if> is IMO the best way to do non-coupled navigation with JSF, I wouldn't allow any navigation logic near my business logic.

              • 4. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)

                Interesting, I will take another look at Wicket (I visited their site a long a go, but I couldnt find any navigation examples, all the examples I could find worked with a single page).


                At first I tried to embrace the use of EntityHome/List with CONVERSATION scope as the best way to work when creating an application with Seam, but after a lot of problems and the opportunity to start another application, I chose to use more PAGE oriented components, and everything started to be a lot easier.


                I think the component architecture in Seam, has some important limitations because of its non page oriented architecture, it is specially hard to deal with entities with recursive relationships and with navigation/conversation graphs that have recursion, take for example the @PerNestedConversation, Seam own documentation says that:



                Warning: this is ill-defined, since it implies that a component will be visible for some part of a request cycle, and invisible after that. It is not recommended that applications use this feature!


                But in my experience most non-trivial models have at least 1 recursive relationship, and many of them have processes with multiple nested levels (also known as subroutines). Even Dan Allen avoided dealing with this subject  in the Seam in Action book! If that is not an indicator that something is not right with the current model (or perhaps implementation) of using EntityHome/List I do not know what is (In fact I am preparing a little example project to show what I believe are flaws in the way nested conversations are handled in Seam, they simply do not work as expected).


                I have also read a lot of post of people having problems exchanging information between parent and child conversations, or cleaning up form data manually instead of relaying on the creation of a new conversation, I think @In/@Out at least in their current incarnation are just unable to deal elegantly with this kind of problems, and if we are going to end up using lots of programmatic stuff like Component.instance or Conversation.instance for anything non-trivial maybe we should revise Seam architecture, after all those pseudo-singletons are like global variables and that is not the OOP way of solving problems.


                Another problem is the lack of encapsulation that leads to problems of magic modification of variables that I have not seen since I stopped programming with pointers in C++. These are the kind of problems that OOP encapsulation should be shielding us against, don't you agree?


                I hope you do not get me wrong, I like Seam a lot, but I am starting to feel that the complexity curve breaks the declarative way of working really fast, and if the programmatic way ends up being the real way of solving the problems maybe we should find the way to embrace it instead of fighting against it. After all, navigation is an algorithm too, why not a full language like Java to deal with it?

                • 5. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)
                  pmuir

                  You really make two points:



                  1) That you prefer a Page orientated approach

                  This is your choice, but it's not the idea Seam was designed around.



                  2) That Nested Conversations don't work right

                  We know nested conversations aren't as well tested as standard conversations; when I built apps with Seam, I never saw a need for them. We're always willing to try to solve these problems and fix them; but at some point you will have to actually do some work ;-)


                  and sub-point



                  3) We need to revise architecture

                  This is Web Beans, and you need to get involved with that effort to make any major changes.

                  • 6. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)

                    Pete Muir wrote on Oct 17, 2008 11:11:


                    You really make two points:

                    2) That Nested Conversations don't work right

                    We know nested conversations aren't as well tested as standard conversations; when I built apps with Seam, I never saw a need for them.


                    Well, then, please enlighten me :-P, how do you deal with recursive/nested database model/business workflow? (So far I have dumped @PerNestedConversation and I am starting to use java.util.Stack variables inside my Seam components, but it just doesn't feel quite right...)


                    We're always willing to try to solve these problems and fix them; but at some point you will have to actually do some work ;-)

                    Yes, I know, I will have to help, I am just not familiarized enough with Seam internal code :-(. But I will, it is just a matter of time :-).


                    and sub-point

                    3) We need to revise architecture

                    This is Web Beans, and you need to get involved with that effort to make any major changes.

                    How do I do that? Just kidding, I guess I'll start downloading from SVN



                    • 7. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)

                      Another disadvantage of the current xml based navigation. There is no debugger: JBIDE-3383

                      • 8. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)
                        kragoth

                        The biggest problem with the current navigation is that there is no contract between caller and receiver. The way I have implemented navigation for our system enforces that no matter what navigation you do you must provide the correct data. With the current seam approach navigation errors can only be detected at runtime. My approach brings errors back into compile time to do away with a lot of errors.


                        All navigation in the system I'm working on is done IN CODE. There is only 1 navigation rule in pages.xml and that is for the login screen. (And I could probly get rid of that but... its so nice and easy to leave it there :P)


                        Any time that developers are forced to drop down to strings is never a good sign. It means that you lose all context and you now must assume that whoever navigates to you knows exactly what data to outject etc to get to you.


                        I'm not saying my model is perfect, but it definitly has made our team able to produce their code a lot faster and a lot simpler. Sure its a little verbose due to java's implementation of annonymous subclasses etc but it works and works well.


                        The core to my navigation framework is two fold. We have broken our pages up into modules. Basically all pages that relate to a single entity forms one module. The implication of this is that all navigations between pages in the same module will by definition be in the same conversation. But all navigation between pages of different modules will be in seperate conversations.


                        So If I have two modules say... searchForManufacturer.xhtml, searchForCar.xhtml
                        Manufactures, and Cars.


                        Then the Manufactures module might have pages:
                        viewManufacturer.xhtml
                        addNewManufacturer.xhtml


                        In the Cars module I might have:
                        viewCar.xhtml
                        addCar.xhtml.


                        So if I go to the addCar page one of the buttons there will be to Choose Manufacturer Clicking on this button will start a brand new conversation and navigate to the searchForManufacturer page. The way this all happens is slightly complicated so... I'm not sure if I should post it here but oh well.
                        What happens is this. The click method will create what we call a

                        LookupNavigationAction<ManufactureSearchBean>

                        annonymous subclass and pass this to my NavigationManager. The NavManager goes ok, you want to do a navigation from one module to another and the SeamBean you are going to invoke the navigation method on is provided in the generic type of this subclass.
                        So it leaves the current conversation, instantiates the seam bean in a new conversation and then invokes the appropriate method (provided in one of the implemented methods of the subclass which loooks like this: navForward(ManufactureSearchBean searchBean)).


                        Anyway that's a really really fast overview of what I'm doing. It works really well. None of my team members have to worry about long running conversations and wether or not they need to join or begin or end or any of the other problems that go with it. Recursion works perfectly as there is no nested conversations, all conversations are stand alone long running conversations. The implementation is type safe and allows for contracts between pages. This also reduces the amount of xml that quickly gets out of hand in large systems (yes it does and we all know it :P, also reduces checkin conflicts because we are not all working on the xml for navigation rules).


                        If anyone is interested in seeing exactly how I do this let me know. I think most people would find it quite usefull (at least after doing it the old way I'm very happy with how we are doing it now).



                        And how do i subscribe to a thread sigh :P

                        • 9. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)
                          kragoth

                          DOH! where is the edit button when you need it!
                          These lines are wrong....



                          So If I have two modules say... searchForManufacturer.xhtml, searchForCar.xhtml Manufactures, and Cars.
                          Then the Manufactures module might have pages: viewManufacturer.xhtml addNewManufacturer.xhtml
                          In the Cars module I might have: viewCar.xhtml addCar.xhtml.

                          They should say this!
                          So if I have four modules say....



                          • searchForManufacturer

                          • searchForCar

                          • Cars

                          • Manufacturers



                          In the searchForManufacturer module I would have.



                          • manufacturerSearch.xhtml



                          In the searchForCar module I would have.



                          • carSearch.xhtml



                          In the Cars module I would have



                          • addCar.xhtml

                          • viewCar.xhtml



                          And similar pages in the Manufacturers module.

                          • 10. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)

                            Interesting, could you post a code snippet somehow equivalent to the what I posted in the first post of this thread? I like your idea of grouping your pages module and have them share a LRC, but I believe  that in the model I propose there is no need for LRC, you only need temporary conversations and the page scope... do you agree?


                            Can you share some introductory information on how could I build my own NavigationManager?... Mmmmm... Or maybe we should aim sighter and create a framework that allows us to create custom navigation managers? That way it would be possible to plug-in different navigation strategies for Seam: The traditional .pages.xml, the modular Tim Evers way, the WebObjectsNostalgia Francisco's way, etc, etc. And let the best navigation manager win the battle!



                            What do you think about that?

                            • 11. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)

                              Tim Evers wrote on Dec 11, 2008 03:19:


                              And how do i subscribe to a thread sigh :P



                              You did took quite a loooooong time to answer :-P.


                              I hope I do not have to wait another 2 months for your next post ;-)






                              • 12. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)

                                And no custom logging: JBSEAM-3831

                                • 13. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)
                                  vladimir.kovalyuk

                                  I have to agree with Francisco. Seam conversation model and API should be revisited. It is not complete and does not support many cases required to design robust UI. For instance Seam does not provide an extension point which allows me to enhance or control a conversation lifecycle. Even more, I didn't find all the code controlling conversation lifecycle incapsulated in a sole class. The example of a mess is org.jboss.seam.core.Manager class - you can find there fields and methods related to current conversation and some settings together, published API and internal API together.


                                  Some cents about JSF.
                                  I think JSF can't be used to generalize page composition and navigation. It has nothing to do with OO practices at all. Ok, for small web applications declarative approach suites very well and OOD seems overkill. But in robust applications we have to deal with complexity which is proven to be solved using OOP and OOD. JSF can't help with. And more - Facelets and component libraries adds its own execution contexts what increases mess in UI design and makes it very buggy. JSF 2.0 does not provide anything new to help to solve complexity. That's why I'm looking at Wicket and GWT (although I don't like Google's approach to downcast Java to JS 'cause it makes me to have 2-3 classes to represent entities in the applications, correct me if I'm wrong).


                                  Pete, you said Seam conversations was designed with JSF in mind. Probably it does not make sence to employ JSF-tied conversation model in Wicket integration. And instead of that probably it would make sence to come up with a new OO-oriented conversation model (only for Wicket).


                                  About navigation. If you have 80% of navigation rules in your application similar to each other you will certainly think about how to gather all them to a sole piece of code (Otherwise you will find yourself patching all the rules in your application caused by simple task). There are 2 approaches - viewid wildcards and Java classes. I would prefer the latter. And again - it's due to proven OO practices. What Seam component does help me to go with the second approach?


                                  WebBeans does not seem to go one step toward OO.

                                  • 14. Re: Crazy Idea?: Programmatic Navigation (Static or Dynamic)

                                    Vladimir Kovalyuk wrote on Dec 11, 2008 17:16:


                                    Some cents about JSF.
                                    I think JSF can't be used to generalize page composition and navigation. It has nothing to do with OO practices at all. Ok, for small web applications declarative approach suites very well and OOD seems overkill.



                                    Some people think that the declarative approach is better for bigger applications... In my opinion it has nothing to do with size, it has is related to navigation complexity, and if your navigation is complex enough you are going to need a real language to deal with it. The declarative approach is good for document oriented stuff but not for data oriented web applications.



                                    But in robust applications we have to deal with complexity which is proven to be solved using OOP and OOD. JSF can't help with. And more - Facelets and component libraries adds its own execution contexts what increases mess in UI design and makes it very buggy. JSF 2.0 does not provide anything new to help to solve complexity. That's why I'm looking at Wicket and GWT (although I don't like Google's approach to downcast Java to JS 'cause it makes me to have 2-3 classes to represent entities in the applications, correct me if I'm wrong).


                                    The funny thing is that the Seam team felt that the standard XML declarative navigation of JSF was insufficient and created they own extended not standard XML declarative navigation. Wouldn't it be better if Seam offered a programmatic API for navigation that could be extended to support XML declarative navigation if and only if an application demands requires it?



                                    Pete, you said Seam conversations was designed with JSF in mind. Probably it does not make sence to employ JSF-tied conversation model in Wicket integration. And instead of that probably it would make sence to come up with a new OO-oriented conversation model (only for Wicket).



                                    Perhaps that could be done, but I do not want to work with Wicket, I want to use JSF, therefore I do not want Seam to become more Wicket oriented, but I'd love it if Seam could make JSF more object (Wicket?) oriented, specially navigation wise. (Paradoxical no?)



                                    About navigation. If you have 80% of navigation rules in your application similar to each other you will certainly think about how to gather all them to a sole piece of code (Otherwise you will find yourself patching all the rules in your application caused by simple task). There are 2 approaches - viewid wildcards and Java classes. I would prefer the latter. And again - it's due to proven OO practices. What Seam component does help me to go with the second approach?


                                    I totally agree with you.


                                    WebBeans does not seem to go one step toward OO.


                                    After reading a litte about WebBeans, it seems to have nothing to do with navigation, and everything to do with IoC. But I guess WebBeans could be useful as a foundation to build a new framework with an object oriented navigation API like the one I propose at the begining... Am I right?




                                    1 2 Previous Next