You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Morten Mortensen <MO...@tdc.dk> on 2006/11/04 00:10:34 UTC

Myfaces and URLs with dynamic segments

Anyone capable of creating a MyFaces/JSF application "App.WAR" including
an intercepting filter parsing some of the URI like writing this in the
browser -

http://localhost:8080/App/Prefix/Machine17/4713/Overview/index.html

- where the filter recognizes "Prefix", which triggers parsing of
"Machine17" and "4713" (using these parsed values as dynamic parameters
for beans) and forwards the request to an actual ressource
"/Overview/index.html" within the WAR file.

I can make this work up to showing all components, but all links/actions
on the actual page generated and which are supposed to refer to the page
itself refer to http://localhost:8080/App/Overview/index.html and not
the wanted
http://localhost:8080/App/Prefix/Machine17/4713/Overview/index.html.

Can anyone perform this stunt to its full extent?

Regards
Morten Sabroe Mortensen


SV: Myfaces and URLs with dynamic segments

Posted by Morten Mortensen <MO...@tdc.dk>.
I found a trick: Overriding the ViewHandler's getActionURL(). This
solves it all.

However, I wonder why the JSF API is so... underengineered. To overwrite
this single method, a proxy ViewHandler must be implemented and the
getActionURL() method overridden -

  /**
   *
   */
  public String getActionURL(FacesContext context,
                             String viewId)
  {
    String res=null;

    {
      String url=
        super.getActionURL(context,
                           viewId);

      if (url.contains("/Prefix/"))
      {
        url=
          url.replace("/Prefix/",
                      "/Prefix/Machine17/4713/");
      }

      res=url;
    }

    return res;
  }

To make the Application instanse unaware of things, the setViewHandler()
and getViewHandler() must be overridden too and in a thoughtful manner -

  /**
   *
   */
  private ViewHandler viewHandler;

  /**
   *
   */
  public ViewHandler getViewHandler()
  {
    ViewHandler res=null;

    {
      if (viewHandler==null)
      {
        ViewHandler h=super.getViewHandler();
        if (h!=null)
        {
          viewHandler=new SystemViewHandler(h);
        }
      }

      res=viewHandler;
    }

    return res;
  }

  /**
   *
   */
  public void setViewHandler(ViewHandler viewHandler)
  {
    this.viewHandler=viewHandler;
    super.setViewHandler(viewHandler);
  }

Then, you can not inject your own proxy Application instance by setting
your own ApplicationFactory in the configuration, because if you do,
then you can not obtain the original Application instance to be wrapped,
because this is JSF-implementation specific and was only obtainable
through the factory about to be overridden. This is most silly, because
I do not want to replace everything, but just change a bit of the
behaviour.

Instead, you put this in a top filter - or even better, a
ContextListener - to inject the new Application instance overridding
just the two methods -

    //Make sure the faces application is set:
    {
      ApplicationFactory f=(ApplicationFactory)
       FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
      Application a=f.getApplication();
      if (!(a instanceof SystemApplication))
      {
        Application b=new SystemApplication(a);
        f.setApplication(b);
      }
    }

So now I have a working solution. But I am stunned at the clumsiness of
the "elegant" JSF API; it sure could use some simple
"chain-of-responsibility" and "proxy" openings. The JSF API is written
with a complete replacement in mind, because it very badly fits purposes
of overridding single elements of the original API binding.

Regards
Morten Sabroe Mortensen 
 

________________________________

Fra: Morten Mortensen [mailto:MOMOR@tdc.dk] 
Sendt: 4. november 2006 00:11
Til: users@myfaces.apache.org
Emne: Myfaces and URLs with dynamic segments




Anyone capable of creating a MyFaces/JSF application "App.WAR" including
an intercepting filter parsing some of the URI like writing this in the
browser -

http://localhost:8080/App/Prefix/Machine17/4713/Overview/index.html
<http://localhost:8080/App/Prefix/Machine17/4713/Overview/index.html>  

- where the filter recognizes "Prefix", which triggers parsing of
"Machine17" and "4713" (using these parsed values as dynamic parameters
for beans) and forwards the request to an actual ressource
"/Overview/index.html" within the WAR file.

I can make this work up to showing all components, but all links/actions
on the actual page generated and which are supposed to refer to the page
itself refer to http://localhost:8080/App/Overview/index.html
<http://localhost:8080/App/Overview/index.html>  and not the wanted
http://localhost:8080/App/Prefix/Machine17/4713/Overview/index.html
<http://localhost:8080/App/Prefix/Machine17/4713/Overview/index.html> .

Can anyone perform this stunt to its full extent? 

Regards 
Morten Sabroe Mortensen