Copy link to clipboard
Copied
Hi,
I've encountered this error when using
annotationManager.addAnnotations(annotations);
It is really difficult to debug because it works fine on a PDF, until you add a certain annotation and then it stops working. From my best guess It seems to happen when the quadPoints contain more than 20+ items.
I will paste my full source code below.
Please advise urgently.
Kind regards
<script>
var document_data = [{
"@context": [
"https://www.w3.org/ns/anno.jsonld",
"https://comments.acrobat.com/ns/anno.jsonld"
],
"id": "4ababa2a-2de5-8e18-b0h9-c85939ab8a4",
"type": "Annotation",
"motivation": "commenting",
"bodyValue": "hi",
"target": {
"source": "6d07d124-ac85-43b3-a867-36930f502ac6",
"selector": {
"node": {
"index": 0
},
"opacity": 0.4,
"subtype": "note",
"boundingBox": [
578,
825,
595,
842
],
"strokeColor": "#fccb00",
"type": "AdobeAnnoSelector"
}
},
"creator": {
"id": "LMF-2",
"name": "LMF-2",
"type": "Person"
},
"created": "2022-09-30T08:55:18Z",
"modified": "2022-09-30T08:55:18Z"
},{
"@context": [
"https://www.w3.org/ns/anno.jsonld",
"https://comments.acrobat.com/ns/anno.jsonld"
],
"id": "ebb99746-af83-8d67-55h1-9adbc9ac8a4",
"type": "Annotation",
"motivation": "commenting",
"bodyValue": "hi2",
"target": {
"source": "6d07d124-ac85-43b3-a867-36930f502ac6",
"selector": {
"node": {
"index": 0
},
"quadPoints": [
90,
684,
506,
684,
90,
671,
506,
671,
90,
671,
385,
671,
90,
657,
385,
657
],
"opacity": 0.4,
"subtype": "highlight",
"boundingBox": [
90,
684,
385,
657
],
"strokeColor": "#fccb00",
"type": "AdobeAnnoSelector"
}
},
"creator": {
"id": "LMF-2",
"name": "LMF-2",
"type": "Person"
},
"created": "2022-09-30T08:55:38Z",
"modified": "2022-09-30T08:55:38Z"
},{
"@context": [
"https://www.w3.org/ns/anno.jsonld",
"https://comments.acrobat.com/ns/anno.jsonld"
],
"id": "87b29110-8be8-813f-4bh3-c919ba82981",
"type": "Annotation",
"motivation": "commenting",
"bodyValue": "",
"target": {
"source": "6d07d124-ac85-43b3-a867-36930f502ac6",
"selector": {
"node": {
"index": 0
},
"quadPoints": [
309.9162011173185,
739.3463687150838,
505.44692737430177,
739.3463687150838,
309.9162011173185,
725.659217877095,
505.44692737430177,
725.659217877095,
89.9441340782123,
725.659217877095,
505.44692737430177,
725.659217877095,
89.9441340782123,
711.9720670391062,
505.44692737430177,
711.9720670391062,
89.9441340782123,
711.9720670391062,
306.9832402234637,
711.9720670391062,
89.9441340782123,
698.2849162011173,
306.9832402234637,
698.2849162011173
],
"opacity": 0.4,
"subtype": "highlight",
"boundingBox": [
309.9162011173185,
739.3463687150838,
306.9832402234637,
698.2849162011173
],
"strokeColor": "#fccb00",
"type": "AdobeAnnoSelector"
}
},
"creator": {
"id": "LMF-2",
"name": "LMF-2",
"type": "Person"
},
"created": "2022-09-30T09:04:59Z",
"modified": "2022-09-30T09:04:59Z"
},];
const annotations = document_data;
/*
Copyright 2020 Adobe
All Rights Reserved.
NOTICE: Adobe permits you to use, modify, and distribute this file in
accordance with the terms of the Adobe license agreement accompanying
it. If you have received this file from a source other than Adobe,
then your use, modification, or distribution of it requires the prior
written permission of Adobe.
*/
var viewerConfig = {
/* Enable commenting APIs */
enableAnnotationAPIs: true, /* Default value is false */
embedMode: "FULL_WINDOW",
};
/* Wait for Adobe Document Services PDF Embed API to be ready */
document.addEventListener("adobe_dc_view_sdk.ready", function () {
const eventOptions = {
listenOn: [
"ANNOTATION_ADDED", "ANNOTATION_CLICKED",
"ANNOTATION_UPDATED", "ANNOTATION_CLICKED",
"ANNOTATION_DELETED", "ANNOTATION_CLICKED",
]
}
const profile = {
userProfile: {
name: 'LMF-2',
}
};
/* Initialize the AdobeDC View object */
var adobeDCView = new AdobeDC.View({
/* Pass your registered client id */
clientId: "removed_for_security",
/* Pass the div id in which PDF should be rendered */
divId: "adobe-dc-view",
});
/* Invoke the file preview API on Adobe DC View object and return the Promise object */
var previewFilePromise = adobeDCView.previewFile({
/* Pass information on how to access the file */
content: {
/* Location of file where it is hosted */
location: {
url: "https://some.domain.com/public/s3_files/uploadsPy3quFjSCSQF8vNJ4tOSCDWxlJhCfh8QAP1Kr0OG.pdf",
/*
If the file URL requires some additional headers, then it can be passed as follows:-
header: [
{
key: "<HEADER_KEY>",
value: "<HEADER_VALUE>",
}
]
*/
},
},
/* Pass meta data of file */
metaData: {
/* file name */
fileName: "Py3quFjSCSQF8vNJ4tOSCDWxlJhCfh8QAP1Kr0OG.pdf",
/* file ID */
id: "6d07d124-ac85-43b3-a867-36930f502ac6"
}
}, viewerConfig);
adobeDCView.registerCallback(
AdobeDC.View.Enum.CallbackType.GET_USER_PROFILE_API,
function() {
return new Promise((resolve, reject) => {
resolve({
code: AdobeDC.View.Enum.ApiResponseCode.SUCCESS,
data: profile
});
});
},
{});
/* Use the annotation manager interface to invoke the commenting APIs*/
previewFilePromise.then(function (adobeViewer) {
adobeViewer.getAnnotationManager().then(function (annotationManager) {
annotationManager.registerEventListener(
function(event) {
var status = true;
for (let i = 0; i < annotations.length; i++) {
if(annotations[i].id == event.data.id){
status = false;
}
}
if(event.type == "ANNOTATION_DELETED" || event.type == "ANNOTATION_UPDATED"){
status = true;
}
// "ANNOTATION_UPDATED", "ANNOTATION_CLICKED",
if(status) {
console.log(event);
console.log('qawsed');
var workflow_id = $('.workflow_id').val();
var document_data = JSON.stringify(event.data, null, 2);
// var document_data = event.data;
$.ajax({
url : base_url+'/correspondence/pdf-comment-save',
type : "post",
data: {
'_token' : csrf_token,
'data' : document_data,
'type' : event.type,
'workflow_id' : workflow_id
},
success : function(data){
var response = $.parseJSON(data);
if(response.status == true) {
showMessage('success',response.message);
} else {
showMessage('error',response.message);
}
}
});
}
},
eventOptions
);
/* API to add annotations */
annotationManager.addAnnotations(annotations)
.then(function () {
console.log("Annotations added through API successfully")
})
.catch(function (error) {
console.log(error)
// console.log('1');
});
/* API to get all annotations */
annotationManager.getAnnotations()
.then(function (result) {
console.log("GET all annotations", result)
})
.catch(function (error) {
console.log(error)
// console.log('2');
});
/* API to delete annotations based on annotation ID filter */
var filter = {
annotationIds: ["3adeae16-a868-4653-960e-613c048dddc5", "079d66a4-5ec2-4703-ae9d-30ccbb1aa84c"]
};
annotationManager.deleteAnnotations(filter)
.then(function () {
console.log("Deleted annotations based on annotation ID filter.")
})
.catch(function (error) {
console.log(error)
// console.log('3');
});
/* API to delete annotations based on page range filter */
filter = {
pageRange: {
startPage: 4,
endPage: 6
}
};
annotationManager.deleteAnnotations(filter)
.then(function () {
console.log("Deleted annotations based on page range filter")
})
.catch(function (error) {
console.log(error)
// console.log('4');
});
/* API to get annotations after deletion */
annotationManager.getAnnotations()
.then(function (result) {
console.log("GET annotations result after deleting annotations", result)
})
.catch(function (error) {
console.log(error)
// console.log('5');
});
});
});
});
</script>
Copy link to clipboard
Copied
Ok, I appreciate providing more understanding. I'd also be curious to find out what the solution will be. Because if this gets fixed, then the next question is: If a user of my system makes an annotation which fails, and I cannot reproduce it, am I out of luck and have to delete or modify that annotation manually in a production database?
I can provide a document and the payload received from the Adobe Embed APIs, but in terms of UI interaction, how am i supposed to reproduce something that could happen infrequently every 1/1000-10k annotations.
We do nothing to modify the bounding box and or actual annotation data received from the Embed SDK at all.
Copy link to clipboard
Copied
If I remember right (and I apologize, I'm juggling a lot of different threads and other stuff, I'm not officially support here, just the developer relations person) - you said the 'bad' annotation was actually one _made_ by Embed, saved to your DB, and then when restored, failed. If you had _any_ clue as to how the bad annotation was made, and could reproduce that, it would give us a way to see. So for example, "User did X on the PDF, our stuff saved it to a db, and on restore, it failed." It's the "did X" part we need to figure out so we can reproduce it.
Is there _any_ chance something dumb is happening (err, I don't mean you being dumb, just a simple code mistake) when storing the JSON, and I'm thinking like a string truncation, or perhaps a floating point # dropping some significant digits?
Copy link to clipboard
Copied
Good question.. The user highlighted an entire page and a structured table on that entire page.. There could be some serialization happening between server and JS that I don't know about, but it pretty much goes straight into our database. When the document is loaded, we get comments from DB and send it back to Adobe via AddAnnotationsInPdf.
Out of 800 or so comments we've successfully inserted in the DB, this has only happened on two-3 of them.
Copy link to clipboard
Copied
Are you storing the annotations just as a big JSON string in the db?
Copy link to clipboard
Copied
Yes, with some separate columns. For example, target, creator, stylesheet, motivation
Copy link to clipboard
Copied
So in theory, if you have access to a PDF where this has happened, we could build a web app that:
* Lets you make annotations, and it dumps the JSON into a box or something.
* Click a button to 'reload' the PDF, sans annotations
* Click a button to load the annotations
And see if things break.
Copy link to clipboard
Copied
Let me try that, I pasted the json body of the target below, I can maybe reproduce it with a random button that inserts a specific annotation created from my audit data. Will get back to you soon. Meanwhile, logging a different issue
Copy link to clipboard
Copied
Boom, reproduced it from my audit data
Copy link to clipboard
Copied
Ok, so if you can email me the PDF, tell me how you made the 'bad' annotation, I can try make a web app here to reproduce it.
Copy link to clipboard
Copied
Can I send only one page?
Copy link to clipboard
Copied
Also, technically the annotation doesn't exist in my world until the JS ANNOTATION_ADDED event fires, then it basically sends the json to my server, i check permissions, and save.
So there was no annotation made by me really in that context
Copy link to clipboard
Copied
If one page is enough, sure. Your last post confuses me though. You _did_ make a new annotation, save it, restore it, and got the error, right?
Copy link to clipboard
Copied
I updated an existing annotation in my database target and bodyValue properties, the only ones that really matter when it comes to displaying the annotation (stylesheet not applicable to this one).. I loaded a document where I could see annotations, and then I reproduced the exception where all comments dissapeared when comment failed to load..
I already know the call to AddAnnotationsInPdf will reject this annotation, why would I try to make a new annotation using that method?
Additionally, why would I call CreateAnnotation if I'm not doing it anywhere in my code? Even if that fails, I get this data from the Annotation event callback, I don't create any annotation at all. Adobe creates it
Copy link to clipboard
Copied
I'm afraid I'm confused then. I thought the root of the issue was - it was possible to create an annotation in Embed that when loaded again and 'injected' via the API would throw an error. That's what I meant by a reproduceable case. "I do so and so annotation, save it, restore it later, and the previously valid annotation is now invalid."
Copy link to clipboard
Copied
Yes exactly, but the "previously valid annotation" never happens on my side.. it happens on Adobes side.. All I do is listen to the callbacks, and am a data messenger.
Copy link to clipboard
Copied
My job is to listen to callbacks, store it, and trust Adobe gives me a valid annotation. Thats a contract between the User and Adobe, not my system.. If I modified what Adobe was giving me back, sure, but I don't
Copy link to clipboard
Copied
But I want to be clear - when you say it happens on Adobe's side, it is a human making an annotation, and you are listening for the event so you know when to store the data, right?
Copy link to clipboard
Copied
Correct regarding the above..
Side note:
What's to stop someone from having access to a document, wanting to mess it up, and sending bad bounding boxes manually by messing with the JSON? They can actively ruin collaboration for every other participant and there is nothing the app service provider (me) can do about it
Copy link to clipboard
Copied
In the case of Adobe not accepting any annotations if there is one bad one
Copy link to clipboard
Copied
Ok, so now we're back to what I said. You have a PDF where you can make an annotation, that when your code picks it up, stores it, and restores it, it breaks things. So if you can email me that PDF (jedimaster@adobe.com), and describe the annotation ("I added a comment" or "I drew a line."), I can try to reproduce from that.
To your side note: I don't think there is anything that can be done there. There is, I believe, a schema for annotation data, you could verify that, but a person could modify stuff to send bad data. As you have pointed out, the API to add annotations rejects everything if bad data is sent, and I've filed an ER to change that (again, no promises it will be done).
p.s. It's end of day on my side so I'll be back to help tomorrow.