On Wed, May 4, 2011 at 11:42 AM, Thiago H. de Paula Figueiredo <thiag...@gmail.com> wrote: > I wouldn't call this composition (IMHO it's a class transformation), but > this is really cool and shows how flexible, reusable and all-around awesome > Tapestry is. :)
Semantics. The class transformation, informed by the annotation, drives the composition, just as the Java extends keyword drives inheritance. > > On Wed, 04 May 2011 15:34:48 -0300, Adam Zimowski <zimowsk...@gmail.com> > wrote: > >> Another lovely day with Tapestry! Inspired by Taha's blog entry on >> Tapestry Magic, our app instead of this mess: >> >> public class OrderHistoryPage extends AuthenticatedPage >> >> looks sexy like never before with this: >> >> @RequiresLogin(ssoClass= UserUiBean.class, pageClass= Login.class) >> public class OrderHistoryPage extends BasePage >> >> Here are the pieces: >> >> Custom Annotation >> /** >> * Tells Tapestry that a page requires authenticated user. If a page is >> * annotated with this, and user is not logged in, that page shall >> redirect >> * to a login screen instead of rendering itself. >> * >> * @author Adam Zimowski >> */ >> @Target({ElementType.TYPE}) >> @Retention(RetentionPolicy.RUNTIME) >> @Documented >> public @interface RequiresLogin { >> >> /** >> * Class whose instance lives in session and represents >> authenticated user. >> */ >> Class<?> ssoClass(); >> >> /** >> * Page class to which Tapestry should redirect guests instead of >> * displaying secured page >> */ >> Class<? extends BasePage> pageClass(); >> } >> >> Annotation Worker >> /** >> * Transforms page classes annotated with {@link RequiresLogin} adding >> advice >> * which tests if the user is logged in, then redirects to login page if >> user >> * is guest. >> * >> * @author Adam Zimowski >> */ >> public class RequiresLoginAnnotationWorker implements >> ComponentClassTransformWorker { >> >> private final TransformMethodSignature ONACTIVATE_SIGNATURE = >> new TransformMethodSignature( >> 0, "java.lang.Object", "onActivate", null, null); >> >> private Logger log = >> >> LoggerFactory.getLogger(RequiresLoginAnnotationWorker.class); >> >> private ApplicationStateManager asm; >> >> >> public RequiresLoginAnnotationWorker(ApplicationStateManager aAsm) >> { >> asm = aAsm; >> } >> >> @Override >> public void transform(ClassTransformation aTransformation, >> MutableComponentModel aModel) { >> >> RequiresLogin annotation = aTransformation >> .getAnnotation(RequiresLogin.class); >> >> if (annotation == null) { >> return; >> } >> >> final Class<?> ssoClass = annotation.ssoClass(); >> final Class<?> pageClass = annotation.pageClass(); >> >> if(log.isDebugEnabled()) { >> log.debug(".. transforming {} ..", >> aTransformation.getClassName()); >> } >> >> TransformMethod methodTransformer = null; >> try { >> methodTransformer = >> >> aTransformation.getOrCreateMethod(ONACTIVATE_SIGNATURE); >> } >> catch(Throwable t) { >> throw new >> RuntimeException(RequiresLogin.class.getSimpleName() + >> " annotation requires package scope " + >> "[ Object onActivate() ] method.", t); >> } >> >> methodTransformer.addAdvice( >> new ComponentMethodAdvice() { >> public void >> advise(ComponentMethodInvocation invocation) { >> invocation.proceed(); >> if(!asm.exists(ssoClass)) { >> >> if(log.isDebugEnabled()) { >> log.debug( >> >> "redirecting to {} page ...", >> >> pageClass.getSimpleName()); >> } >> >> invocation.overrideResult(pageClass); >> } >> } >> } >> ); >> } >> } >> >> Service Contribution >> @Contribute(ComponentClassTransformWorker.class) >> public void contributeComponentClassTransformWorker( >> OrderedConfiguration<ComponentClassTransformWorker> >> aWorkers) { >> >> aWorkers.addInstance( >> RequiresLogin.class.getSimpleName(), >> RequiresLoginAnnotationWorker.class, >> "before:OnEvent"); >> } >> >> Page class usage: >> >> @RequiresLogin(ssoClass = UserUiBean.class, pageClass = Login.class) >> public class UserProfilePage extends BasePage { ... >> >> >> Feel free to re-use! Para-Ta-Ta-Taaaaa ........... I'M LOVIN' IT !!!!! >> >> Adam >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org >> For additional commands, e-mail: users-h...@tapestry.apache.org >> > > > -- > Thiago H. de Paula Figueiredo > Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and > instructor > Owner, Ars Machina Tecnologia da Informação Ltda. > Consultor, desenvolvedor e instrutor em Java, Tapestry e Hibernate > Coordenador e professor da Especialização em Engenharia de Software com > Ênfase em Java da Faculdade Pitágoras > http://www.arsmachina.com.br > > --------------------------------------------------------------------- > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org > For additional commands, e-mail: users-h...@tapestry.apache.org > > -- Howard M. Lewis Ship Creator of Apache Tapestry The source for Tapestry training, mentoring and support. Contact me to learn how I can get you up and productive in Tapestry fast! (971) 678-5210 http://howardlewisship.com --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org