I use callbacks heavily, although not sure if that's exactly what you
need. I have an Authenticate component for instance which validates
itself against the database, submits itself and creates a member
session on success. It uses a callback of a hosting page to find out
what page to go to upon successfull login. I do that thru an interface
which a hosting page can (although doesn't have to) implement. If
IAuthenticate is implemented by a hosting page, then component will
use a callback to delegate all the login responsibility (except the
validation) onto the page. If ClassCastException occurs (when page
does not implement IAuthenticate) the component uses its default
logic.

I have two pages that use Authenticate component:  Home page and a
Login page. Home page is happy with component's default behavior, so
it does not implement IAuthenticate thus not proving a callback. Login
page, on the other hand wants to control the Login process, and so it
implements IAuthenticate.

This works very nicely for me.

-----------------------------------------------------------------------------------------------

package org.opendating.tapestry.components.support;

import org.apache.tapestry.IPage;

/**
 * Allows to define custom Login behavior for pages that utilize Authenticate
 * component (which provides a Login feature). Implementing this interface
 * is not mandatory because by default, Authenticate will execute a standard
 * action which is to create a session and a member object (which gets put in
 * the session), and returning back to the same page.
 *
 * @author Adam Zimowski
 */
public interface IAuthenticate {

        /**
         *
         * @param aError <i>true</i> if login error occurred, <i>false</i> 
otherwise.
         * @return destination page after successfull login.
         */
        public IPage onLogin(boolean aError);
        
        /**
         * If <i>true</i> is returned, then Authenticate component will 
automatically
         * create member object, and put it in session. If <i>false</i> is 
returned
         * the Authenticate component merely calls the implemented version of
         * onLogin(boolean) and returns the desitnation page.
         *
         * @return <i>true</i> if session and member object should be created,
         *      <i>false</i> otherwise.
         */
        public boolean createMemberOnLogin();
}

-----------------------------------------------------------------------------------------------

package org.opendating.tapestry.components;

import org.apache.tapestry.IPage;
import org.apache.tapestry.annotations.Bean;
import org.apache.tapestry.valid.ValidationDelegate;
import org.opendating.exceptions.MemberException;
import org.opendating.model.Member;
import org.opendating.tapestry.components.support.IAuthenticate;
import org.opendating.tapestry.log.LoggableBaseComponent;
import org.opendating.tapestry.state.IMember;

public abstract class Authenticate extends LoggableBaseComponent
        implements IMember {

        @Bean
        public abstract ValidationDelegate getDelegate();

        public abstract String getLoginId();
        
        public abstract String getPassword();
        
        public IPage onLogin() {

                boolean isError = getDelegate().getHasErrors();
                if(aDbg()) _aLog.debug("error? " + isError);

                IAuthenticate loginPage = null;
                try {
                        loginPage = (IAuthenticate)getPage();
                        if(!loginPage.createMemberOnLogin())
                                return loginPage.onLogin(isError);
                }
                catch(ClassCastException cce) {
                        if(!isError) {
                                String host = getPage().getPageName();
                                _aLog.info("default login; page '" + host + "' 
did not implement " +
                                        IAuthenticate.class.getSimpleName());
                        }
                }
                
                if(!isError) {
                        Member member = null;
                        try { member = new Member(getLoginId()); }
                        catch(MemberException me) {
                                _aLog.error(me.getMessage());
                        }

                        if(aDbg()) {
                                _aLog.debug("isLoggedIn: " + isLoggedIn());
                                _aLog.debug("loginId: " + getLoginId());
                                _aLog.debug("systemId: " + 
member.getSystemId());
                        }
                        
                        setMember(member);
                        
                        if(aDbg())
                                _aLog.debug("isLoggedIn: " + isLoggedIn());
                }
                
                try { return loginPage.onLogin(isError); }
                catch(NullPointerException npe) { return null; }
        }
        
}

-----------------------------------------------------------------------------------------------

Note that Home page does not implement IAuthenticate:

package org.opendating.tapestry.pages;

import org.opendating.tapestry.log.LoggableBasePage;
import org.opendating.tapestry.state.IMember;

public abstract class Home extends LoggableBasePage implements IMember {

        public static final String NAME = "Home";

        public String getUserName() {
                
                String guest = "Guest";
                
                try {
                        if(isLoggedIn())
                                return getMember().getLoginId();
                        else
                                return guest;
                }
                catch(Exception e) { return guest; }
        }
}

-----------------------------------------------------------------------------------------------

But Login page does because it wants custom Login logic:

package org.opendating.tapestry.pages;

import org.apache.tapestry.IPage;
import org.apache.tapestry.annotations.InjectComponent;
import org.apache.tapestry.annotations.Persist;
import org.opendating.tapestry.components.Authenticate;
import org.opendating.tapestry.components.support.IAuthenticate;
import org.opendating.tapestry.log.LoggableBasePage;

/**
 * Page designed specifically for Login only, which would be used in situations
 * when user forges a URL trying to access member-only pages. In such
situations
 * instead of accessing page illegaly, this login page would be displayed.
 *
 * There is nothing that prevents from using this page as a main Login gateway,
 * however, a more flexible approach is available because any given page can
 * use "Authenticate" component which provides a Login feature.
 *
 * @author Adam Zimowski
 */
public abstract class Login extends LoggableBasePage implements IAuthenticate {

        public static final String NAME = "Login";

        @Persist("client")
        public abstract String getReturnPage();
        public abstract void setReturnPage(String aPage);
        
        @InjectComponent("authenticator")
        public abstract Authenticate getLoginComponent();

        public IPage onLogin(boolean aError) {
                
                if(!aError) {

                        String page = getReturnPage();
                        if(aDbg()) _aLog.debug("returning to: " + page);
                        
                        return getRequestCycle().getPage(page);
                }
                
                return null;
        }

        public boolean createMemberOnLogin() {
                return true;
        }
}


Hope it helps.


On 3/4/06, Peter Svensson <[EMAIL PROTECTED]> wrote:
> Hi!
>
> I am making a small simple component which wraps contrib:Table but only
> requires source, so it figures out names and ordering by reflection.
> Anyway, it works great, and now I would like to make another component which
> wraps it and adds delete buttons (Maybe with the T-deli checkbox groups to
> select all and/or all shown (http://www.t-deli.com/)).
>
> But one thing I can't find either in Kens book or while googling heavily,
> which is how to specify a method/callback function to be called when someone
> does submit one or more deletions to the component.
>
> I think I should use some kind of listener, but since I'm quite new to all
> this I'm hoping for directions.
>
> Cheers,
> PS
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to