[
https://issues.apache.org/jira/browse/GEODE-9392?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17380890#comment-17380890
]
Barrett Oglesby commented on GEODE-9392:
----------------------------------------
A {{select *}} query fails in the same way if a field of the value is a
PdxInstance and that PdxInstance contains an unsupported data type.
For example, if the region contains Product objects and a Product contains a
Relevance object which contains a java LocalDataTime.
LocalDateTime is not supported by PdxToJSON, so the query fails with a similar
stack to the above struct one:
{noformat}
[info 2021/07/14 15:53:00.349 PDT server1 <Function Execution Processor2>
tid=0x3f] Exception occurred:
org.apache.geode.pdx.JSONFormatterException: Could not create JSON document
from PdxInstance
at
org.apache.geode.pdx.JSONFormatter.fromPdxInstance(JSONFormatter.java:241)
at org.apache.geode.pdx.JSONFormatter.toJSON(JSONFormatter.java:226)
at
org.apache.geode.management.internal.cli.domain.DataCommandResult$SelectResultRow.valueToJson(DataCommandResult.java:731)
at
org.apache.geode.management.internal.cli.domain.DataCommandResult$SelectResultRow.resolvePdxToColumns(DataCommandResult.java:711)
at
org.apache.geode.management.internal.cli.domain.DataCommandResult$SelectResultRow.resolveObjectToColumns(DataCommandResult.java:688)
at
org.apache.geode.management.internal.cli.domain.DataCommandResult$SelectResultRow.createColumnValues(DataCommandResult.java:680)
at
org.apache.geode.management.internal.cli.domain.DataCommandResult$SelectResultRow.<init>(DataCommandResult.java:663)
at
org.apache.geode.management.internal.cli.functions.DataCommandFunction.createSelectResultRow(DataCommandFunction.java:270)
at
org.apache.geode.management.internal.cli.functions.DataCommandFunction.select_SelectResults(DataCommandFunction.java:256)
at
org.apache.geode.management.internal.cli.functions.DataCommandFunction.select(DataCommandFunction.java:224)
at
org.apache.geode.management.internal.cli.functions.DataCommandFunction.select(DataCommandFunction.java:177)
at
org.apache.geode.management.internal.cli.functions.DataCommandFunction.execute(DataCommandFunction.java:126)
Caused by: java.lang.IllegalStateException: The pdx field valueChangeDate has a
value 2021-07-14T15:52:54.970 whose type class java.time.LocalDateTime can not
be converted to JSON.
at
org.apache.geode.pdx.internal.json.PdxToJSON.writeValue(PdxToJSON.java:148)
at
org.apache.geode.pdx.internal.json.PdxToJSON.getJSONString(PdxToJSON.java:178)
at
org.apache.geode.pdx.internal.json.PdxToJSON.getJSON(PdxToJSON.java:60)
{noformat}
> A gfsh query returning a Struct containing a PdxInstance behaves differently
> than one returning just the PdxInstance in some cases
> ----------------------------------------------------------------------------------------------------------------------------------
>
> Key: GEODE-9392
> URL: https://issues.apache.org/jira/browse/GEODE-9392
> Project: Geode
> Issue Type: Bug
> Components: gfsh
> Reporter: Barrett Oglesby
> Priority: Major
>
> This is true when the PdxInstance contains a data type that is not supported
> by PdxToJSON (like Date or Character).
> If objects like this are stored as PdxInstances:
> {noformat}
> public class Position {
> private String id;
> private Date tradeDate;
> private Character type;
> ...
> }
> {noformat}
> A query like this is successful:
> {noformat}
> Executing - query --query='select * from /positions'
> Result : true
> Limit : 100
> Rows : 10
> tradeDate | id | type
> ------------- | -- | ----
> 1624316618413 | 3 | "a"
> 1624316618324 | 0 | "a"
> 1624316618418 | 5 | "a"
> 1624316618421 | 6 | "a"
> 1624316618407 | 1 | "a"
> 1624316618426 | 8 | "a"
> 1624316618428 | 9 | "a"
> 1624316618415 | 4 | "a"
> 1624316618423 | 7 | "a"
> 1624316618410 | 2 | "a"
> {noformat}
> But a query like this is not:
> {noformat}
> Executing - query --query="select key,value from /positions.entries where
> value.id = '0'"
> Result : false
> Message : Could not create JSON document from PdxInstance
> {noformat}
> It fails with this exception in the server:
> {noformat}
> org.apache.geode.pdx.JSONFormatterException: Could not create JSON document
> from PdxInstance
> at
> org.apache.geode.pdx.JSONFormatter.fromPdxInstance(JSONFormatter.java:241)
> at org.apache.geode.pdx.JSONFormatter.toJSON(JSONFormatter.java:226)
> at
> org.apache.geode.management.internal.cli.domain.DataCommandResult$SelectResultRow.valueToJson(DataCommandResult.java:732)
> at
> org.apache.geode.management.internal.cli.domain.DataCommandResult$SelectResultRow.resolveStructToColumns(DataCommandResult.java:717)
> at
> org.apache.geode.management.internal.cli.domain.DataCommandResult$SelectResultRow.resolveObjectToColumns(DataCommandResult.java:692)
> at
> org.apache.geode.management.internal.cli.domain.DataCommandResult$SelectResultRow.createColumnValues(DataCommandResult.java:680)
> at
> org.apache.geode.management.internal.cli.domain.DataCommandResult$SelectResultRow.<init>(DataCommandResult.java:663)
> at
> org.apache.geode.management.internal.cli.functions.DataCommandFunction.createSelectResultRow(DataCommandFunction.java:270)
> at
> org.apache.geode.management.internal.cli.functions.DataCommandFunction.select_SelectResults(DataCommandFunction.java:256)
> at
> org.apache.geode.management.internal.cli.functions.DataCommandFunction.select(DataCommandFunction.java:224)
> at
> org.apache.geode.management.internal.cli.functions.DataCommandFunction.select(DataCommandFunction.java:177)
> at
> org.apache.geode.management.internal.cli.functions.DataCommandFunction.execute(DataCommandFunction.java:126)
> Caused by: java.lang.IllegalStateException: PdxInstance returns unknwon
> pdxfield tradeDate for type Mon Jun 21 16:03:38 PDT 2021
> at
> org.apache.geode.pdx.internal.json.PdxToJSON.writeValue(PdxToJSON.java:148)
> at
> org.apache.geode.pdx.internal.json.PdxToJSON.getJSONString(PdxToJSON.java:185)
> at
> org.apache.geode.pdx.internal.json.PdxToJSON.getJSON(PdxToJSON.java:61)
> at
> org.apache.geode.pdx.JSONFormatter.fromPdxInstance(JSONFormatter.java:239)
> {noformat}
> Its because of the difference in processing a PdxInstance (first query) and a
> Struct (second query) in resolveObjectToColumns:
> {noformat}
> private void resolveObjectToColumns(Map<String, String> columnData, Object
> value) {
> if (value instanceof PdxInstance) {
> resolvePdxToColumns(columnData, (PdxInstance) value);
> } else if (value instanceof Struct) {
> resolveStructToColumns(columnData, (StructImpl) value);
> }
> ...
> }
> {noformat}
> They both end up in SelectResultRow.valueToJson:
> {noformat}
> private String valueToJson(Object value) {
> ...
> if (value instanceof String) {
> return (String) value;
> }
> if (value instanceof PdxInstance) {
> return JSONFormatter.toJSON((PdxInstance) value);
> }
> ObjectMapper mapper = new ObjectMapper();
> try {
> return mapper.writeValueAsString(value);
> } catch (JsonProcessingException jex) {
> return jex.getMessage();
> }
> }
> {noformat}
> In the PdxInstance case, the fields are passed in individually and handled by
> the first condition (String) and the ObjectMapper (Date, Character):
> {noformat}
> SelectResultRow.resolveObjectToColumns value=PDX[13681235,Position]{id=3,
> tradeDate=Mon Jun 21 16:03:38 PDT 2021, type=a}; valueClass=class
> org.apache.geode.pdx.internal.PdxInstanceImpl
> SelectResultRow.valueToJson value=Mon Jun 21 16:03:38 PDT 2021;
> valueClass=class java.util.Date
> SelectResultRow.valueToJson value=3; valueClass=class java.lang.String
> SelectResultRow.valueToJson value=a; valueClass=class java.lang.Character
> {noformat}
> In the Struct case, the value passed in is a Pdxinstance which is handled by
> the JSONFormatter:
> {noformat}
> SelectResultRow.resolveObjectToColumns
> value=struct(key:0,value:PDX[13681235,Position]{id=0, tradeDate=Mon Jun 21
> 16:03:38 PDT 2021, type=a}); valueClass=class
> org.apache.geode.cache.query.internal.StructImpl
> SelectResultRow.valueToJson value=0; valueClass=class java.lang.String
> SelectResultRow.valueToJson value=PDX[13681235,Position]{id=0, tradeDate=Mon
> Jun 21 16:03:38 PDT 2021, type=a}; valueClass=class
> org.apache.geode.pdx.internal.PdxInstanceImpl
> {noformat}
> JSONFormatter delegates to PdxToJSON which doesn't understand Characters or
> Dates and throws the IllegalStateException.
> If I change the last else clause in PdxToJSON.writeValue so that it uses
> ObjectMapper like SelectResultRow.valueToJson does like:
> {noformat}
> } else {
> ObjectMapper mapper = new ObjectMapper();
> try {
> jg.writeString(mapper.writeValueAsString(value));
> } catch (JsonProcessingException jex) {
> jg.writeString(jex.getMessage());
> }
> }
> {noformat}
> The query is successful:
> {noformat}
> Executing - query --query="select key,value from /positions.entries where
> value.id = '0'"
> Result : true
> Limit : 100
> Rows : 1
> key | value
> --- | -----------------------------------------------------
> 0 | {"tradeDate":"1624317757557","id":"0","type":"\"a\""}
> {noformat}
> I'm not sure if this is a valid fix, but it will handle a lot more cases than
> PdxToJSON.writeValue does now.
--
This message was sent by Atlassian Jira
(v8.3.4#803005)