Streamezzo S.A. - All rights reserved
Copyright 2001-2010
How to build your own custom components
The Streamezzo SDK offers you the possibility to use components in order to help you to quickly build rich media applications and by providing customizable and prebuilt pieces of code. But components can also be seen as a development philosophy in order to capitalize your work and to stop reinventing the wheel.
You are totally free to build your own components and this tutorial will tell you the steps we follow to develop ours
This article assumes you already have working knowledge of RSP and that you have read the Components - Introduction.
Component packaging
JAR deliverable
Let's take a look at how a component is released. As previously said, a component is delivered as a library ([component name].jar) that can be used like any other third party lib.
Indeed this archive will contain the pre-compiled RSP files, i.e. the java classes equivalent to the RSP files. Having the component RSP files in your source folder is equivalent to having the component JAR in the library folder, but in this last case you do not need to re-compile the component at each build. There is another advantage: you can deliver a component while keeping the sources not accessible.

Parameters
A component is designed to be inserted into a RSP file using the <include> tag. As previously said, having the component in its JAR form is equivalent as having it in as sources; that means that you can call the <include>tag with the name of the targeted RSP as if it was in your source folder. The MANIFEST.MF of a component JAR contains a special directive that exposes the RSP files that can be included, e.g :
Rsp-Files: MyComponentContent.rsp,MyComponentView.rsp
The component can be customized by passing request attributes to the included page, therefore each component proposes Java constant classes that define all the parameters used by the component. Those constant classes are included in the component JAR. A typical component call will look like this:
<%
stzRequest.addRequestAttribute(MyComponentViewConstants.PARAM,"value");
%>
tag. This makes the include too verbose, thus we created a utility class, the RequestParameterContext object. A RequestParameterContext can hold a set of couples (name, value). The parameters are added to the request only when the setup(stzRequest) is called, and a simple call to clean(stzRequest) will remove all the added attributes. The RequestParameterContext is also designed to leave the request in the exact state as it was before, that means that if you add an attribute in your context that is already set in the request, the install call will overwrite the previous value, but the clean call will restore the previously set value.
Volume Bar Component
During this tutorial, we will create a very simple re-usable component that can be used to display the device volume level. This is how it looks like:

The component images and size are fully customizable, the caller provides the assets and the component will layout them and create an animation that will be linked to the volume level.

Project structure
Let's create the component project structure.
We consider that having a project that is always up and ready to be emulated (as is) is a good practice. That is why you must add the features one by one. So what do we need at this point to have a project ready to emulate ?
To emulate a component we need to create the component RSP files, the Java constant classes and a sample 'service' that uses the component. I am sorry but we are going to produce a significant effort just to have an empty service ;).
A component project is structured like this:
-
src/, contains the component source files -
src/sample/, contains the sample service .rsp files -
src_java/, contains the .java constant classes -
lib/, contains the needed libraries -
ant/, contains the build file
Step 1
Let's now create the first Java constant class: create a new file named VolumeBarParameters.java in src_java/com/streamezzo/volumebar. Just add the INSERT_TARGET constant.
package com.streamezzo.volumebar;
/**
* A simple component used to popud a volume bar.
* @odp.component VolumeBar
* @odp.rspFile VolumeBar.rsp
* @odp.component.mainDescription
*/
public final class VolumeBarParameters
{
/**
* The DEF of the Transform node where this component will be inserted.
* @odp.required
* @odp.type A global DEF
*/
public static final String INSERT_TARGET = "InsertTarget";
}
Step 2
Let's create the main component RSPfile, VolumeBar.rsp. Notice that, as this page is designed to be included, you must NOT provide a <header> tag.
Just leave the file empty for now :
<%@page import="com.streamezzo.odp.utils.RequestUtils" %>
<%@page import="com.streamezzo.volumebar.*" %>
<%
String insertTarget = RequestUtils.getStringRequestAttribute(stzRequest, VolumeBarParameters.INSERT_TARGET);
%>
Step 3
Let's create the sample RSPfile, Sample.rsp. This RSP will load the sample images and include the component:
<%@page import="com.streamezzo.odp.utils.RequestParameterContext" %>
<%@page import="com.streamezzo.volumebar.*" %>
<%
RequestParameterContext params = new RequestParameterContext();
params.addParameter(VolumeBarParameters.INSERT_TARGET,"Global:VolumeBarAnchor");
params.setup(stzRequest);
%>
<%
params.clean(stzRequest);
%>
Step4
At this point the project skeleton is formed, but nothing compiles, we need to compile the .java files, create a .jar (java library) and add this JAR as a service library. A component compilation is a 2-step process :
- First, compile the Java constant classes,
- Second, compile the component RSP files with the previous compiled classes in the classpath.
We will use Ant to compile the Java constant classes. Let's create a build.xml
file in the ant/
folder, and add a compileJava target; This target compiles the .java sources and archives them in the internal.jar file.
The internal.jar can now be added as a service library.
Release process
How to compile the component
We use the Workbench Developer's stz.server.package
to create a fake server package. Then we can extract the generated Java classes.
How to package the component
The generated RSP Java files are now located in the myService.zip archive generated by the compile
target. To package the component we need to create a JAR that merges the RSP generated classes plus the constant classes. As previously said, the JAR Manifest file must contain the list of all the available RSPs; this is done thanks to the pathconvert task.
How to build the component headless
As we use Workbench Developer
TM
Ant targets (eg :stz.server.package), the Ant build can only be launched inside a running instance of Workbench Developer
TM
. Nevertheless there is a way to launch Workbench Developer
TM
in a headless
mode in order to build your component from your build machine. Notice that Workbench Developer
TM
must be installed on the build machine, but you'll be able to launch the build from a simple DOS command line.
How to generate the component documentation
We provide a specific tool that can generate the component generation from the Java constant classes. Our tool parses the Java classes and collects the information given by the specifics javadoc tags, the collected datas are merged into a XML file. The XML file is transformed using a xsl stylesheet. The official ODP component documentation is generated with this tool.
This a list of the odp doclets :
Class level doclet:
-
@odp.component -
Declares that this constant class is related to the given component (e.g
@odp.component VolumeBar). -
@odp.rspFile -
Declares that this constant class defines the attribute constants for the given RSP (e.g
@odp.rspFile VolumeBar.rsp). -
@odp.component.mainDescription - Declares that javadoc comment of this class is the component description. A component can have multiple Java constant classes, but only the class documentation of this class is used as the component description.
/**
* A simple component used to popup a volume bar.
* @odp.component VolumeBar
* @odp.rspFile VolumeBar.rsp
* @odp.component.mainDescription
*/
public final class VolumeBarParameters
Field level doclet :
-
@odp.required - If this tag is present, the parameter is mandatory.
-
@odp.defaultValue -
Declares the default value of this attribute (e.g
@odp.defaultValue "SMALL") -
@odp.type -
The type of this attribute (e.g
@odp.type Html color) -
@odp.category - Can be used to group related parameters
/**
* The DEF of the Bitmap representing the full volume bar.
* @odp.required
* @odp.type A global Def
* @odp.category Volume
*/
public static final String VOLUME_FULL_BITMAP = "DesignMediaControlBarVolumeFull";
Full sample
The sample source code can be downloaded here.