I'm trying to use your wonderful Metawidget, but I've some problem and doubt. I hope you could and want to help me.
I would like to use MW with java beans created by JAXB and display them with Icefaces.
I've these problems:
* In the generated JAXB classes (for example in the attached LdmDetailsMsg) booleans type are converted in Boolean member variables, but instead of having getXXX methods to access to their value they have isXXX methods . So when I try to display them I get this Exception: javax.el.PropertyNotFoundException: Property 'boleanObj' not readable on type java.lang.Boolean
How can I bind the member variables to the isXXX methods ?
* In the LdmMsg I have a member variable which is a List of LdmDetailsMsg. In order to display it I'm developing a CollectionsWidgetBuilder that extends IceFacesWidgetBuilder. I would like to create a widget that display each LdmDetailsMsg contained in the list into a panelTabSet (something like Airport Destination in the attached LDM_example.jpg), but I would like that the widget inside the panelTab is generated through MW (inspecting the LdmDetailsMsg). How can accomplish this? How can I "link" the parent panelTabSet widget whith each LdmDetailsMsg tab? How can I recall the widget creation for the LdmDetailsMsg in the list within my CollectionsWidgetBuilder and put them into my panelTabSet .Have you any suggestion?
I hope Ii've been clear enought ( I don't think so because of my english! :-) ) and you could help me!!
Thanks a lot,
Simone
@XmlRootElement(name = "LdmMsg", namespace = "http://www.iata.org/txm/sitamsgtypes")
public class LdmMsg {
@XmlElement(name = "Ldm_Details")
protected List<LdmDetailsMsg> ldmDetails;
@XmlAttribute(name = "Status", required = true)
protected String status;
@XmlAttribute(name = "Callsign", required = true)
protected String callsign;
@XmlAttribute(name = "Date_Departure")
protected String dateDeparture;
@XmlAttribute(name = "Aircraft_Registration", required = true)
protected String aircraftRegistration;
@XmlAttribute(name = "Aircraft_Version", required = true)
protected String aircraftVersion;
@XmlAttribute(name = "Conf_Crew")
protected String confCrew;
@XmlAttribute(name = "Flight_Type")
protected String flightType;
@XmlAttribute(name = "Ldm_Status")
protected String ldmStatus;
@XmlAttribute(name = "Received_Date")
protected String receivedDate;
/**
* Gets the value of the ldmDetails property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the ldmDetails property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getLdmDetails().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link LdmDetailsMsg }
*
*
*/
public List<LdmDetailsMsg> getLdmDetails() {
if (ldmDetails == null) {
ldmDetails = new ArrayList<LdmDetailsMsg>();
}
return this.ldmDetails;
}
[...]
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "LdmDetailsMsg", namespace = "http://www.iata.org/txm/sitamsgtypes")
public class LdmDetailsMsg {
@XmlAttribute(name = "Dest_Airport", required = true)
protected String destAirport;
@XmlAttribute(name = "Nil")
protected Boolean nil;
@XmlAttribute(name = "Passengers_Number", required = true)
protected String passengersNumber;
@XmlAttribute(name = "Cabin_Baggage")
protected String cabinBaggage;
@XmlAttribute(name = "Total_Deadload")
protected String totalDeadload;
@XmlAttribute(name = "Total_Weight_Load")
protected String totalWeightLoad;
@XmlAttribute(name = "Compartment_Load", required = true)
protected String compartmentLoad;
@XmlAttribute(name = "Pax")
protected String pax;
@XmlAttribute(name = "Pad")
protected String pad;
@XmlAttribute(name = "Remark")
protected String remark;
/**
* Gets the value of the destAirport property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getDestAirport() {
return destAirport;
}
/**
* Sets the value of the destAirport property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setDestAirport(String value) {
this.destAirport = value;
}
/**
* Gets the value of the nil property.
*
* @return
* possible object is
* {@link Boolean }
*
*/
public Boolean isNil() {
return nil;
}
/**
* Sets the value of the nil property.
*
* @param value
* allowed object is
* {@link Boolean }
*
*/
public void setNil(Boolean value) {
this.nil = value;
}
[img]http://img528.imageshack.us/img528/5674/ldmexample.jpg[/img]
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
If it's okay with you, I'd like to answer your questions one at a time, in case we end up with multiple conversations in the same thread, which gets very confusing! So:
1. The error you are getting (javax.el.ProperyNotFoundException) appears to be coming from JSF (javax.el) not Metawidget? This is possibly because Boolean (big 'B') getters are meant to be 'get', not 'is'. Only boolean (little 'b') getters are meant to be 'is'. Can you please confirm this? Can you try a simple…
<h:inputText value="#{myLdmDetailsMsg.nil}"/>
…without Metawidget, and see if that works?
Then we can look at your second question.
Regards,
Richard.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
you are right! The error is due to JAXB that creates isXXX access methods instead of the getXXX for Boolean object.
Now I have to find the way to manage this, but this is a problem between me and JAXB! :-)
Thanks again!
PS: I'm trying your code for the secodn question!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I've resolved the first problem and now JAXB correctly create getter Methods for Boolean object ( I needed to upgrade to JAXB version 2.2 and use the -enableIntrospection flag).
I've also added an xmlAnnotationInspector to extract XmlAttribute information from JAXB java beans ( I needed also to implement an XmlJavaBeanPropertyStyle to inspect protected members variables).
Now I'm facing another problem: if I set the COMPONENT_ATTRIBUTE_NOT_RECREATABLE attribute to panelTabSet, when I switch to another bean from the combo I get an exception :
javax.servlet.ServletException: java.io.IOException: javax.el.PropertyNotFoundException: Property 'ldmDetails' not found on type it.trs.atc.ahs.gcm.sita.decoder.BTMMsg
com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:158)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
com.icesoft.faces.webapp.xmlhttp.BlockingServlet.service(BlockingServlet.java:56)
If I've understood right, it is because the panelTabSet is not destroyed and so it try to set the ldmDetails property also for the new selected BTMMsg bean. Right?
On the other hand, if I don't set the attibute COMPONENT_ATTRIBUTE_NOT_RECREATABLE I cannot switch between tabs (as you said to me) because the panelTabSet lost its state.
Have you any suggestion ?!?
Thanks a lot again !
Simone
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I've not yet implemented your last improvement (I've not much time for now), but I'm able to add and remove tabs on the fly using java reflection for the creation of a new object of the list in the onAdd method, getting its type from the PARAMETERIZED_TYPE attribute.
This is the code of my IceFacesTabsWidgetBuilder:
publicclassIceFacesTabsWidgetBuilderimplementsWidgetBuilder<UIComponent,UIMetawidget>{privatestaticLoglogger=LogFactory.getLog(IceFacesTabsWidgetBuilder.class);//// Public methods//@OverridepublicUIComponentbuildWidget(StringelementName,Map<String,String>attributes,UIMetawidgetmetawidget){// Not for us?Stringtype=attributes.get(TYPE);if(type==null){returnnull;}Class<?>clazz=ClassUtils.niceForName(type);if(!List.class.isAssignableFrom(clazz)){returnnull;}finalUIMetawidgetfinalWidget=metawidget;finalStringparamType=attributes.get(PARAMETERIZED_TYPE);logger.debug("\n\n\n**************THIS IS A LIST!****************************************");logger.debug("elementName \t= "+elementName);logger.debug("metawidget \t= "+metawidget);logger.debug("attributes \t= "+attributes);Set<String>keys=attributes.keySet();for(Stringitem:keys){logger.debug(" key="+item+" \t\t--- value="+attributes.get(item));}logger.debug("");// Create a Stub to wrap around the PanelTabSet.//// This is because://// 1. PanelTabSet will not switch tabs if it is destroyed/recreated. We must set// COMPONENT_ATTRIBUTE_NOT_RECREATABLE on it (see// http://metawidget.sourceforge.net/doc/reference/en/html/ch02s04.html#section-architecture-widgetbuilders-implementing-your-own-faces).// This limits some dynamicism, such as being able to dynamically add tabs, but there are// further ways around that//// 2. COMPONENT_ATTRIBUTE_NOT_RECREATABLE only works if there is a 'value' expression that// OverriddenWidgetBuilder can match against//// 3. PanelTabSet is a little unusual in how it treats its 'value' expression (binding it to// a UI mechanism, rather than a model mechanism) so we need to avoid using it. We use the// Stub's 'value' expression instead//UIStubstub=newUIStub();FacesContextcontext=FacesContext.getCurrentInstance();finalELContextelContext=context.getELContext();finalExpressionFactoryexpressionFactory=context.getApplication().getExpressionFactory();// retrieve the variable binded to the metawidget in the .jspx file// (in this case "#{iataSentDetails.objSelected}" in iataSentDetails.jspx)ValueExpressionmetawidgetValueExpression=metawidget.getValueExpression("value");StringmetawidgetValueExpressionString=FacesUtils.unwrapExpression(metawidgetValueExpression.getExpressionString());logger.debug("metawidgetValueExpression="+metawidgetValueExpression);logger.debug("metawidgetValueExpressionString="+metawidgetValueExpressionString);// this is the List<?>variable(inthiscase#{iataSentDetails.objSelected.ldmDetails})// for which we have to create the PanelTabSet metawidget to returnfinalStringitemsListValueExpressionString=metawidgetValueExpressionString+StringUtils.SEPARATOR_DOT_CHAR+attributes.get(NAME);finalValueExpressionitemsListValueExpression=expressionFactory.createValueExpression(elContext,FacesUtils.wrapExpression(itemsListValueExpressionString),Object.class); logger.debug("itemsListValueExpression=" + itemsListValueExpression );logger.debug("itemsListValueExpressionString="+itemsListValueExpressionString);// bind the value to the stubstub.setValueExpression("value",itemsListValueExpression);// Create tab setfinalPanelTabSetpanelTabSet=newPanelTabSet();// panelTabSet.setPartialSubmit(partialSubmit );panelTabSet.getAttributes().put(UIMetawidget.COMPONENT_ATTRIBUTE_NOT_RECREATABLE,true);finalList<UIComponent>tabsContainer=panelTabSet.getChildren();// Lookup the List from the parent Metawidget to see how many items it has// questa e' proprio la lista che abbiamo associato prima (ad es.// iataSentDetails.objSelected.ldmDetails )finalListitemsList=(List)itemsListValueExpression.getValue(elContext);createTabs(itemsList,tabsContainer,itemsListValueExpressionString,finalWidget);// Add a button to create a new item of the listHtmlCommandButtonaddButton=newHtmlCommandButton();addButton.setValue("Add");addButton.addActionListener(newActionListener(){@OverridepublicvoidprocessAction(ActionEventevent)throwsAbortProcessingException{logger.debug("ADD ACTION ="+event);onAdd(itemsList,paramType,tabsContainer,itemsListValueExpressionString,finalWidget);}});addButton.getAttributes().put(UIMetawidget.COMPONENT_ATTRIBUTE_NOT_RECREATABLE,true);addButton.setImmediate(true);// Add a button to remove the selected item of the listHtmlCommandButtondelButton=newHtmlCommandButton();delButton.setValue("Del");delButton.addActionListener(newActionListener(){@OverridepublicvoidprocessAction(ActionEventevent)throwsAbortProcessingException{logger.debug("DEL ACTION="+event);onDel(itemsList,panelTabSet,tabsContainer,itemsListValueExpressionString,finalWidget);}});delButton.getAttributes().put(UIMetawidget.COMPONENT_ATTRIBUTE_NOT_RECREATABLE,true);delButton.setImmediate(true);stub.getChildren().add(addButton);stub.getChildren().add(delButton);stub.getChildren().add(panelTabSet);// Return tab setlogger.debug("component ="+stub);logger.debug("**************END LIST TAB CREATION !****************************************\n\n\n");returnstub;}/** * @param list * @param tabs * @param tabSetValueExpressionString * @param finalWidget */privatevoidcreateTabs(ListitemsList,List<UIComponent>tabsContainer,StringitemsListValueExpressionString,UIMetawidgetfinalWidget){// clear the tabs metawidget and recreate them (in order to avoid index problem on deletion)tabsContainer.clear();// Create one tab per item...for(inti=0,length=itemsList.size();i<length;i++){PanelTabpanelTab=createNewPanelTab(i,itemsListValueExpressionString,finalWidget);tabsContainer.add(panelTab);}}/** * Add a new metawidget for the item list * @param index index of the item in the list * @param itemsListValueExpressionString * @param finalWidget */privatePanelTabcreateNewPanelTab(intindex,StringitemsListValueExpressionString,UIMetawidgetfinalWidget){FacesContextcontext=FacesContext.getCurrentInstance();finalELContextelContext=context.getELContext();finalExpressionFactoryexpressionFactory=context.getApplication().getExpressionFactory();PanelTabpanelTab=newPanelTab();panelTab.setTitle("Airport "+(index+1));panelTab.setLabel("Airport "+(index+1));// ...with each tab itself containing a Metawidget.//// The 'value' expression of each Metawidget uses the EL #{foo.bar[0]} notation for// accessing arraysHtmlMetawidgettabMetawidget=newHtmlMetawidget();// binding of the actual indexed item of the listfinalValueExpressionactualItemListValueExpression=expressionFactory.createValueExpression(elContext,FacesUtils.wrapExpression(itemsListValueExpressionString+'['+index+']'),Object.class);logger.debug("actualItemListValueExpression="+actualItemListValueExpression);logger.debug("actualItemListValueExpressionString="+actualItemListValueExpression.getExpressionString());// associo l'i-esimo item al value della tabtabMetawidget.setValueExpression("value",actualItemListValueExpression);tabMetawidget.setValueExpression("readOnly",finalWidget.getValueExpression("readOnly"));panelTab.getChildren().add(tabMetawidget);returnpanelTab;}/** * @param itemsList * @param paramType * @param tabsContainer * @param itemsListValueExpressionString * @param finalWidget * @throws AbortProcessingException */privatevoidonAdd(ListitemsList,StringparamType,List<UIComponent>tabsContainer,StringitemsListValueExpressionString,UIMetawidgetfinalWidget)throwsAbortProcessingException{try{logger.debug("initial list size="+itemsList.size());logger.debug("paramType="+paramType);Classc=Class.forName(paramType);Constructorconstructor=c.getConstructor();ObjectnewItem=constructor.newInstance();itemsList.add(newItem);intindex=itemsList.indexOf(newItem);logger.debug("Item added "+newItem);logger.debug("list size="+itemsList.size());// add the new itemPanelTabpanelTab=createNewPanelTab(index,itemsListValueExpressionString,finalWidget);tabsContainer.add(panelTab);}catch(Exceptione){logger.error(e.getMessage(),e);thrownewAbortProcessingException(e.getMessage(),e);}}/** * * @param itemsList * @param panelTabSet * @param tabsContainer * @param itemsListValueExpressionString * @param finalWidget * @throws AbortProcessingException */privatevoidonDel(ListitemsList,PanelTabSetpanelTabSet,List<UIComponent>tabsContainer,StringitemsListValueExpressionString,UIMetawidgetfinalWidget)throwsAbortProcessingException{try{FacesContextcontext=FacesContext.getCurrentInstance();finalELContextelContext=context.getELContext();logger.debug("initial list size="+itemsList.size());intselectedTab=panelTabSet.getSelectedIndex();logger.debug("selectedPanelTab="+selectedTab);UIComponentremovedPanelTab=tabsContainer.remove(selectedTab);logger.debug("removedPanelTab ="+removedPanelTab);UIComponenttabMetawidget=removedPanelTab.getChildren().get(0);logger.debug("removedTabMetawidget ="+tabMetawidget);ValueExpressiontabValueExpression=tabMetawidget.getValueExpression("value");logger.debug("tabValueExpression="+tabValueExpression);ObjectremovedObject=tabValueExpression.getValue(elContext);logger.debug("removedObject="+removedObject);itemsList.remove(removedObject);logger.debug("final list size="+itemsList.size());//recreate tabs of the updated list.createTabs(itemsList,tabsContainer,itemsListValueExpressionString,finalWidget);if(selectedTab>0){panelTabSet.setSelectedIndex(selectedTab-1);}}catch(Exceptione){logger.error(e.getMessage(),e);thrownewAbortProcessingException(e.getMessage(),e);}}}
In order to retrieve the information of the XmlAttribute annotation I've implemented an XmlAnnotationInspector, an XmlAnnotationConfig and an XmlJavaBeanPropertyStyle that can read them from protected members:
publicclassXmlAnnotationInspectorextendsBaseObjectInspector{privatestaticLoglogger=LogFactory.getLog(XmlAnnotationInspector.class);/** * */publicXmlAnnotationInspector(){this(newXmlAnnotationConfig());}publicXmlAnnotationInspector(BaseObjectInspectorConfigconfig){super(config);}@OverrideprotectedMap<String,String>inspectProperty(Propertyproperty)throwsException{Map<String,String>attributes=CollectionUtils.newHashMap();XmlAttributexmlAttrib=property.getAnnotation(XmlAttribute.class);if(xmlAttrib!=null&&xmlAttrib.required()){attributes.put(REQUIRED,TRUE);}returnattributes;}}publicclassXmlAnnotationConfigextendsBaseObjectInspectorConfig{/** * */publicXmlAnnotationConfig(){//set the specific property stylesetPropertyStyle(newXmlJavaBeanPropertyStyle());}}publicclassXmlJavaBeanPropertyStyleextendsJavaBeanPropertyStyle{@OverrideprotectedMap<String,Property>inspectProperties(Class<?>clazz){// TreeMap so that returns alphabetically sorted propertiesMap<String,Property>properties=CollectionUtils.newTreeMap();// Lookup fields, getters and setterslookupFields(properties,clazz);returnproperties;}/** * Lookup all field-based properties. * <p> * This method will be called before <code>lookupGetters</code> and <code>lookupSetters</code>. */@OverrideprotectedvoidlookupFields(Map<String,Property>properties,Class<?>clazz){// Note: we must use clazz.getFields(), not clazz.getDeclaredFields(), in order// to avoid Applet SecurityExceptionsfor(Fieldfield:clazz.getDeclaredFields()){// Exclude static fieldsintmodifiers=field.getModifiers();if(Modifier.isStatic(modifiers)||Modifier.isPrivate(modifiers)){continue;}// Get name and typeStringfieldName=field.getName();Class<?>type=field.getType();// Exclude based on other criteriaif(isExcluded(field.getDeclaringClass(),fieldName,type)){continue;}properties.put(fieldName,newFieldProperty(fieldName,field));}}}
I hope this could be useful !!!
Thanks again for your help,
Simone
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Metawidget v1.05 now released, including the new support for annotating private fields. I'd be most grateful if you could download it and confirm it works for you (removes the need for your XmlJavaBeanPropertyStyle).
Regards,
Richard.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello,
I'm trying to use your wonderful Metawidget, but I've some problem and doubt. I hope you could and want to help me.
I would like to use MW with java beans created by JAXB and display them with Icefaces.
I've these problems:
* In the generated JAXB classes (for example in the attached LdmDetailsMsg) booleans type are converted in Boolean member variables, but instead of having getXXX methods to access to their value they have isXXX methods . So when I try to display them I get this Exception: javax.el.PropertyNotFoundException: Property 'boleanObj' not readable on type java.lang.Boolean
How can I bind the member variables to the isXXX methods ?
* In the LdmMsg I have a member variable which is a List of LdmDetailsMsg. In order to display it I'm developing a CollectionsWidgetBuilder that extends IceFacesWidgetBuilder. I would like to create a widget that display each LdmDetailsMsg contained in the list into a panelTabSet (something like Airport Destination in the attached LDM_example.jpg), but I would like that the widget inside the panelTab is generated through MW (inspecting the LdmDetailsMsg). How can accomplish this? How can I "link" the parent panelTabSet widget whith each LdmDetailsMsg tab? How can I recall the widget creation for the LdmDetailsMsg in the list within my CollectionsWidgetBuilder and put them into my panelTabSet .Have you any suggestion?
I hope Ii've been clear enought ( I don't think so because of my english! :-) ) and you could help me!!
Thanks a lot,
Simone
Simone,
Thank you for your interest in Metawidget.
If it's okay with you, I'd like to answer your questions one at a time, in case we end up with multiple conversations in the same thread, which gets very confusing! So:
1. The error you are getting (javax.el.ProperyNotFoundException) appears to be coming from JSF (javax.el) not Metawidget? This is possibly because Boolean (big 'B') getters are meant to be 'get', not 'is'. Only boolean (little 'b') getters are meant to be 'is'. Can you please confirm this? Can you try a simple…
…without Metawidget, and see if that works?
Then we can look at your second question.
Regards,
Richard.
Simone,
I have blogged a response to your second question here: http://kennardconsulting.blogspot.com/2010/11/metawidget-collections-support-part-2.html
Hope that helps,
Richard.
Hi Richard,
Thanks a lot!
I'll try it as soon as possible and I'll let you know the results !!
Simone
Richard,
you are right! The error is due to JAXB that creates isXXX access methods instead of the getXXX for Boolean object.
Now I have to find the way to manage this, but this is a problem between me and JAXB! :-)
Thanks again!
PS: I'm trying your code for the secodn question!
Hi Richard,
I'm doing progress!
http://img713.imageshack.us/img713/6469/ldmexample2.jpg
http://img16.imageshack.us/img16/2295/ldmexample3.jpg
I've resolved the first problem and now JAXB correctly create getter Methods for Boolean object ( I needed to upgrade to JAXB version 2.2 and use the -enableIntrospection flag).
I've also added an xmlAnnotationInspector to extract XmlAttribute information from JAXB java beans ( I needed also to implement an XmlJavaBeanPropertyStyle to inspect protected members variables).
Now I'm facing another problem: if I set the COMPONENT_ATTRIBUTE_NOT_RECREATABLE attribute to panelTabSet, when I switch to another bean from the combo I get an exception :
If I've understood right, it is because the panelTabSet is not destroyed and so it try to set the ldmDetails property also for the new selected BTMMsg bean. Right?
On the other hand, if I don't set the attibute COMPONENT_ATTRIBUTE_NOT_RECREATABLE I cannot switch between tabs (as you said to me) because the panelTabSet lost its state.
Have you any suggestion ?!?
Thanks a lot again !
Simone
Simone,
I have tried to answer your question here: http://kennardconsulting.blogspot.com/2010/11/metawidget-collections-support-part-2_24.html
Hope that helps,
Richard.
Simone,
Just to let you know I have come up with an improved solution (no COMPONENT_ATTRIBUTE_NOT_RECREATABLE, no binding attribute):
http://kennardconsulting.blogspot.com/2010/11/metawidget-collections-support-part-2_25.html
Hope that helps,
Richard.
Hi Richard,
this is the result I 've obtained http://img522.imageshack.us/img522/6750/ldmexample4.jpg.
I've not yet implemented your last improvement (I've not much time for now), but I'm able to add and remove tabs on the fly using java reflection for the creation of a new object of the list in the onAdd method, getting its type from the PARAMETERIZED_TYPE attribute.
This is the code of my IceFacesTabsWidgetBuilder:
In order to retrieve the information of the XmlAttribute annotation I've implemented an XmlAnnotationInspector, an XmlAnnotationConfig and an XmlJavaBeanPropertyStyle that can read them from protected members:
I hope this could be useful !!!
Thanks again for your help,
Simone
Simone,
Very interesting! Thanks for posting your work.
I have added a feature to Metawidget v1.05…
http://kennardconsulting.blogspot.com/2010/10/javabean-convention-relating-public.html
…that may remove the need for your custom XmlJavaBeanPropertyStyle. Can you see if it would meet your needs?
Regards,
Richard.
Simone,
Metawidget v1.05 now released, including the new support for annotating private fields. I'd be most grateful if you could download it and confirm it works for you (removes the need for your XmlJavaBeanPropertyStyle).
Regards,
Richard.