You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Bill Lear <ra...@zopyra.com> on 2003/04/15 19:16:28 UTC

Help with Ad Banner component

I decided to create my first reusable Tapestry component, an "Ad
Banner" component.  The component "displays" an advertisement image
and when clicked, the component logs the click and redirects the user
to the appropriate site.

To my amazement, I've gotten it working (aside from the redirect), and
would like some feedback as to whether I've gone about it in a
reasonable way, and how perhaps to refine it.

An HTML page includes an ad banner by simply doing something like this:

    <span jwcid="adBanner"/>

Then, in the page specification:

    <component id="adBanner" type="AdBanner">
        <binding name="imageURL" expression="bannerImageURL"/>
        <binding name="imageHeight" expression="bannerImageHeight"/>
        <binding name="imageWidth" expression="bannerImageWidth"/>
        <binding name="imageAlt" expression="bannerImageAlt"/>
        <binding name="listener" expression="listeners.click"/>
    </component>

Here is the AdBanner.html file:

<span jwcid="$content$">
<span jwcid="link"><span jwcid="image"/></span>
</span>

And here is the AdBanner.jwc file:

<component-specification allow-body="no" allow-informal-parameters="no">
    <parameter name="imageURL" type="java.lang.String" direction="in"
               required="yes"/>

    <parameter name="imageHeight" type="java.lang.String" direction="in"
               required="yes"/>

    <parameter name="imageWidth" type="java.lang.String" direction="in"
               required="yes"/>

    <parameter name="imageAlt" type="java.lang.String" direction="in"
               required="yes"/>

    <parameter name="listener" type="org.apache.tapestry.IActionListener"
               direction="auto" required="yes"/>

    <component id="link" type="ActionLink">
        <inherited-binding name="listener" parameter-name="listener"/>
    </component>

    <component id="image" type="Any">
        <inherited-binding name="src" parameter-name="imageURL"/>
        <inherited-binding name="height" parameter-name="imageHeight"/>
        <inherited-binding name="width" parameter-name="imageWidth"/>
        <inherited-binding name="alt" parameter-name="imageAlt"/>
        <static-binding name="element" value="img"/>
    </component>
</component-specification>

I have two questions:

    1) I would like to simplify this by using a java class which
       encapsulates the URL, height, width, alt, and link (perhaps
       the listener also?).  Then, I would hope, my page specification
       would shorten to something like this:

           <component id="adBanner" type="AdBanner">
               <binding name="banner" expression="topBanner"/>
           </component>

      and my AdBanner.jwc file would shorten to look something like this:

           <parameter name="banner" type="com.foobar.Banner" direction="in"
                      required="yes"/>

           <component id="link" type="ActionLink">
               <inherited-binding name="listener"
                                  parameter-name="banner.handleClick"/>
           </component>

           <component id="image" type="Any">
              <inherited-binding name="src" parameter-name="banner.image"/>
              <inherited-binding name="height" parameter-name="banner.height"/>
              <inherited-binding name="width" parameter-name="banner.Width"/>
              <inherited-binding name="alt" parameter-name="banner.Alt"/>
              <static-binding name="element" value="img"/>
           </component>

       Before I attempt this: has anyone done something similar?  Is
       this a reasonable refinement or are there better ways of doing
       this?  The thing that worries me is the 'inherited-binding'
       above --- not even sure I can reference, e.g., 'banner.image'
       and have it work, so before I spend several hours trying to
       get this to work, I thought I'd ask others ...

    2) When the user clicks on the banner ad, the banner needs to
       redirect the user to the appropriate place.  This makes me
       believe that the banner will need to be serialized in the
       user's session so that the listener can be called on the
       appropriate object.  My question is: perhaps I should just
       encode something in the link so that the redirect destination
       can be fetched from permanent storage?  This means that I would
       (for example) declare the banner in the java class to be
       transient (I think), and then on the click I could just get
       the appropriate ID from the link parameters and do the redirect
       and logging from there.  Does this sound reasonable?
       Any hints on how best to do this?

Sorry for the long post, but I figured this is quite a common idiom.

At some point, I may want to mimic the advertising system I wrote for
a company I helped to start about 8 years ago, Deja News.  It (the ad
system) allowed you to store HTML content in the DB and to serve it
dynamically, substituting for redirect variables, and all sorts of
fancy things.  But, this is my first Tapestry component, so I wanted
to start slowly:-)

Thanks for any help you can offer.


Bill

RE: Help with Ad Banner component

Posted by Bill Lear <ra...@zopyra.com>.
On Tuesday, April 15, 2003 at 14:15:01 (-0400) Howard M. Lewis Ship writes:
>...
>I like this idea so much I may use it as an example in my book!

Hey, no fair!:-)

Actually I was feeling my way toward something like this, though of
course it would have taken me three weeks to come up with your
suggestions.

Thanks for the feedback.


Bill

RE: Help with Ad Banner component

Posted by "Howard M. Lewis Ship" <hl...@attbi.com>.
I kind of see the relationship between your Banner component and the
information needed to display and process it much like the relationship
between a PropertySelection and its model.

I would define an interface to encapsulate the data needed by the Banner.

In addition, I would define a new engine service to specifically perform the
logging and redirect related to a particular banner ad.

I would also come up with an abstraction for where banner ad information
comes from.

Let's say you have a BannerSource that provides BannerInfos.  The
BannerSource would have methods for getting a random BannerInfo or a
specific BannerInfo via some form of id.

The Banner component can obtain a random BannerInfo from the BannerSource.
It uses the BannerInfo to display the correct image and other information.
It uses the banner service to encode a reference to the BannerInfo, encoding
its id into the URL.

When clicked, the banner service can get the BannerInfo from the
BannerSource.  It can then log the clickthru and throw a RedirectException
to forward the client web browser to the right advertiser.

For best results, have an IBannerSource interface with different
implementations for database- or flat-file (probably XML) banner sources.

The best part is that all of this ... the BannerSource implementations, the
engine service, the components ... all of it could be packaged as a Tapestry
component library: use it and go.

I like this idea so much I may use it as an example in my book!

--
Howard M. Lewis Ship
Creator, Tapestry: Java Web Components
http://jakarta.apache.org/tapestry