HCL Notes: How to increase limit for text? - lotus-notes

For a project I am programming in HCL Domino and using a Notes Database. My problem is that the value I want to store as text is greater than the maximum limit for text (32KB).
As an alternative rich text came into my mind. Within the application it works just fine. Yet if I directly apply any changes in the database the text will be formatted differently. If I use the application again the text will be look something like this:
<font size="2" face="sans-serif"><?xml version="1.0" encoding="UTF-8"?><br /> ...
But instead it should be xml Code:
<?xml version="1.0" encoding="UTF-8"?> ...
Is there any way to avoid this problematic? Is it even possible to change the maximum capacity for the normal text field? (with text it worked fine) For me it seems like the additional features of rich text like formatting text are causing the problem.

I have no Idea what you do to change the content of the text item as you do not provide any code what makes debugging nearly impossible. The easy way to achieve what you want is to use a NotesItem and set its "IsSummary" Property to False.
Be aware: Don't store a document with such a value in frontend, otherwise the 32k limit will come back. Here is some example code:
Dim bigItem as NotesItem
'- for new docs
Set bigItem = New NotesItem( doc, "NameOfYourItem" )
'- for existing docs
Set bigItem = doc.GetFirstItem( "NameOfYourItem" )
bigItem.IsSummary = False
bigItem.Values = "YourIncredibleLongValue"
You cannot show items that are non summary in views (same as Richtextitems), so depending on what you want to achieve this might not be a solution for you.

As an alternative to Torstens answer on using a non summary field, you can use the Large Summary option introduced in Domino 9.01 FP8 to increase the limit to 64K for text fields:
load compact -LargeSummary on database.nsf

Related

Xpages how to sort preselected large amount data from view

I have a domino database with the following view:
Project_no Realization_date Author
1/2005 2015-01-02 Alex/Acme
3/2015 2015-02-20 John/Acme
33/2015 2016-06-20 Henry/Acme
44/2015 2015-02-13 John/Acme
...
Now I want to get all projects from this view that starts i.e with "3" (partial match), sort them by Realization_date descending and display first 1000 of them on Xpage.
View is large - some selection can give me 500.000 documents.
The FT search view option is not acceptable because it returns 5.000 docs only.
Creation of ArrayList or ListMap resulted with java out of memory exception (java Domino objects are recycled). Exceeding the memory may help of course but we have 30k users so it may be insufficient.
Do you have any ideas how can I achive this?
I think the key is goiong to be what the users want to do with the output, as Frantisek says.
If it's for an export, I'd export the data without sorting, then sort in the spreadsheet.
If it's for display, I would hope there's some paging involved, otherwise it will take a very long time to push the HTML from the server to the browser, so I'd recommend doing an FT Search on Project_no and Realization_date between certain ranges and "chunking" your requests. You'll need a manual pager to load the next set of results, but if you're expecting that many, you won't get a pager that calculates the total number of pages anyway.
Also, if it's an XAgent or displaying everything in one go, set viewState="nostate" on the relevant XPage. Otherwise, every request will get serialized to disk. So the results of your search get serialized to disk / memory, which is probably what's causing the Java memory issues you're seeing.
Remember FT_MAX_SEARCH_RESULTS notes.ini variable can be amended on the server to increase the (default) maximum from 5000.
500,000 is a very high set of results and is probably not going to make it very user-friendly for any subsequent actions on them. I'd probably also recommend restricting the search, e.g. forcing a separate entry of the "2015" portion or preventing entry of just one number, so it has to be e.g. "30" instead of just "3". That may also mean amending your view so the Project_no format displays as #Right("0000" + #Left(Project_no,"/"), 4), so users don't get 3, 30, 31, 32....300, 301, 302...., but can search for "003" and find just 30, 31, 32..., 39. It really depends on what the users are wanting to do and may require a bit of thinking outside the box, to quickly give them access to the targeted set of documents they want to action.
I would optimize data structure for your view. For example make a ArrayList<view entry>, that will represent the minimum information from your view. It mimics the index. The "view entry" is NOT Notes object (Document, ViewEntry), but a simplified POJO that will hold just enough information to sort it (via comparator) and show or lookup real data - for example Subject column to be shown and UNID to make a link to open that document.
This structure should fit into few hundred bytes per document. Troublesome part is to populate that structure - even with ViewNavigator it may take minutes to build such list.
Proper recycling should be ok but...
You could also "revert" to classic Domino URLS for ex ?yourviewname?ReadViewEntries&startkey=3&outputformat=JSON and render that JSON via Javascript UI component of some kind
If the filtering is based on partial match for the first sorted column, there's a pure Domino based solution. It requires that the Domino server is 8.5.3 or newer (view.resortView was introduced in 8.5.3), and that the realization_date column has click to sort.
Create a filtered collection with getAllEntriesByKey( key, false ) <-- partial match
Call view.resortView( "name_of_realization_date_column" )
Create a collection of all entries, now sorted by realization_date
Intersect the sorted collection with the filtered collection. This gives you the entries you want sorted by realization_date. E.g. sortedCollection.intersect( filteredCollection )
Pseudocode:
..
View view = currentDb.getView( "projectsView" );
view.setAutoUpdate( false );
ViewEntryCollection filteredCollection = view.getAllEntriesByKey( userFilter, False );
// Use index where view is sorted by realization_date
view.resortView( "realization_date" );
// All entries sorted by realization_date
ViewEntryCollection resortedCollection = view.getAllEntries();
resortedCollection.intersect( filteredCollection );
// resortedCollection now contains only the entries in filteredCollection, sorted by realization_date
..
I'm not certain if this would be faster than creating a custom data structure, but I would think it's worth to test :)

What exactly is a Lotus Notes document's "size" field?

Background is that I am trying to eliminate duplicated documents that have arisen (from a rogue replication?) in a huge database - tens of thousands of docs. I am composing a view field that uniquely identifies a document so that I can sort on that field and remove the duplicates via LotusScript code. Trouble is that there is a rich text "Body" field that contains most of the action/variability and you can't (AFAICS) use #Abstract in a view column...
Looking around for an alternative I can see that there is a system variable "size" which includes any attachments size, so I am tentatively using this. I note that duplicated docs (to the eye) can differ in reported size by up to about 30 bytes.
Why the small differences? I can code the LS to use a 30-byte leeway, but I'd like to know the reason for it. And is really 30 bytes or something else?
Probably document's item $Revisions has one more entry. That means that the document was saved one more time.
If the cause of this "copy thousands of documents" accident was replication then you might be lucky that documents contain an item $Conflict. This item contains the DocumentUniqueId of the original document and you could pair them this way.

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.

Display large rich text field values on to the web in XPages

I have a rich text field storing comma separated numbers (large numbers from 11111 to 99999 with three character prefix - so xxx11111, xxx11112 etc). I am using the appendText property and in the document I noticed that after around 16KB another rich text field with the same name is created.
But when I display this information on the web:
<xp:inputRichText id="inputRichText1" readonly="true" value="#{doc.RichTextField}">
</xp:inputRichText>
it's only displaying upto xxx16351. What am I missing here?
Any help would be appreciated.
You might want to alter your approach. What should work is Tim's MIME usage. So instead of RichText you write into a MIME field and the Domino engine takes care of size and rendering.
In any case, speak after me:
There is no RichText on the web, it is a ghost of Christmas past, there is only MIME.
Let us know how it goes
Is it only displaying the content from the first rich text field? I suspect that the value binding to fields will only retrieve from the first NotesItem with that name, rather than aggregating all NotesItems with that name.

Programatic control using Telerik OpenAccess ORM and the RadGrid

Ok, between following documentation, posts and videos that use syntax and tools that are no longer used or available, I'm really lost as to how to go about even using Telerik's OpenAccess. So I thought I'd ask for some help and hopefully someone out there has done this before.
I want to simply bind my OpenAccess entities to a RadGrid, but I want to use TemplateColumn in my RadGrid (in editmode, I want to use other controls like datepickers, dropdowns, etc.) Therefore, like the old way of doing things, I want to fire off the RadGrid's ItemDataBound event, for example, find the controls and set the controls to the appropriate values.
Old way that we were used to (You know, like the old fashioned way of something like setting a RadTextBox to a value from the RadGrid's DataSource, which was a DataReader:):
string strID = e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["campaignID"].ToString();
RadTextBox rtxtTitle = (RadTextBox)e.Item.FindControl("rtxtTitle");
rtxtTitle.Text = DataBinder.Eval(e.Item.DataItem, "title").ToString();
Does anyone have sample out there of how to do this? I would assume that I would also need to know how to bind the RadGrid in the first place, so an example of that would also be helpful (NOT using the actual OpenAccessDataSource control - I want to bind it in the NeedDataSource event of the RadGrid).
Thanks in advance...
The sample I found on the Telerik web site for DataBinding an OpenAccess result to a DataGrid looks like this:
IObjectScope scope = ScopeFactory.GetScope(HttpContext.Current);
string query = String.Format("SELECT * FROM {0}Extent", viewName);
IQueryResult result = scope.GetOqlQuery(query).Execute();
RadGrid1.DataSource = result.ToList();
This looks to be using OQL, but you could also use LINQ. I would toss this question to the OpenAccess team on the forums. They can probably point you to better resources.

Resources