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

Reply via email to