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]