Re: How to add a qurey parameter to all generated links?

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: How to add a qurey parameter to all generated links?

Preston L. Bannister
Preston L. Bannister wrote:
>>>> I have a web application (to be implemented using Tapestry) that
>>>> will be called from another web application with a single
>>>> parameter.  All the generated links within the application should
>>>> encode this parameter into the link (most likely in the query
>>>> string?).  I could push the parameter into the session, but I want
>>>> the user to be able to bookmark the link and capture the parameter.
>>>>
>>>> For whatever reason it is not clear to me where this should be
>>>> hooked into the Tapestry framework...

Finally got back(!) to this particular problem, and after far too much
mucking around in the code, came up with an answer of sorts.  What seems
to do the trick is to override the ILink implementations to change the
render used for links.

For example the re-done PageLink class looks like:
--------------------------------------------------------------------
public abstract class PageLink extends AbstractLinkComponent {

     public ILink getLink(IRequestCycle cycle) {
         String targetPage = getTargetPage();
         INamespace namespace = getTargetNamespace();
         String parameter = ((null == namespace) ? targetPage :
namespace.constructQualifiedName(targetPage));
         IEngineService service =
cycle.getEngine().getService(Tapestry.PAGE_SERVICE);
         ILink o = service.getLink(cycle,this,new String[] { parameter });
         return o;
     }
     protected void finishLoad() {
         setRenderer(DefaultLinkRenderer.SHARED_INSTANCE);
     }
     public abstract String getTargetPage();
     public abstract INamespace getTargetNamespace();
}
--------------------------------------------------------------------

Note the call to setRender() in finishLoad(), and that the class
DefaultLinkRenderer is in fact from an application (not from the
Tapestry library).

The added parameter is built into the link by the DefaultLinkRenderer.
--------------------------------------------------------------------
public class DefaultLinkRenderer implements ILinkRenderer {

     // A shared instance used as a default for any link that doesn't
explicitly override.
     public static final ILinkRenderer SHARED_INSTANCE = new
DefaultLinkRenderer();

     public void renderLink(IMarkupWriter writer, IRequestCycle cycle,
ILinkComponent linkComponent) {
         if (null !=
cycle.getAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME)) {
             throw new ApplicationRuntimeException(
 
Tapestry.getMessage("AbstractLinkComponent.no-nesting"),
                     linkComponent,
                     null,
                     null
                     );
         }
 
cycle.setAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME,linkComponent);
         if (linkComponent.isDisabled()) {
             if (getHasBody()) {
                 linkComponent.renderBody(writer,cycle);
             }
         } else {
             ILink l = linkComponent.getLink(cycle);
             String url = l.getURL(linkComponent.getAnchor(),true);
             String id = cycle.getRequestContext().getParameter("id");
             url = url + "&id=" + id;
             if (getHasBody()) {
                 writer.begin(getElement());
                 writer.attribute(getUrlAttribute(),url);
                 beforeBodyRender(writer,cycle,linkComponent);
                 IMarkupWriter wrappedWriter = writer.getNestedWriter();
                 linkComponent.renderBody(wrappedWriter,cycle);
                 afterBodyRender(writer,cycle,linkComponent);
                 linkComponent.renderAdditionalAttributes(writer,cycle);
                 wrappedWriter.close();
                 writer.end();
             } else {
                 writer.beginEmpty(getElement());
                 writer.attribute(getUrlAttribute(),url);
                 beforeBodyRender(writer,cycle,linkComponent);
                 afterBodyRender(writer,cycle,linkComponent);
                 linkComponent.renderAdditionalAttributes(writer,cycle);
                 writer.closeTag();
             }
         }
         cycle.removeAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME);
     }

     protected String constructURL(ILink link, String anchor,
IRequestCycle cycle) {
         return link.getURL(anchor,true);
     }
     protected void beforeBodyRender(IMarkupWriter writer, IRequestCycle
cycle, ILinkComponent link) {
         // do nothing
     }
     protected void afterBodyRender(IMarkupWriter writer, IRequestCycle
cycle, ILinkComponent link) {
         // do nothing
     }
     protected String getElement() {
         return "a";
     }
     protected String getUrlAttribute() {
         return "href";
     }
     protected boolean getHasBody() {
         return true;
     }
}
--------------------------------------------------------------------

Doubtless the above is somewhat mangled by line wrap.  This would better
be sent in HTML format, but though the rationale faded away long ago,
the ban remains.

Whether the above solution is particularly elegant is an entirely
different question.  It seems that link generation should be more a
top-level notion in the page generation model, perhaps.


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: How to add a qurey parameter to all generated links?

Robert Zeigler
Question: why not just specify your custom renderer to the page link
component?

<a jwcid="@PageLink" page="somePage"
renderer="ognl:defaultLinkRenderer">Some Link</a>

You could wrap the page link component in your own custom component,
specify the renderer in your custom component, and then just you your
AppPageLink (or whatever you decide to call it) throughout your
application. :)

Robert

Preston L. Bannister wrote:

> Preston L. Bannister wrote:
>
>>>>> I have a web application (to be implemented using Tapestry) that
>>>>> will be called from another web application with a single
>>>>> parameter.  All the generated links within the application should
>>>>> encode this parameter into the link (most likely in the query
>>>>> string?).  I could push the parameter into the session, but I want
>>>>> the user to be able to bookmark the link and capture the parameter.
>>>>>
>>>>> For whatever reason it is not clear to me where this should be
>>>>> hooked into the Tapestry framework...
>
>
> Finally got back(!) to this particular problem, and after far too much
> mucking around in the code, came up with an answer of sorts.  What seems
> to do the trick is to override the ILink implementations to change the
> render used for links.
>
> For example the re-done PageLink class looks like:
> --------------------------------------------------------------------
> public abstract class PageLink extends AbstractLinkComponent {
>
>     public ILink getLink(IRequestCycle cycle) {
>         String targetPage = getTargetPage();
>         INamespace namespace = getTargetNamespace();
>         String parameter = ((null == namespace) ? targetPage :
> namespace.constructQualifiedName(targetPage));
>         IEngineService service =
> cycle.getEngine().getService(Tapestry.PAGE_SERVICE);
>         ILink o = service.getLink(cycle,this,new String[] { parameter });
>         return o;
>     }
>     protected void finishLoad() {
>         setRenderer(DefaultLinkRenderer.SHARED_INSTANCE);
>     }
>     public abstract String getTargetPage();
>     public abstract INamespace getTargetNamespace();
> }
> --------------------------------------------------------------------
>
> Note the call to setRender() in finishLoad(), and that the class
> DefaultLinkRenderer is in fact from an application (not from the
> Tapestry library).
>
> The added parameter is built into the link by the DefaultLinkRenderer.
> --------------------------------------------------------------------
> public class DefaultLinkRenderer implements ILinkRenderer {
>
>     // A shared instance used as a default for any link that doesn't
> explicitly override.
>     public static final ILinkRenderer SHARED_INSTANCE = new
> DefaultLinkRenderer();
>
>     public void renderLink(IMarkupWriter writer, IRequestCycle cycle,
> ILinkComponent linkComponent) {
>         if (null !=
> cycle.getAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME)) {
>             throw new ApplicationRuntimeException(
>
> Tapestry.getMessage("AbstractLinkComponent.no-nesting"),
>                     linkComponent,
>                     null,
>                     null
>                     );
>         }
>
> cycle.setAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME,linkComponent);
>         if (linkComponent.isDisabled()) {
>             if (getHasBody()) {
>                 linkComponent.renderBody(writer,cycle);
>             }
>         } else {
>             ILink l = linkComponent.getLink(cycle);
>             String url = l.getURL(linkComponent.getAnchor(),true);
>             String id = cycle.getRequestContext().getParameter("id");
>             url = url + "&id=" + id;
>             if (getHasBody()) {
>                 writer.begin(getElement());
>                 writer.attribute(getUrlAttribute(),url);
>                 beforeBodyRender(writer,cycle,linkComponent);
>                 IMarkupWriter wrappedWriter = writer.getNestedWriter();
>                 linkComponent.renderBody(wrappedWriter,cycle);
>                 afterBodyRender(writer,cycle,linkComponent);
>                 linkComponent.renderAdditionalAttributes(writer,cycle);
>                 wrappedWriter.close();
>                 writer.end();
>             } else {
>                 writer.beginEmpty(getElement());
>                 writer.attribute(getUrlAttribute(),url);
>                 beforeBodyRender(writer,cycle,linkComponent);
>                 afterBodyRender(writer,cycle,linkComponent);
>                 linkComponent.renderAdditionalAttributes(writer,cycle);
>                 writer.closeTag();
>             }
>         }
>         cycle.removeAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME);
>     }
>
>     protected String constructURL(ILink link, String anchor,
> IRequestCycle cycle) {
>         return link.getURL(anchor,true);
>     }
>     protected void beforeBodyRender(IMarkupWriter writer, IRequestCycle
> cycle, ILinkComponent link) {
>         // do nothing
>     }
>     protected void afterBodyRender(IMarkupWriter writer, IRequestCycle
> cycle, ILinkComponent link) {
>         // do nothing
>     }
>     protected String getElement() {
>         return "a";
>     }
>     protected String getUrlAttribute() {
>         return "href";
>     }
>     protected boolean getHasBody() {
>         return true;
>     }
> }
> --------------------------------------------------------------------
>
> Doubtless the above is somewhat mangled by line wrap.  This would better
> be sent in HTML format, but though the rationale faded away long ago,
> the ban remains.
>
> Whether the above solution is particularly elegant is an entirely
> different question.  It seems that link generation should be more a
> top-level notion in the page generation model, perhaps.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: How to add a qurey parameter to all generated links?

Howard Lewis Ship
In Tapestry 4.0, you could easily override the
tapestry.url.LinkFactory service for this purpose.

On 5/12/05, Robert Zeigler <[hidden email]> wrote:

> Question: why not just specify your custom renderer to the page link
> component?
>
> <a jwcid="@PageLink" page="somePage"
> renderer="ognl:defaultLinkRenderer">Some Link</a>
>
> You could wrap the page link component in your own custom component,
> specify the renderer in your custom component, and then just you your
> AppPageLink (or whatever you decide to call it) throughout your
> application. :)
>
> Robert
>
> Preston L. Bannister wrote:
> > Preston L. Bannister wrote:
> >
> >>>>> I have a web application (to be implemented using Tapestry) that
> >>>>> will be called from another web application with a single
> >>>>> parameter.  All the generated links within the application should
> >>>>> encode this parameter into the link (most likely in the query
> >>>>> string?).  I could push the parameter into the session, but I want
> >>>>> the user to be able to bookmark the link and capture the parameter.
> >>>>>
> >>>>> For whatever reason it is not clear to me where this should be
> >>>>> hooked into the Tapestry framework...
> >
> >
> > Finally got back(!) to this particular problem, and after far too much
> > mucking around in the code, came up with an answer of sorts.  What seems
> > to do the trick is to override the ILink implementations to change the
> > render used for links.
> >
> > For example the re-done PageLink class looks like:
> > --------------------------------------------------------------------
> > public abstract class PageLink extends AbstractLinkComponent {
> >
> >     public ILink getLink(IRequestCycle cycle) {
> >         String targetPage = getTargetPage();
> >         INamespace namespace = getTargetNamespace();
> >         String parameter = ((null == namespace) ? targetPage :
> > namespace.constructQualifiedName(targetPage));
> >         IEngineService service =
> > cycle.getEngine().getService(Tapestry.PAGE_SERVICE);
> >         ILink o = service.getLink(cycle,this,new String[] { parameter });
> >         return o;
> >     }
> >     protected void finishLoad() {
> >         setRenderer(DefaultLinkRenderer.SHARED_INSTANCE);
> >     }
> >     public abstract String getTargetPage();
> >     public abstract INamespace getTargetNamespace();
> > }
> > --------------------------------------------------------------------
> >
> > Note the call to setRender() in finishLoad(), and that the class
> > DefaultLinkRenderer is in fact from an application (not from the
> > Tapestry library).
> >
> > The added parameter is built into the link by the DefaultLinkRenderer.
> > --------------------------------------------------------------------
> > public class DefaultLinkRenderer implements ILinkRenderer {
> >
> >     // A shared instance used as a default for any link that doesn't
> > explicitly override.
> >     public static final ILinkRenderer SHARED_INSTANCE = new
> > DefaultLinkRenderer();
> >
> >     public void renderLink(IMarkupWriter writer, IRequestCycle cycle,
> > ILinkComponent linkComponent) {
> >         if (null !=
> > cycle.getAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME)) {
> >             throw new ApplicationRuntimeException(
> >
> > Tapestry.getMessage("AbstractLinkComponent.no-nesting"),
> >                     linkComponent,
> >                     null,
> >                     null
> >                     );
> >         }
> >
> > cycle.setAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME,linkComponent);
> >         if (linkComponent.isDisabled()) {
> >             if (getHasBody()) {
> >                 linkComponent.renderBody(writer,cycle);
> >             }
> >         } else {
> >             ILink l = linkComponent.getLink(cycle);
> >             String url = l.getURL(linkComponent.getAnchor(),true);
> >             String id = cycle.getRequestContext().getParameter("id");
> >             url = url + "&id=" + id;
> >             if (getHasBody()) {
> >                 writer.begin(getElement());
> >                 writer.attribute(getUrlAttribute(),url);
> >                 beforeBodyRender(writer,cycle,linkComponent);
> >                 IMarkupWriter wrappedWriter = writer.getNestedWriter();
> >                 linkComponent.renderBody(wrappedWriter,cycle);
> >                 afterBodyRender(writer,cycle,linkComponent);
> >                 linkComponent.renderAdditionalAttributes(writer,cycle);
> >                 wrappedWriter.close();
> >                 writer.end();
> >             } else {
> >                 writer.beginEmpty(getElement());
> >                 writer.attribute(getUrlAttribute(),url);
> >                 beforeBodyRender(writer,cycle,linkComponent);
> >                 afterBodyRender(writer,cycle,linkComponent);
> >                 linkComponent.renderAdditionalAttributes(writer,cycle);
> >                 writer.closeTag();
> >             }
> >         }
> >         cycle.removeAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME);
> >     }
> >
> >     protected String constructURL(ILink link, String anchor,
> > IRequestCycle cycle) {
> >         return link.getURL(anchor,true);
> >     }
> >     protected void beforeBodyRender(IMarkupWriter writer, IRequestCycle
> > cycle, ILinkComponent link) {
> >         // do nothing
> >     }
> >     protected void afterBodyRender(IMarkupWriter writer, IRequestCycle
> > cycle, ILinkComponent link) {
> >         // do nothing
> >     }
> >     protected String getElement() {
> >         return "a";
> >     }
> >     protected String getUrlAttribute() {
> >         return "href";
> >     }
> >     protected boolean getHasBody() {
> >         return true;
> >     }
> > }
> > --------------------------------------------------------------------
> >
> > Doubtless the above is somewhat mangled by line wrap.  This would better
> > be sent in HTML format, but though the rationale faded away long ago,
> > the ban remains.
> >
> > Whether the above solution is particularly elegant is an entirely
> > different question.  It seems that link generation should be more a
> > top-level notion in the page generation model, perhaps.
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [hidden email]
> > For additional commands, e-mail: [hidden email]
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>


--
Howard M. Lewis Ship
Independent J2EE / Open-Source Java Consultant
Creator, Jakarta Tapestry
Creator, Jakarta HiveMind

Professional Tapestry training, mentoring, support
and project work.  http://howardlewisship.com

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: How to add a qurey parameter to all generated links?

Preston L. Bannister
In reply to this post by Robert Zeigler
Specifying a renderer for each PageLink in the HTML would be tedious,
especially given all the links within this application *must* encode
this additional parameter.

Perhaps I do not understand your meaning.

Robert Zeigler wrote:

> Question: why not just specify your custom renderer to the page link
> component?
>
> <a jwcid="@PageLink" page="somePage"
> renderer="ognl:defaultLinkRenderer">Some Link</a>
>
> You could wrap the page link component in your own custom component,
> specify the renderer in your custom component, and then just you your
> AppPageLink (or whatever you decide to call it) throughout your
> application. :)


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: How to add a qurey parameter to all generated links?

Robert Zeigler
That's why you make your custom component. Or, in tapestry-4.0, you can
do as Howard suggested. It would be all of five minutes work (probably
closer to 2 or less, with spindle) to create a component that wraps
PageLink and sets the renderer once i that component; you can then
use your custom component throughout your app /instead/ of page link.
Seems a bit simpler an approach than subclassing to return the
appropriate link renderer. But, to each his own. :)

Robert

Preston L. Bannister wrote:

> Specifying a renderer for each PageLink in the HTML would be tedious,
> especially given all the links within this application *must* encode
> this additional parameter.
>
> Perhaps I do not understand your meaning.
>
> Robert Zeigler wrote:
>
>> Question: why not just specify your custom renderer to the page link
>> component?
>>
>> <a jwcid="@PageLink" page="somePage"
>> renderer="ognl:defaultLinkRenderer">Some Link</a>
>>
>> You could wrap the page link component in your own custom component,
>> specify the renderer in your custom component, and then just you your
>> AppPageLink (or whatever you decide to call it) throughout your
>> application. :)
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]