Hi

This is a simple example of using ComponentClassTransformWorker and also may
be used for graceful degradation for ajax in case javascript is disabled

All it does is convert a call

@XHR
Object onClick(){
   //Processing ...
   return zone.getBody();
}

to

Object onClick(){
   //Processing
   if(!request.isXHR()){
      return null;
   }else {
      return zone.getBody();
   }
}


Here is the code

Annotation

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface XHR {

}


Worker

import org.apache.tapestry5.model.MutableComponentModel;
import org.apache.tapestry5.services.ClassTransformation;
import org.apache.tapestry5.services.ComponentClassTransformWorker;
import org.apache.tapestry5.services.ComponentMethodAdvice;
import org.apache.tapestry5.services.ComponentMethodInvocation;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.TransformMethod;
import org.apache.tapestry5.services.TransformMethodSignature;

import com.google.code.tapestryaddons.XHR;

public class XHRWorker implements ComponentClassTransformWorker {

   private Request request;

   public XHRWorker(Request request){
      this.request = request;
   }

   public void transform(ClassTransformation transformation,
         MutableComponentModel model) {
      for(final TransformMethod method:
         transformation.matchMethodsWithAnnotation(XHR.class)){
         TransformMethodSignature signature = method.getSignature();

         if(!"void".equals(signature.getReturnType())){
            method.addAdvice(new ComponentMethodAdvice(){

               public void advise(ComponentMethodInvocation invocation) {
                  invocation.proceed();
                  Object result = invocation.getResult();
                  if(!request.isXHR()){
                     result = null;
                  }
                  invocation.overrideResult(result);
               }

            });

         }
      }
   }

}


and obviously the contribution

   public void contributeComponentClassTransformWorker(
         OrderedConfiguration<ComponentClassTransformWorker> configuration){
      configuration.addInstance("XHRWorker", XHRWorker.class);
   }


A simple example

Template File

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns:t='http://tapestry.apache.org/schema/tapestry_5_1_0.xsd'>
   <t:eventLink t:zone='zone' t:id='click'>Ajax Link</t:eventLink>
   <br/>
   <t:zone t:id='zone'>Clicked ${count} times</t:zone>
</html>

and java file

import org.apache.tapestry5.annotations.InjectComponent;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.corelib.components.Zone;

import com.google.code.tapestryaddons.XHR;

public class XHRDemo {
   @Persist
   private int count;

   @InjectComponent
   private Zone zone;

   @XHR
   Object onClick(){
      count++;
      return zone.getBody();
   }

   public int getCount(){
      return count;
   }
}

Reply via email to