Can replication\save conflicts be identified in Xpages - xpages

If I know a notes document opened in Xpages has created a replication\save conflict duplicate document and then search for the document ID in Xpages then both (or all) the documents are shown in an Xpage set up with a specific Notes view in my application. But is there any way I can tell which one is the parent document and which one(s) are the replication response documents? I need to be able to see this on the Xpages front end and not just in the Notes database backend.

If you create a view with #IsAvailable($Conflict) as the selection formula, you can identify conflicts. They have a $REF field which maps to the parent document.
Because XPages allows us to have multiple datasources on an XPage, it should be feasible to open the conflict have dominoDocument datasources for the conflict and the parent document (the non-conflict).

If your view has the option 'Show response documents in a hierarchy' then your parent document comes always first and right after it all the replication conflicts. You can show the replication conflicts this way:
<xp:viewPanel
value="#{view1}"
id="viewPanel1"
var="rowData">
...
<xp:viewColumn
columnName="yourColumnName"
id="viewColumn2"
value="#{javascript:
if (rowData.getDocument().hasItem('$Conflict')) {
var parentId = rowData.getDocument().getItemValue('$REF');
return '[Replication ot Save Conflict]';
}
return rowData.getColumnValue('yourColumnName')
}">
<xp:this.facets>
<xp:viewColumnHeader
value="Unid"
xp:key="header"
id="viewColumnHeader2">
</xp:viewColumnHeader>
</xp:this.facets>
</xp:viewColumn>
</xp:viewPanel>
Orphan replication conflict documents with deleted parent document don't show up in this kind of view.
If your view has not the option 'Show response documents in a hierarchy' set then all replication conflicts would be visible even the orphans. Documents are sorted by the column values so the replication conflicts wouldn't be necessary right beneath the parents document. In this case you might want to show the parent's DocumentUniqueID in addition with the help of parentId variable.

Although previous answers will help, they complicate everything at page level. Get rid of conflicts in their source - so XPage or background code doesn't need to.
In our applications every view used for XPages has selection formula enriched with
& !#IsAvailable( $Conflict )
That way no matter what code (datasource, component, SSJS, Java, #Formula) in XPage does not need to handle conflicts.
Edited to answer your question:
In adition to above, you can have special view with conflicts only (selection of #isAvailable( $Conflict )) sorted by #Text( $REF ) column. You are not able to show any other data for conflict documents.
Then, you can add column that will lookup whether document with specific UNID has any conflict documents and highlight them, show conflict count, or something else.
My two cents though - conflict resolving in Notes client is much clever idea.

All these responses are great but in the end why are conflicts getting generated? There should be logic in the design so that a minimal group of people can edit a document at any one time. If all your users are editor level then re-think your application. Most users should be author access and the use of authors field defines who can edit that document, which might change depending on the workflow status.

Related

XPages : How to get document collection for dominoView datasource with 'search' property in SSJS

I filtered out XPages view with 'search' option. Then I'd like to access all of the documents by SSJS.
If I access the bound Notes view by database.getView("ViewName"), the view is not searched and could not get the searched result.
How can I access the document collection?
The dominoView data source is just a wrapper that runs calls on the underlying view to return a subset of entries to display in a view component (Data Table, View Panel, Repeat, Data View etc). Consequently, unless the rows property is set to a large enough value to get a handle on all responses, you’re unlikely to be able to access what you want that way.
The best approach will be to run the search on the backend view in SSJS / Java.
See https://www.intec.co.uk/understanding-xpages-views/ for a more detailed explanation of the different elements involved and their inter-relationships.

filtering/searching on a repeat control

In my application, i would like to replace a viewpanel with a repeat control.
However, part of the functionality is there is a UI aspect that allows users to select certain fields (that correspond to the view), and only display the documents that match. The view is doing a filter that allows users to select aspects of the view to create a search (the code is under search of the view) that allows the view panel to be updated with the results of the search.
one of the things that is curious is that the viewpanel has a value of "#{javascript:view2}" vice an actual view name.
The viewpanel defines the search view and the ...
I'd like to be able to apply that same functionality to the repeat control. I don't see those attributes on the repeat control... Any pointers? Its been a while since i've worked with xpages... long enough that I've forgotten a lot already....
TIA !
Read this blog post I did a while back, it should explain what you need.
The view panel doesn't filter anything, it just displays rows from a datasource, same as a repeat control. Indeed you can add components to a ViewPanel's column, pulling from the current row by adding a var property to the dominoView datasource.
The view is bound to #{javascript:view2} (which would be better done by binding to #{view2} - there's no need to call SSJS here). view2 is a dominoView datasource somewhere on your page. The datasource is a wrapper that has properties to capture the settings for filtering and searching that you want to do. At runtime, they are calculated and changes the ViewEntries in the datasource.
Finally there's is the underlying Domino View object available also to LotusScript. This holds and will always hold all entries. The dominoView datasource queries that using the filtering and searching properties and retrieves a ViewEntryCollection or a ViewNavigator.
So whether you use a View Panel, Repeat Control, Data View or whatever else, those are just components to visually represent a collection of ViewEntries or Documents. All can be bound to a dominoView datasource. Where repeat controls and Data Views give you extra power is you can bind them to any kind of collection, not just a dominoView datasource (e.g. DocumentCollection, ViewEntryCollection, multi-value field, Java collection, etc).
I often find that doing the searches in Java and then passing the results to the repeat as a List work better and allow more options. I can get all the information I need in Java and load that into a Map or Tree. This gives me the ability to do custom sorting in the Java class and also to combine data from other views/databases easily. Since the data is now in memory it gets reloaded fast. The only thing you have to watch for is the size of the data. If you have a view with many entries (10K?) you might not want to load everything into memory...
Howard
I'm not sure if you've found a solution yet, but consider using jQuery dataTables. Oliver Busse wrote a very detailed blog post about integrating dataTables into XPages.
To get the specific formatting, I used a repeat control to include the "td", "tr" and "thead" attributes Oliver listed in his blog post.

Xpages, Inherited documents in view panel by using #Unique

I have two forms project(Document) and comment(Response to Response) I want to create a view that displays all comments of selected Project
Any help would be appreciated.
I love doing this type of stuff in xPages.
For a moment, don't think about project and response. Think uniqueID. In order to make the project document reference the comment you add a unique ID to each of them that will reference each other. Don't use response docs in xPages, there is no need I see. When you save the comment, save the unique ID of the parent document to a field on the comment document by referencing this value where document1 is the datasource of the parent and document3 is the document of the child.
<xp:modifyField name="uid"
value="#{javascript:document1.getDocument().getUniversalID()}"
var="document3">
</xp:modifyField>
Now that you have a bunch of parent and children docs, you create a categorized view where you are only capturing the comments. Use a view selection formula to exclude the parent form. Make the first column the uniqueID that you previously captured. You now have a view that will keep all the comments categorized by the unique id of the parent.
Now in the xpage you now need to filter on the key value. You filter by computing the keys to the value of the parent document. Here document1 is the parent.
<xp:dominoView var="view2" viewName="rejections"
keys="#{javascript:document1.getDocument().getUniversalID()}">
</xp:dominoView>
The great thing about doing this is it will work in a viewPanel, dataView, or a repeat control since you are referencing the data not the UI.
If you wanted to do comments of comments there are a couple of approaches but I think they would all have the same structure. If you made it this far start looking at repeat controls they will let you break free of the normal notes views.
I moved away from using Parent and response documents in Notes years ago because they were just too much trouble. I also moved away fro using the UNID as the 'link' for several reasons. The first is that the UNID can change (resolve a save/rep conflict) Second archiving is all but impossible because again the UNID changes when the document is copied to another DB. So when I create a 'parent' document I store #Unique into a field I call LinkKey, and store that value in all 'response' documents. When I create the response then I store a new #Unique into a field rLinkKey. This way a response to a response knows it's originator (LinkKey) and it's direct parent (rLinKey). Now you can extend this any number of levels deep fairly easily.
This worked OK in native Notes with some kludge, but now in XPages with repeat controls the real power comes from nested Repeat Control. Something I have always wanted to do in Notes but was never able to is now a piece of cake.
The down side is that getDocumentByUNID() is going to be faster that getDocumentByKey(LinkKey, true) but the other advantages far out weigh the unnoticeable time difference (IMHO)

Can (or should) I use one view for multiple View Controls

In traditional Notes programming it was a best practice to use hidden views for things like DbLookups and non-hidden views for user facing views. This way you wouldn't get a request for a user to add a field to a view and break your lookups. Keep presentation separated form logic.
I still follow this in Xpages. But I was wondering if we can (or should) reuse hidden views that are used for data sources for more than one presentation view. In other words should there be a one to one correspondence between a view and a view type control. Are there limitations to having a many to one relationship?
I think that in the XPages world... assuming it's 100% an XPages app there's much less need for using Views as "presentation". Since you can change things in your view and repeat controls for the presentation.
So you might end up having 1 view with many more fields then you need but that feeds multiple view controls and you're just showing the columns of interest etc. The iffy part is if you're going to use the view control for sorting columns and all that. I don't actually use the view control much. I find it too limiting. I prefer repeat controls.
So to answer you're question I think you absolutely should reuse views as many times as you want. From a performance perspective the less views the better typically I think.
These days I do less with views overall. I make Java Objects to represent my document. So I'll use some views to find the correct documents and then push them into java objects. Then in Java I'll use code to sort things different ways and send that back out to a repeat control. Works very well and that lets me cut down on views. BUT if you're doing this with 3,000+ documents... there can be some delays for the initial injection so in some situations I might have to get back to actually touching the views just to get better performance.
There is no need to maintain a one-to-one relationship between View design elements and View panel controls in an XPages application, and IMHO you shouldn't.
Consider a traditional Notes client application with only one Form design element and many, many View design elements. When your main/only presentation tools are the Form and the View elements you tend to get a lot of Views to meet the various presentation requirements of the application. Of course each added View will spawn an Index, increasing the size and decreasing performance in the application.
One great feature of XPages is the separation of the data and the presentation layer. This allows you to reuse the same Domino View data source on several XPages with different presentation requirements -- each XPage displaying a different set of columns or uses a different iterator control to display the view data (xp:viewPanel, xp:repeat, xp:dataTable, xe:dataView, xe:dynamicViewPanel, or xe:djxDataGrid).
When I'm developing a new XPages application with no traditional Notes client access I find that I tend to create fewer, flatter, and often wider views (i.e. more columns).
I'm getting wider views with more columns because its more efficient to return column values then field values in the underlying document. All of the iterator controls have a var variable to address the entries in the Domino View data source, even xe:djxDataGrid via its REST Service. When using a Domino View data source I tend to set var="viewEntry" to reflect its NotesXspViewEntry type.
So, when there is no column for the field values I need to return (say to a Computed Field in a View Column or in another facet of an iterator control) I have to get it from the underlying document like so:
<xp:text escape="true" id="computedField3">
<xp:this.value><![CDATA[#{javascript:
return viewEntry.getDocument().getItemValueString("City") + ", " + viewEntry.getDocument().getItemValueString("State");
}]]></xp:this.value>
</xp:text>
But if I just tack on the City and State columns to my View design for the Domino View data source then the following code runs faster:
<xp:text escape="true" id="computedField2">
<xp:this.value><![CDATA[#{javascript:
return viewEntry.getColumnValue("City") + ", " + viewEntry.getColumnValue("State");
}]]></xp:this.value>
</xp:text>
And faster still is the EL equivalent:
<xp:text escape="true" id="computedField1"
value="#{viewEntry.City}, #{viewEntry.State}">
</xp:text>
Since I address the View column in my XPages code by programmatic name and not by position, adding new columns to my View design as I need them doesn't seem to break anything (at least not yet ;)

Dynamic field binding inside a repeat control

I have a strange thing, I'm using dynamic field binding in a custom control.
The field binding is created like this.
XPage (Datasource "document" is placed here)
Custom Control (String passed in)
(to get errors if there are any)
Repeat (CompositeData is passed to a bean that returns the strings for Rows,columns)
Repeat (repeat 1 variable used for Columns)
Custom Control (fieldname is passed in)
field binding is done like this
#{document[compositeData.fieldName]}
The problem is that when I save the XPage I get an error in the messages control
Document has been saved by another user - Save created a new document as a response to that modified document.
And all fields are cleared.
Any ideas how to debug this or is there something I'm missing?
The "Document has been saved by another user" error is only tip of the iceberg - there are some really strange problems with reapeats that repeats fields that are bound and repeatControls property is set to false. The decoding part of xpages lifecycle cannot handle it properly - the controls will be losing data. You should use repeatControls set to true as Martin suggests.
"Repeat control variable doesn't exists" is probably caused by the property that removes repeats set to true. You can solve this by either changing it to false or by adding additional data context that will keep repeated value.
And finally for this to have add/remove functionality You can use Dynamic Content Control and show(null) hack to rebuild the repeat content.
To manage this complexity better I would advise You to stop using document data source and start creating some managed beans.
If You will follow my suggestions I guarantee that You will get the functionality You are looking for as I have few apps that works great and have this kind of complex data editors in them.
I don't know if it'll help you, but I pass both the document datasource and the field name as parameters to a DynamicField control, and use it like this:
compositeData.dataSource[compositeData.fieldName]
The type of the datasource is com.ibm.xsp.model.DataSource, it's listed as dataInterface under Data Sources.
Do you have repeatControls="true" set for the repeat control?
It sounds like you've got the datasource defined multiple times on the XPage (plus custom controls). Either that or the save button has save="true" but the code saves the document back-end, or code in multiple places saves the same document. I've used the same method of passing the datasource down to the custom control, but that may just be because that was what I saw on a blog.

Resources