I am checking a sessionScope variable in an XPage in beforePageLoad, and if it is null, setting it to a random value.
For some reason it often is equal to null, and so I keep losing the variable, even as quickly as 5 minutes even though I have the Session Timeout in the database set to 90 minutes.
I have tried the ExtLib KeepSessionAlive, set to as little as 180 seconds, no luck. I also tried the code here:
http://openntf.org/XSnippets.nsf/snippet.xsp?id=keeping-your-xpage-session-alive-%E2%80%93-without-keepsessionalive
This also does not seem to work. This is a test server so not under any load. I have always found sessionScope variables pretty reliable up to now. What am I doing wrong?
var cartID = sessionScope.cartID;
if (cartID == null) {
sessionScope.cartID = #Unique();
}
John,
Please make sure that you persist changes between requests, in your XSP Properties.
Also, John in reply to your comment: The debug toolbar is not going to communicate with the server for you. It just reports the actions that are taking place with your UI. It is an invaluable tool for me in tracking issues like you are having.
Related
Has anyone figured out a way to delete a time entry record from a time sheet record, without actually deleting the time sheet? My use case is that I have been syncing work time from JIRA to NetSuite for over a year now. When there is an error or they need to update their time, my integration just deletes it and recreates everything. Never an issue, since the time sheets are not submitted or approved yet, at that point.
Now, we have installed this SuitePeople bundle (sadly, the project managers working on that did not test anything...:/ ), which has completely changed time tracking. Aside from custom fields no longer showing up in the columns (a whole different issue), they are now generating generic timesheets for people to show time off. Those time sheets are not able to be deleted, and their time entries are not able to even be edited (presumably since they were created by the system - at least that's what NetSuite says).
My last hope is to add/edit/delete time entry records when the additional system generated time sheets have been added. But, anytime I try to delete a time entry, I'm given the error that timeentry is not a valid record type (since it is a subrecord).
Any thoughts? Feeling completely at a loss here...
This is good to know since I have a direct integration with JIRA worklogs as well but no SuitePeople.
Can you cancel/reject the timesheet?
Turned out that I had to run this through a RESTlet, where SuiteScript is able to directly search and delete time entry records. Here are the important parts of that script, in case anyone runs into this as well.
var timeEntrySearch=search.create({
type:'timeentry',
columns:[{name:'employee'},{name:'hours'},{name:'internalid'},{name:'memo'}],
filters:[{name:'date',operator:'within',values:[startDate,endDate]},{name:'employee',operator:'is',values:[userID]}]
}).run().each(function(result){
log.debug('results',JSON.stringify(result));
var memoField=result.getValue({name:'memo'});
if(memoField.indexOf('JIRA Time')!=-1){responseArray.push(result);}
return true;
});
for(var el in responseArray){
try{
log.debug('Deleting',JSON.stringify(responseArray[el].id));
record.delete({type:'timeentry',id:responseArray[el].id});
}catch(deleteErr01){
log.debug('ERROR[deleteErr01]',JSON.stringify(deleteErr01));
continue;
}
}
TypeAhead works fine If you don't have so many documents. If i delete lots of them typeAhead works. I think there is a limitation #DbColumn() in typeahead option.
How to solve this problem? It's like a 64k size problem but any suggestion is important
Thanks in advance
C.A.
Are you using #DBColumn() or #DBLookup() to populate your typeahead? They do have 64K limits. (I'm not sure as I read your question, so I ask for clarification).
If so, you might want to consider looking at links like this Can typeahead results be returned from a java function,
I've recently done one with a massive number of documents (millions). I used this, but since it was taking a lot of time to return, I changed it to get the first selected entry in the view (based on the value from the AJAX typeahead), created a ViewNavigator from that entry, and used the setBufferMaxEntires property to restrict the size of the returned ViewNavigator. This lets the process go quite fast.
Brian
UPDATE:
As requested. I started with using results like I linked above, then I added
ViewEntry startEntry = canQLView.getEntryByKey(searchValue, false);
allObjects.addElement(startEntry);
if (startEntry != null) {
ViewNavigator matchingEntries = canQLView.createViewNavFrom(startEntry);
matchingEntries.setBufferMaxEntries(10);
ViewEntry entry = matchingEntries.getFirst();
You can see I get a single entry rather than a ViewEntryCollection, start my ViewNavigator from that entry, and the setBufferMaxEntries property restricts how much is fetched - you can change it, but a low number is sensible since it's a typeahead.
Cheers,
Brian
Correct, there is the 64Kb limit on #DbColumn(), it's not an XPages-specific limitation and various blog posts confirm it. Ensure typeahead is only provided once the user has entered an appropriate number of characters that can restrict. After all, the typeahead should return a small number of entries for the user to select from, otherwise it's not much use. Then use #DbLookup with "[PARTIALMATCH]" or getAllEntriesbyKey. There are a number of blog posts available that give code samples.
Preamble: the last time I had an issue with something from the extension libraries, I immediately posted a bug report on openNTF.org. It then turned out that I had missed a property setting that made everything work perfectly. To prevent this issue from happening again, I decided to post the question here first, can anyone reproduce the error that I am having, or am I missing a property on the xe:DynamicViewPanel control?
tested ExtLib versions tested:
901v00_06.20140424-0600
901v00_02.20131212-1115
Domino/Notes version used Domino 9.0.1
Steps to reproduce
Create a dashboard XPage application. - data is stored in a different database.
Using a dynamicViewPanel control, access a database that lies ON THE SAME SERVER and show information from that database in the view.
Click on a document link in the dynamic view panel and look at the URL in the browser. When the dynamicViewPanel is pointing to a view in a different database hosted on the same server as the dashboard, the url looks like this : http://path/Portal.nsf/%24%24OpenDominoDocument.xsp?databaseName=CN=Maestro/O=hol-dev/C=DE!!path/Portal.nsf&documentId=A6727D8AF7D2FE19C1257C9E0034A14C&action=editDocument
The appropriate Xpage defined by the form name of the document being clicked on will open and the data saved in that document will even be loaded.
Click on a button that performs any action with the defined document datasource. It can be as simple as printing a string to the server when notesXspDoc.isNewNote(). You will get an error message saying that (in the case above) NotesXSPDocument.isNewNote() null. This means that the variable IS NOT null, but for some reason you are getting a null error response.
This error will only happen when the dashboard and the data database are on the same domino server. As soon as one of them are moved, it will work perfectly AND the URL will be correctly written; the server name of the databaseName parameter will be written in the abbreviated way.
In an attempt to understand/fix this issue, I took a closer look at the code in the Extension Library class com.ibm.xsp.extlib.component.dynamicview.UIDynamicViewPanel. There, I found the call to super(XspViewPanel).getDocumentUrl(). My guess is that the error lies in that function, but that is not a class that is defined by the ExtLibs. At the very least I would be interested to know what is written there.
educated guesswork
I am pretty certain of the following: The page when first open loads because key information is saved in the requestScope. This information is not not passed on to the java DominoDocument object which is created by the NotesXspDocument javascript 'class'. When (in the background) the DomDoc.restoreDocument() function is called, it tries to locate the database CN (as returned by the param.get("databaseName") function) and fails. Thus, no further function can be called on the object since an exception would always be thrown. (This is all an educated guess on my part)
My Questions clearly stated
Is this a known bug and I am just not finding it in my google searches?
Am I just not seeing a property of the ViewPanel that would fix this error?
Is there a better work around other than setting the "ignoreUrlParams" property of the document data source and calculating the server/documentID?
Thank you very much for all assistance given!
EDIT
Changing the "ignoreRequestParams" property to true and calculating the databaseName and the documentID does not make a difference at all. I am really confused as to why it does not work, I would think that calculating the source information and not paying any attention to the request parameters would solve it, but i am having the same issues. Any further assistance would be greatly appreciated!
After a great deal of testing, deleting functions and re-adding them, I think I have the answer I sought. I cannot really say why this is, and I find it a crappy design if my thoughts are correct.
I found that when I commented out a certain javascript line which opened the database in a background java class to find out the user's current roles, it worked again. Upon further investigation, when I took out the java lines that recycled the source database, the dashboard worked again. This means, however, that the background c++ object is still existing in the background somewhere. In this project, it seems to only be an issue when the source DB and dashboard DB are hosted on the same server.
I am going to answer my question with "No, this is not a bug in the dynamicViewPanel", but rather a questionable design from IBM itself. Either we should be recycling our Notes objects, or we should not be recycling our Notes objects, or we should be given a very detailed description of when and when not to recycle. Maybe I am just not used doing my own GC. Here is the code that was giving me a hard time (some variable names have changed to protect the anonymity of the customer):
public String getDatabaseRoles(){
Session session = null;
Database db = null;
Vector<String> roles = null;
try {
session = SessionHelper.getCurrentSession();
db = DatabaseController.getApplicationInstance().getDbFile().getDatabase();
roles = db.queryAccessRoles(session.getEffectiveUserName());
} catch (NullDatabaseException e) {
// already logged
} catch (NotesException e) {
ErrorWriter.getSessionInstance().writeError(new Date(), ErrorLevel.ERROR, "EprDatabaseController.getDatabaseRoles()",
e);
} catch (NullSessionException e) {
// already logged
} finally {
//if(db != null) try {db.recycle();} catch(NotesException e) {} //commented out due to issues when portal is on same server as data.
//if(session != null) try {session.recycle();} catch(NotesException e) {}
}
StringBuilder roleStr = new StringBuilder();
if(roles != null){
for(String role : roles){
if(!StringHelper.isNullOrEmpty(role)){
roleStr.append(role);
roleStr.append(":");
}
}
}
ErrorWriter.getSessionInstance().writeError(new Date(), ErrorLevel.TRACE, "DatabaseController.getEPRDatabaseRoles()",
"Database Roles: " + roleStr.toString());
return roleStr.toString();
}
Again, just so workarounds are already answered for future readers,
have the source database on a different server.
set the ignoreUrlParams property of the document datasource and calculate the the documentID and databaseName correctly inserting the server name as abbreviated.
This not being the true answer of my question, I am just putting this here for future user ease.
I have a lot of fields on a form. Not exactly sure how many but it has to be close to 100, if not over.
I have a change event of one field doing a partial refresh of a computed field with the following formula.
return document1.getItemValueString("txtCustomScore");
txtCustomScore is the field that has the event.
It takes 3-4 seconds to update this field. Are all of those other field somehow affecting how long it takes to refresh this field? It is taking 3-4 seconds.
I even tried getValue instead of getItemValueString. As suggested in this thread:
Setting a document field with replaceItemValue from a rich text control?
But it still takes 3-4 seconds to update the computed field.
Is there anyway to fix this other than eliminating fields from the form?
Yes it does. Even for a partial refresh all component values get evaluated and the server side result tree is built. As Tommy suggested, partial execution mode might be your answer
I strongly encourage you to watch the XPages Masterclass Video Series 1 (See: http://tonymcguckin.wordpress.com/2013/04/22/xpages-masterclass-series-1/).
From this you will then be able to introspect the XPages Request Processing Lifecycle phases and Profile your application. This will uncover the exact reasons behind the processing cost.
I'm having trouble with the webparts variables... I came from standard ASP language, so, to me, store variables in session and other parts is the common way to do everything =)
Now i had to create a webpart, the wp has to write a graph from parameter and i cannot understand HOW variables works: i cannot understand WHEN saved and WHEN erased and other thing like this!
Let me explain: i have a web part with the configuration toolbar on the right in which i put the values.. Everytime a button is pressed or a value in the dropdown list changes, it raises an event which causes the "CreateChild" function..
Many times the data is "stored", other time they are not!
That's the way i used to store value (in the ApplyChanges override function):
WPChartGenerator wpParent = (WPChartGenerator)this.ParentToolPane.SelectedWebPart;
wpParent.WebUrl = txtWebUrl.Text.Trim();
And in the CreateChild event i get the value like:
WPChartGenerator wpParent = (WPChartGenerator)this.ParentToolPane.SelectedWebPart;
this.ddlWeb = new DropDownList();
this.ddlWeb.ID = "ddlweb" + wpParent.ID;
ddlWeb.SelectedValue = wpParent.WebService;
Now.. Sometimes this works, for example, when i push a button I invoke in the code of the button and then the code to store every value.. In some case (like buttons) this works, in other (like dropdown list index changed event) this fails and i found every object in the wpParent equal to it's initial value.
Another thing i noticed, is that in certain cases when an event is triggered, the first thing to be executed (even first than the event's associated code) il CreateChild (even first than OnLoad!!!)
Can anybody tell me what I'm doing in the wrong way? Do anybody has a good tutoria for this matter?
Thanks & sorry 4 my School level English =)
Forget to say that every variable has been implemented as a Property, like that:
[WebBrowsable(false)]
[Personalizable(PersonalizationScope.Shared)]
[WebPartStorage(Storage.Shared)]
public string WebUrl
{
get
{
return this.webUrl;
}
set
{
this.webUrl = value;
}
}
I can't see all the code there so I don't really know what you're doing wrong (i.e. do you actually have an ApplyChanges method) but from the way you've worded your question it sounds like you really need to start at the beginning, follow one of these walkthrough tutorials and make sure you understand the basics and then start adding in the code for your project.
MSDN - Creating Web Parts for SharePoint (VS2010)
MSDN - Walkthrough: Creating a Basic SharePoint Web Part (WSS 3.0)
Developing SharePoint 2007 Web Parts