I’m writing some client-side code, and I’d like to use BigDecimal. I know initially BigDecimal wasn’t supported by GWT’s compiler, but it has been supported since GWT 2.1. I know there were some projects (e.g. GWT-math) for BigDecimal support in older versions of GWT, but I was expecting it to work out of the box with recent vaadin?
To reproduce:
Creat a new addon project in eclipse (using maven vaadin-archetype-widget v7.4.4)
add a BigDecimal field to the State
Compile
Output:
<snip>
[INFO]
Compiling module com.curocomp.vaadinaddon.test.demo.DemoWidgetSet
[INFO]
Computing all possible rebind results for 'com.vaadin.client.metadata.ConnectorBundleLoader'
[INFO]
Rebinding com.vaadin.client.metadata.ConnectorBundleLoader
[INFO]
Invoking generator com.vaadin.server.widgetsetutils.ConnectorBundleLoaderFactory
[INFO]
Populating eager bundle
[INFO]
Visiting UnsafeHtmlRendererConnector with ConnectorInitVisitor
[INFO]
UnsafeHtmlRendererConnector will be in the eager bundle
[INFO]
Will serialize class com.vaadin.shared.communication.SharedState as a b
<snip>
[INFO]
Populating ColorPickerGridConnector bundle
[INFO]
Visiting ColorPickerGridConnector with ConnectorInitVisitor
[INFO]
ColorPickerGridConnector will be in the ColorPickerGridConnector bundle
[INFO]
Will serialize class com.vaadin.shared.ui.colorpicker.ColorPickerGridState as a bean
[INFO]
[ERROR]
java.math.BigDecimal has the property 'scale' without getter defined.
My state object:
public class TestState extends com.vaadin.shared.AbstractComponentState {
public BigDecimal decimalData = BigDecimal.ONE;
}
I’d really appreciate any suggestions to what I might be doing wrong!
I’ve just tried something equivalent using a pure GWT project (from gwt-maven-plugin archetype) that returns a BigDecimal froma n RPC call, and the pure GWT project works fine.
Is this caused by how Vaadin uses/configures the GWT compiler? The vaadin jars do contain com.google.gwt.user.client.rpc.core.java.math.BigDecimal_CustomFieldSerializer etc. so I’m still thinking this
should work as expected with Vaadin?
Is there a way for me to work around this? Perhaps giving the Vaadin state/rpc serialisation config or a hint to use the BigDecimal_CustomFieldSerializer ?
Or does this require a patch / fix to vaadin itself?
The clientside serializer is registered and invoked on the clientside. However the server-side serializer doesn’t get registered, so is ignored. For passing a BigDecimal from server to client, this will confusingly be enough - but it doesn’t allow the server to construct a BigDecimal returned from the client.
Unfortunately it seems that just registering a server-side JSONSerializer will not be sufficient, as the customSerializers are only used if the default actions fail - including casting to a Number.
What are the chances of a feature to fix this in the next release? I’m happy raise a ticket / submit a patch if it’s likely to be accepted?
I cannot find a way to register the JSONSerializer on server- and client-side. Where must both objects have to be registered? I found the class JsonCodec, but most of the “interesting” parts are private.
As you noted, all the interesting parts are private, so I coudln’t find a nice way to provide custom serializers to the server side. I (for a rather nasty experiment) was able to use my server-side serializers by using Reflection to add them to the static JsonCode.customSerializers map from VaadinServlet.servletInitialized().
In my case, providing a custom serializer for BigDecimal wasn’t sufficient, because the customSerializers are only considered after the default serialization policies. For BigDecimal, this would therefore always be serialized by castning to Number, and taking the Double value. (see JsonCodec.java:649 / 650)
Overall, this was very unsatisfactory. The “least bad” solution I came up with (and the approach I took in the end) is to not use BigDecimal (or other “problematic” types) in my state/RPC interfaces. My BigDecimal_Serializer implementations above (and the equivelents in the GWT source) use a string representation to serialise BigDecimal, so I have taken to simply using the String representation on my state objects. I still use BigDecimal on server-side and in the client-side widget, converting to/from strings in the server-side component and in the client-side connector.
Quite a disapointing solution, but at least one I can rationalise…
Thanks a lot for your help… So you can confirm that the GWT-serialization mechanisms like adding _CustomFieldSerializer implementations are not considered during Vaadin compilation? Is this right? Unfortunately, that would be a very disappointing but useful piece of information.
I’m a user, so only know what I’ve discovered digging around the code.
But as far as I can see, they’re not considered for vaadin’s state serialization. I didn’t actually dig into whether the same applies for the RPC interfaces.
If you end up discovering more, I would be very interested to hear!