blob: c7fe610d774a2b69ae923e16d5fa407bfbbd1802 [file] [log] [blame]
~~ Licensed to the Apache Software Foundation (ASF) under one or more
~~ contributor license agreements. See the NOTICE file distributed with
~~ this work for additional information regarding copyright ownership.
~~ The ASF licenses this file to You under the Apache License, Version 2.0
~~ (the "License"); you may not use this file except in compliance with
~~ the License. You may obtain a copy of the License at
~~
~~ http://www.apache.org/licenses/LICENSE-2.0
~~
~~ Unless required by applicable law or agreed to in writing, software
~~ distributed under the License is distributed on an "AS IS" BASIS,
~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~~ See the License for the specific language governing permissions and
~~ limitations under the License.
------
Myfaces Builder Plugin
------
Summary
This is a maven plugin that uses javadoc annotations to generate the necessary JSF configuration
files (.tld, faces-config.xml, etc) and optionally Tag, Validator and Component classes.
See the documentation menu in the left-hand navigation pane for more information.
Introduction
A JSF component library needs to provide hand-written:
* component classes
* renderer classes
* converter and validator classes
[]
It then needs to also provide:
* jsp taglib files
* facelets taglib files
* tag classes
[]
However in most cases, the second category of artifacts can be generated from the
first ones. Tag classes generally just copy data from one format to another and
do not have any custom logic; they can effectively be created using code templates.
The config files are mostly just a "summary" of the information in the hand-written
classes above, and so are also a candidate for generation.
In addition, components have a lot of getter/setter methods for properties, where the
getter/setter implementations are very repetitive. Components also need to provide
state-handling methods (saveState/restoreState) which are also repetitive. In both
cases, the necessary methods can potentially be generated given metadata about the
properties belonging to a component.
Requirements
* Minimise the amount of code duplication, ie where a single change requires changes
in two different places
* Minimise bugs due to inconsistencies between data that should match.
* Reduce the boredom factor
* Allow optimisations in handling of JSF classes (eg state-saving improvements) to
be implemented in just one place, rather than having to repeat the same fix in
every place that uses the same boilerplate code.
* Keep the code simple to understand for people new to MyFaces. A solution that will
discourage people from committing patches to myfaces code is worse than no solution.
* Don't make building the code more complicated.
* Don't make debugging of the code more complicated
* Provide a solution that can be applied to as many myfaces projects as possible;
a separate build tool per project is not desirable. Note, however, that each
project must "opt in", so any successful tool must satisfy the needs of multiple
projects, or be sufficiently extensible for other projects to extend it to match.
* Allow external code to subclass components that are within a project which has
been built by the myfaces-builder-plugin. MyFaces components are meant to be
used as a base for other code; it would be nice to be able to offer a build tool
that users can apply to their own code when extending myfaces classes in order
to inherit the same metadata.
Gathering and saving meta-data
In order to drive all of the above artifact generation, metadata about the artifacts
to be generated is needed. There are several reasonable ways to gather this info.
* For several years, Trinidad has used xml files to declare the necessary data.
* The Tobago project uses java1.5 annotations (with compile-scope retention) plus
introspection of the classes (via the apt tool and the com.sun.mirror api) to
derive the necessary data.
* The use of javadoc annotations for metadata (eg xdoclet) also has a long successful
history as a way to represent metadata.
[]
In addition, people will no doubt invent other solutions in the future.
Therefore, the myfaces-builder-plugin provides "pluggable" metadata gathering in order
for different projects to represent their metadata as they wish. In fact, it should
support "chaining" of metadata gathering, so that part of the data can be gathered one
way, and part of it another way.
After a project using the myfaces-builder-plugin is published, people can then derive
their own components from the classes in the published jarfile. They can always implement
their own solution for defining the necessary tag classes, config files, etc. However it
would be nice to allow this plugin to also be usable on that external code. And in fact
this same issue also occurs internally within myfaces, eg between the -api and -impl jars
of a JSF implementation. There are a number of possible solutions, but the one chosen is
for myfaces-builder-plugin to generate a .xml file containing the metadata it has gathered
about a project, and for this file to be published in the META-INF directory of each
jarfile. This file can then be used as another source of meta-data by the builder plugin
itself; ie if the builder has built project A, then it can use the file it left in the
META-INF of A.jar in order to help build components that extend the classes in A.
Generating output
The whole point of the artifacts being generated (config files or java code) is that they
are very repetitive internally, varying only due to the metadata information. Therefore
a templating mechanism should be used to generate these.
However there are a large number of possible templating solutions. In addition, the
trinidad plugin has a history of generating output via hard-coding print statements in
java rather than using templating.
The builder plugin therefore also provides a "pluggable" generation mechanism, so that
projects can customise the process as they need.
Initially, builder will support the org.antlr.StringTemplate library as the template
mechanism, mainly because that is what Tobago currently uses. However there is no
reason why other approaches cannot be used.
Representing MetaData internally
Classes in the "model" package store all the metadata that can be gathered. The model is
therefore the union of all data needed by all supported projects.
The model objects are created/populated by the model-builders, and then used by the
various generator modules.
The metadata itself can be written to xml and read back from xml. This allows the following:
* the task of gathering the metadata can be one maven goal, with output being a file.
* the task of generating artfacts from metadata can just read the previously-created metadata
file without repeating the data-gathering process.
[]
It also means that:
* metadata can be stored in a file in the META-INF of a published jar
* the builder plugin can re-read the file from the META-INF of a published jar, allowing
libraries to easily *extend* classes declared in a published jar and still have access
to the metadata for those ancestor classes. ------