Juzu is a web framework based on MVC concepts for developing applications. Juzu is an open source project developed on GitHub licensed under the Apache 2 License.

Plugins

This chapter continues the exploration of the architecture of Juzu, it is an essential read if you want to understand how Juzu globally works and a recommanded read if you extend Juzu. Juzu philosophy is to provide a minimal core that is extended with plugins: this design allows to extend Juzu with no need to touch its core.

Plugins

Juzu plugins can be classified according several criterions. Let’s study the different kind of plugins possible.

Metamodel plugins

A metamodel plugin is executed at compilation time when the application is compiled. Usually it reacts to Java annotations in order to:

  • Validate the application : make checks depending on Java annotations

  • Read or write application resources : create new resources

  • Generate Java code : the generated code will be transparently compiled by the Java compiler

When a metamodel plugin is not happy, it can fail the current by reporting an error to the Java compiler.

Runtime plugins

A runtime plugin is executed during the execution of the web application. A runtime plugin can create objects that will be available for the application. Such objects are usually consumed by the application thanks to the IOC container.

Entity processors

Entity processors map the request and response stream to Java objects.

Value types

Value types map the controller request parameters to request parameters.

Provider factories

A provider factory provides plugability for integrating beans that are not managed natively by the IOC container but needs to be integrated inside the container.

Templating engine

Juzu can easily be extended with new templating engine. Templating engine integrates of course at runtime, however they can optionally be part of the compilation phase of the application for validating templates or for creating resources or classes to be used at runtime.

Value types

Value types is a Juzu plugin for dealing with controller parameters that can trivially be converted from and to strings. In this section we will explain how the juzu.impl.value.ValueType interface works.

Implementing the ValueType

The ValueType abstract class
public abstract class ValueType<T> {

  /**
   * The list of java classes this implementation can handle.
   *
   * @return the list of types.
   */
  public abstract Iterable<Class<?>> getTypes();

  /**
   * Parse a string and returns the corresponding value type.
   *
   * @param element the element annotations
   * @param s the string to parse
   * @return the corresponding value
   * @throws java.lang.Exception any exception preventing the parse to succeed
   */
  public abstract T parse(AnnotatedElement element, String s) throws Exception;

  /**
   * Format a value and returns the corresponding string.
   *
   * @param element the element annotations
   * @param value the value to format
   * @return the corresponding string
   */
  public abstract String format(AnnotatedElement element, T value);

}

The base implementation should extend the ValueType interface and provide a class type for the <T> generic parameter of the class:

The ValueType abstract class
public class DateValueType extends ValueType<java.util.Date> {
  ...
}

The getTypes() interface should return the class type the value type is converting:

The getTypes implementation
public Iterable<Class<?>> getTypes() {
  return Collections.singleton(java.util.Date.class);
}
several types can be returned by the method, this is used by the ValueType that handle primitive types such as int, boolean, etc…

Finally the parse and format methods need to be implemented too:

The parse and format implementations
public Date parse(AnnotatedElement element, String s) throws ParseException {
  return getSimpleDateFormat(element).parse(s);
}

public String format(AnnotatedElement element, Date value) {
  return getSimpleDateFormat(element).format(value);
}

The parse and format methods provides access to the element that is converted, the purpose of those objects is to provide access to optional annotation the element may have. Such annotations can be used by the value type for doing the conversion:

Using the annotated element for configuring the SimpleDateFormat object
private SimpleDateFormat getSimpleDateFormat(AnnotatedElement element) {
  Format format = element.getAnnotation(Format.class);
  return format != null ? new SimpleDateFormat(format.value()) : new SimpleDateFormat();
}

Declaring the ValueType

Value types are declared in the META-INF/services/juzu.impl.value.ValueType file, such plugins are loaded via the java.util.ServiceLoader interface.

Entity processing

Juzu allows the application to interact with request and response entities with the juzu.request.ClientContext and the juzu.Response.Body objects. Those objects are binary data (or character data) oriented and provide a low level interface for reading or writing request entities.

Juzu provides also a plugable higher level API for dealing with request entities such as File Upload or Json. In this section we will explain how to implement such plugins.

Entity unmarshallers

Entity unmarshallers are plugins that decodes a juzu.request.ClientContext into a set of arguments that will be used by Juzu when invoking the controller. The unmarshaller can manipulate those arguments, usually reading the request entity. The juzu.impl.request.EntityUnmarshaller abstract class has two methods to implement, let’s review them.

The EntityUnmarshaller abstract class
public abstract class EntityUnmarshaller {

  /**
   * Decide wether or not this reader accept to read the specified <code>mediaType</code> argument.
   *
   * @param mediaType the media type to test
   * @return true if the media type is accepted
   */
  public abstract boolean accept(String mediaType);

  /**
   * Unmarshall the entity from the {@link juzu.request.ClientContext}. This unmarshaller can modify the
   * request control arguments:
   * <ul>
   *   <li>the contextual arguments can be iterated and the value updated</li>
   *   <li>the parameter arguments map can be freely modified</li>
   * </ul>
   *
   * @param mediaType the request media type
   * @param context the client context for reading the entity
   * @param contextualArguments the contextual arguments
   * @param parameterArguments the contextual parameters
   * @throws IOException anything preventing the read operation to succeed
   */
  public abstract void unmarshall(
      String mediaType,
      ClientContext context,
      Iterable<Map.Entry<ContextualParameter, Object>> contextualArguments,
      Map<String, RequestParameter> parameterArguments) throws IOException;

}

Implementing an unmarshaller

The accept method is quite simple to implement, it should return true when the unmarshaller wants to unmarshall the incoming request, for instance:

@Override
public boolean accept(String mediaType) {
  return mediaType.equals("application/json");
}

The unmarshall method will be invoked when the accept method returns true. At this moment, the unmarshaller should read the entity data using the ClientContext interface and update the request arguments. There are two kinds of request arguments that can be modified:

  • parameter arguments using the parameterArguments method parameter

  • contextual arguments using the contextualArguments method parameter

Parameter arguments is a mutable map that provides string parameter values, those parameters are used by Juzu at a later stage when invoking the controller handler. Those parameters can be used as is, or can be transformed into other types via the ValueType extension or the @Mapped bean mapping. The File Upload unmarshaller will create parameter arguments when reading the file upload form.

Contextual arguments are any controller argument that are not parameter arguments (i.e any type that is not a ValueType or annotated with @Mapped). The unmarshall method can iterate over such arguments and modify them freely. The ContextualParameter object provides the name, class+ and _generic type+ of the argument. Those shall be used by the unmarshaller to properly modify the arguments. The _File Upload unmarshaller will look at the contextual arguments having the type org.apache.commons.fileupload.FileItem and the right argument name to do the match.

Declaring an unmarshaller

Unmarshallers are declared in the META-INF/services/juzu.impl.request.EntityUnmarshaller file, such plugins are loaded via the java.util.ServiceLoader interface.

Entity marshallers

Entity marshallers are plugins that encodes an object, usually returned by a controller handler into binary data sent with the response. The juzu.impl.request.EntityMarshaller abstract class has a single method marshall to implement, let’s review it.

Implementing a marshaller

The EntityMarshaller abstract class
public abstract class EntityMarshaller {

  /**
   * Marshall the object for the specified <code>mimeType</code> or return null.
   *
   * @param mimeType the mime type to test
   * @param annotations the contextual annotations
   * @param object the object to marshall  @return the corresponding streamable
   */
  public abstract Streamable marshall(String mimeType, AnnotatedElement annotations, Object object);

}

The marshall method will be invoked by Juzu, when a controller returns an unknown object response (i.e an object that does not inherit from the juzu.Response class). The marshall method can either return a null response to signal that it cannot handle it or a Streamable implementation that will be used to create a juzu.Response.

Declaring a marshaller

Unmarshallers are declared in the META-INF/services/juzu.impl.request.EntityMarshaller file, such plugins are loaded via the java.util.ServiceLoader interface.

Provider factories

Provider factories provide plugability for integrating beans that are not managed by the IOC container. A provider factory is dynamic: it is a factory for javax.inject.Provider that returns a provider for a specificied class. Usually provider factories will lookup the service in a registry (like another IOC container) and returns a provider that return them lazily or not.

The provider factory defines the getProvider method:

  /**
   * Returns a provider for a specific type or null if it cannot be produced.
   *
   * @param implementationType the implementation class object
   * @param <T>                the implementation generic type
   * @return a provider for this class or null
   * @throws Exception any exception that would prevent to obtain the provider
   */
  <T> Provider<? extends T> getProvider(Class<T> implementationType)
    throws Exception;

The factory implementation must provide a public zero argument constructor and it will be instantiated during the application boostrap by Juzu to obtain the provider. The returned providers will then be bound into the IOC container.

The IOC container uses the java.util.ServiceLoader discovery mechanism for finding provider factories when injection occurs.

Let’s study a simple example with a provider for the current time:

Time provider factory
package my;

public class TimeProviderFactory implements java.inject.ProviderFactory {
  public <T> Provider<? extends T> getProvider(final Class<T> implementationType) throws Exception {
    if (implementationType == java.util.Date.class) {
      return new Provider<T>() {
        public T get() {
          return implementationType.cast(new java.util.Date());
        }
      };
    }
    else {
      return null;
    }
  }
}

This provider should be declared in the META-INF/services/juzu.inject.ProviderFactory file:

Time provider configuration
my.TimeProvider

Templating SPI

This chapter dives into the template life cycle from the compilation time to the run time. We will describe the template Service Provider Interface (SPI), the SPI is designed to make Juzu templating extensible and integrating template engines in Juzu. This chapter is optional is you are only writing ab application with Juzu, however it is a must read if you want to know more Juzu internals or if you want to understand how to integrate a template engine in Juzu.

When a Juzu application is compiled, the Juzu annotation processor detects the @Path annotations and triggers the compilation of the related templates. The template compilation can be split in two parts:

Compiling a Groovy template

Let’s study an example with the Groovy template at compilation time.

Life cycle
Figure 1. Compiling a Groovy template

When the Java compiler is invoked, the following steps are executed

  1. The Java compiler triggers the Juzu annotation processor when it finds the @Path annotation

  2. Juzu resolves the relative path to the templates package of the application

    1. When the template cannot be resolved a compilation error is triggered

    2. Otherwise the template is loaded

  3. The template provider is looked up according to the file name extension, it generates the index.groovy_ source file

  4. Juzu creates the index class that extends the juzu.template.Template class annotated by the @Path("index.gtmpl") annotation

After that the only remaining part is to compile the index.groovy_ source to a class. It can be achieved either at build time using the groovyc compiler or at load time when the index template is loaded using a GroovyClassLoader. The former approach makes the build a bit more complex (but not much as Groovy compilation is fairly well supported in build systems or IDEs) as it requires to run a Groovy compilation but it will perform additional validation of the template as well as reduce the load time of the template. The later approach will detect any compilation error (such as Groovy syntax error) at runtime and the index.groovy_ compilation will take a few milliseconds.

This flexibility allows to use the lazy approach during development and when the application is released then the Groovy compiler can be used to compile the index.groovy_.

Type safe URL resolution

Groovy templates provides the @{…} syntax for generating URL from the application controllers. This section gives an overview of the underlying resolution mechanism.

URL resolution
Figure 2. Template URL resolution during compilation
  • Parse: the template is parsed into its model representation

  • Resolve: the index link is resolved againt the controller meta model

  • Validate: the index link is validated

  • Emit: the corresponding index.groovy_ file is emitted and save on the class output

  • Compile: the Groovy source is compiled into a class by the groovyc compiler (this part is done after javac)

Template Service Provider Interface

Juzu provides a Service Provider Interface (SPI) for integrating thirdparty template engine. Actually all template system are integrated with the SPI. We will study briefly the integration points so you can integrate a template engine of your choice in Juzu.

Template providers

The juzu.impl.template.spi.TemplateProvider is the main entry point when a templating system is integrated. The provider is triggered during the compilation phase by the APT system built into the Java compiler.

public abstract class TemplateProvider<M extends Serializable> {
  ...
}

The provider must declare the template model <M> generic type, this type must be a serializable as Juzu will sometimes write template models on the disk during the compilation. This usually happens only in Eclipse due its incremental compiler architecture. The type specified by the provider is privately managed (i.e it is opaque for Juzu) and it symbolizes an internal representation of the parsed source (usually an Abstract Syntax Tree), it will be used in various methods of the provider.

Let’s have a review of the methods of this class to have a better understanding.

  /**
   * Returns the template source extension without the dot recognised by
   * this provider. For instance it should return <code>gtmpl</code>
   * for groovy templates.
   *
   * @return the source extension
   */
  public abstract String getSourceExtension();

The getSourceExtension() method is used to determine what file extension the provider can compile. The implementation should return a constant value, for instance the Groovy provide simply returns the gtmpl value.

  /**
   * Parse the provided char sequence and return the corresponding template model.
   *
   * @param context the parse context
   * @param source the source to parse
   * @return the corresponding template model
   * @throws TemplateException any template related exception
   */
  public abstract M parse(
      ParseContext context,
      CharSequence source) throws TemplateException;

  /**
   * Process the template.
   *
   * @param context the process context
   * @param templateModel  the template to process
   * @throws TemplateException any template related exception
   */
  public abstract void process(
      ProcessContext context,
      TemplateModel<M> templateModel) throws TemplateException;

  /**
   * Provide an opportunity for emitting a file on the disk.
   *
   * @param context the emit context
   * @param templateModel the template
   * @throws TemplateException any template related exception
   * @throws IOException any io exception
   */
  public abstract void emit(
      EmitContext context,
      TemplateModel<M> templateModel) throws TemplateException, IOException;

The parse, process and emit methods care about transforming the template source to its final representation: the compiled template.

  • The parse method is invoked with the content of the template and returns a template model. The representation returned by the parse method is a parsed representation of the template source. If a parsing error occurs the method can throw a TemplateException.

  • The process method is invoked after the template is parsed with the necessary context for performing further processing of the template, for instance the Groovy templating engine performs the resolution of type safe URLs or type safe parameters declaration at this moment. During the process:

    • The provider can resolve other templates using the ProcessContext, if the template to resolve is not yet loaded it will trigger the parse/process/emit lifecycle, it if was already processed the template is simply returned

    • The implementation can resolve controller methods and translate them into method invocation, this is used for checking type safe URL and translating them into controller companion invocation

    • The juzu.impl.template.spi.TemplateModel argument models the template, it has several fields such as the underlying model or the template path

    • The implementation can declare type safe parameters using the TemplateModel#addParameter(String) method. The declared parameters will be generated on the juzu.template.Template subclass

  • The emit method is invoked when the template processing is over. The EmitContext interface can be used to create resources during this round.

  /**
   * Return the template stub type.
   *
   * @return the template stub class
   */
  public abstract Class<? extends TemplateStub> getTemplateStubType();

Finally the getTemplateStubType() returns the type of a java class that will be used for creating a template stub. For each template, a stub is created, the stub is responsible for loading the template at runtime, i.e the original template or the compiled template that may have been generated during compilation during the emit callback.

Template stub

Template stubs are java classes created by Juzu for managing a template at runtime on behalf of the provider. Each provider provides its own stub implementation as a juzu.impl.template.spi.TemplateStub subclass.

A stub must provide a public constructor accepting a java.lang.String argument: the template id. The template id if the class name of the generated template. In addition, a stub must implement two abstract methods:

  /**
   * Init the template with the associated resource.
   *
   * @param loader   the class loader
   */
  protected abstract void doInit(ClassLoader loader);

  /**
   * Performs template rendering.
   *
   * @param renderContext the render context
   * @throws TemplateExecutionException any execution exception
   * @throws IOException any io exception
   */
  protected abstract void doRender(TemplateRenderContext renderContext)
      throws TemplateExecutionException, IOException;

The doInit method loads the template using the provided ClassLoader, it will be call only once before the template is rendered. Usually it uses the template id provided during the construction of the template to locate the template on the disk, in its original form or in its compiled form.

The doRender method renders the template using the provided TemplateRenderContext. The render context provides the necessary hooks such as:

  • Producing markup

  • Setting the title

  • Obtaining the locale

  • Accessing parameters or application beans for resolving expressions

Template at work

After having described the various pieces of the templating SPI, let’s look at how the template generated stubs are used by Juzu templating system at runtime.

When the controller declares the index.gtmpl template the compiler produces three artifacts * the index class template inherits juzu.template.Template: it is the only class visible from the controller and the whole application * the index.groovy_ Groovy template is the effective template code: it produces the markup, resolve expressions, etc…

At work
Figure 3. index groovy at work

When a controller is instantiated, the index template instance is injected into the controller, the @Path annotation plays an essential role because it’s a qualifier and that qualifier is used to distinguish the correct subclass to inject in the controller.

When the template is created, the corresponding template stub is instantiated. When the template needs to be rendered, the doInit(ClassLoader) method of the stub is invoked. At this moment the Groovy index_ class is loaded from the class loader, when the class is not found, the index.groovy_ is loaded and it is compiled on the fly.

Qualified template class

Controller can be injected with the juzu.template.Template class, however they can also be injected with the template subclass that was genereted by Juzu: instead of using the qualified template injection, the controller declares the template index subclass. This approach cab be used when type safe parameters are used as only the index type declares the fluent API.

For instance if the index.gtmpl declares the color parameter the index class will look like:

@Path("index.gtmpl")
public class index extends Template {

  ...

  public index with() {
    return new index.Builder();
  }

  public class Builder extends Template.Builder {

    public Builder color(String color) {
      // Generated code
    }
  }
}

The controller can then use the fluent API:

public class Controller {

  @Inject
  @Path("index.gtmpl")
  Template index;

  @View
  public Response.Content index() {
    return index.with().color("red").ok();
  }
}