Posts Tagged With: Attachments

Exploring requestScope, viewScope and multiple source documents in #xpages

As I’ve mentioned previously, much of my current work revolves around one database used to allow organizations to request grants for one of our projects. In doing so, when they open the XPage to request a grant, there are four separate attachment documents as source documents to the XPage, as well as the main document and a contact document. One of the issue I had with our initial roll out of the database was that users uploading their attachments ended up creating many rep/save conflicts and getting every attachments loaded on every source document except the contact document. I had no idea why, but it was in production already and with less than 100 grant requests, I simply manually fixed all the rep/saves as they created them. Basically, using a hammer to repair ceramics.

The problematic code was, unbeknownst to me, my source declarations.

<xp:this.data>
	<xp:dominoDocument var="workplanDoc" formName="AttachAnnex" />
	<xp:dominoDocument var="projectBudgetDoc" formName="AttachAnnex" />
	<xp:dominoDocument var="budgetAssumptionsDoc"  formName="AttachAnnex" />
	<xp:dominoDocument var="performanceIndicatorsDoc" formName="AttachAnnex" />
</xp:this.data>

I knew something was wrong. I’d originally had those four source documents declared at the top of the XPage, but when I moved them onto a custom control, it seemed to me that I’d resolved them problem. Unfortunately, I think it was only working some of the time (new grant requests, which had no documentId= in the URL, I suspect), if at all.

So, I wondered and I searched. Then, the daily compilation of Lotus Notes questions on Stack Overflow came through. The first item was labelled “XPage xe:Dialog box is edit previous create document”, which didn’t seem too interesting, but the snippet from the question raised my eyebrows, “I have a custom control that create a new document through ext-lib dialog box that work fine. However when the action is performed the second time it edit the document instead of creating a new …” I realized he was dealing with multiple data sources and having problems similar to mine. So, I opened the question and found great advice from Patrick Sawyer.

set ignoreRequestParams to true and then set the scope to request

Then, I followed links to his post to get more information, finding that even though I’d read Patrick’s question about multiple data sources and commented on it, no less, that I had no recollection of that solution (provided by Tim Tripcony!) So, I changed my code.

<xp:this.data>
	<xp:dominoDocument var="workplanDoc" formName="AttachAnnex"
	 ignoreRequestParams="true" scope="view" />
	<xp:dominoDocument var="projectBudgetDoc" formName="AttachAnnex"
	 ignoreRequestParams="true" scope="view" />
	<xp:dominoDocument var="budgetAssumptionsDoc" formName="AttachAnnex"
	 ignoreRequestParams="true" scope="view" />
	<xp:dominoDocument var="performanceIndicatorsDoc" formName="AttachAnnex"
	 ignoreRequestParams="true" scope="view" />
</xp:this.data>

Tim explained the function of ignoreRequestParameters well in his answer to Patrick’s question:

If you omit the ignoreRequestParams attribute, then this data source doesn’t ignore the URL request parameters. Instead, it looks for parameters named databaseName, formName, documentId, and action. If any of these parameters are included in the URL, the value of each overrides what is defined on the data source.

So, what was happening was that if you started a grant request via the simple link, which was just the XPage URL, ending with “Application.XSP” then there were no parameters to worry about and the source documents might be created properly. However, if the users followed the link I’d emailed them, pointing to their specific document, with action=editDocument, and documentId= the UNID of their grant request, it would use those values and upload the attachment to main document, modify the form name to “AttachAnnex” and, with multiple uploads of many attachments, create a flurry of save conflicts. I’d go through and change form names on one of them and save the others, so they all got assigned new UNIDs.

Now, I tried both requestScope and viewScope, finally settling on viewScope. If I use requestScope, then each attachment upload creates a new Notes document with the attachment on it. If I use viewScope, then, for the span of that user session, each upload that the user does to that source document goes onto the same Notes document. If they come back and upload more documents in a separate session, it should create a new Notes document that would hold all of the attachments uploaded for that source document. So, with requestScope, if the user had 10 files to upload, some for each source document, they would be creating 10 Notes documents, regardless of whether they uploaded them in one sitting or several. With viewScope, if they uploaded 3 files to workplanDoc in one sitting, all 3 files would end up on 1 Notes document. Since I’d already worked out how to handle the linking to attachments for multi-attachment Notes documents, I chose viewScope, which keeps the attachments more organized.

Now, if I were to experiment, I expect that using sessionScope would create problems for any user who submits multiple grant requests, as it would use a four source documents for their entire session. This would put every workplan attachment onto one workplan Notes document that would end up associated only with the last grant request they edited. I could be even more foolish and grant the source documents applicationScope, which would put every attachment that any use uploaded into one of the four application-wide source documents, each time, associating it with a different grant request. Nightmarish!

I’d been wondering, and heard multiple speakers who discussed scope at various conferences say, “I’m not real sure why you’d use requestScope, but I know there are reasons.” Well, creating new source documents from an XPage that uses multiple source documents is just such a reason.

Categories: Xpages | Tags: , , , , , , | 1 Comment

Nesting repeats to provide links to attachments in #XPages

Another of the challenges in my assessment XPage problem is that the evaluators will need to open the attachments that were submitted with each grant request. There are two issues here – first, that the attachments are uploaded to multiple separate documents from the grant request and, second, that there might be multiple attachments on each of those documents.

We chose to have the attachments on separate documents to reduce the size of the request document and lower the likelihood of truncation or replication issues. The users requesting these grants are all located in Africa and may well be in remote locations. So, bandwidth issues, even for the browser side, are of paramount concern for us. We’ve had some issues in the past on the Notes side with some truncations or with replication issues and found it better to keep documents smaller as a precaution.

So, for each request, there can be up to 4 documents with an unknown number of attachments associated with each request. As such, I stumbled upon the idea of using a repeat-within-a-repeat to display the links for each attachment.

First, I made sure to get only the attachment documents that I want by filtering my source view (as discussed previously):

<xp:dominoView viewName="AnnexLinks" var="linksView">
    <xp:this.keys><![CDATA[#{javascript:appDoc.getItemValueString("appUniqueID");}]]></xp:this.keys>
</xp:dominoView>

Then, I needed to build my repeat control. The code itself is actually very brief. My AnnexLinks view is very simple, with only three columns: AppUniqueID (my index, which is not the document unique ID, by the way), the AttachmentType and the URLs for the attachments.

The URLs column builds a unique URL for each attachment:

unid := @Text ( @DocumentUniqueID );
base := "0/" + unid + "/$file/";
base + @AttachmentNames

Since there can be multiple values in the URLs column for a single document, I have the link embedded inside a repeat control, using that value as an array to populate my link. I’m computing the filename back from the URL to use as the link label, but using the AttachmentType for the document in the outer repeat to display a label for the attachments.

<xp:repeat id="repeat3" rows="30" value="#{linksView}" var="rowData" indexVar="rowIndex">
    <xp:text escape="true" id="computedField1" value="#{rowData.AttachmentType}" style="font-weight:bold">
    </xp:text>
    <xp:label value=" files:" id="label2" style="font-weight:bold">
    </xp:label>
    <xp:repeat id="repeat4" rows="30" value="#{rowData.URLs}" var="url">
        <xp:link escape="true" id="link1" value="#{url}">
            <xp:this.text><![CDATA[#{javascript:@RightBack(url,"/") + " ";}]]></xp:this.text>
        </xp:link>
        <br />
    </xp:repeat>
</xp:repeat>

It’s shocking to me that something that ends up so small can accomplish what seemed like a huge tasks initially. On my notepad, I’ve got all kinds of SSJS written to get a handle to the attachment documents, then to try building an array of URLs, synchronized with a list of filenames to be used as labels. Fortunately, by poking around for URL info (h/t to Stephan Wissel – this will have to be updated for XPiNC and upgradeability) and referring back to my copy of Mastering XPages, I was able to sort out how to do it in just a few lines of simple, elegant code.

Categories: Xpages | Tags: , , , , | 1 Comment

Create a free website or blog at WordPress.com.

%d bloggers like this: