[ 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)