| ~~ 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. ------ |