Hey team, I am testing my new entity type locally....
# troubleshoot
r
Hey team, I am testing my new entity type locally. I successfully write the entity record but failed to get the entity with error:
java.lang.UnsupportedOperationException: Failed to find Typeref schema associated with Config-based Entity
Here is the stack trace:
Copy code
Caused by: java.lang.UnsupportedOperationException: Failed to find Typeref schema associated with Config-based Entity
        at com.linkedin.metadata.models.ConfigEntitySpec.getAspectTyperefSchema(ConfigEntitySpec.java:78)
        at com.linkedin.metadata.entity.EntityService.toAspectUnion(EntityService.java:765)
        at com.linkedin.metadata.entity.EntityService.lambda$null$8(EntityService.java:632)
        at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
        at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1384)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
        at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:566)
        at com.linkedin.metadata.entity.EntityService.lambda$getLatestAspectUnions$9(EntityService.java:633)
        at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1321)
        at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
        at java.util.HashMap$EntrySpliterator.forEachRemaining(HashMap.java:1699)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
        at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:566)
        at com.linkedin.metadata.entity.EntityService.getLatestAspectUnions(EntityService.java:630)
        at com.linkedin.metadata.entity.EntityService.getSnapshotRecords(EntityService.java:619)
        at com.linkedin.metadata.entity.EntityService.getSnapshotUnions(EntityService.java:611)
        at com.linkedin.metadata.entity.EntityService.getEntities(EntityService.java:510)
        at com.linkedin.metadata.entity.EntityService.getEntity(EntityService.java:495)
        at com.linkedin.metadata.resources.entity.EntityResource.lambda$get$0(EntityResource.java:116)
        at com.linkedin.metadata.restli.RestliUtil.toTask(RestliUtil.java:30)
        ... 85 common frames omitted
Is the
Config-based Entity
not supported by Restli endpoint?
cc: @big-carpet-38439 (seems you are oncall 🙂 )
b
Oh interesting
Can you post the CURL you are making?
I've been testing this recently actually,... It just depends which read endpoint you are using (there are unfortunately a few)
r
Copy code
@Test
  public void test() throws Exception {
    DataDocUrn dataDocUrn = new DataDocUrn("querybook", "123456");
    MetadataChangeProposalWrapper wrapper = MetadataChangeProposalWrapper.builder()
        .entityType("dataDoc")
        .entityUrn(dataDocUrn.toString())
        .upsert()
        .aspect(new DataDocInfo()
            .setDataDocUrl(new Url("<https://querybook.com//datadoc/784>"))
            .setTitle("Test")
            .setDescription("test")
            .setLastModified(new ChangeAuditStamps()))
        .build();

    EventFormatter eventFormatter = new EventFormatter(EventFormatter.Format.PEGASUS_JSON);
    ObjectMapper objectMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
    JacksonDataTemplateCodec dataTemplateCodec = new JacksonDataTemplateCodec(objectMapper.getFactory());
    String eventString = dataTemplateCodec.mapToString(eventFormatter.convert(wrapper).data());
    RestEmitter emitter = RestEmitter.create(b -> b.server("<http://localhost:8080>"));
    MetadataWriteResponse writeResponse = emitter.emit(wrapper).get();
  }
I wrote a unit test to do this
I think the endpoint is `/aspects?action=ingestProposal`endpoint according to the url
<http://localhost:8080/aspects?action=ingestProposal>
The curl cmd to get the entity is
curl '<http://localhost:8080/entities/urn%3Ali%3AdataDoc%3A(querybook,123456)>'
b
Oh got it
So the part that will fail unfortunately is the entities CURL
We've recently moved to a "V2" of the entities endpoint which allows you to fetch for entities created by the Config Entity Registry. The legacy endpoint only supports deprecated snapshots 😕
Let me send the curl
r
ah,
Thanks for the upate
b
Copy code
curl '<http://localhost:8080/entitiesV2/><urn>'
Try that one and let's see what we get
r
curl '<http://localhost:8080/entitiesV2/urn%3Ali%3AdataDoc%3A(querybook,123456)>
this works
maybe we annotate the GET and BATCH_GET method as deprecated in
EntityResource.java
?
anyway, thanks for checking!!
b
amazing
Yeah we should definitely do that
We've already migrated our own internal callers to the v2, just need to publicly deprecate that one now
👍 1
r
Could you help review this curl cmd to see why the server complain could not parse the request?
Copy code
curl '<http://localhost:8080/aspects?action=ingestProposal>' -X POST --data '{
   "proposal":{
      "aspectName":"dataDocInfo",
      "entityUrn":"urn:li:dataDoc:(querybook,123456)",
      "entityType":"dataDoc",
      "changeType":"UPSERT",
      "aspect":{
         "contentType":"application/json",
         "value":"{
            \"description\":\"test\",
            \"lastModified\":{},
            \"title\":\"Test\",
            \"dataDocUrl\":\"<https://querybook.com/lasik/datadoc/784>\"
         }"
      }
   }
}'
h
I am not an expert, but you may want to double check lastModified's value. If its of type AuditStamp, you will need to populate the values for for time and actor fields like this
b
Correct^ this is likely due to missing a field
r
but the value string is generated from test code, like
Copy code
String eventString = dataTemplateCodec.mapToString(eventFormatter.convert(wrapper).data());
let me try to fill the
lastModified
plus1 1