Kontakt

28
Jul

Today I committed some changes for Tapestry 5.2 that allow you to access annotations placed on service implementation classes. As you probably know Tapestry creates proxies for services. The proxy implements the service interface and delegates method invocations to the actual service instance. When you inject a service into your page, component or another service you get a proxy which creates an instance of the service implementation class on demand. The first time a method is invoked on the proxy, the actual service is instantiated and initialized.

Until today Tapestry’s proxies did not expose annotations of service implementation classes. If you have placed annotations on a service implementation class you was not able to read them reflectively. The reason was the way how proxy classes were fabricated. Tapestry just skipped copying annotations from implementation class to proxy. This caused some problems when integrating third party libraries into Tapestry applications. For example imagine you want to expose your service as a web service and place the @WebService on the service implementation class. Because the annotation was not copied to the service proxy class, your service was not identified as web service.

import javax.jws.WebService;
import javax.jws.WebMethod;

@WebService
public class CalculatorImpl implements Calculator {  

   @WebMethod
   public int add( int x, int y )  {
      return x + y;
   }
}

As of version 5.2 the annotations from service implementation class will be placed on the proxy class if this implementation is bound to its interface inside a bind method.

public class AppModule {  

   public static void bind(ServiceBinder binder)  {
      binder.bind(Calculator.class, CalculatorImpl.class);
   }
}

In case of build methods annotations are still lost. For build methods there is no way to determine the implementation class at proxy creation time. A proxy invokes the build method to instantiate the actual service on demand. At this time you know the implementation class but it’s just too late. The proxy class already have been fabricated.

public class AppModule {  

   public static Calculator buildCalculator()  {
      return new CalculatorImpl();
   }
}
26
Jul

I was invited to present Tapestry 5 at Herbstcampus in Nürnberg, Germany. Herbstcampus is a conference for software developers, architects, and project managers with a technology focus in .NET and Java. My talk Fliegede Teppiche – Moderne Webanwendungen mit Tapestry 5 (Flying carpets – Modern web applications with Tapestry 5) takes place on September 14th, 2010. If you are living in Bavaria, this is a chance to learn Tapestry in a 70 minutes session. I’ll give an overview over Tapestry concepts and new features in the upcoming release 5.2. As always I will show a lot of demos.

20
Jul

In the article Advanced Service Builders in Tapestry IoC: Strategy Pattern I described how to implement the Strategy pattern with Tapestry. In this post I’ll cover the Gang of Four Chain of Responsibility Pattern. I’ll start with a simple example that demonstrates how to implement the pattern in Tapestry. At the end of the article, I’ll show you how the Chain of Responsibility Pattern is used inside Tapestry.

The use case

Suppose you need to support several authentication mechanisms in your application. Let’s say you need to support authentication based on both HTTP Basic authentication header (RFC 1945) and HTTP Digest authentication header (RFC 2617). Probably you would specify a service interface like AuthenticationService:

public interface AuthenticationService {
   boolean isAuthenticated();
}

You would also provide two implementations of the service. The implementation details are not interesting yet.

  • HttpBasicAuthenticationService: authentication based on HTTP Basic authentication header
  • HttpDigestAuthenticationService: authentication based on HTTP Digest authentication header

Both implementations can be bound to their interface in the application module. Note that you need to provide the service id to disambiguate both implementations of the AuthenticationService interface.

public class AppModule {

   public static void bind(ServiceBinder binder) {

      binder.bind(AuthenticationService.class,
                  HttpBasicAuthenticationService.class)
            .withId("HttpBasic");
      binder.bind(AuthenticationService.class,
                  HttpDigestAuthenticationService.class)
            .withId("HttpDigest");
   }
}

Naive Approach

Now let’s first have a look at a naive usage of the AuthenticationService service. Let’s implement a simple ComponentRequestFilter which is responsible for recognizing whether an incoming request is authenticated or not.  In the following example we need to inject both implementations of AuthenticationService service using the @InjectService annotation. The value of the annotation is used to identify the service to be injected. When a component event request is handled or a page is rendered we check if the request is authenticated by invoking both services HttpBasic and HttpDigest one after another. If the request is unauthenticated, the filter will set the WWW-Authenticate header and send a 401 HTTP error indicating the request requires HTTP authentication.

public class AuthenticationFilter implements ComponentRequestFilter {

   @InjectService("HttpBasic")
   private AuthenticationService basicAuthService;

   @InjectService("HttpDigest")
   private AuthenticationService digestAuthService;

   @Inject
   private Response response;

   public void handleComponentEvent(
         ComponentEventRequestParameters parameters,
         ComponentRequestHandler handler) throws IOException {

      if (isAuthenticated()) {
         handler.handleComponentEvent(parameters);
      }
   }

   public void handlePageRender(
         PageRenderRequestParameters parameters,
         ComponentRequestHandler handler) throws IOException {

      if (isAuthenticated()) {
         handler.handlePageRender(parameters);
      }

   }

   private boolean isAuthenticated() throws IOException {

      if (this.basicAuthService.isAuthenticated()) {
         return true;
      }

      if (this.digestAuthService.isAuthenticated()) {
         return true;
      }

      this.response.setHeader("WWW-Authenticate",
            "Basic realm=\"Tapestry\"");

      this.response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
            "Request unauthorized");

      return false;
   }
}

Injecting both services HttpBasic and HttpDigest and invoking them one after another is not really nice. If you decide to provide a further authentication mechanism in the future, you’ll have to change the AuthenticationFilter class. Imagine you decided to support the authentication based on a Remember-Me-Token. In this case you need to provide a new implementation of AuthenticationService interface which will be injected into AuthenticationFilter using the service id. Now you have three different instances of AuthenticationService that are invoked one after another.

Chain of Responsibility

Now let me show you how to improve our example. We’ll implement the AuthenticationService as a Chain of Responsibility. Instead of providing different implementations of AuthenticationService interface with dfferent service ids, we use the ChainBuilder service to build a chain of AuthenticationService inside a build method.

The ChainBuilder service is used to assemble a Chain Of Command implementation of an interface (the command interface) from an ordered list of objects implementing that interface (the commands). The commands of the chain are contributed to the service configuration.

public class AppModule {

   public static void contributeAuthenticationService(
       OrderedConfiguration<AuthenticationService> config) {

      config.addInstance("HttpBasic",
              HttpBasicAuthenticationService.class);
      config.addInstance("HttpDigest",
              HttpDigestAuthenticationService.class);
   }

   public static AuthenticationService buildAuthenticationService(
         List<AuthenticationService> configuration,
         ChainBuilder chainBuilder) {

      return chainBuilder.build(AuthenticationService.class,
                                configuration);
   }
}

The result is that there is a single instance of AuthenticationService service inside the Registry. You don’t need to disambiguate different instances of the service by providing unique ids and don’t have to care which instance to inject. You just inject the AuthenticationService service and use it. Note that we are not using the @InjectService annotation anymore. Now it is fine to use the @Inject annotation. Tapestry will call the Chain of Command behind the scenes for you. Now AuthenticationFilter can be simplified.

public class AuthenticationFilter implements ComponentRequestFilter {

   @Inject
   private AuthenticationService authenticationService;

   @Inject
   private Response response;

   public void handleComponentEvent(
         ComponentEventRequestParameters parameters,
         ComponentRequestHandler handler) throws IOException {

      if (isAuthenticated()) {
         handler.handleComponentEvent(parameters);
      }
   }

   public void handlePageRender(
         PageRenderRequestParameters parameters,
         ComponentRequestHandler handler) throws IOException {

      if (isAuthenticated()) {
         handler.handlePageRender(parameters);
      }

   }

   private boolean isAuthenticated() throws IOException {

      if (this.authenticationService.isAuthenticated()) {
         return true;
      }

      this.response.setHeader("WWW-Authenticate",
            "Basic realm=\"Tapestry\"");

      this.response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
            "Request unauthorized");

      return false;
   }
}

Now that you know how to create a Chain of Command with Tapestry, let me explain you how Tapestry works down the list of commands.

ChainBuilder Service

As you already learned, the ChainBuilder service creates a Chain Of Command based on a command interface and commands. Behind the scenes Tapestry generates an implementation of the command interface at runtime. For each method in the interface, the chain implementation will call the corresponding method on each command object in turn.  There are several situations when a chain is terminated:

  • If the return type of the interface method is boolean and a command in the chain returned true.
  • If the return type of the interface method is numeric and a command in the chain returned a non-zero value.
  • If the return type of the interface method is other than boolean or numeric and a command in the chain returned a non-null value.
  • If a command in the chain throws an Exception.

Note that in case of void methods only throwing an Exception can terminate the chain.

Now let me explain how chains can be terminated. In the following example you can see HttpBasicAuthenticationService service. It first checks if the Authorization header is set. If the header is not available, then false is returned. In this case the next command in the chain is invoked. If the header is present the command executions continues. If the credentials are available and valid, then true is returned. This terminsates the chain.

public class HttpBasicAuthenticationService implements AuthenticationService {
   @Inject
   private Request request;

   public boolean isAuthenticated() {
      String header = this.request.getHeader("Authorization");

      if (header == null || !header.startsWith("Basic ")) {
         return false;
      }

      String[] tokens = getCredentials(header);

      if (tokens.length != 2) {
         return false;
      }

      return tokens[0].equals("igor")
                  && tokens[1].equals("secret");

   }

   public String[] getCredentials(String header) {
      ...
   }
}

Real Life Example

Now that you know how to implement the Chain Of Command Pattern let me show you how this pattern is used inside Tapestry. As you know Tapestry performs the transformation of the page and component classes at runtime. This bytecode transformation is performed by the ComponentClassTransformWorker service which is implemented as a Chain of Command. The commands of the chain transform a component or page class in turn. For example there is an internal implementation of the  ComponentClassTransformWorker interface which is responsible for transforming a component or a page class in that way that you as page author can inject services into that component or page via @Inject annotation. Another command in the chain is responsible for identifying parameters via the @Parameter annotation on component fields. Almost for every annotation, used in a component or a page, there is a specialized command which is a part of the class transformation chain.

Here is see an extract from TapestryModule:

public class TapestryModule {

    public void contributeComponentClassTransformWorker(
        OrderedConfiguration<ComponentClassTransformWorker>
                     configuration){

        configuration.addInstance("Inject",
                                  InjectWorker.class);
        configuration.addInstance("InjectService",
                                  InjectServiceWorker.class);
        configuration.addInstance("InjectPage",
                                  InjectPageWorker.class);

        ...

        configuration.add("OnEvent", new OnEventWorker());

        ...
        configuration.addInstance("Parameter",
                                  ParameterWorker.class,
                                  "after:Inject*");
   }

   public ComponentClassTransformWorker buildComponentClassTransformWorker(
         List<ComponentClassTransformWorker> configuration,
         ChainBuilder chainBuilder) {

      return chainBuilder.build(
                           ComponentClassTransformWorker.class,
                           configuration);
   }
}

Summary

In this post I described how to implement Chain of Responsibility Pattern using Tapestry IoC. Based on the authentication example you learned how to decouple a sender of a request and its receiver by giving more than one service a chance to handle the request.

In the next post of this series I’ll cover further advance techniques for building services. You’ll learn how to use Shadow services.

16
Jun

In web applications it’s often necessary to execute extra logic at application startup. When your application is starting, you might want to schedule a task for one-time or repeated execution. A typical use case is the initialization of the database. Imagine you deliver a demo version of your application to a customer in order to convince him that you did a better job than your competitors. When the customer drops the WAR file into the servlet container, the application should be usable immediately. In this case you might want to create some demo data (e.g. demo accounts with default credentials) at start time.

In Tapestry you can execute some logic at Registry startup by making contributions to the RegistryStartup service configuration. The values contributed are Runnable objects. Here is an example:

public class AppModule {

  public static void contributeRegistryStartup(
         OrderedConfiguration<Runnable> configuration,
         DatabaseStartup dbStartup) {

      configuration.add("DbStartup", new Runnable() {
          dbStartup.init();
      }, "before:*");
  }
}

Startup Methods in Tapestry 5.2

In Tapestry 5.2 the way of providing extra logic to be executed at Registry startup has been simplified. Instead of making contributions to the RegistryStartup service configuration you can provide startup methods inside your modules. As you can see in the following example you just annotate an arbitrary module method with @Startup annotation and that’s it. Tapestry will detect these methods and invoke them after the registry has been started.

public class AppModule {

  @Startup
  public static void initApplication(DatabaseStartup dbStartup) {
      dbStartup.init();
  }
}

Note that RegistryStartup service configuration is ordered. Providing the order constraint it’s possible to control in what order the contributions are executed. In contrast the order of startup methods is determined by the alphabetical order of the method names. You should not rely on that. The alphabetical ordering of module methods is a part of the internal API and may be changed in the upcoming releases.

11
Jun

I’m pleased to announce the amazing news. Manning Publications Co. will translate my Tapestry 5 book into English. Tapestry folks have been waiting for a book on Tapestry 5 for a long time and I’m excited to finally move forward with this book.

We have a great team. Joachim Van der Auwera will translate the German copy into English. I’ll update the translated book with the Tapestry 5.2 contents. There is a lot of innovative stuff in the 5.2 trunk the world should know about. I’m also going to extend some chapters which were covered in the German version not in the depth. Maybe some of the articles from this blog will be available in the book. The German version has around 430 pages. The Manning book on Tapestry will get additional 50 – 70 pages. Finally Howard Lewis Ship is interested in joining the project as technical editor. If Howard will be available he will review whether the book covers his vision of Tapestry.

I would like to thank Angelika Ritthaler from Addison Wesley and Christina Rudloff from Manning Publications Co. for making this book real.

Stay tuned!

4
Jun

The Jazoon 2010 is closed. I enjoyed the most of the talks and met some folks. My talk JavaServer Faces 2.0 vs. Tapestry 5 took place on Thursday, 3 June in the arena 7. Unfortunately my presentation will not be available as video since only talks in the largest arena 5 has been recorded. The slides of the talk are available here. However, I enjoyed the conference and will submit some presentation proposals next year again.

Directly after my talk Roger Kitains, a JSF co-specification lead, was giving a presentation Exploring HTML5 With JavaServer Faces 2.0. He was attending my presentation and I had the pleasure to discuss Tapestry and JSF with him. Roger told me he enjoyed my talk and was impressed by Tapestry. He likes Tapestry’s annotation-based approach and implicit type conversion which probably will be adapted in the upcoming JSF version.

Also Andy Bosch, another JSF guru, was attending my talk. He was impressed by the Live Class Reloading feature. Probably we’ll give together a JSF vs. Tapestry talk in the future. I believe that such a talk would be very funny. I would concentrate on Tapestry part and he would present JSF.

I also had a chance to meet Evgeni Kabanov, the founder and CTO of ZeroTurnaround, who gave an amazing talk on class loaders. I was interested in his talk and was not disappointed. We discovered Zurich together and had the pleasure to discuss the Live Class Realoading in Tapestry and JRebel during a dinner in a Japanese restaurant. By the way, if some of the readers is not using Tapestry but wants to be productive, you should give JRebel a try.

As summary of my talk I will publish a series of articles on JSF vs. Tapestry topic in order to share with you the result of my research.

Here are some pics which has been taken during my presentation.

30
Mai

The Jazoon program committee moved the speaking slot for my talk JavaServer Faces 2.0 vs. Tapestry 5 from 13:30 t0 11:30. I’ll be speaking Thursday, 3 June 2010, 11:30-12:20 at Arena 7. More details can be found here.

See you there!

28
Mai

When talking about Tapestry I’m often asked about the proper page pool settings. It seems that a lot of Tapestry users bother their head about the proper settings. It’s hardly surprising me because you never know how many hits your application will be receiving. Thus my answer to the question is always: “It depends!”.

As of version 5.2 you don’t have to think about your page pool settings until your application is launched because you can modify these settings remotely. Tapestry registers a managed bean (MBean) with an MBean server. You can use JConsole to interact with the registered MBean. To enable the JMX agent for local access, you need to set the following system property when you start your web server:

-Dcom.sun.management.jmxremote

When you start JConsole you will see an MBean registered by Tapestry.  This MBean has 4 writable properties:

  • SoftLimit corresponds to symbol tapestry.page-pool.soft-limit
  • SoftWait corresponds to symbol tapestry.page-pool.soft-wait
  • HardLimit corresponds to symbol tapestry.page-pool.hard-limit
  • ActiveWindow corresponds to symbol tapestry.page-pool.active-window

For more details about page pool settings read here and here. Also note that symbol tapestry.page-pool.hard-limit was deprecated in Tapestyr 5.2 because the number of request processing threads can also be configured by the servlet container.

26
Mai

I’ve been promoted to the Project Management Committee (PMC) role. At the Apache Software Foundation a PMC is the official managing body of a project and is responsible for the strategic direction and success of the project. One of my roles as PMC will be Tapestry marketing and evangelization. I’ll try to make Tapestry more popular in Europe, especially in Germany.

20
Mai

As you might probably know Tapestry IoC is the heart and sole of Tapestry.  Almost every Tapestry feature is the result of the architecture based on Tapestry IoC. This is why Tapestry is so exciting and cool.

The ideas behind Tapestry IoC are so beautiful that I can’t live without them. In my daily job I’m using Tapestry IoC in non-web applications as well as in Tapestry applications. Occasionally I’m browsing the source code of open source or commercial Tapestry-based applications and wonder that some developers don’t use the best features of Tapestry IoC. I guess it’s because they are not aware of these features. That’s why I’ll publish a series of articles on advanced techniques to build services. The series starts with the Go4 Strategy Pattern. Let’s start with a very easy example.

Introduction to Strategy Pattern

Suppose you are writing an online shop such as Amazon. All the products are stored in a storage (such as a database). When you display a product to a customer you need to show the price of the product. Now imagine you are located in a country that has different sales tax rates for different goods. For example Germany has a 19% sales tax for non-book-goods. The sales tax for books and newspapers is only 7%. As you can see in the following example we need ugly if-else-statements when determining the sales tax rate of an item.

public class SalesTaxRateSourceImpl implements SalesTaxRateSource {

   public Double getRate(Item item) {

      if(item instanceof Book || item instanceof Newspaper) {
         return 1.07;
      }

      return 1.19;
   }
}

Let’s rewrite the implementation of SalesTaxRateSource service implementing the Gang of Four Strategy Pattern. The idea is to implement different strategies for calculation of sales tax rates. The strategies are:

  • DefaultSalesTaxRateSource: provides the sales tax rate of 19%
  • ReducedSalesTaxRateSource: provides the reduced sales tax rate of 7%

The implementations of the interfaces may look like follows.

public class DefaultSalesTaxRateSource implements SalesTaxRateSource{

   public Double getRate(Item item) {
      return 1.19;
   }
}
public class ReducedSalesTaxRateSource implements SalesTaxRateSource{

   public Double getRate(Item item) {
      return 1.07;
   }
}

Now we need to map these two implementations of the SalesTaxRateSource interface to certain implementations of the Item interface. This can be done in a contribute method for the SalesTaxRateSource service. Note that we map Book and Newspaper to ReducedSalesTaxRateSource. All the other implementations of Item are mapped to DefaultSalesTaxRateSource. This configuration is used to construct a strategy-based implementation of SalesTaxRateSource service.  For this purpose we create a StrategyRegistry from the contributed configuration inside the buildSalesTaxRateSource() method. The injected service StrategyBuilder is used to create an implementation of SalesTaxRateSource from StrategyRegistry on-the-fly.

The StrategyBuilder service creates an implementation which uses all the configured strategies behind the scenes. It executes all the ugly if-else-statements for you. It analyzes the first parameter of each service method to select the appropriate strategy. In our case we have only one service method with a single parameter.

public class AppModule {

    public static void contributeSalesTaxRateSource(
          MappedConfiguration<Class, SalesTaxRateSource> config) {

        config.addInstance(Item.class,
                           DefaultSalesTaxRateSource.class);

        config.addInstance(Book.class,
                           ReducedSalesTaxRateSource.class);

        config.addInstance(Newspaper.class,
                           ReducedSalesTaxRateSource.class);

	}

    public static SalesTaxRateSource buildSalesTaxRateSource(
            Map<Class, SalesTaxRateSource> configuration,
            StrategyBuilder strategyBuilder) {

        StrategyRegistry<SalesTaxRateSource> registry
                = StrategyRegistry.newInstance(
                    SalesTaxRateSource.class, configuration);

        return strategyBuilder.build(registry);
    }

}

You might ask yourself why you need this advanced service builder technique. You could manage different strategies in a simple map and just ask a strategy for a class. That’s almost correct but leaks one important feature StrategyRegistry offers. The lookup of strategies inside StrategyRegistry is based on an inheritance search. This is the reason why we mapped Item to DefaultSalesTaxRateSource. All Item implementations but Book and Newspaper are mapped to DefaultSalesTaxRateSource.

Now let me demonstrate the advantage of the inheritance-based strategy search. Imagine you extracted a common interface from Book and Newspaper: let’s say it is called Readable. Now the contribution can be simplified because you don’t need to map both Book and Newspaper to the same strategy. You only need to map their common interface:

public class AppModule {

    public static void contributeSalesTaxRateSource(
          MappedConfiguration<Class, SalesTaxRateSource> config) {

        config.addInstance(Item.class,
                           DefaultSalesTaxRateSource.class);

        config.addInstance(Readable.class,
                           ReducedSalesTaxRateSource.class);

	}
    ...
}

Real Life Example

Now that you know how to use Strategy pattern with Tapestry IoC, let’s see how this pattern is used inside Tapestry. As you might know event handler methods may have different return types. The value returned from an event handler method determines how Tapestry will render a response. This is accomplished by the ComponentEventResultProcessor service which is implemented as Strategy pattern. This service is built from a StrategyRegistry which is responsible for matching up a given return type of an event handler method with a registered strategy for that type. When Tapestry handles an event it analyzes the return type of the handler method and selects  a strategy to handle the returned type. The allowed return types are described here.

In the following example you can see a Demo page with two handler methods for the action event.

public class Demo {

    public Object onActionFromInternalLink() {
        return NextPage.class
    }

    public Object onActionFromExternalLink()
                throws MalformedURLException {
        return new URL("http://tapestry5.de/");
    }
}

The method onActionFromInternalLink() handles the event action that was fired by the component with id internalLink. The value returned by this method is a class of a page named NextPage. When this method is invoked, Tapestry will lookup a strategy to handle the result type java.lang.Class. The responsible strategy is the class ClassResultProcessor which just creates an internal link to a page and sends a redirect to that link. In case of method onActionFromExternalLink() Tapestry will find a strategy which is responsible to send a redirect to a URL.

Here is the simplified extract from TapestryModule:

public class TapestryModule {

    public void contributeComponentEventResultProcessor(
        MappedConfiguration<Class, ComponentEventResultProcessor>
                     configuration){

        configuration.add(
            URL.class,
            new ComponentEventResultProcessor<URL>() {
                public void processResultValue(URL value)
                           throws IOException
                    response.sendRedirect(value.toExternalForm());
            }
        });

        configuration.addInstance(
            Class.class, ClassResultProcessor.class);
    }
}

Summary

In this post I described how to implement Strategy Pattern using Tapestry IoC. Hopefully this post will help you to clean up your code by removing ugly if-else-statements. If you are not using Tapestry yet, you should give Tapestry IoC a try.

In the next post I’ll cover the Gang of Four Chain of Responsibility Pattern.

Tapestry 5 Blog - Copyright © 2009 - Eclectic Theme by Your Inspiration Web - Powered by WordPress