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

Daniel Cave edited comment on NIFI-1935 at 6/10/16 7:00 PM:
------------------------------------------------------------

I had to revisit the issues to remind myself of the cases/issues involved.  
Previously I had issues with it not properly reading from the attribute due to 
the way that attributes are interpreted when they are JSON (i.e. as a JSON 
string value with the element being the attribute name), however this may have 
been fixed.  I retested it as of today based on 0.x, and ConvertJSONToAvro says 
it cannot find schema if you try to read it from an attribute (likely due to 
the same reason AttributesToJson fails to properly convert it, since it cant 
read avro.brinary and requires it to be a true string).  Also, 
ConvertJSONToAvro doesn't register the data provenance, which is a bug and 
needs a ticket and fix for.

However, the case for this processor is interrelated with use cases for 
InferAvroSchema (which also required the changes to SplitJSON).  If I write the 
schema out as an attribute and the only use of that schema is to convert the 
json to avro, then you are correct that the existing processor is sufficient.  
However, writing the schema to an attribute presents other issues and limits 
its usefulness.  My use cases for the schema also involve using the same schema 
to generate SQL/CQL/Hive/etc statements for ingestion as well as sending the 
avro to a schema registry and programatically creating RDDs.  To do all this I 
need the schema as content in its proper JSON form.  In theory, 
AttributesToJSON would do this, however it isn't language aware and will create 
JSON with { <attributeName> : <attributeValue>  }  where the attributeName is 
schema and the attributeValue would be the avro schema as a JSON string (there 
is a similar issue in using InvokeHTTP with the response as an attribute), 
however due to the way the schema exists in the attribute it actually returns 
an empty string (since the attribute is actually in avro.binary form).  The 
processor seems to have been meant for simple attributes and not complex ones 
as putting an avro schema in one creates where the attribute contents itself is 
avro or JSON.  EvaluateJsonPath is also an option, however again once you 
extract the avro schema from attribute you'll find that it's not in a proper 
format and isn't valid JSON or a valid schema anymore.

Basically, there are four options to fix the issue:  Do Infer twice (once to 
content and once to attribute, not desirable due to overhead ramifications on 
small devices with sub-second throughput and involves fixing the schema 
attribute issue), upgrade ConvertJSONToAvro to handle schemas from either 
content or attribute, make major changes to AttributeToJson or create a new 
complex version of it, or to split Convert into Convert and ConvertDynamic 
where one can accept the schema from a flowfile content (which has other use 
cases as well).  I chose the latter as it created the least amount of backwards 
compatibility issues.  That is not to say it is necessarily the best choice of 
the four in all cases, it was the lesser of evils for the community in my view 
for now.  If you guys disagree or I've missed a better way to extract the 
schema then I'm certainly open to discussion and revisiting my design for 
dynamically handling everything from source to sink (any sink).  Keep in mind, 
some of the sink processors require everything in flowfile content 
(PutCassandra), some hybrid (ExecuteSQL), and some all in attributes 
(PutHiveQL).  So since those design inconsistent processors are already in 
public use, I have to be able to interpret the avro schema and create 
statements for any of the three in order to be able to handle the JSON and sink 
or transfer it into any source which means I need to be able to do varying 
kinds of parsing to it depending on the sink.

Let me know what you think.  Also, keep in mind in building this response to 
you I found three new bugs in at least three processors that need new tickets:  
evaluateAttributeExpressions() doesnt seem to be able to handle avro.binary 
(affects anything evaluating an attribute I assume, and may apply to normal 
blobs too), ConvertJsonToAvro isn't writing any data provenance on failure, 
InferAvroSchema writing JSON to attribute doesn't write in the right form.


was (Author: daniel cave):
I had to revisit the issues to remind myself of the cases/issues involved.  
Previously I had issues with it not properly reading from the attribute due to 
the way that attributes are interpreted when they are JSON (i.e. as a JSON 
string value with the element being the attribute name), however this may have 
been fixed.  I retested it as of today based on 0.x, and ConvertJSONToAvro says 
it cannot find schema if you try to read it from an attribute (likely due to 
the same reason AttributesToJson fails to properly convert it, since it cant 
read avro.brinary and requires it to be a true string).  Also, 
ConvertJSONToAvro doesn't register the data provenance, which is a bug and 
needs a ticket and fix for.

However, the case for this processor is interrelated with use cases for 
InferAvroSchema (which also required the changes to SplitJSON).  If I write the 
schema out as an attribute and the only use of that schema is to convert the 
json to avro, then you are correct that the existing processor is sufficient.  
However, writing the schema to an attribute presents other issues and limits 
its usefulness.  My use cases for the schema also involve using the same schema 
to generate SQL/CQL/Hive/etc statements for ingestion as well as sending the 
avro to a schema registry and programatically creating RDDs.  To do all this I 
need the schema as content in its proper JSON form.  In theory, 
AttributesToJSON would do this, however it isn't language aware and will create 
JSON with { <attributeName> : <attributeValue>  }  where the attributeName is 
schema and the attributeValue would be the avro schema as a JSON string (there 
is a similar issue in using InvokeHTTP with the response as an attribute), 
however due to the way the schema exists in the attribute it actually returns 
an empty string (since the attribute is actually in avro.binary form).  The 
processor seems to have been meant for simple attributes and not complex ones 
as putting an avro schema in one creates where the attribute contents itself is 
avro or JSON.  EvaluateJsonPath is also an option, however again once you 
extract the avro schema from attribute you'll find that it's not in a proper 
format and isn't valid JSON or a valid schema anymore.

Basically, there are four options to fix the issue:  Do Infer twice (once to 
content and once to attribute, not desirable due to overhead ramifications on 
small devices with sub-second throughput and involves fixing the schema 
attribute issue), upgrade ConvertJSONToAvro to handle schemas from either 
content or attribute, make major changes to AttributeToJson or create a new 
complex version of it, or to split Convert into Convert and ConvertDynamic 
where one can accept the schema from a flowfile content (which has other use 
cases as well).  I chose the latter as it created the least amount of backwards 
compatibility issues.  That is not to say it is necessarily the best choice of 
the four in all cases, it was the lesser of evils for the community in my view 
for now.  If you guys disagree or I've missed a better way to extract the 
schema then I'm certainly open to discussion and revisiting my design for 
dynamically handling everything from source to sink (any sink).  Keep in mind, 
some of the sink processors require everything in flowfile content 
(PutCassandra), some hybrid (ExecuteSQL), and some all in attributes 
(PutHiveQL).  So since those design inconsistent processors are already in 
public use, I have to be able to interpret the avro schema and create 
statements for any of the three in order to be able to handle the JSON and sink 
or transfer it into any source which means I need to be able to do varying 
kinds of parsing to it depending on the sink.

Let me know what you think.  Also, keep in mind in building this response to 
you I found three new bugs in at least three processors that need new tickets:  
evaluateAttributeExpressions() doesnt seem to be able to handle avro.binary 
(affects anything evaluating an attribute I assume, and may apply to normal 
blobs too), ConvertJsonToAvro is writing data provenance on failure, 
InferAvroSchema writing JSON to attribute doesn't write in the right form.

> Added ConvertDynamicJsonToAvro processor
> ----------------------------------------
>
>                 Key: NIFI-1935
>                 URL: https://issues.apache.org/jira/browse/NIFI-1935
>             Project: Apache NiFi
>          Issue Type: New Feature
>          Components: Extensions
>    Affects Versions: 1.0.0, 0.7.0
>            Reporter: Daniel Cave
>            Assignee: Alex Halldin
>            Priority: Minor
>             Fix For: 1.0.0, 0.7.0
>
>         Attachments: 
> 0001-NIFI-1935-Added-ConvertDynamicJSONToAvro.java.-Added.patch
>
>
> ConvertJsonToAvro required a predefined Avro schema to convert JSON and 
> required the presence of all field on the incoming JSON.  
> ConvertDynamicJsonToAvro functions similarly, however it now accepts the JSON 
> and schema as incoming flowfiles and creates the Avro dynamically.
> This processor requires the InferAvroSchema processor in its upstream flow so 
> that it can use the original and schema flowfiles as input.  These two 
> flowfiles will have the unique attribute inferredAvroId set on them by 
> InferAvroSchema so that they can be properly matched in 
> ConvertDynamicJsonToAvro.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to