richard ratta wrote:
> The more I think about this the more confused I get as to why changing
> a very specific annotation processor is the solution.
>
> JSF defines two strategies for rendering components. One is with a
> renderkit
> and the flexibility it offers . It defines a second strategy where
> components render themselves.
>
> Your design appears to fall into the second strategy. In fact why
> doesn's the template component superclass
> implement the template rendering as well ?
Why don't all the JSF standard components do it this way? Why don't any
of the Woodstock components do it that way? The JSFTemplating-based
Renderer have the SAME answer.
There is NO difference between a Renderer that is template-based vs. one
that is Java-based (except that there is not .java file for a
template-based Renderer to annotate ;) ).
> You don't need the a renderer at all as you claim, it just becomes
> part of your
> inherited component behavior.
This reduces the options a component developer and the end users of the
component have for Rendering a UIComponent. The would have hard-coded a
1-to-1 mapping between the output of the UIComponent and the UIComponent
itself b/c there would be no mapping done at all.
I do not want this. I want 1 UIComponent to be capable of being
Rendered to N different devices / markup. I want the end-user to be
able to override the default Renderer and provide their own
implementation. Perhaps they'd extend the TemplateRenderer and add some
monitoring / auditing features... perhaps they'd generate .java code
from the template and use a .java based renderer which they've
modified... perhaps they'd write their own alternate implementation of
the Renderer. These are the SAME use-cases for which JSF provides the
Renderer mappings.
> We know that the current annotation processor supports components that
> do not have a
> a renderkit renderer. Unfortunately the processor reports warnings
> because of this
> but that is because of its specific nature.
>
> Just curious, what happens if a Woodstock component were to add the
> @Renderer
> annotation in error or is it appropriate in any way for the Woodstock
> components ?
The way I intended for this change to be used is to add the
"rendererClass" attribute to a @Component annotation:
@Component(type="com.sun.webui.jsf.DropDown",
family="com.sun.webui.jsf.DropDown",
rendererClass="com.sun.webui.jsf.renderkit.html.DropDownRenderer",
...)
The above would work and you would not be required to annotate the
DropDown Renderer. However... good practice would be to annotate it.
And for cases where you have 1 UIComponent w/ many Renderers would not
be satisified by this implementation.
Adding the @Renderer annotation to a UIComponent class works provided
that you use the rendererClass property as well... AND you don't have a
@Component annotation. The way the current annotation processor is
written, it doesn't support 2 annotations on a single class... or at
least I haven't figured out the correct syntax to get that to work. I
think the problem is that when you specify both annotations, the first
annotation annotates the 2nd annotation instead of both annotating the
class. Separating w/ commas didn't seem to help. There's a good change
I'm doing something wrong when defining the annotation, though.
> This really flies in the face of the strategy to have renderkits for
> the Woodstock components
> as well as JSF.
? I don't see how.
> This makes me think even more so that if your components don't
> utililize renderers in a
> renderkit, then they are either components that are not rendered, or
> they render themselves.
They DO utilize this... but they do not DEFINE the Renderer in the
Renderkit when using the template Renderer.
Thanks!
Ken
>
> -rick
>
> richard ratta wrote:
>
>>
>>
>> Ken Paulsen wrote:
>>
>>>
>>>
>>> richard ratta wrote:
>>>
>>>> I would like to see real requirements for this change, a little
>>>> more on what
>>>> is needed and why this change satisfies those requirements.
>>>>
>>>>> The motivation for this new feature is to be able to skip creating
>>>>> a new Renderer for a component entirely. Jason Lee and I are
>>>>> experimenting around with the Woodstock annotations +
>>>>> JSFTemplating's TemplateRenderer to create components. I think
>>>>> this is a good combination that reduces development to 2 files:
>>>>> UIComponent file, and a template file. However, the current
>>>>> annotations require a Renderer class to be present to place a
>>>>> @Renderer annotation... and we don't have such a file in our
>>>>> environment.
>>>>
>>>>
>>>>
>>>> This rationalization really isn't very clear, technically speaking.
>>>>
>>>> I also don't see the relationship between a renderer-type and the
>>>> renderer-class which is the relationship
>>>> JSF defines. There is no relationship in JSF between a Component
>>>> and a renderer-class. It is
>>>>
>>>> component-family
>>>> renderer-type
>>>> renderer-class
>>>>
>>>> And we have created complexities by dynamically changing a
>>>> component's renderer-type
>>>> at runtime based on the "type of request"; "normal" or "ajax".
>>>>
>>>
>>> Hi Rick,
>>>
>>> Yes, JSF supports an N to N mapping between UIComponent and
>>> Renderers. You can map N components to a single Renderer, or 1
>>> UIComponent can end up being server by N different Renderers. In
>>> order for this to work, as you pointed out, there cannot exist a
>>> hard-coded relationship between the UIComponent class and the
>>> Renderer class.
>>>
>>> For this reason this solution is not perfect... however, in my
>>> scenario there is only 1 Java file, yet I'd like to take advantage
>>> of the code generation done by the annotations so I can alleviate
>>> developers of the need to write ANY xml in the faces-config.xml
>>> file. I don't see any other practical way to do this w/ the current
>>> Woodstock annotations / development environment.
>>>
>>> Also, if you look at the @annotations as the "default" generated
>>> faces-config.xml file. Then this change *ONLY* provides a *default*
>>> mapping between the UIComponent and 1 possible Renderer. I see this
>>> as VERY valuable in my use case. Let me elaborate on my use case....
>>>
>>> I have a template that might look something like:
>>>
>>> myComp.jsf:
>>>
>>> <span id="$this{componentId}"><b>$property{value}</b></span>
>>>
>>> Ok... that's a VERY simple component that wraps the "value" property
>>> of the component in a span w/ bold tags... but valid... see my TSS
>>> article for a much more complicated example
>>> (http://www.theserverside.com/tt/articles/article.tss?l=JSFTemplateComponent).
>>>
>>>
>>> I then have a UIComponent that is something like:
>>>
>>> public class MyComp extends TemplateInsertComponentBase implements
>>> NamingContainer {
>>> public MyComp() {
>>> super();
>>> setRendererType("com.sun.MyComp");
>>> setLayoutDefinitionKey("jsftemplating/myComp.jsf");
>>> }
>>>
>>> public String getFamily() {
>>> return "com.sun.MyComp";
>>> }
>>> }
>>>
>>> I don't have ANY other files for the component... however, I would
>>> like to use Woodstock annotations to further simplify this so that I
>>> don't have to configure the *faces-config.xml* file or write a *JSP
>>> tag class*. With the current annotations I can't quite do this
>>> because I do NOT have a Renderer class
>>
>>
>> then what is
>> 'rendererClass="com.sun.jsftemplating.renderer.TemplateRenderer"' ?
>> Why not just annotate that renderer, to support the family,
>> "com.sun.Template" with renderer
>> type "com.sun.Template", and have anyone that wants to use you
>> "templates" make their component
>> belong to that family ?
>>
>> Currently the annotation processor does enforce a 1 to 1 mapping and
>> that is what I would rather
>> see fixed so that it supports the JSF mapping possibilities.
>>
>> Adding other arbitraty rules and annotations just makes the
>> annotations more cofusing.
>> If they followed the JSF spec with respect to mapping components to
>> renderers then
>> it is easier to understand since it follows a standard specification.
>> That should solve your use case as well, no ?
>>
>> I'm surprised everyone wants to get away from faces-config.xml. It
>> seemed pretty useful to
>> me to be able to map and define meta-data for compoents,
>> unfortunately we didn't conform to
>> it more strictly.
>>
>>
>> -rick
>>
>>> where I can put the @Renderer annotation. With my proposed change,
>>> I can add
>>> *rendererClass="com.sun.jsftemplating.renderer.TemplateRenderer"* to
>>> the @Component annotation and everything works.
>>>
>>> Does this make more sense?
>>>
>>> If we can do this... I'd like to write a java.sun.com article
>>> explaining how this is done. My TSS article has already generated a
>>> lot of interest, I think combining this with the Woodstock
>>> annotations offers a solution that a lot of people would be
>>> interested in.
>>>
>>>> See more inline
>>>>
>>>
>>> ... (see below)
>>>
>>>>
>>>> - RendersInfo(Map annotationValueMap) {
>>>> + RendersInfo(Map annotationValueMap, String className) {
>>>> this.annotationValueMap = annotationValueMap;
>>>> + this.className = className;
>>>> }
>>>>
>>>> You are changing an existing interface here.
>>>> Any existing code that relies on the previous interface will break.
>>>> You have to support the original interface as well as the new one.
>>>
>>>
>>>
>>> Yes, you are correct. However, this is a class that is used
>>> (indirectly) by APT only during compile time and doesn't manifest
>>> itself at all during runtime (afaik). So unless someone has
>>> extended the framework Woodstock has to develop their own JSF
>>> annotations AND directly instantiates this static inner class
>>> (DeclaredRendererInfo.RendersInfo), then this isn't a problem.
>>>
>>> Nevertheless, I'd be happy to support the old single-argument
>>> constructor as well since this is easy to do and good practice.
>>>
>>> Ken
>>>
>>>>
>>>> -rick
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>> Ken Paulsen wrote:
>>>>
>>>>>
>>>>> I would like to commit a minor change to the annotations woodstock
>>>>> provides. The change allows a @Component annotation to take a
>>>>> "rendererClass" attribute to specify a Renderer that should be
>>>>> used to Renderer the UIComponent.
>>>>>
>>>>> The motivation for this new feature is to be able to skip creating
>>>>> a new Renderer for a component entirely. Jason Lee and I are
>>>>> experimenting around with the Woodstock annotations +
>>>>> JSFTemplating's TemplateRenderer to create components. I think
>>>>> this is a good combination that reduces development to 2 files:
>>>>> UIComponent file, and a template file. However, the current
>>>>> annotations require a Renderer class to be present to place a
>>>>> @Renderer annotation... and we don't have such a file in our
>>>>> environment.
>>>>>
>>>>> I have run the annotation processor before and after this change
>>>>> and compared the results. There is no difference at all (as there
>>>>> shouldn't be since it only adds an optional property which isn't
>>>>> currently present on any Woodstock components).
>>>>>
>>>>> The diffs are attached. Please let me know if you have any
>>>>> objections to me checking in this change. Or if I should check it
>>>>> in somewhere other than the HEAD.
>>>>>
>>>>> Thanks!
>>>>>
>>>>> Ken
>>>>>
>>>>> woodstock/annotations> cvs -q diff -u
>>>>> Index: library/src/com/sun/faces/annotation/Component.java
>>>>> ===================================================================
>>>>> RCS file:
>>>>> /cvs/woodstock/annotations/library/src/com/sun/faces/annotation/Component.java,v
>>>>>
>>>>> retrieving revision 1.1
>>>>> diff -u -r1.1 Component.java
>>>>> --- library/src/com/sun/faces/annotation/Component.java 15 Feb
>>>>> 2007 21:47:16 -0000 1.1
>>>>> +++ library/src/com/sun/faces/annotation/Component.java 31 Aug
>>>>> 2007 21:28:05 -0000
>>>>> @@ -134,6 +134,8 @@
>>>>> * is set to false), then providing a value for this element
>>>>> has no effect.
>>>>> */
>>>>> public String tagRendererType() default "";
>>>>> +
>>>>> + public String rendererClass() default "";
>>>>>
>>>>> /**
>>>>> * An optional short description of this component, typically
>>>>> used as a tool
>>>>> Index: library/src/com/sun/faces/annotation/Renderer.java
>>>>> ===================================================================
>>>>> RCS file:
>>>>> /cvs/woodstock/annotations/library/src/com/sun/faces/annotation/Renderer.java,v
>>>>>
>>>>> retrieving revision 1.1
>>>>> diff -u -r1.1 Renderer.java
>>>>> --- library/src/com/sun/faces/annotation/Renderer.java 15 Feb
>>>>> 2007 21:48:01 -0000 1.1
>>>>> +++ library/src/com/sun/faces/annotation/Renderer.java 31 Aug
>>>>> 2007 21:28:05 -0000
>>>>> @@ -82,6 +82,8 @@
>>>>> @Target(ElementType.ANNOTATION_TYPE)
>>>>> public @interface Renders {
>>>>>
>>>>> + public String rendererClass() default "";
>>>>> +
>>>>> /**
>>>>> * The renderer type for this component and renderer
>>>>> combination. If
>>>>> * this annotation contains a single component family, and
>>>>> a renderer type
>>>>> Index: processor/src/com/sun/faces/mirror/DeclaredRendererInfo.java
>>>>> ===================================================================
>>>>> RCS file:
>>>>> /cvs/woodstock/annotations/processor/src/com/sun/faces/mirror/DeclaredRendererInfo.java,v
>>>>>
>>>>> retrieving revision 1.1
>>>>> diff -u -r1.1 DeclaredRendererInfo.java
>>>>> ---
>>>>> processor/src/com/sun/faces/mirror/DeclaredRendererInfo.java
>>>>> 15 Feb 2007 21:56:49 -0000 1.1
>>>>> +++
>>>>> processor/src/com/sun/faces/mirror/DeclaredRendererInfo.java
>>>>> 31 Aug 2007 21:28:06 -0000
>>>>> @@ -44,9 +44,10 @@
>>>>> this.annotationValueMap = annotationValueMap;
>>>>> renderings = new ArrayList<RendersInfo>();
>>>>> if (this.annotationValueMap.containsKey(VALUE)) {
>>>>> + String qn = decl.getQualifiedName();
>>>>> for (Object value : (List)
>>>>> this.annotationValueMap.get(VALUE)) {
>>>>> Map nestedAnnotationValueMap = (Map) value;
>>>>> - renderings.add(new
>>>>> RendersInfo(nestedAnnotationValueMap));
>>>>> + renderings.add(new
>>>>> RendersInfo(nestedAnnotationValueMap, qn));
>>>>> }
>>>>> }
>>>>> }
>>>>> @@ -60,15 +61,28 @@
>>>>> */
>>>>> static public class RendersInfo {
>>>>>
>>>>> + static String RENDERER_CLASS = "rendererClass";
>>>>> static String RENDERER_TYPE = "rendererType";
>>>>> static String COMPONENT_FAMILY = "componentFamily";
>>>>>
>>>>> Map annotationValueMap;
>>>>> + String className;
>>>>>
>>>>
>>>>> + /**
>>>>> + * The renderer class (the qualified name by default).
>>>>> + */
>>>>> + public String getRendererClass() {
>>>>> + if
>>>>> (this.annotationValueMap.containsKey(RENDERER_CLASS)) {
>>>>> + return (String)
>>>>> this.annotationValueMap.get(RENDERER_CLASS);
>>>>> + }
>>>>> + return this.className;
>>>>> + }
>>>>> +
>>>>> /**
>>>>> * The renderer type.
>>>>> */
>>>>> Index:
>>>>> processor/src/com/sun/faces/mirror/FacesAnnotationProcessor.java
>>>>> ===================================================================
>>>>> RCS file:
>>>>> /cvs/woodstock/annotations/processor/src/com/sun/faces/mirror/FacesAnnotationProcessor.java,v
>>>>>
>>>>> retrieving revision 1.2
>>>>> diff -u -r1.2 FacesAnnotationProcessor.java
>>>>> ---
>>>>> processor/src/com/sun/faces/mirror/FacesAnnotationProcessor.java
>>>>> 9 Jun 2007 13:35:41 -0000 1.2
>>>>> +++
>>>>> processor/src/com/sun/faces/mirror/FacesAnnotationProcessor.java
>>>>> 31 Aug 2007 21:28:08 -0000
>>>>> @@ -197,6 +197,30 @@
>>>>> this.declaredComponentSet.add(componentInfo);
>>>>>
>>>>> this.declaredClassMap.put(typeDecl.getQualifiedName(),
>>>>> componentInfo);
>>>>> typeInfo = componentInfo;
>>>>> + // Check to see if this annotation also
>>>>> specifies a Renderer
>>>>> + Object rendererClass =
>>>>> annotationValueMap.get("rendererClass");
>>>>> + if ((rendererClass != null)
>>>>> + &&
>>>>> !rendererClass.toString().equals("")) {
>>>>> + // Create the "Renders" Map
>>>>> + Map renders = new HashMap();
>>>>> + renders.put("rendererClass",
>>>>> rendererClass);
>>>>> + Object type =
>>>>> annotationValueMap.get("tagRendererType");
>>>>> + if ((type == null) ||
>>>>> type.toString().equals("")) {
>>>>> + type =
>>>>> annotationValueMap.get("type");
>>>>> + }
>>>>> + renders.put("rendererType", type);
>>>>> + ArrayList families = new ArrayList();
>>>>> +
>>>>> families.add(annotationValueMap.get("family"));
>>>>> + renders.put("componentFamily", families);
>>>>> +
>>>>> + List list = new ArrayList();
>>>>> + list.add(renders);
>>>>> + Map rendererMap = new HashMap();
>>>>> + rendererMap.put("value", list);
>>>>> + DeclaredRendererInfo rendererInfo =
>>>>> + new
>>>>> DeclaredRendererInfo(rendererMap, (ClassDeclaration) typeDecl);
>>>>> +
>>>>> this.declaredRendererSet.add(rendererInfo);
>>>>> + }
>>>>> } else if
>>>>> (typeDecl.getAnnotation(Renderer.class) != null) {
>>>>> // This is a renderer class
>>>>> Map<String,Object> annotationValueMap =
>>>>> Index:
>>>>> processor/src/com/sun/faces/mirror/generator/FacesConfig.template
>>>>> ===================================================================
>>>>> RCS file:
>>>>> /cvs/woodstock/annotations/processor/src/com/sun/faces/mirror/generator/FacesConfig.template,v
>>>>>
>>>>> retrieving revision 1.2
>>>>> diff -u -r1.2 FacesConfig.template
>>>>> ---
>>>>> processor/src/com/sun/faces/mirror/generator/FacesConfig.template
>>>>> 17 Feb 2007 23:50:09 -0000 1.2
>>>>> +++
>>>>> processor/src/com/sun/faces/mirror/generator/FacesConfig.template
>>>>> 31 Aug 2007 21:28:08 -0000
>>>>> @@ -52,7 +52,7 @@
>>>>> <renderer>
>>>>> <component-family>${componentFamily}</component-family>
>>>>> <renderer-type>${rendering.rendererType}</renderer-type>
>>>>> -
>>>>> <renderer-class>${rendererInfo.qualifiedName}</renderer-class>
>>>>> +
>>>>> <renderer-class>${rendering.rendererClass}</renderer-class>
>>>>> </renderer>
>>>>> #end
>>>>> #end
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: dev-unsubscribe_at_woodstock.dev.java.net
>>>>> For additional commands, e-mail: dev-help_at_woodstock.dev.java.net
>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: dev-unsubscribe_at_woodstock.dev.java.net
>>>> For additional commands, e-mail: dev-help_at_woodstock.dev.java.net
>>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe_at_woodstock.dev.java.net
>> For additional commands, e-mail: dev-help_at_woodstock.dev.java.net
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_woodstock.dev.java.net
> For additional commands, e-mail: dev-help_at_woodstock.dev.java.net
>