You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by simon <si...@chello.at> on 2008/01/31 23:24:43 UTC

Re: [Myfaces Wiki] Update of "Code Generation" by SimonKitching

On Thu, 2008-01-31 at 21:40 +0000, Apache Wiki wrote:
> Dear Wiki user,
> 
> You have subscribed to a wiki page or wiki category on "Myfaces Wiki" for change notification.
> 
> The following page has been changed by SimonKitching:
> http://wiki.apache.org/myfaces/Code_Generation

Ok, as promised here is the wiki page summarising the recent email
thread. I hope I've got everybody's opinions fairly represented, but of
course if corrections need to be made - hack away!

Personally I'm keen to try to build something along the lines I was
proposing - but first need to help get a new Orchestra release out.

There isn't any hurry on getting this tomahawk build process sorted is
there? I don't see any reason why tomahawk 1.1.7 cannot go out with the
current build process..

Regards, Simon


Re: [Myfaces Wiki] Update of "Code Generation" by SimonKitching

Posted by Mike Kienenberger <mk...@gmail.com>.
> > http://wiki.apache.org/myfaces/Code_Generation
> 2) Generating base classes instead of templates from xml-config-files

For what it's worth, what you're describing here is the Generation Gap
pattern.   I've got a lot of experience using it with Cayenne over the
years (and WebObjects years before that), and it's effective.   It's
sometimes painful to write and maintain your base class in a
templating language, though, but once your base class is done, you
don't need to mess with it again, so this is a one-time painful
experience.   And yes, you would typically generate an empty concrete
subclass whenever one doesn't exist (the first time code generation
runs for a given component).

I check the code thus generated into the repository.   I also keep the
generated code in a subpackage called *.generated off the concrete
subclasses's package.

Re: [Myfaces Wiki] Update of "Code Generation" by SimonKitching

Posted by Leonardo Uribe <lu...@gmail.com>.
Hi

I have checked this topic of the wiki
http://wiki.apache.org/myfaces/Code_Generation:
Generating base classes instead of templatesAnd based on some work with
tomahawk I have some observations to do:

*".......Note that (in a feature that may surprise some Java developers) it
appears quite valid for a class to have a package-scoped parent; the class
can still be subclassed or instantiated from outside the package. It
inherits public and protected members from its package-scoped parent which
can be called as normal. The only constraint is that it cannot be cast to
its parent type, as this is not accessible (although the Class object for
that type can still be obtained). It is not yet known whether inserting such
a package-scoped ancestor class into the ancestry of a component class in
the javax.faces package scope would be acceptable to the JSF TCK or not. If
the TCK accepts this, then the approach of generating a base class could
also be applied to myfaces core components......".
*
In some cases doing something like this:

abstract class AbstractHtmlInputText
        extends javax.faces.component.html.HtmlInputText
        implements UserRoleAware, DisplayValueOnlyCapable
{

works but in other cases do not, It throws an exception like this:

java.lang.IllegalAccessException: Class
javax.faces.component._ComponentAttributesMap can not access a member of
class org.apache.myfaces.custom.tabbedpane.AbstractHtmlPanelTabbedPane with
modifiers "public abstract"
    at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
    at java.lang.reflect.Method.invoke(Method.java:588)
    at javax.faces.component._ComponentAttributesMap.getComponentProperty
(_ComponentAttributesMap.java:390)
    at javax.faces.component._ComponentAttributesMap.put
(_ComponentAttributesMap.java:311)
    at javax.faces.component.UIComponent.setValueExpression(UIComponent.java
:112)
    at
org.apache.myfaces.custom.tabbedpane.HtmlPanelTabbedPaneTag.setProperties(
HtmlPanelTabbedPaneTag.java:389)
    at javax.faces.webapp.UIComponentELTag.createComponent(
UIComponentELTag.java:100)

There are some methods on java api that use reflection to set some
variables, and fails if the parent class is not public, so I do not believe
that this approach works for myfaces core api, and pass the TCK.

*"....With this setup, we have the question of which source directory the
generated base class gets written to. Option (1) is to write it to a
generated-source dir, option (2) is to write it to the normal source
dir....."
*
*".....Question: When there are multiple source trees for a module, does
maven build against them all simultaneously? That is, if a normal source
file references a source file in the generated-source tree which itself
references a source file in the normal source tree, does this work?..."
*
Yes, this works and it is awesome. One successful example is this hierarchy
used for t:schedule

javax.faces.UIComponentBase
-----------myfaces core api
org.apache.myfaces.custom.schedule.AbstractUIScheduleBase    ----------- on
src/main/java
org.apache.myfaces.custom.schedule.UIScheduleBase
------------ generated on target/maven-faces-plugin/main/java
org.apache.myfaces.custom.schedule.UISchedule
------------ on src/main/java
org.apache.myfaces.custom.schedule.HtmlSchedule
------------ generated on target/maven-faces-plugin/main/java

On eclipse I works like if all files were on the same directory. Code
completion works using base classes (with templates do not!).

Generate in src/main/java or in target/maven-faces-plugin/main/java is
transparent for the IDE. If we generate in src/main/java, the generated code
will mix with hand written code, if we translate generated code to a
separate directory on src/main/java technically it is equivalent to generate
in target/maven-faces-plugin/main/java.

In conclusion: Actually 100%  of the components in tomahawk (I have only a
problem with t:tree2 that can be solved with more work) can use abstract
classes aproach (with some little modifications on myfaces-faces-plugin).
The list of modifications is this. :

- component-includes parameter on component-extension
- component-serial-uid parameter on component-extension
- is-get-local-method-scope and is-get-local-method parameters on
property-extension to generate automatically getLocalXXX method
- is-set-method-scope and is-set-method parameters on property-extension to
generate automatically isSetXXXX method.

regards

Leonardo Uribe

Re: [Myfaces Wiki] Update of "Code Generation" by SimonKitching

Posted by Martin Marinschek <ma...@gmail.com>.
Hi Zdenek,

> writing:
> - check if special setter -> use it AND
> - store in map

this won't work, of course - we are in a setter already, so we cannot
use the attribute-map - thanks for setting me straight again. What you
are suggesting would effectively change the API of every single
JSF-component (contrary to your opinion, having getters and setters
_does_ make sense to me - especially if you access the components from
Java, and in any case, the spec mandates having them in the component
class). We need to find a different way of doing things.

regards,

Martin

Re: [Myfaces Wiki] Update of "Code Generation" by SimonKitching

Posted by Sochor Zdeněk <zd...@ataco.cz>.
Hi,

Martin Marinschek napsal(a):
> Hi Zdenek,
>
>   
>> A question was raised about why state isn't retrieved from the
>> attributes map - this cannot be used, however, cause it would use
>> reflection internally and call the getter of the method, if a value is
>> not directly stored in the attributes map. As soon as the getter is
>> called, after the check for the local value returns null, you will get
>> back the value from a value-expression, and you do not want to save this
>> value in the state, as the value-expression itself is already stored!
>>     
>
> so you want to get rid of the concept of a local value completely, and
> store everything in the attribute map? Now I see. This might actually
> work, yes.
>
>   
1. getting rid of attributes' local values - yes,
2. getting rid of most getters/setters w/o special code in them (as 
typical use today)

2 should be possible with JSP tags, don't know about Facelets (maybe 
tag-handlers could do this)

 From spec and API's JavaDoc i got this idea of processing attributes:

reading:
- check if special getter -> use it (if it looks at Map/VB is optional)
- check if in map -> use it
- check if value binded -> resolve and use it (or use default in some cases)

writing:
- check if special setter -> use it AND
- store in map

using in lifecycle's process:
- Restore view:
   - restore Map (done by ancester in API)
- Apply Request:
  - resolve all ValueBindings and store them in Map to avoid multiple 
resolving
     - basically reading all attributes defined in tld and still not in Map
  This should make this work for Mojarra's all getter/setter way (if 
"forgot" writing values into Map)
   - possible optimization could be in "lazy" fetching attributes when 
needed (once fetched, store in Map)
  To avoid saving these generated attributes' values, add/alter special 
key in Map (e.g. "o_a_m_generatedAttributes") with array containing 
names of those attributes
- next phases:
  - use values from Map (if not lazily fetched already complete, adding 
new entries when not along with modifications of special key's value)
    - NOT using reading of attributes as above if already in Map
  - writing attributes as above and if attribute's name present in 
special key's array, remove it from that array
     - any direct modifications w/o deletion in array (e.g. for internal 
processing) made in Map's values of generated attributes will be ignored 
in state saving
- Render Response:
  - clean Map of generated stuff:
      - remove all entries with null value
      - remove all entries with names in special key's array
      - remove special key
  - saving Map (done by ancester in API)

Having attributes both in Map and local properties (as of today and 
present in API) is not an obstruction - values in local properties take 
precedence,
because Map is stored/restored first.

Using this could possibly make any kind of generator for COMPONENT 
classes needless - all generic code for all attributes would be written 
once.

Only setters/getters i'd like to see in components' classes are with 
special behaviour code (but still using Map in the end).

Tasks in this approach:
- generating TAGS (JSP and Facelets)
- create utility class for
  a) getting values from Map to use in component's methods, e.g:
  static public Boolean getBoolean(UIComponent comp, String attr, 
Boolean default) {
     Object res = comp.getAttributes().get(attr);
     if (obj != null) return (Boolean)res;
     // check if in special key - it may got resolved to null -> return 
default
     // not in special key -> resolve it, add to Map (along with adding 
to special key's array)
     // resolved != null ? return (Boolean)resolved : default;
  }
  (I think default can be got from TLD for JSF 1.2)
  b) setting values to Map, e.g.
  static public void setBoolean(UIComponent comp, String attr, Boolean 
value) {
    // if special setter, use it
     comp.getAttributes().put(attr, value);
     if (comp.getAttributesMap().get("o_a_m_generatedAttributes") != null) {
      // remove attr from array
    }
  }

This way it would be only in Tag class/TLD to define new attributes 
which would be automatically saved/restored.
(This also fulfills JSF 1.1 spec in handling generic atributes from 
section 3.1.10)

OR (to be really on business of thread):

With this approach it would be pretty easy to support one method of 
generating libs:
Annotations (or XDoclet) written for component class defining attributes 
- name, type, default value, target language, description...
This annotation should inherit all definitions from component's parent 
class.
- this way developer can really see which attributes he can really use 
in component's code AND
- the class is compilable on it's own (it's accessing already existing Map)


Regards,
  Zdenek
> regards,
>
> Martin
>
>
>   

Re: [Myfaces Wiki] Update of "Code Generation" by SimonKitching

Posted by Martin Marinschek <ma...@gmail.com>.
Hi Zdenek,

> A question was raised about why state isn't retrieved from the
> attributes map - this cannot be used, however, cause it would use
> reflection internally and call the getter of the method, if a value is
> not directly stored in the attributes map. As soon as the getter is
> called, after the check for the local value returns null, you will get
> back the value from a value-expression, and you do not want to save this
> value in the state, as the value-expression itself is already stored!

so you want to get rid of the concept of a local value completely, and
store everything in the attribute map? Now I see. This might actually
work, yes.

regards,

Martin

Re: [Myfaces Wiki] Update of "Code Generation" by SimonKitching

Posted by Sochor Zdeněk <zd...@ataco.cz>.
Hi all,
  some clarifications from my side:

Quote 1:

One of the last developers to work on the old code-generation framework 
commented that it was "very painful". Not sure whether this comment was 
about the basic concept of this approach, or just the implementation.


It was about changes made to code within generation marks in Tomahawk 
Core components. To make the old generator work again, it had to be 
extended to take in account:
  a) modifications in either getter or setter (or both), which comprises 
of custom added behavior (overriding other properties, additional checks)
  b) modifications in save/restoreState methods (overriding several 
properties based on checks)
  c) missing attributes everywhere - xml, tld, tag, component (basicly 
everywhere it could be)

 I think items a) and b) aren't addressed in current Trinidad's generation.


Quote 2:

A question was raised about why state isn't retrieved from the 
attributes map - this cannot be used, however, cause it would use 
reflection internally and call the getter of the method, if a value is 
not directly stored in the attributes map. As soon as the getter is 
called, after the check for the local value returns null, you will get 
back the value from a value-expression, and you do not want to save this 
value in the state, as the value-expression itself is already stored!


- saveState/restoreState for components derived from API's base already 
saves/restores the whole Map, so no need to do it again in derived 
classes -> no additional reflection (which should never be done in the 
first place).
- if a value isn't in attribute map it means it's not a crucial value to 
restore state, is it? (mind that all value bindings and listeners are 
saved/restored by API's base too)

Regards,
  Zdenek

Re: [Myfaces Wiki] Update of "Code Generation" by SimonKitching

Posted by Martin Marinschek <ma...@gmail.com>.
> I look at the vast list of bugs raised against tomahawk 1.1.6, and look
> at the scary output of the maven reports (findbugs, pmd, etc) and think
> that there are higher priorities than reinventing the build process
> right now, when the current approach works. Yes it is ugly, but 1.1.7 is
> mostly a bugfix release; we don't need to add many components or change
> many APIs. We do want to promote a couple of sandbox components which is
> a nuisance but can be managed.

for all this, I want a generator (and we haven't had one for ages -
I'm not gonna wait for more time). Don't forget facelets-support, by
the way. Do you really want another tomahawk-release without it? Plus,
as I said before, I want to play around with performance, and need a
generator for this as well. I am advocating we can go with the
Trinidad-approach plus changing over from templates to base-classes
for now; and you can always change this again if you have time later -
it will be A LOT easier with a generator in place.

> Of course this is open-source, so nobody can be told what to work on,
> and what not. But I don't personally want to be testing a temporary new
> build process while also testing a tomahawk rc.

you only have to test the rc - you will not note any differences to
the old approach of doing components, I promise. The changes in the
new component generator to the one in Trinidad will be minimal, so
there is not much to test - the component generator of Trinidad is
well tested.

>I think it would be
> better to solve the build process issue just once, but it looks like
> that would delay a tomahawk release - unless we get consensus to use the
> trinidad approach (which doesn't seem to be the case ATM).

as Leonardo will probably do the release work, it's his choice what he
tries/can achieve before he does the release

> The last tomahawk release is over 6 months ago, which is the release
> cycle for a whole Ubuntu distro, or a linux kernel...it would be nice to
> get one out without further delays.

yes - and finally we have found someone who actually does the release
work with Leonardo, so please, just let him continue doing his work.

regards,

Martin

Re: [Myfaces Wiki] Update of "Code Generation" by SimonKitching

Posted by simon <si...@chello.at>.
On Thu, 2008-01-31 at 23:59 +0100, Martin Marinschek wrote:

>         Personally I'm keen to try to build something along the lines
>         I was
>         proposing - but first need to help get a new Orchestra release
>         out.
> 
> If you can solve the problem with restore-state and save-state and
> your solution does not decrease runtime performance, and you show me a
> compact way of including all meta-data in annotations, I'd be very
> grateful to see you hack away! However, we should discuss the options
> we have for getting the restore-state and save-state problem fixed
> first - I am pretty sure we will not find one if we want to extend
> from the JSF base classes.

Yep, it's just an idea at the moment; actually trying it will show
whether there are reasonable solutions to your points or not..

> 
> 
>         There isn't any hurry on getting this tomahawk build process
>         sorted is
>         there? I don't see any reason why tomahawk 1.1.7 cannot go out
>         with the
>         current build process..
> 
> I do not see a reason why it should - especially as even the
> trinidad-based approach will make it easier for you to work on your
> component-based approach, cause you can then generate your generator
> base-classes with the generator and don't have to go through all
> component-classes. Work that Leonardo has already done for you. We
> need to switch to using a generator - improving the way of generating
> things is then easy. I also need a generator cause I finally want to
> improve the performance in the components - and for checking out
> several ways of doing this, it is necessary to have a generator
> (except we find a solution along your lines with regards to
> restoreState/saveState).

I look at the vast list of bugs raised against tomahawk 1.1.6, and look
at the scary output of the maven reports (findbugs, pmd, etc) and think
that there are higher priorities than reinventing the build process
right now, when the current approach works. Yes it is ugly, but 1.1.7 is
mostly a bugfix release; we don't need to add many components or change
many APIs. We do want to promote a couple of sandbox components which is
a nuisance but can be managed.

And the thought of changing the build process for 1.1.7, then changing
it again for 1.1.8 is not too tempting. 

Of course this is open-source, so nobody can be told what to work on,
and what not. But I don't personally want to be testing a temporary new
build process while also testing a tomahawk rc. I think it would be
better to solve the build process issue just once, but it looks like
that would delay a tomahawk release - unless we get consensus to use the
trinidad approach (which doesn't seem to be the case ATM).

The last tomahawk release is over 6 months ago, which is the release
cycle for a whole Ubuntu distro, or a linux kernel...it would be nice to
get one out without further delays.

Regards,
Simon


Re: [Myfaces Wiki] Update of "Code Generation" by SimonKitching

Posted by Martin Marinschek <ma...@gmail.com>.
> @Component(
>   type = "...",
>   family = "...",
>   rendererType = "...",
>   tagClass = "...",
>   events = {
>     @ComponentEvent(
>       type = "...",
>       phases = { "...", "..." }),
>     ...
>   )
> public abstract class MyComponent extends UIXComponent
> {
>   @ComponentProperty(
>     description = "or is this better in javadoc? -- harder to code the
> generator, but easier to document",
>     extensions = {
>       @PropertyExtension(name = "preferred", value = Boolean.TRUE),
>       @PropertyExtension(name = "...", value = "...")
>     })
>   private String _foo;
>
>   @ComponentPropertySkel
>   public abstract String getFoo();
>
>   public void broadcast(FacesEvent event)
>   {
>     // custom code
>   }
> }


another option - why don't you add it to the wiki?I would be against it,
cause it is one of these options which need a full rebuild on a change in
the component-class.

regards,

Martin

Re: [Myfaces Wiki] Update of "Code Generation" by SimonKitching

Posted by Andrew Robinson <an...@gmail.com>.
Okay, feel free to flame.

Possibility of merging annotations w/ code generation:

@Component(
  type = "...",
  family = "...",
  rendererType = "...",
  tagClass = "...",
  events = {
    @ComponentEvent(
      type = "...",
      phases = { "...", "..." }),
    ...
  )
public abstract class MyComponent extends UIXComponent
{
  @ComponentProperty(
    description = "or is this better in javadoc? -- harder to code the
generator, but easier to document",
    extensions = {
      @PropertyExtension(name = "preferred", value = Boolean.TRUE),
      @PropertyExtension(name = "...", value = "...")
    })
  private String _foo;

  @ComponentPropertySkel
  public abstract String getFoo();

  public void broadcast(FacesEvent event)
  {
    // custom code
  }
}

This would be in a pre-processing folder of maven (not src/main/java). The
plugin can then take this file an build the concrete class from it.

This is basically the same as the trinidad approach but it merges the xml
with the template.

This way you don't get tedious xml like:
      <property-extension>
        <mfp:method-binding-signature>
          <mfp:return-type>java.lang.String</mfp:return-type>
        </mfp:method-binding-signature>


Just a thought.

-Andrew


On Jan 31, 2008 3:59 PM, Martin Marinschek <ma...@gmail.com>
wrote:

> Hi Simon,
>
> Ok, as promised here is the wiki page summarising the recent email
> > thread. I hope I've got everybody's opinions fairly represented, but of
> > course if corrections need to be made - hack away!
>
>
> I've added and clarified where I thought it was appropriate.
>
> Personally I'm keen to try to build something along the lines I was
> > proposing - but first need to help get a new Orchestra release out.
>
>
> If you can solve the problem with restore-state and save-state and your
> solution does not decrease runtime performance, and you show me a compact
> way of including all meta-data in annotations, I'd be very grateful to see
> you hack away! However, we should discuss the options we have for getting
> the restore-state and save-state problem fixed first - I am pretty sure we
> will not find one if we want to extend from the JSF base classes.
>
> There isn't any hurry on getting this tomahawk build process sorted is
> > there? I don't see any reason why tomahawk 1.1.7 cannot go out with the
> > current build process..
>
>
> I do not see a reason why it should - especially as even the
> trinidad-based approach will make it easier for you to work on your
> component-based approach, cause you can then generate your generator
> base-classes with the generator and don't have to go through all
> component-classes. Work that Leonardo has already done for you. We need to
> switch to using a generator - improving the way of generating things is then
> easy. I also need a generator cause I finally want to improve the
> performance in the components - and for checking out several ways of doing
> this, it is necessary to have a generator (except we find a solution along
> your lines with regards to restoreState/saveState).
>
> regards,
>
> Martin
>

Re: [Myfaces Wiki] Update of "Code Generation" by SimonKitching

Posted by Martin Marinschek <ma...@gmail.com>.
Hi Simon,

Ok, as promised here is the wiki page summarising the recent email
> thread. I hope I've got everybody's opinions fairly represented, but of
> course if corrections need to be made - hack away!


I've added and clarified where I thought it was appropriate.

Personally I'm keen to try to build something along the lines I was
> proposing - but first need to help get a new Orchestra release out.


If you can solve the problem with restore-state and save-state and your
solution does not decrease runtime performance, and you show me a compact
way of including all meta-data in annotations, I'd be very grateful to see
you hack away! However, we should discuss the options we have for getting
the restore-state and save-state problem fixed first - I am pretty sure we
will not find one if we want to extend from the JSF base classes.

There isn't any hurry on getting this tomahawk build process sorted is
> there? I don't see any reason why tomahawk 1.1.7 cannot go out with the
> current build process..


I do not see a reason why it should - especially as even the trinidad-based
approach will make it easier for you to work on your component-based
approach, cause you can then generate your generator base-classes with the
generator and don't have to go through all component-classes. Work that
Leonardo has already done for you. We need to switch to using a generator -
improving the way of generating things is then easy. I also need a generator
cause I finally want to improve the performance in the components - and for
checking out several ways of doing this, it is necessary to have a generator
(except we find a solution along your lines with regards to
restoreState/saveState).

regards,

Martin

Re: [Myfaces Wiki] Update of "Code Generation"

Posted by Martin Marinschek <ma...@gmail.com>.
Hi Simon,

this is true - but what happens if someone else tries to access
component attributes via reflection?

regards,

Martin

On 2/8/08, Simon Kitching <sk...@apache.org> wrote:
>
> In the practice the problem is that jsf core (myfaces and ri) uses
> reflection to set the attributes and the following case fail:
>
> Fail with the following exception
>
> java.lang.IllegalAccessException: Class javax.faces.component._Util can not
> access a member of class org.apache.myfaces.test.AbstractComponent with
> modifiers "public"
>         at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
>         at java.lang.reflect.Method.invoke(Unknown Source)
>         at javax.faces.component._Util.getValue(_Util.java:54)
>         at javax.faces.component.BaseComponent.getValueReflection(
> BaseComponent.java:32)
>         at javax.faces.other.ComponentTest.main(ComponentTest.java:14)
>
> This behavior is a JDK bug:
>
> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4071957
> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4533479
>
> One possible workaround is put the following line before invoke:
>
>             readMethod.setAccessible(true);
>
> Or make AbstractComponent public.
>
> The conclusion is that the abstract base class should be public if and only
> if it has in his body a attribute definition available on the tld. If the
> abstract base class has some different code it can be package scope. This
> behavior discard this approach for myfaces core api!
>
> I'm not sure this behaviour is a bug, or that it is fatal for the purposes
> of generating base classes for myfaces-api.
>
> When a Method object refers to a public method in a package-scoped class,
> then Method.invoke fails with the above exception *when executed by some
> class outside that package*. However it succeeds fine when invoked by code
> within that package (eg its concrete subclass) or by the class itself. I
> have tested this behaviour and it is the same on both java1.6 and java1.3.
> It also seems quite reasonable behaviour.
>
> So one solution is for the generated base class to override getAttributes()
> to return a custom map where that class itself implements the fetching of
> the attributes it implements, and delegates to the map created by
> UIComponentBase.getAttributes() for anything else. This seems quite
> feasable.
>
> Regards,
> Simon
> --
> View this message in context:
> http://www.nabble.com/Re%3A--Myfaces-Wiki--Update-of-%22Code-Generation%22-by-SimonKitching-tp15216313p15353739.html
> Sent from the My Faces - Dev mailing list archive at Nabble.com.
>
>


-- 

http://www.irian.at

Your JSF powerhouse -
JSF Consulting, Development and
Courses in English and German

Professional Support for Apache MyFaces

Re: [Myfaces Wiki] Update of "Code Generation"

Posted by Simon Kitching <sk...@apache.org>.
In the practice the problem is that jsf core (myfaces and ri) uses
reflection to set the attributes and the following case fail:

Fail with the following exception

java.lang.IllegalAccessException: Class javax.faces.component._Util can not
access a member of class org.apache.myfaces.test.AbstractComponent with
modifiers "public"
        at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at javax.faces.component._Util.getValue(_Util.java:54)
        at javax.faces.component.BaseComponent.getValueReflection(
BaseComponent.java:32)
        at javax.faces.other.ComponentTest.main(ComponentTest.java:14)

This behavior is a JDK bug:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4071957
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4533479

One possible workaround is put the following line before invoke:

            readMethod.setAccessible(true);

Or make AbstractComponent public.

The conclusion is that the abstract base class should be public if and only
if it has in his body a attribute definition available on the tld. If the
abstract base class has some different code it can be package scope. This
behavior discard this approach for myfaces core api!

I'm not sure this behaviour is a bug, or that it is fatal for the purposes
of generating base classes for myfaces-api.

When a Method object refers to a public method in a package-scoped class,
then Method.invoke fails with the above exception *when executed by some
class outside that package*. However it succeeds fine when invoked by code
within that package (eg its concrete subclass) or by the class itself. I
have tested this behaviour and it is the same on both java1.6 and java1.3.
It also seems quite reasonable behaviour.

So one solution is for the generated base class to override getAttributes()
to return a custom map where that class itself implements the fetching of
the attributes it implements, and delegates to the map created by
UIComponentBase.getAttributes() for anything else. This seems quite
feasable.

Regards,
Simon
-- 
View this message in context: http://www.nabble.com/Re%3A--Myfaces-Wiki--Update-of-%22Code-Generation%22-by-SimonKitching-tp15216313p15353739.html
Sent from the My Faces - Dev mailing list archive at Nabble.com.