Why DominoDocumentData.setConcurrencyMode has no effect for Domino document data source? - xpages

I used to save the current DominoDocument of the XPage in some way like:
UIViewRootEx2 view=(UIViewRootEx2) FacesContext.getCurrentInstance().getViewRoot();
DominoDocumentData ddd=(DominoDocumentData) view.getData().get(0);
DominoDocument dominoDoc=(DominoDocument) ddd.getDataObject();
//ddd.setConcurrencyMode("force");
dominoDoc.save();
To use the concurrencyMode property of the data source to avoid conflicts, I add the following line.
ddd.setConcurrencyMode("force");
I expect this behaves the same as setting the property in the XPage:
<xp:dominoDocument var="document1" formName="Test" computeWithForm="onsave" concurrencyMode="force"></xp:dominoDocument>
But it fails. It always uses the value set in the XPage source and ignores the value set in the code. Anybody knows the reason? Thanks.

I would say: works as designed. During one of the jsf phases the design is read and the value overwritten.
In JSF and thus XPages you don't mess from "Controller Code" (the stuff in your button) with the "View rendering" (your XPages source). You rather bind the property to your model (a scope variable is a good candidate) and let the runtime run its course.
So your code would be
<xp:dominoDocument var="document1"
formName="Test"
computeWithForm="onsave"
concurrencyMode="#{viewScope.myConcurrency}">
</xp:dominoDocument>
and
viewScope.myConcurrency = "force"
Hope that clarifies it.

Related

Domino Document cannot be opened twice on public access xpage

I have an Xpage with access set to public for clients to fill in a form. When I send the client the link to the page and they open it for the first time. Everything runs smoothly. However, if they close the browser and click on the link again they receive this error:
{Unexpected runtime error
The runtime has encountered an unexpected error.
Error source
Page Name:/xpClientForm.xsp
Exception
Could not open the document
Invalid universal id}
I am using a switch facet to cycle between forms depending on the client type.
The domino document id is being stored in a sessionScope beforepageload and the document dynamically computes it based on that sessionScope variable.
Here is the code:
SessionScope assignment on beforepageload
var cData = getClientData(id);
sessionScope.docId = cData.docID;
Document datasource
<xp:panel style="height:100px" id="pnlDocData">
<xp:this.data>
<xp:dominoDocument var="document1"
formName="frmA" action="editDocument"
documentId="#{javascript:sessionScope.docID;}" scope="request">
</xp:this.data>
</xp:panel>
However when i execute this custom control on a page that does not have public access. It runs fine with no issues irrespective of how many times i open the link.
Any help will be greatly appreciated.
You need to set ignoreRequestParams="true" on the dominoDocument datasource. Otherwise it's using the document ID in the URL or trying to create a new document, which the user probably doesn't have access to do.
Computing the document ID is the less common scenario, which is using the URL for document location is the default.

Binding data to a single document from multiple custom controls

I have an Xpage with multiple custom controls that make up a form. When I click the submit button I get a multiple documents saving the multiple custom control data as a separate document.
I have the data sources configured at the custom control level.
How can I make it that all the custom control save the data to one single document?
Thanks,
Just put them on the XPage. If you use a variable name (e.g. for a datasource, a dataContext etc), the runtime will just look outwards from the current component in the hierarchy to find the relevant object. If you're having problems thinking of the XML source code in a three-dimensional way, the Outline view is good for this.
So from within a Custom Control, you can reference a datasource on the XPage, as long as it is defined in an ancestor of the custom control on the XPage or is a previous sibling. So in the structure below, document1 will be accessible from anywhere in the ccFriends custom control.
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.data>
<xp:dominoDocument var="document1" formName="Profile">
</xp:dominoDocument>
</xp:this.data>
<xc:ccFriendsAlt></xc:ccFriendsAlt>
You can also pass the data source object as a custom property to the custom control if you can't follow Paul's suggestion of keeping the same variable name for your data source.
http://lpar.ath0.com/2013/04/22/passing-document-data-objects-to-xpages-custom-controls/

How do I properly use a Custom Control's "Datasource Picker editor"?

I'm passing a doc datasource into a Custom Control using a property defintion named docDatasource and set to a datatype com.ibm.xsp.model.domino.DominoDocumentData. Just by chance I stumbled upon an editor type named "Datasource Picker". Sounded promising, so I set it to use for m prop definition.
Upon binding the CC into my Xpage - where my doc DS is defined - I indeed can use the picker to choose my datasource ,just as I had expected. But then building the Xpage code I receive an error saying
The value of the property docDatasource cannot be primitive.
So obviously the datatype and the editor don't go along well. There's no harm done really, but I'm curious to learn what else this editor could be used for.
What to do with name of the data source passed to custom control parameter: retrieve its object by simple binding #{requestScope[compositeData.docDatasource]}.
That will return your data source and you can use this binding where needed. Or store it inside local variable and use it instead.
I dont know where you went wrong.
Here is xpage source:
<xp:this.data>
<xp:dominoDocument var="document1" formName="asdf" action="openDocument" documentId="08f6"/>
</xp:this.data>
<xc:doccc dds="#{javascript:document1}"/>
and custom control:
<xp:label id="label1">
<xp:this.value><![CDATA[#{javascript:compositeData.dds.getItemValueString("fl_name");}]]></xp:this.value>
</xp:label>
with custom control property named dds, type com.ibm.xsp.model.domino.DominoDocumentData and editor DataSourcePicker.

xpages display a new doc. inside a dialog

i have an issue that it gives me some headache lately.
In my XPage there is a view displaying some docs ( let say Pdoc as datasource ) and I open/create them inside a <xe:dialog>. This dialog has only Pdoc declared as datasource, and it inherits some values from the Xpage datasrouce. My clickable column formula is:
// some var declarations
var formName = rowData.getDocument().getItemValueString("Form");
if ( formName == "fmP" )
{ viewScope.put("dlgDocUnid", pe.getUniversalID())
getComponent("exampleDialog").show(); }
On the same XPage, I can create a new Pdoc using the same dialog via a button, New Pdoc.
The problem is: when I opened an existing Pdoc and then just save it or close it, and after I use the button to create a newNote => the old / previous ( already saved Pdoc ) is showed...
If firstly I just created a new note Pdoc, it works, and it is showing a new empty Pdoc.
My dialog data code:
<xp:this.data>
<xp:dominoDocument var="Pdoc" formName="fmPersContact"
ignoreRequestParams="true" scope="request" action="editDocument">
<xp:this.documentId><![CDATA[#{javascript:viewScope.get("dlgDocUnid");}]]></xp:this.documentId>
</xp:dominoDocument>
</xp:this.data>
I use the .documentId for the open method from the viewPanel. I think here is the problem. I think ,( I'm not sure), I should compute this documentId in such way that when I create a newNote this documentID shouldn't be anymore the viewScope.get("dlgDocUnid").
Thanks for your time.
If I understood correctly, you have defined two data sources within the XPage and you try to consume them in the dialog, right? Instead I suggest defining a single data source within a panel inside the xe:dialog.
I have blogged about a similar example. In this example, tooltip dialog has been used but it's the same logic, you might replace xe:tooltipDialog with xe:dialog.
http://lotusnotus.com/lotusnotus_en.nsf/dx/mini-patterns-for-xpages-parameter-editing-with-dialogs-1.htm
The idea here is that you use a viewScope variable named noteId. To open an existing document, set this variable to the note id of the existing document. To create a new document, the value will be set as NEW. Then you define the data source within the dialog according to this variable:
<xe:dialog>
<xp:panel style="width:500.0px">
<xp:this.data>
<xp:dominoDocument
var="document1"
formName="Parameter"
action="#{viewScope.noteId eq 'NEW'?'createDocument':'editDocument'}"
documentId="#{viewScope.noteId eq 'NEW'?'':viewScope.noteId}"
ignoreRequestParams="true">
</xp:dominoDocument>
</xp:this.data>
..... Dialog content ....
</xp:panel>
</xe:dialog>
When you put the data source inside the dialog, you don't refresh the page to load or prepare data sources before launching the dialog which is your current problem I guess.
Could it be that you forgot to deactivate the flag to ignore request parameters.
Sounds like the dialog is always associated with the current document instead of the parameters from the docid

xpages dynamically change xpage acl?

I have a basic workflow app, and I am having diffiulty.
In the db ACL, I have all the people and groups involved set to Editor.
In an XPage acl, I am trying to enter a computed value for the name. (a field I have called nextApprover, which is stored on the form/document associated with the xpage.
I've tried
document1.getItemValue("nextApprover");
AND
getComponent("nextApprover").getValue();
both create a runtime error executing the Javascript computed expression.
All I am trying to do is allow the nextApprover the rights to edit the document when it is in their "box" and allow the rest of the users the ability to read it at that particular time. I've looked around for a while now.
Any suggestions?
You can't access the datasource document1 in XPages ACL name calculation because the ACL is first calculated and only later the datasource. That's why you get the JavaScript runtime error.
Here is an alternative to XPages ACL:
Define your datasource document1 with action="openDocument"
<xp:this.data>
<xp:dominoDocument
var="document1"
action="openDocument"
... />
</xp:this.data>
That will open the document by default in READ mode.
Then switch in beforePageLoad event to EDIT mode with context.setDocumentMode("edit") if the current user name is in your field nextApprover:
<xp:this.beforePageLoad><![CDATA[#{javascript:
if (document1.getItemValue("nextApprover").get(0).equals(session.getEffectiveUserName())) {
context.setDocumentMode("edit")
}
}]]></xp:this.beforePageLoad>
You might have to change the if clause depending on what is really in your field nextApprover.
You get better security by using Authors-items on documents instead of XPage ACL.
Try this (if document1 is datasource name):
document1.getValue("nextApprover");
If it does not work with this and you still want to use XPage ACL please post your error and XPage XML source for the ACL part.

Resources