Kontakt

Archive for Mai, 2010

Speaking slot at Jazoon 2010 changed

Sonntag, Mai 30th, 2010

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!

Remote Page Pool Management

Freitag, Mai 28th, 2010

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.

Project Management Committee Member

Mittwoch, Mai 26th, 2010

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.

Advanced Service Builders in Tapestry IoC: Strategy Pattern

Donnerstag, Mai 20th, 2010

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.

New Tapestry Logo

Montag, Mai 17th, 2010

I’m pleased to present a new Tapestry logo. The Tapestry Team decided to replace the old logo which represented Tapestry for years.

Tapestry Logo

The new logo emphasizes Tapestry’s strengths: power, speed, innovation, coolness and fun.

Tapestry Ferrari .

Wait. Don’t hold your breath. Tapestry wasn’t acquired by Ferrari. It’s just a joke created by a fellow worker Sebastian. I like it very much and going to use it in my presentations to animate the attenders. Do you like it?

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