NotesMIMEEntity is null when opening document using sessionAsSigner - xpages

On a XPage I'm using the following code to load some text from a document's MIME entity:
var dcl:NotesDocumentCollection=database.getView("myView").getAllDocumentsByKey("key",true);
var doc:NotesDocument=dcl.getFirstDocument();
var entity:NotesMIMEEntity=doc.getMIMEEntity("data");
var text=entity.getContentAsText();
This works without errors. When replacing database with sessionAsSigner.getCurrentDatabase() an error is raised, stating that the MIME entity is null (testing environment = Server: Notes 8.5.3 | Client: Firefox 15). Here is some additional information I got from manually debugging the code:
sessionAsSigner is a valid NotesSession object
doc is a valid NotesDocument that is readable for me, i.e. using the
getItemValue methods works without error
doc.hasItem("data") is true, i.e. the MIME entity field exists
However, using doc.getMIMEEntity("data") returns null even though it's not empty. The problem even occurs for documents without authors and readers fields. Why does using sessionAsSigner allow to open the document and get item values, but not allow to read the MIME entity?

To solve the issue, call
sessionAsSigner.setConvertMime(false);
before using the sessionAsSigner object. This prevents MIME items from being converted to rich text when opening a document. Otherwise NotesDocument.getMIMEEntity returns null.

Related

How to fix ClassCastException when using localized n-m relations with Smartedit?

In Hybris 6.7.0, using I have a component that contains a localized list of another component.
I have been able to implement this using a n-m localized relationtype to implement a localized list that contains the component.
It works perfectly in CMS cockpit. However, in smartedit, it causes a ClassCastException.
The default converter seems to fail to recognize the collection type and therefore trying to cast the collection to a item model which causes the error.
Is there anyway to implement a localized collection that won't causes the exception in SmartEdit?
I have tried using a map and collection pair for the localization instead of a localized relation but the same problem occurred.
2019-3-7 - Updates: After a series of trial and error, I have realized that the LocalizedCollection will never be called because all localized attribute in Hybris is stored with an item type of MapType, which does not trigger the localizedCollection getter as it check if the localized attributs is of type CollectionType.
It seems to be a bug on SAP side. I am currently trying to come up with a temporary fix for the problem.

How to get hidden field value in crm plugin?

I have a hidden field in crm form and setting value for hidden field on save button click using JavaScript.
I am trying to select the hidden filed value in c# plugin code on postcaseCreate event, but getting Key is not found in dictionary error, Can anyone tell me what I am missing here.
if (localContext.PluginExecutionContext.InputParameters.Contains("Target")
&& localContext.PluginExecutionContext.InputParameters["Target"] is Entity)
{
// Obtain the target entity from the input parmameters.
caseEntityObj = (Entity)localContext.PluginExecutionContext.InputParameters["Target"];
string productIds = caseEntityObj.FormattedValues["my_hiddenfiedld"].ToString();
if (caseEntityObj == null) return;
}
Try to replace line
string productIds = caseEntityObj.FormattedValues["my_hiddenfiedld"].ToString();
with line
string productIds = caseEntityObj["my_hiddenfiedld"].ToString();
Why do you want to use FormattedValues? Is hidden field optionset? If yes and you need to get correspond text you will have to retrieve attribute using RetrieveAttribute message and get text of optionset from response.
The "Target" input parameter has only the attributes that were submitted to the framework. The system forms only submit attributes that contain changed data (or do not equal default values) as an optimization. If you created your own client UpdateRequest or CreateRequest and only submitted a few attributes, then your plugin's Target collection would only contain those few attributes as well.
In your case, I'm guessing that your hidden field isn't changing on an update and so it isn't included in your Target attribute collection.
If your plugin logic will always need to know the current value of a field regardless of whether it is included in the submitted attribute collection, you need to register a PreImage. Registering a PreImage tells CRM that you always need to know the current value of a certain field during this plugin. This is the value of the field before the current action.
Docs on PreImages: https://msdn.microsoft.com/en-us/library/gg309673.aspx#bkmk_preandpost
Pseudo code:
Use .Contains() to check Target attribute collection for attribute name.
If true, get value of attribute from Target attributes as this is the actual change just submitted by client.
If false, use .Contains() to check PreImage attribute collection for attribute name.
If true, get value of attribute from PreImage as this is the most recent value from the database.
Hope that helps!
Thanks Josh,Andril,
I created two steps in plugin code like postCaseCreate,PostCaseupdate event and one postImage and then I am getting value like below on postCase create event
string productIds = caseEntityObj["my_hiddenfiedld"].ToString();
For update getting the value from image. It is working fine. thanks a lot guys.
Entity postImageEntity = (context.PostEntityImages != null && context.PostEntityImages.Contains(this.postImageAlias)) ? context.PostEntityImages[this.postImageAlias] : null;
productIds = postImageEntity.Attributes["my_hiddenproducts"].ToString();

Should I be able to pass a NotesDocumentCollection in a sessionScope variable?

I have one page that does a NotesDatabase search and of course returns a collection. I am storing that collection in a sessionScope variable and calling a page where I what ti display the results.
if ( collection1.getCount() == 0)
{
displayErrorMsg("Your search returned zero results. Please try another search.",getClientId("title"), "Zero Results");
}
else
{
sessionScope.put("searchResults",collection1);
var extCont = facesContext.getExternalContext();
extCont.redirect("xp_vwIssueSearchResults.xsp");
}
The page has a data table with the content of the scope variable as it's datasource:
sessionScope.get("searchResults");
When I call this page I get, NotesException: Object has been removed or recycled.
Should I be able to pass a NotesDocumentCollection in a sessionScope variable? I have some thoughts on work arounds but it would sure be nice to pass the NotesDocumentCollection.
You can't keep Notes objects like views, documents, collections for a longer time. In general, you should work with Notes object in a way, that you save the data you're interested in somewhere and recycle (=destroy) the Notes objects right away. The reason is that the Domino server can't save the Notes objects for you between two request because Notes objects aren't serializable (serializable = ability to save objects on disk and restore them back to memory).
In your case, you could save
the search query or
the result values as an Array of Objects (JavaScript) or a List of Maps (Java) or
the documentUniqueIDs of document collection's documents
in your sessionScope variable and use them in your redirected page.

How does `mongoose` handle adding documents that have FIELDS that are __NOT__ part of the schema?

I'm playing around with quick start guide for mongoose.
http://mongoosejs.com/docs/index.html
I assumed that it would throw an error when I saved a document with a field NOT defined in the schema. Instead, it created a new document in the collection but without the field. (Note: I realize mongodb itself is "schema-less" so each document in a collection can be completely different from each other.)
two questions
How does mongoose handle adding documents that have fields that are NOT part of the schema? It seems like it just ignore them, and if none of the fields map, will create an empty document just with an ObjectId.
And how do you get mongoose to warn you if a specific field of a document hasn't been added even though the document successfully saved?
(The question is - I believe - simple enough, so I didn't add code, but I definitely will if someone requests.)
Thanks.
Q: How does mongoose handle adding documents that have fields that are NOT part of the schema?
The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db.
- mongoose docs
Q: How do you get mongoose to warn you if a specific field of a document hasn't been added even though the document successfully saved?
The strict option may also be set to "throw" which will cause errors
to be produced instead of dropping the bad data. - mongoose docs
...but if you absolutely require saving keys that aren't in the schema, then you have to handle this yourself. Two approaches I can think of are:
1. To save keys that aren't in the schema, you could set strict to false on a specific model instance or on a specific update. Then, you'd need to write some validation that (a) the values in the document conformed to your standards and (b) the document saved in the database matched the document you sent over.
2. You could see if the Mixed schema type could serve your needs instead of disabling the validations that come with strict. (Scroll down to 'usage notes' on that link, as the link to the 'Mixed' documentation seems broken for the moment.)
Mongoose lets you add "validator" and "pre" middleware that perform useful functions. For instance, you could specify the required attribute in your schema to indicate that a specific property must be set. You could also specify a validator that you can craft to throw an error if the associated property doesn't meet your specifications. You can also set up a Mongoose "pre" validator that examines the document and throws an Error if it finds fields that are outside of your schema. By having your middleware call next() (or not), you can control whether you proceed to the document save (or not).
This question/response on stackoverflow can help with figuring out whether or not an object has a property.

copy MIME atachments from document to document

XPages application uses "template" documents containing two fields binded to RichText editor and file upload/download controls.
Regular documents initially link to template document, with one datasource for common fields (title, category, readers/authors...) of current document, and second datasource shows read only RT+attachments from template.
When user decides to alter RT/attachments, he unlinks document from template - by copying RT+attachments from template to current document.
The problem: standard Java snippet for RT copy (and attachments too) is:
session.setConvertMime(true);
RichTextItem rti = (RichTextItem)docTemplate.getFirstItem("Body");
rti.copyItemToDocument(docCurrent, "Body");
rti = (RichTextItem)docTemplate.getFirstItem("Files"); <====
rti.copyItemToDocument(docCurrent, "Files");
docCurrent.save(); //saves in RT format, next save via XPage converts to MIME
This always works for Body field (although it alters formatting a bit), but it rarely works for attachments.
Resave of template document in Notes client converts RT from MIME to native RT format and code works without problem.
Not working means:
exception java.lang.ClassCastException: lotus.domino.local.Item incompatible with lotus.domino.RichTextItem at line with arrow.
missing Files field (Body is created correctly tho)
For some attachments code seem to work (text file), for bigger or binary it fails (23k .doc, 3M .pdf).
LotusScript alternative of above code called as agent does not help either.
Datasource property computeWithForm is not used by purpose.
Question: what is proper technique for copying MIME attachment(s) between documents?
The quickest way would be using Document.copyAllItems(Document doc, boolean replace) and than removing what is unnecessary.

Resources