[QFJ-962] FieldMap.setField(int key, Field<?> field) does not properly convert values Created: 15/Nov/18 Updated: 15/Jun/20 |
|
| Status: | Open |
| Project: | QuickFIX/J |
| Component/s: | Engine |
| Affects Version/s: | 2.1.0 |
| Fix Version/s: | 3.0.0 |
| Type: | Bug | Priority: | Default |
| Reporter: | amichair | Assignee: | Wojciech Zankowski |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Issue Links: |
|
||||||||
| Description |
|
However, this is misleading and introduces a bug, since the two are not equivalent. Specifically, the type-specific overloads do proper type conversions on the value, while the generic setField does not. For example, if you pass a DoubleField with a very large or small value, it will convert it into a string in scientific notation (with exponent) which is invalid in the FIX protocol, whereas calling the type-specific setField(DoubleField field) will properly use the DoubleConverter to convert it correctly. When this method was non-public this was less of a problem, assuming its internal usages are correct (I don't know if this is the case, but assume it is). However making it public now creates a pitfall for anyone using this method in client code which will likely result in a bug on some data. The solution would be to either implement it fully with proper type conversion (e.g. using the switch statement from |
| Comments |
| Comment by Christoph John [ 16/Nov/18 ] |
|
Hi amichair, maybe we should add the javadoc comment as you suggested and provide an additional method, say setFieldConverted(int key, Field<?> field) , so users can choose which method suits them best. Cheers, |
| Comment by Christoph John [ 16/Nov/18 ] |
|
Briefly had a look at this. What about making Field abstract (According to a comment in the class it is only non-abstract to have JNI compatibility. But that was like 10 years ago.) and adding an abstract convertToString() method that does the necessary conversion in the subclasses? Example for BooleanField:
@Override
public String convertToString() {
return BooleanConverter.convert(getValue());
}
Then we can call in FieldMap:
public void setField(int key, Field<?> field) {
setString(key, field.convertToString());
}
That way we can ensure that we always have a conversion method for a field and don't need a lengthy if-else statement. What do you think? |
| Comment by amichair [ 22/Nov/18 ] |
|
Encapsulating the converters inside the Field classes sounds like a good idea regardless of this issue or of Field being abstract I have't delved into this one yet, but perhaps instead of convertToString, maybe toString itself should just do this properly? |
| Comment by Wojciech Zankowski [ 29/Jul/19 ] |
|
Pull request created with implementation of the idea: https://github.com/quickfix-j/quickfixj/pull/226 |