You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@click.apache.org by Garth Dahlstrom <ir...@gmail.com> on 2009/07/02 06:11:47 UTC

A few click newbie questions...

Hi All,

I'm new to click, I have some questions as I get into it....

1) Is there a way to prevent auto binding of fields?  i.e. In the template
project there are: public String title = "some text";
which someone can pass &title="something bad" into my page when I don't want
that.

2) Can anyone point me at an example of a page that redirects to itself
adding a getRequestParameter to it's own URL before rendering?
I tried to do it with:
if (getContext().getRequestParameter("app") == null) {
  getContext().setRequestAttribute("app", "default");
  setForward(this);
  // redirect to self without rendering...
}
in my onInit() method, but that doesn't bounce and just spins inside my
Tomcat server (also tried with setRedirect, I'm likely not doing this right)

I may have missed this stuff in the click book PDF or the example code when
I was scanning it, so if it's in there feel free to point me to the
particular example / page I should reference.

Cheers,
-G
              __
--- == __/ t.O ==--
http://stacktrace.org/

Re: A few click newbie questions...

Posted by Bob Schellink <sa...@gmail.com>.
Garth Dahlstrom wrote:
> 
> Hmm... going private or protected, fields must be added to the model via 
> addModel or is there annotation to do it?


Yes you can add it to the model. Starting with 2.1.0 there is the 
option of using the Bindable annotation. However for backward 
compatibility Click defaults to using public fields. You can change 
this by passing "annotation" to the autobinding property:

   <pages package="org.apache.click.examples.page" 
autobinding="annotation"/>

Then you can specify your fields as:

   @Bindable public String xyz;

Note the field is still declared public, however only those with 
Bindable annotations are considered.

Bindable is quite new in Click and there are plans to expand its 
functionality for finer grained control. You can view the details 
here: http://cwiki.apache.org/confluence/display/CLICK/Java+5+Support

Currently the documentation for Bindable is lacking a bit too.

> 
> When I try to use 'getContext().getRequestAttribute("app")', it always 
> return null, which causes it to go into a redirect loop.


Strange, the following works for me:

   public class ForwardPage extends Page {

     public void onInit() {
       if (getContext().getRequestAttribute("app") == null) {
         getContext().setRequestAttribute("app", "default");
         setForward(this);
         // redirect to self without rendering...
       }
     }
   }

The first time the Page is hit, it sets the attribute and forwards to 
itself.

If you already know this just ignore otherwise: Forward in Click is 
the same as Forward in Servlets. In other words the same request is 
used in the forwarded Page, which is why the check for 
getRequestAttribute should work. However doing a redirect means a HTTP 
304 is returned to the browser, which initiates another separate 
request to the server. Since this is a brand new request the "app" 
request attribute isn't present anymore.

Since you're using 2.1.0, the easiest option for redirect is probably 
the code you used in your original request:

   public RedirectPage extends Page{
     public void onInit() {

       // Note we check against the incoming request parameter,
       // not request attribute
       if (getContext().getRequestParameter("app") == null) {
         Map map = new HashMap();
         map.put("app", "default");
         setRedirect(RedirectPage.class, map);
         // redirect to self without rendering...
       }
     }
   }


> I worked around it with the code below (autobinding on, 2.1.0RC1, Tomcat 6):
> 
> // Redirect /context/page -> /context/page?app=default before refreshing 
> and rendering the page...
> public class MyPage extends BorderPage {
>     public String app = null;
> ...
> public void onInit() {
>                 if ((app == null || app.trim().length() == 0) && 
> getContext().getSession().getAttribute("app") == null) {
>                         Map params = new HashMap();
>                         params.put("app", "default");
>                         setRedirect(this.getClass(), params);
>                         return;
>                 } else if (app != null) {
>                         getContext().getSession().setAttribute("app", app);
>                 }
> 
>                 app = (String) 
> getContext().getSession().getAttribute("app");
> ....
> 
> Hopefully that is helpful to others


You're approach above will certainly work too, but it means one will 
store the state in the users session.

Hope this helps.

kind regards

bob

Re: A few click newbie questions...

Posted by Garth Dahlstrom <ir...@gmail.com>.
Hi Bob,

Thanks for your answers, they were helpful.

On Thu, Jul 2, 2009 at 2:20 AM, Bob Schellink <sa...@gmail.com> wrote:

> You can define the field as private or protected and Click won't bind it.
> You can also globally switch off autobinding in click.xml
> with autobinding="false".
>

Hmm... going private or protected, fields must be added to the model via
addModel or is there annotation to do it?


> if (getContext().getRequestAttribute("app") == null) {
>  ...
> }
>
> That should break the recursive call.
>
> Click 2.1.0 will support passing parameters to redirect:
>
> Map params = new HashMap();
> params.put("app", "default");
> setRedirect(this, params);


When I try to use 'getContext().getRequestAttribute("app")', it always
return null, which causes it to go into a redirect loop.

I worked around it with the code below (autobinding on, 2.1.0RC1, Tomcat 6):

// Redirect /context/page -> /context/page?app=default before refreshing and
rendering the page...
public class MyPage extends BorderPage {
    public String app = null;
...
public void onInit() {
                if ((app == null || app.trim().length() == 0) &&
getContext().getSession().getAttribute("app") == null) {
                        Map params = new HashMap();
                        params.put("app", "default");
                        setRedirect(this.getClass(), params);
                        return;
                } else if (app != null) {
                        getContext().getSession().setAttribute("app", app);
                }

                app = (String)
getContext().getSession().getAttribute("app");
....

Hopefully that is helpful to others

-G

Re: A few click newbie questions...

Posted by Bob Schellink <sa...@gmail.com>.
Hi Garth,

Garth Dahlstrom wrote:
> I'm new to click, I have some questions as I get into it....
>
> 1) Is there a way to prevent auto binding of fields?  i.e. In the 
> template project there are: public String title = "some text";
> which someone can pass &title="something bad" into my page when I 
> don't want that.

You can define the field as private or protected and Click won't bind 
it. You can also globally switch off autobinding in click.xml
with autobinding="false".

> 2) Can anyone point me at an example of a page that redirects to 
> itself adding a getRequestParameter to it's own URL before rendering?
> I tried to do it with:
> if (getContext().getRequestParameter("app") == null) {
>   getContext().setRequestAttribute("app", "default");
>   setForward(this);
>   // redirect to self without rendering...
> }
> in my onInit() method, but that doesn't bounce and just spins inside 
> my Tomcat server (also tried with setRedirect, I'm likely not doing 
> this right)

Ah, request parameter and request attributes doesn't affect each other. 
Further the request parameters are immutable
and cannot be changed. Instead check the request attribute for the 
presence of the "app" attribute:

if (getContext().getRequestAttribute("app") == null) {
  ...
}

That should break the recursive call.

Click 2.1.0 will support passing parameters to redirect:

Map params = new HashMap();
params.put("app", "default");
setRedirect(this, params);

kind regards

bob