-
1. Re: Scaffolding broken for aB123 field names
luca.masini Jul 28, 2012 11:25 AM (in response to anthonyhib)I think that forge is correct, property getters capitalize the first letter as in JavaBean specs.
Ciao
-
2. Re: Scaffolding broken for aB123 field names
koen.aers Jul 30, 2012 1:51 AM (in response to anthonyhib)Hey Anthony,
Like Luca, I also think that the Forge behaviour is the correct one. What exactly is the problem you see in the scaffolding when using thise names?
Cheers,
Koen
-
3. Re: Scaffolding broken for aB123 field names
anthonyhib Jul 30, 2012 3:58 AM (in response to koen.aers)Hi Koen and Lucas,
first, thanks for your answer.
I think the main point in the interpretation of the java bean naming convention.
Everybody is ok with the URL (3 upper case letters) pattern, however as soon as there are only 2 letters with one in upper case, problems appear.
We trusted eclipse getter/setter generation, and maybe that's our mistake but I guess many people are relying on it.
I created a new class
@Entity
public class AB123_MYCLASS
{
private Long iD123;
private Long ID456;
@Id
private Long id789;
private String aB123;
private String CD456;
private String ef789;
...
}
then generate getter and setter with eclipse, then run scaffolding.
Results: only ef789 cd456 are visibles.
1st issue, should forge also take care of get+ lowercase +something else pattern when scaffolding?
Generating the getter and setter with forge makes everything work (of course).
for eclipse, aB123 -> getaB123 setaB123
for forge, aB123 -> getAB123 setAB123
2nd issue, that could lead to a id interaction problem in the classes located inside the view package.
Basically how should one handle a field named aFIELD ? I really think it should be getaFIELD setaFIELD.
Cheers,
Anthony
-
4. Re: Scaffolding broken for aB123 field names
luca.masini Jul 30, 2012 9:13 AM (in response to anthonyhib)1 of 1 people found this helpfulAnthony I should never answer from my iPhone
To infer the correct getter name I runned this simple snippet of code that tries to infer the variable name from the getter:
System.out.println("variable name for getiD123() is " + Introspector.decapitalize("iD123"));
System.out.println("variable name for getID456() is " + Introspector.decapitalize("ID456"));
System.out.println("variable name for getId789() is " + Introspector.decapitalize("Id789"));
System.out.println("variable name for getaB123() is " + Introspector.decapitalize("aB123"));
System.out.println("variable name for getCD456() is " + Introspector.decapitalize("CD456"));
System.out.println("variable name for getEf789() is " + Introspector.decapitalize("ef789"));
and this is the output:
variable name for getiD123() is iD123
variable name for getID456() is ID456
variable name for getId789() is id789
variable name for getaB123() is aB123
variable name for getCD456() is CD456
variable name for getEf789() is ef789
So I think that you're right and that forge is missing the point.
Infact the static method that tries to do the inverse work seems to be broken:
public static String capitalize( String in ) {
return Character.toUpperCase( in.charAt( 0 ) ) + in.substring( 1 );
}
As you can see it doesn't take in account the JavaBean naming design pattern.
I think that this issue can be easily solved, to answer you question (if you want to fix it by yourself) the class is org.metawidget.util.simple.StringUtils, so I think you should add a private forge method that implements the inverse of Introspector.decapitalize.
Hope this answer your question.
Ciao.
L.
-
5. Re: Scaffolding broken for aB123 field names
anthonyhib Jul 30, 2012 12:02 PM (in response to luca.masini)Thanks Lucas,
it's weird that this issue is happening so often, I've seen it in various well known frameworks.
Thanks to you, I've located the places where I can **hack** my particular naming things.
However, I'm 99% my hack is not covering all the use cases described by the spec and I won't be stupid to propose this as a patch, that would waste your time.
In parallel, I've pinged Richard to warn him about the issue.
Thanks a lot to you and Koen, you saved me hours.
Anthony
-
6. Re: Scaffolding broken for aB123 field names
kennardconsulting Jul 31, 2012 2:34 AM (in response to anthonyhib)1 of 1 people found this helpfulHi Anthony,
Thanks for reaching out to me. I'd question whether 'getaFIELD' is actually correct JavaBean convention (see message to Luca below). However if you must support it I have good news and bad news.
The good news is Metawidget is pluggable in many different dimensions, and has quite extensive support for plugging in different 'property styles' (as we call them) to suit JavaBeans, GroovyBeans, Scala or your own property notation. Please see http://metawidget.org/doc/reference/en/html/ch04.html#section-inspectors-base-object-propertystyle-implementing-your-own
The bad news is the Metawidget/Forge integration is not mature with respect to letting you change Metawidget's configuration (https://issues.jboss.org/browse/FORGE-425). So you'll need to find a way to a) put your own PropertyStyle-implementation on the Forge classpath; b) update forge-scaffold-plugins/resources/.../metawidget.xml to use your new PropertyStyle. Possibly the easiest way to do this (for now) is simply unzip the forge-scaffold-faces module JAR and update the XML file.
You may also want to ping Ryan Bradley, who has been working on Forge/Spring/Metawidget integration, to see if he has any ideas.
Regards,
Richard.
-
7. Re: Scaffolding broken for aB123 field names
kennardconsulting Jul 31, 2012 3:17 AM (in response to luca.masini)Hi Luca,
I don't think you can assume that 'capitalize' needs to be the inverse of 'decapitalize'. If you look at the JavaBean spec it says...
PropertyDescriptor: "Note that the property name should start with a lower case character, which will be capitalized in the method names"
...and in the java.beans.PropertyDescriptor code it does...
public PropertyDescriptor(String propertyName, Class<?> beanClass)
throws IntrospectionException {
this(propertyName, beanClass, "is" + capitalize(propertyName), "set" + capitalize(propertyName));
}
...
readMethodName = "get" + getBaseName();
...
String getBaseName() { return capitalize(getName()); }
...
public static String capitalize(String name) {
return name.substring(0, 1).toUpperCase(ENGLISH) + name.substring(1);
}
...there is no discussion about 'if the second letter is capitalized then...' (like there is for decapitalize). The only algorithm/implementation I can find is simply 'uppercase the first letter'. Is there some other algorithm for 'capitalize' that I should be using?
Your proposed convention ('getiD123') would seem to have undesirable consequences. For example...
public class CourtCase {
public String getName() {...}
public void settle( BigDecimal settlementAmount ) {...}
public boolean isolate() {...}
}
...would find 'action' methods (settle, isolate) to be JavaBean properties 'tle' and 'olate'?
Regards,
Richard.
-
8. Re: Scaffolding broken for aB123 field names
anthonyhib Jul 31, 2012 2:44 AM (in response to kennardconsulting)Thanks Richard,
I mainly hacked (not only) isGetter/Setter of ForgePropertyStyle
/*if (!StringUtils.isCapitalized(propertyName)) { return null; }*/ return ForgeStringUtils.decapitalize(propertyName); }
public class ForgeStringUtils { public static String decapitalize(String name) { if (name == null || name.length() == 0) { return name; } if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) && Character.isUpperCase(name.charAt(0))){ return name; } char chars[] = name.toCharArray(); chars[0] = Character.toLowerCase(chars[0]); return new String(chars); } public static String capitalize( String in ) { if (in.length() > 1 && Character.isUpperCase(in.charAt(1)) && Character.isLowerCase(in.charAt(0))) return in; return Character.toUpperCase( in.charAt( 0 ) ) + in.substring( 1 ); } }
Since I'm in a hurry I did it to handle our naming convention, it is certainly not robust enough.
-
9. Re: Scaffolding broken for aB123 field names
kennardconsulting Jul 31, 2012 3:12 AM (in response to anthonyhib)Luca,
Though I think it may be a bug, it appears Introspector.getBeanInfo really does return 'tle' and 'solate' as I describe above. Conversely, if you do new PropertyStyle( "aFIELD" ) it goes looking for a method called "setAFIELD". So I'm not sure what to think. It appears to disagree with itself!
Probably the safest thing to do (given this is a fringe case) is to behave the same as Introspector. So I've now updated Metawidget.
Anthony,
Could you please try Forge using Metawidget 2.4-SNAPSHOT (https://repository.jboss.org/nexus/content/repositories/snapshots/org/metawidget/modules/metawidget-all/2.4-SNAPSHOT/), and confirm it works without needing your custom ForgePropertyStyle?
Thanks everybody for bringing this to my attention.
-
10. Re: Scaffolding broken for aB123 field names
luca.masini Jul 31, 2012 3:50 AM (in response to kennardconsulting)I think that JavaBeans specs about naming convention are an abstract concept, like love or philosophy.
I looked up the method decapitalize that is into the Introspector and the algorithm is different and goes in the way I read in "Design Pattern" about naming convention in that old spec (I think 8.3 is the one we are interested in):
public static String decapitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) && Character.isUpperCase(name.charAt(0))){
return name;
}
char chars[] = name.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
As you pointed, this is different from what we can read into the PropertyDescriptor class and is similar to what I see IDE do (Eclipse and Idea).
The fact is that I think capitalize(decapitalize(name)) should be equals to name and capitalizing the first letter this is not always true.
I think you final solution should do the work.
Thank you.
L.
-
11. Re: Scaffolding broken for aB123 field names
anthonyhib Aug 2, 2012 8:06 AM (in response to kennardconsulting)Hi Richard,
I
1- extracted the forge sources
2- modified scaffold pom to use the latest metawidget snapshot
However I'm not sure how I need to update the 4 metawidget xml config files located in the scaffold-faces modules in order to totally ignore the custom forgePropertyStyle. I've tried the following
<?xml version="1.0"?> <metawidget xmlns="http://metawidget.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:processor="java:org.metawidget.statically.faces.component.widgetprocessor" xsi:schemaLocation="http://metawidget.org http://metawidget.org/xsd/metawidget-1.0.xsd java:org.metawidget.statically.faces.component.html http://metawidget.org/xsd/org.metawidget.statically.faces.component.html-1.0.xsd java:org.metawidget.inspector.composite http://metawidget.org/xsd/org.metawidget.inspector.composite-1.0.xsd" version="1.0"> <!-- metawidget-search.xml is used to generate the search fields --> <staticHtmlMetawidget xmlns="java:org.metawidget.statically.faces.component.html"> <inspector> <compositeInspector xmlns="java:org.metawidget.inspector.composite" config="CompositeInspectorConfig"> <inspectors> <array> <propertyTypeInspector xmlns="java:org.metawidget.inspector.propertytype" config="org.metawidget.inspector.impl.BaseObjectInspectorConfig"> <propertyStyle> <forgePropertyStyle id="forgePropertyStyle" xmlns="java:org.jboss.forge.scaffold.faces.metawidget.inspector.propertystyle" config="ForgePropertyStyleConfig"> <project> <forgeProject/> </project> </forgePropertyStyle> </propertyStyle> </propertyTypeInspector> <forgeInspector xmlns="java:org.jboss.forge.scaffold.faces.metawidget.inspector" config="org.metawidget.inspector.impl.BaseObjectInspectorConfig"> <!--propertyStyle> <forgePropertyStyle refId="forgePropertyStyle"/> </propertyStyle--> </forgeInspector> <jpaInspector xmlns="java:org.metawidget.inspector.jpa" config="JpaInspectorConfig"> <!--propertyStyle> <forgePropertyStyle refId="forgePropertyStyle"/> </propertyStyle--> </jpaInspector> <beanValidationInspector xmlns="java:org.metawidget.inspector.beanvalidation" config="org.metawidget.inspector.impl.BaseObjectInspectorConfig"> <!--propertyStyle> <forgePropertyStyle refId="forgePropertyStyle"/> </propertyStyle--> </beanValidationInspector> </array> </inspectors> </compositeInspector> </inspector> <inspectionResultProcessors> <array> <notRequiredInspectionResultProcessor xmlns="java:org.jboss.forge.scaffold.faces.metawidget.inspectionresultprocessor"/> </array> </inspectionResultProcessors> <widgetBuilder> <compositeWidgetBuilder xmlns="java:org.metawidget.widgetbuilder.composite" config="CompositeWidgetBuilderConfig"> <widgetBuilders> <array> <entityWidgetBuilder xmlns="java:org.jboss.forge.scaffold.faces.metawidget.widgetbuilder" config="EntityWidgetBuilderConfig"> <config> <forgeConfig/> </config> </entityWidgetBuilder> <htmlWidgetBuilder xmlns="java:org.metawidget.statically.faces.component.html.widgetbuilder"/> </array> </widgetBuilders> </compositeWidgetBuilder> </widgetBuilder> <widgetProcessors> <array> <standardBindingProcessor xmlns="java:org.metawidget.statically.faces.component.widgetprocessor"/> <readableIdProcessor xmlns="java:org.metawidget.statically.faces.component.widgetprocessor"/> <standardConverterProcessor xmlns="java:org.metawidget.statically.faces.component.widgetprocessor"/> <cssStyleProcessor xmlns="java:org.metawidget.statically.faces.component.html.widgetprocessor"/> <unsearchableWidgetProcessor xmlns="java:org.jboss.forge.scaffold.faces.metawidget.widgetprocessor"/> </array> </widgetProcessors> <layout> <htmlPanelGridLayout xmlns="java:org.metawidget.statically.faces.component.html.layout" config="HtmlPanelGridLayoutConfig"> <columnStyleClasses> <array> <string>label</string> <string>component</string> <string>required</string> </array> </columnStyleClasses> <messageStyleClass> <string>error</string> </messageStyleClass> </htmlPanelGridLayout> </layout> </staticHtmlMetawidget> </metawidget>
without success, forge is still generating wrong getter/setter.
Second test by leaving the getter/setter generation to eclipse, then scaffolding -> the aFIELD named field isn't caught.
Let me know if my metawidget config is silly.
Thanks
Anthony
-
12. Re: Scaffolding broken for aB123 field names
kennardconsulting Aug 2, 2012 6:49 PM (in response to anthonyhib)You shouldn't need to touch the 4 metawidget.xml config files at all. Just updating the Metawidget JARs to 2.4-SNAPSHOT should be sufficient?
Please try reverting everything back to the original Forge distribution and try again?
-
13. Re: Scaffolding broken for aB123 field names
anthonyhib Aug 3, 2012 2:46 AM (in response to kennardconsulting)Hi Richard,
First there is still a bug in ForgePropertyStyle which excludes any accessor not having an upper case character after get/set -> so I left my fix there.
Next, I removed my custom
ForgeStringUtils
to go back to metawidget.With your update:
- Use case 1: getter/setter generated with eclipse -> scaffold is now generated however the view bean is still point to wrong field naming.
String bSTRING = this.search.getBSTRING(); if (bSTRING != null && !"".equals(bSTRING)) { predicatesList.add(builder.like(root.<String> get("bSTRING"), '%' + bSTRING + '%')); }
should be
String bSTRING = this.search.getbSTRING(); if (bSTRING != null && !"".equals(bSTRING)) { predicatesList.add(builder.like(root.<String> get("bSTRING"), '%' + bSTRING + '%')); }
this is certainly a pure forge issue.
- Use case 2: getter/setter generated with forge -> works but naming used by forget is not correct
Thanks a lot Richard.
Message was edited by: Anthony Patricio
-
14. Re: Scaffolding broken for aB123 field names
anthonyhib Aug 3, 2012 3:03 AM (in response to anthonyhib)same for the ID binding
still in the view bean, the update method is wrong
else
{
this.entityManager.merge(this.aENTITY);
return "view?faces-redirect=true&id=" + this.aENTITY.getAID();
}
should be
else
{
this.entityManager.merge(this.aENTITY);
return "view?faces-redirect=true&id=" + this.aENTITY.getaID();
}