[ 
https://issues.apache.org/jira/browse/GEODE-9392?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17380896#comment-17380896
 ] 

Barrett Oglesby commented on GEODE-9392:
----------------------------------------

Code using ObjectMapper like above didn't address the issue.

Since LocalDateTime not supported by default in ObjectMapper, it throws this 
exception:
{noformat}
Caused by: java.lang.RuntimeException: Java 8 date/time type 
`java.time.LocalDateTime` not supported by default: add Module 
"com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling
        at 
org.apache.geode.pdx.internal.json.PdxToJSON.getJSON(PdxToJSON.java:67)
        at 
org.apache.geode.pdx.JSONFormatter.fromPdxInstance(JSONFormatter.java:239)
{noformat}
I added jackson-datatype-jsr310-2.12.3.jar to the server's classpath and used 
this code in the last else clause in PdxToJSON.writeValue:
{noformat}
ObjectMapper mapper = new ObjectMapper();
mapper.findAndRegisterModules();
jg.writeString(mapper.writeValueAsString(value));
{noformat}
And that worked:
{noformat}
Executing - query --query='select * from /data'

Result : true
Limit  : 100
Rows   : 1

productId  | partnerProductId | onlineRelevance
---------- | ---------------- | 
---------------------------------------------------------------------
1000051895 | 1000051895       | 
{"value":"value1","valueChangeDate":"[2021,7,14,16,18,29,784000000]"}
{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