Imported ejb entity into tapestry project looks like this its in "generated sorces (jax-ws)"
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.datatype.XMLGregorianCalendar;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "money", propOrder = {
"moneyAmount",
"moneyCurrency",
"moneyDate",
"moneyFinishDate",
"moneyIO",
"moneyId",
"moneyName",
"moneyNextDate",
"moneyNumber",
"moneyPurpose",
"moneyRenewal",
"moneyTs"
})
public class Money {
protected Double moneyAmount;
protected String moneyCurrency;
@XmlSchemaType(name = "dateTime")
protected XMLGregorianCalendar moneyDate;
@XmlSchemaType(name = "dateTime")
protected XMLGregorianCalendar moneyFinishDate;
protected MoneyIO moneyIO;
protected Integer moneyId;
protected String moneyName;
@XmlSchemaType(name = "dateTime")
protected XMLGregorianCalendar moneyNextDate;
protected Integer moneyNumber;
protected String moneyPurpose;
protected MoneyNextTimeType moneyRenewal;
@XmlSchemaType(name = "dateTime")
protected XMLGregorianCalendar moneyTs;
// Getters and Setters for above
...
}
all XMLGregorianCalendar is Date in ejb module
In tapestry page class:
@ejb
statefullEjbMoney
@Persist
@Property
List<Money> mylist
void onPrepareForRender() {
mylist=statefullEjbMoney.findAll();
}
In my template I have:
<table t:type="grid" t:source="mylist"
t:rowsPerPage="10" t:pagerPosition="both"
t:exclude="moneyId,moneyIO,moneyNextDate,moneyFinishDate,cliClientId"
t:reorder="moneyName,moneyPurpose,moneyAmount,moneyCurrency,moneyDate">
[Grid here]
</table>
The stacktrace in the glassfish log is:
Render queue error in SetupRender[Expenses:grid.columns]: Bean editor model for logic.ws.Money does not contain a property named 'moneyDate'.
org.apache.tapestry5.ioc.internal.util.TapestryException: Bean editor model for logic.ws.Money does not contain a property named 'moneyDate'. [at classpath:org/apache/tapestry5/corelib/components/Grid.tml, line 6]
...
Caused by: org.apache.tapestry5.ioc.util.UnknownValueException: Bean editor model for logic.ws.Money does not contain a property named 'moneyDate'.
at org.apache.tapestry5.internal.beaneditor.BeanModelImpl.get(BeanModelImpl.java:160)
at org.apache.tapestry5.internal.beaneditor.BeanModelImpl.reorder(BeanModelImpl.java:223)
at org.apache.tapestry5.internal.beaneditor.BeanModelUtils.reorder(BeanModelUtils.java:107)
at org.apache.tapestry5.internal.beaneditor.BeanModelUtils.modify(BeanModelUtils.java:51)
at org.apache.tapestry5.corelib.components.Grid.getDataModel(Grid.java:523)
at org.apache.tapestry5.corelib.components.GridColumns.setupRender(GridColumns.java:112)
at org.apache.tapestry5.corelib.components.GridColumns.setupRender(GridColumns.java)
at org.apache.tapestry5.internal.structure.ComponentPageElementImpl$SetupRenderPhase.invokeComponent(ComponentPageElementImpl.java:179)
at org.apache.tapestry5.internal.structure.ComponentPageElementImpl$AbstractPhase.invoke(ComponentPageElementImpl.java:138)
... 84 more
If anyone has an idea what is wrong please share?
The exception says the Bean Editor Model doesn't have a property called moneyDate
, which I've always thought was a bit unclear.
To explain, Tapestry doesn't know what an XMLGregorianCalendar
is, so when Tapestry creates the Bean Model for your grid, it helpfully ignores it.
The quick way to solve this is to provide getters on your Money
entity that return standard JDK Calendar
s, and display these properties in your grid.
So in your entity:
public class Money {
@XmlSchemaType(name = "dateTime")
protected XMLGregorianCalendar moneyDate;
public Calendar getMoneyDataCalendar() {
return moneyDate.toGregorianCalendar();
}
...
}
Then use it in your grid:
<table t:type="grid" t:source="mylist" t:rowsPerPage="10" t:pagerPosition="both"
t:exclude="moneyId,moneyIO,moneyNextDate,moneyFinishDate,cliClientId"
t:reorder="moneyName,moneyPurpose,moneyAmount,moneyCurrency,moneyDateCalendar">
[Grid here] Note 'moneyDate' changed to 'moneyDateCalendar' above [/Grid here]
</table>
If you plan to display lots of XMLGregorianCalendar
s then the (more involved) solution is to tell Tapestry about XMLGregorianCalendars and how to display them.
First tell Tapestry to add XMLGregorianCalendar
to the Bean Model by adding this to your Module class:
@Contribute(DefaultDataTypeAnalyzer.class)
public static void contributeDefaultDataTypeAnalyzer(MappedConfiguration<Class<?>, String> config) {
config.add(XMLGregorianCalendar.class, "xmlGregorianCalendar");
}
Now tell Tapestry how to display the new "xmlGregorianCalendar"
. Add to your Module class:
@Contribute(BeanBlockSource.class)
public static void contributeDisplayBlocksForGrid(Configuration<BeanBlockContribution> config) {
config.add(new DisplayBlockContribution("xmlGregorianCalendar", "DisplayBlocks", "xmlGregorianCalendar"));
}
You now have to create a page called DisplayBlocks
with a component with an id xmlGregorianCalendar
:
public class DisplayBlocks {
@Inject
private Locale locale;
@Property
@Environmental
private PropertyOutputContext context;
private final DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
public DateFormat getDateFormat(){
return dateFormat;
}
public Date getCalendarDate() {
XMLGregorianCalendar calendar = (XMLGregorianCalendar) context.getPropertyValue();
if (calendar == null)
return null;
return calendar.getTime();
}
}
<t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
<t:block id="xmlGregorianCalendar">
<t:output value="calendarDate" format="dateFormat"/>
</t:block>
</t:container>
For more info look at the Tapestry source code and see how Tapestry configures itself. In particular look at:
org.apache.tapestry5.services.TapestryModule.contributeDefaultDataTypeAnalyzer()
org.apache.tapestry5.services.TapestryModule.provideDefaultBeanBlocks()
org.apache.tapestry5.corelib.pages.PropertyDisplayBlocks