1 2 Previous Next 18 Replies Latest reply on Apr 30, 2006 7:43 PM by andrew.rw.robinson

    Here is code for annotation based navigation rules

    rdewell

      If you're like me then you're probably loving the XML-less universe of Seam. Well, I couldn't let my managed beans have all the fun.

      It turns out to be terribly simple to implement annotation based navigation rules for JSF. Here's a download to a few class files (no instructions, but pretty easy to figure out), that do just that. You'll be xml-less in no time:

      ---------------
      @Stateless
      @Name("DoSomething")
      @Interceptor(SeamInterceptor.class)
      public class DoSomethingAction {

      @NavigationRules(
      {
      @NavigationRule(outcome="success", view="excellent.xml"),
      @NavigationRule(outcome="failure", view="nope.xml")
      }
      )
      public String action(){
      return "success";
      }

      }
      ---------------

      Note: Seam is required for this particular implementation, though you could pretty easily make it not depend on Seam.

      All you have to do is add the AnnotationNavigationHandler to your faces-config.xml file (see JSF docs), and then start annotating your action methods! It's backwards compatible with regular JSF xml navigation, so you can mix and match:

      http://thoughtatlas.com/annotationNavigation.html

      Enjoy,

      Ryan


        • 1. Re: Here is code for annotation based navigation rules
          rdewell

          Oops, my DoSomethingAction above should of course implement a DoSomething. There is a small example in the downloadable file as well.

          Ryan

          • 2. Re: Here is code for annotation based navigation rules
            marius.oancea

            Nice idea

            • 3. Re: Here is code for annotation based navigation rules
              patrick_ibg

              Very nice...

              Expanding on your original idea, you might want to add a "from-view-id" parameter, and the ability to define nav rules for an entire action class.

              Here's my use case. Note that I renamed your original annotations to reflect the JSF xml tags:

              @Stateful
              @Name ("wizard")
              @Interceptor(SeamInterceptor.class)
              @NavigationRules ({
               @NavigationRule (cases = @NavigationCase (outcome="begin", to="wizard1.xml")),
               @NavigationRule (cases = @NavigationCase (outcome="confirm", to="home.xml")),
               @NavigationRule (
               from = "wizard1.xhtml",
               cases = {
               @NavigationCase (outcome="next", to="wizard2.xml"),
               @NavigationCase (outcome="back", to="error.xml")
               }),
               @NavigationRule (
               from = "wizard2.xhtml",
               cases = {
               @NavigationCase (outcome="next", to="wizard3.xml"),
               @NavigationCase (outcome="back", to="wizard1.xml")
               }),
               @NavigationRule (
               from = "wizard3.xhtml",
               cases = {
               @NavigationCase (outcome="next", to="confirm.xml"),
               @NavigationCase (outcome="back", to="wizard2.xml")
               })
              })
              public class WizardAction
               implements Wizard {
              
               @Begin
               public String begin () {
               // start a conversation
               return "begin" ;
               }
              
               @IfInvalid (outcome = REDISPLAY)
               public String next () {
               // do stuff
               return "next";
               }
              
               public String back () {
               // do stuff
               return "back";
               }
              
               @End
               public String confirm () {
               return "confirm" ;
               }
              }
              


              Funny tho, how it begins to look alot like faces-config.xml. However, it's extremely nice to have the navigation rules in the same class file as the action class.


              • 4. Re: Here is code for annotation based navigation rules
                patrick_ibg

                Typo: to="*.xml" should read to="*.xhtml"

                • 5. Re: Here is code for annotation based navigation rules
                  rdewell

                  Hi Patrick,

                  Good point, and your example would pretty much complete all of the out-of-the-box JSF navigation functionality.

                  I personally found myself never using the "from-view-id" nav concept, and therefore it greatly simplifies things to just attach the rules to the action method itself -- effectively always using "from-action". It also makes the code clearer to have the rules right next to the method being executed, IMO. But, it would be nice to support all JSF nav concepts to be sure.

                  At any rate, I'm sure that someday we'll see a library that digs deeper into JSF navigation, and does for it what Facelets did for the view... Hopefully that library will have an annotation option. I do like everything in one place. :)

                  Ryan

                  • 6. Re: Here is code for annotation based navigation rules
                    gavin.king

                    Cool.

                    Please submit this stuff to JIRA. Currently, what we are working on is allowing navigation to be defined via jBPM process definition. However, I am keen on also supporting an annotation-based alternative.

                    Thanks mate.

                    • 7. Re: Here is code for annotation based navigation rules
                      patrick_ibg
                      • 8. Re: Here is code for annotation based navigation rules

                        I think this is very nice. This pretty much gets rid of just about everything that would change in the faces-config.xml now. This is very good because you can just drop in code + view and it will run. That is powerful.

                        The annotations are too verbose though. There should be lots of defaults. If there is only one rule/case can you just write the one? Can I attach a rule/case to an action method to make it apply only to that action?

                        In a typical action there is one outcome and the possibility of redisplay. It should be as simple as:

                        @Navigation(to="view.xhtml")
                        public String doSomething() {
                         // ...
                         return "ok";
                        }
                        


                        Only if you have multiple outcomes would you need to start getting messy.

                        @NavigationRule(cases= {
                         @Navigation(outcome="path1", to="view.xhtml")
                         @Navigation(outcome="path2", to="view.xhtml")
                         })
                        public String doSomething() {
                         if (...) return "path1";
                         else return "path2";
                        }
                        


                        Of course, the NavigationRule (and even NavigationCase) make sense at the class level too, as defaults for all methods.

                        Honestly, I like this a LOT better than jbpm-based navigation for simple applications.



                        • 9. Re: Here is code for annotation based navigation rules
                          kukeltje

                          This is indeed cool and how much I like jBPM, the process is only part of the application, as is the navigation that goes with it.

                          Wizards e.g. consist of multiple pages which lead to just one process step. Or prefilling forms with info from other db's or external systems is sometimes better not done in the process but in external pages. JSF fits nicely in this picture. All this results 50% pages in the process and 50% as normal pageflows/wizards in a demo application I developed for the company I work for, bypassing a (still shrink-wrapped on the shelve... .yes!!!) non-foss bpm engine).

                          Conclusion:both are needed to get a full blown application.

                          • 10. Re: Here is code for annotation based navigation rules
                            kukeltje

                            hmm... simple applications? I've written a 'simple' demo, wel in fact it is not that simple with coding just 4 actionhandlers in jBPM and configuring NO pages initially since the default task page from jBPM made it fully functional (looks don't count right? It's about the inner ;-)) So I do not agree that it is a LOT better. Combining the two is what makes it powerfull.

                            One thing though... visualizing pageflows and process-flows (I use Eclipse with MyEclipse and the jbpm-ide) is what gives me great things to talk about and saves me writing UML. How would annotations fit in here?

                            • 11. Re: Here is code for annotation based navigation rules
                              rdewell

                              Hi Norman,

                              RE: "If there is only one rule/case can you just write the one?"

                              Yes. You can just write @NavigationRule. Or, you can wrap them in @NavigationRules for multiple rules on the same method. The examples shows multiple.

                              RE: "Can I attach a rule/case to an action method to make it apply only to that action?"

                              Yes. In fact, the downloadable code (linked in first post) ONLY supports attaching @NavigationRule's to action methods because that's the common use-case under which this code was developed.

                              So, the very simplest use-case (and most common in my experience) is:

                              @NavigationRule(outcome="success", view="whatever.xml")
                              public String doSomething(){
                               return "success";
                              }
                              


                              • 12. Re: Here is code for annotation based navigation rules
                                marceloverdijk

                                 

                                "gavin.king@jboss.com" wrote:
                                Cool.

                                Please submit this stuff to JIRA. Currently, what we are working on is allowing navigation to be defined via jBPM process definition. However, I am keen on also supporting an annotation-based alternative.

                                Thanks mate.


                                It would be really nice to get this in the next Seam release. Because this is currently my biggest problem about JSF. All the navigation rules exposed through xml.

                                Regards,
                                Marcel

                                • 13. Re: Here is code for annotation based navigation rules
                                  gavin.king

                                  Well, I guess if you prefer the translation of logical outcome name -> URL to be done via annotations, you would almost be better off just returning a URL instead of having logical named outcomes at all ;)

                                  I actually never really understood the big deal about logical outcomes, claimed to be a major big-time benefit of Struts when it was first created. To me, a URL is *already* a logical name ;)

                                  • 14. Re: Here is code for annotation based navigation rules
                                    marceloverdijk

                                     

                                    "gavin.king@jboss.com" wrote:
                                    Well, I guess if you prefer the translation of logical outcome name -> URL to be done via annotations, you would almost be better off just returning a URL instead of having logical named outcomes at all ;)

                                    I actually never really understood the big deal about logical outcomes, claimed to be a major big-time benefit of Struts when it was first created. To me, a URL is *already* a logical name ;)


                                    Gavin,
                                    I think you are right. The *advantage*?? of using the AnnotationNavigationHandler is that you could mix both techniques: annotations and navigation rules in faces-config.xml.

                                    But if you don't want to use them at all (navigation rules), returning the url is more then sufficient. You would do something like:

                                    public class UrlNavigationHandler extends NavigationHandler {
                                    
                                     @Override
                                     public void handleNavigation(FacesContext ctx, String action, String outcome) {
                                     // we don't want logical outcomes; our outcome is the actual view url.
                                     String view = outcome;
                                     ViewHandler viewHandler = ctx.getApplication().getViewHandler();
                                     UIViewRoot newRoot = viewHandler.createView(ctx, view);
                                     ctx.setViewRoot(newRoot);
                                     }
                                    
                                    }


                                    In your action you do something like:

                                    public String action(){
                                     return "/passowrd.xhtml";
                                     }


                                    Please correct me if wrong. I'm not JSF experienced so I don't know if this will cause any problems.

                                    Regards,
                                    Marcel

                                    1 2 Previous Next