Keyword Library

My company has a native Domino database keyword library that select users can add to. It houses everything from Countries to Part Descriptions. I would not be surprised to find toilet paper brands housed in the keyword library. OK maybe not, but at almost 4,000 documents it has a lot of stuff that is referenced by multiple Domino databases. We also have lots more choices on existing forms that could be added to keyword library.

As I move content to XPages however I am learning DBLookup to a keyword library is not always the best way to do things.

I found a very cool Java XSnippet that works great for doing DBLookups to the keyword library and that is very useful for ever changing keywords – those that the user community updates on a daily, weekly, or even monthly basis.

I did have to post to the XPages Slack community because I had a little trouble getting lookup to reference another database. The XSnippet uses the following syntax to return data from your lookup view.

return org.openntf.Utils.Dblookup(database,”lookupCountries”,new org.openntf.Utils.Params(true,true,true,””,  “Keyword”));

It seemed no matter what I tried I received errors and I really lack the confidence to say hey this should work, what else could it be!

In the end John Jardin who knows boatloads more than I about Java and JavaScript (etc…) suggested to use the following in my JavaScript for my field:

var otherDb:NotesDatabase = session.getDatabase(database.getServer(), “filepath”);

return org.openntf.Utils.Dblookup(otherDb,”lookupCountries”,new org.openntf.Utils.Params(true,true,true,””,  “Keyword”));

I promise I tried that before but getting confirmation from John was enough to make me check other things when my look up still didn’t work. I ended up finding that I had not given Anonymous access to my local non replica copy of lookup DB.

However it was very good that I posted to Slack because Howard Greenberg with TLCC saw my post and questioned me about using DBLookup for static keywords, like Countries. He suggested instead I used Managed Bean for the countries and store that Bean it in the Application Scope via faces-config so it is stored for all the users. Thank you Howard.

Here is what I ended up doing:

/**
*
*/
package com.ibml;

import java.io.Serializable;
import java.util.ArrayList;

/**
* @author caysal
* be sure to add bean to faces-config.xml
* <managed-bean>
* <managed-bean-name>FormUtils</managed-bean-name>
* <managed-bean-class>com.ibml.FormUtils</managed-bean-class>
* <managed-bean-scope>application</managed-bean-scope>
* </managed-bean>
*
* Example of how to use on an XPage
* <xp:comboBox id=”comboBox2″ value=”#{viewScope.countries}”
* defaultValue=”USA”>
* <xp:selectItems value=”${FormUtils.countries}”>
* </xp:selectItems>
* </xp:comboBox>
*/
public class FormUtils implements Serializable {

/**
*
*/
private static final long serialVersionUID = 1L;

/**
*
*/
private ArrayList<String> countries;

/**
* @return the counties
*/
public ArrayList<String> getCountries() {
return countries;
}

/**
* @param countries
* the countries to set – list from state.gov
*/
public void setCountries() {
ArrayList<String> choices = new ArrayList<String>();
choices.add(“Afghanistan”);
choices.add(“Albania”);
choices.add(“Algeria”);
choices.add(“Andorra”);
choices.add(“Angola”);
choices.add(“Antigua and Barbuda”);
choices.add(“Argentina”);
choices.add(“Armenia”);
choices.add(“Aruba”);
choices.add(“Australia”);
choices.add(“Austria”);
choices.add(“Azerbaijan”);
choices.add(“Bahamas, The”);
choices.add(“Bahrain”);
choices.add(“Bangladesh”);
choices.add(“Barbados”);
choices.add(“Belarus”);
choices.add(“Belgium”);
choices.add(“Belize”);
choices.add(“Benin”);
choices.add(“Bhutan”);
choices.add(“Bolivia”);
choices.add(“Bosnia and Herzegovina”);
choices.add(“Botswana”);
choices.add(“Brazil”);
choices.add(“Brunei “);
choices.add(“Bulgaria”);
choices.add(“Burkina Faso”);
choices.add(“Burma”);
choices.add(“Burundi”);
choices.add(“Cambodia”);
choices.add(“Cameroon”);
choices.add(“Canada”);
choices.add(“Cape Verde”);
choices.add(“Central African Republic”);
choices.add(“Chad”);
choices.add(“Chile”);
choices.add(“China”);
choices.add(“Colombia”);
choices.add(“Comoros”);
choices.add(“Congo, Democratic Republic of the”);
choices.add(“Congo, Republic of the”);
choices.add(“Costa Rica”);
choices.add(“Cote d’Ivoire”);
choices.add(“Croatia”);
choices.add(“Cuba”);
choices.add(“Curacao”);
choices.add(“Cyprus”);
choices.add(“Czech Republic”);
choices.add(“Denmark”);
choices.add(“Djibouti”);
choices.add(“Dominica”);
choices.add(“Dominican Republic”);
choices.add(“East Timor (see Timor-Leste)”);
choices.add(“Ecuador”);
choices.add(“Egypt”);
choices.add(“El Salvador”);
choices.add(“Equatorial Guinea”);
choices.add(“Eritrea”);
choices.add(“Estonia”);
choices.add(“Ethiopia”);
choices.add(“Fiji”);
choices.add(“Finland”);
choices.add(“France”);
choices.add(“Gabon”);
choices.add(“Gambia, The”);
choices.add(“Georgia”);
choices.add(“Germany”);
choices.add(“Ghana”);
choices.add(“Greece”);
choices.add(“Grenada”);
choices.add(“Guatemala”);
choices.add(“Guinea”);
choices.add(“Guinea-Bissau”);
choices.add(“Guyana”);
choices.add(“Haiti”);
choices.add(“Holy See”);
choices.add(“Honduras”);
choices.add(“Hong Kong”);
choices.add(“Hungary”);
choices.add(“Iceland”);
choices.add(“India”);
choices.add(“Indonesia”);
choices.add(“Iran”);
choices.add(“Iraq”);
choices.add(“Ireland”);
choices.add(“Israel”);
choices.add(“Italy”);

choices.add(“Japan”);
choices.add(“Kazakhstan”);
choices.add(“Kenya”);
choices.add(“Kiribati”);
choices.add(“Kosovo”);
choices.add(“Kuwait”);
choices.add(“Kyrgyzstan”);
choices.add(“Laos”);
choices.add(“Latvia”);
choices.add(“Lebanon”);
choices.add(“Lesotho”);
choices.add(“Liberia”);
choices.add(“Libya”);
choices.add(“Liechtenstein”);
choices.add(“Lithuania”);
choices.add(“Luxembourg”);
choices.add(“Macau”);
choices.add(“Macedonia”);
choices.add(“Madagascar”);
choices.add(“Malawi”);
choices.add(“Malaysia”);
choices.add(“Maldives”);
choices.add(“Mali”);
choices.add(“Malta”);
choices.add(“Marshall Islands”);
choices.add(“Mauritania”);
choices.add(“Mauritius”);
choices.add(“Mexico”);
choices.add(“Micronesia”);
choices.add(“Moldova”);
choices.add(“Monaco”);
choices.add(“Mongolia”);
choices.add(“Montenegro”);
choices.add(“Morocco”);
choices.add(“Mozambique”);
choices.add(“Namibia”);
choices.add(“Nauru”);
choices.add(“Nepal”);
choices.add(“Netherlands”);
choices.add(“Netherlands Antilles”);
choices.add(“New Zealand”);
choices.add(“Nicaragua”);
choices.add(“Niger”);
choices.add(“Nigeria”);
choices.add(“North Korea”);
choices.add(“Norway”);
choices.add(“Oman”);
choices.add(“Pakistan”);
choices.add(“Palau”);
choices.add(“Palestinian Territories”);
choices.add(“Panama”);
choices.add(“Papua New Guinea”);
choices.add(“Paraguay”);
choices.add(“Peru”);
choices.add(“Philippines”);
choices.add(“Poland”);
choices.add(“Portugal”);
choices.add(“Qatar”);
choices.add(“Romania”);
choices.add(“Russia”);
choices.add(“Rwanda”);
choices.add(“Saint Kitts and Nevis”);
choices.add(“Saint Lucia”);
choices.add(“Saint Vincent and the Grenadines”);
choices.add(“Samoa “);
choices.add(“San Marino”);
choices.add(“Sao Tome and Principe”);
choices.add(“Saudi Arabia”);
choices.add(“Senegal”);
choices.add(“Serbia”);
choices.add(“Seychelles”);
choices.add(“Sierra Leone”);
choices.add(“Singapore”);
choices.add(“Sint Maarten”);
choices.add(“Slovakia”);
choices.add(“Slovenia”);
choices.add(“Solomon Islands”);
choices.add(“Somalia”);
choices.add(“South Africa”);
choices.add(“South Korea”);
choices.add(“South Sudan”);
choices.add(“Spain “);
choices.add(“Sri Lanka”);
choices.add(“Sudan”);
choices.add(“Suriname”);
choices.add(“Swaziland “);
choices.add(“Sweden”);
choices.add(“Switzerland”);
choices.add(“Syria”);
choices.add(“Taiwan”);
choices.add(“Tajikistan”);
choices.add(“Tanzania”);
choices.add(“Thailand “);
choices.add(“Timor-Leste”);
choices.add(“Togo”);
choices.add(“Tonga”);
choices.add(“Trinidad and Tobago”);
choices.add(“Tunisia”);
choices.add(“Turkey”);
choices.add(“Turkmenistan”);
choices.add(“Tuvalu”);
choices.add(“Uganda”);
choices.add(“Ukraine”);
choices.add(“United Arab Emirates”);
choices.add(“United Kingdom”);
choices.add(“Uruguay”);
choices.add(“USA”);
choices.add(“Uzbekistan”);
choices.add(“Vanuatu”);
choices.add(“Venezuela”);
choices.add(“Vietnam”);
choices.add(“Yemen”);
choices.add(“Zambia”);
choices.add(“Zimbabwe”);

this.countries = choices;
}

public FormUtils() {
// TODO Auto-generated constructor stub
setCountries();

}

}

 

 

 

XPiNC open URL link in OS default browser

My company has quite a lot of legacy Domino application that were developed in house and are actively used today. I am adding XPage content to them as fast as I can but have met with lots of resistance along the way. To my users new is not always better, and change is proving a challenge. Making XPages look like native Domino applications is not on my to do list, I tried that and it is pretty hard! (not to mention foolish)

One of the things that I realized that might help them would be a common menu structure for all of the XPage applications, but also to bringing that same menu to the notes client via XPiNC and serve up the legacy Domino applications as well.

This menu (Extension Library navigator and carousel) would replace the current legacy page based menu that provides action and hotspot URL type links to all the native domino applications along with links to external sites that are relevant to our employees…a fancy version of a workspace.

Oh boy.

The links to notes applications (notes://server/app.nsf) worked great. The links to URLs however open in XULRunner and that is not what I wanted. We don’t use the embedded browser in my company. After beating my head against Google for a while and not finding a solution I posted a message to the Slack XPages Community.

Chris Toohey took time out of his day to provide me with a Java snippet and several helpful links.

Here is the Java snippet he provided:

package com.dominoguru.xulHack;
public class xulPunter {
    public static void punt(String url) {
        try {
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec("rundll32 url.dll,FileProtocolHandler " + url);
        }
        catch(Exception e) {
            e.printStackTrace();
     }
    }       
}

 

We only have a handful of non – Windows clients but again thanks to Chris Toohey I used this link Launch Browser in Mac, Linux, Unix : Mac « Development Class « Java to further modify the Java to include them.

Then just in case he also provided me with a link for how to include this in my project build path. Adding a Java Script Library to the Project Build Path for SSJS and XPage Development

He also showed me how to utilize it in an XPage.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view
 xmlns:xp="http://www.ibm.com/xsp/core">

 <xp:link text="Launch Google in Default Browser"
 id="link1">
    <xp:eventHandler event="onclick" submit="true" refreshMode="partial">
        <xp:this.action>
           <![CDATA[#{javascript:
importPackage(com.dominoguru.xulHack);
xulPunter.punt("http://www.google.com");}]]>
        </xp:this.action>
    </xp:eventHandler>
 </xp:link>

</xp:view>

I tested and it worked great. However I ran into an issue using this in my <xe:navbar>. I didn’t realize that by placing SSJS in the onClick event for my basicContainerNode all my links would fire at page load. Not what I was going for either.

Jesse Gallagher and Paul Withers then suggested that I should use the submitValue of the basicContainerNode and then use someContainerControl.getSubmittedValue to read the submitValue.

Remember I am new at this, and I am sure there might be a better way but here is what I ended up doing to make my <xe:navbar> links work. Each basicContainerNode that needs to open URL in default browser has a submitValue

Then I have an if statement that gets that submitValue and passes a value to the sessionScope.myLink and then redirects to the page that opens in an external browser.

 

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex"
   xmlns:xc="http://www.ibm.com/xsp/custom">
 
   <xe:navbar id="navbarAll" headingText="Main Menu" fixed="unfixed-top">
     <xp:eventHandler event="onItemClick" submit="true"
        refreshMode="partial" refreshId="computedField1">
        <xe:this.action>
            <![CDATA[#{javascript:

if (context.getSubmittedValue()== "1") {
sessionScope.myLink = "https://server.domain.com/files/app";
context.redirectToPage("myLinkPage.xsp");
} else if (context.getSubmittedValue()== "2") {
sessionScope.myLink = "https://server.domain.com/wikis/home?lang=en-us#!/wiki/ibml%20Cookbook/page/Welcome";
context.redirectToPage("myLinkPage.xsp");
};
}]]>
         </xe:this.action>
     </xp:eventHandler>
     <xe:this.navbarBeforeLinks>
         <xe:pageTreeNode image="/logo.gif"></xe:pageTreeNode>
     </xe:this.navbarBeforeLinks>
     <xe:this.navbarAfterLinks>
 
        <xe:basicContainerNode label="Corporate">
          <xe:this.children>
             <xe:basicLeafNode label="Connections Files - Corporate Forms"
                 submitValue="1">
             </xe:basicLeafNode>
             <xe:basicLeafNode label="CookTrac" 
                 submitValue="2">
             </xe:basicLeafNode>
          </xe:this.children>
        </xe:basicContainerNode>

      </xe:this.navbarAfterLinks>
 </xe:navbar>

<xp:text escape="true" id="computedField1"
 value="#{sessionScope.myLink}" style="font-weight:bold" rendered="false">
</xp:text>
 
 </xp:view>

Of course my real menu is much more complex. I also did end up putting a context.redirectToPage(“myMenu.xsp”) on myLinkPage.xsp to reopen the main menu as it closes when the link is clicked. (There is likely a better way to do this.)

I was so excited that my menu was working (for me at least) that I forgot that my notes clients have older version of Extension Library and was sad to see the Error 500 and the subsequent error messages in the logs pointing to version when they tried my menu in the notes client. So now off to fight that battle. Good thing I have the XPages Extension Library book and such a great community to help me along.

 

Notes 9.0.1 64-bit for Mac Open Database Issues

I have  PMR  81399,442,000 opened for this because I have never seen this behavior before and have been working with Notes and Domino for over 20 years. I have been scouring the internet trying to find others with these same issues.

We have less than 10 Mac users in our company. Recently they were all upgraded to OS X El Capitan 10.11.3 and IBM Notes 9 64-bit. I am not desktop support or the Notes Administrator anymore, but I have lived in both worlds many moons ago and this issue has fallen into my lap because there has been much finger pointing at database design.

The databases that are having the issues were created over 14 years ago and run rock steady on Windows and Notes. These database are simple form and view databases. Yes their might be an XPage or ten in the database, but they are not being utilized yet.

What is the behavior? Well you click on a database link  or choose File – Open -IBM Notes Application (so far we are seeing this on 3 different databases and perhaps even mail) and it may or may not open to display content to the user. Why would I phrase it like that? A database either opens or it doesn’t, right? If you do a File – Open -IBM Notes Application and nothing happens the database is not open, right? That is what I thought too, until I took a look at the administrator console server status for the user experiencing the issue with database not opening and noticed that the database was showing as open for that user. Then I noticed I could do file application properties on the client and bring back information for the database even though you do not see the database as open?!? Help About this Application same thing.

Closing all tabs and then closing Notes will sometimes allow the database to open correctly the next time. (Most my users have the Notes Preference set for tabs to reopen when Notes starts. I think that is horrible idea, but I have been told people are different from me so…) Sometimes to get the database to display content you have to start opening other database (that are not having the trouble) first. It is not a open delay. These databases open fairly quickly. I have been working for some time to audit all the views selection formulas and column formulas to speed up things.

Sending a view link to the user in an email and having them click on that seems to open the view consistently. I should note that changing the default database view might work for a minute but then the problem returns.

Running in basic mode allows for database open correctly ever time. (it seems) Which from my understanding means that java is not being used.

Moving desktop8.ndk to the trash when things get good and borked also will allow for database open for a little while, sometimes. Clearing out expediter is iffy too.

Did I mention Mac client responsiveness is slow? Oh and sometimes mail goes to “not responding” then if the user closes the mail tab they cannot get mail to open again until they close Notes and reopen? I really wonder if this is the same behavior presenting on the mail database but have not been informed WHEN it was happening only AFTER.

Why am I posting this rant? Hopefully someone will see it and post a solution to the comments before IBM gets back to me on the PMR. This is a frustrating very inconsistent issue that is taking up way too much development time.

 

***IBM just released 9.0.1 FP3 for 64 bit version of Notes and that seems to have resolved this issue.***

Ytria scanEZ made my life EZ today

Came across an issue in one of my databases where response and response to response documents were not showing for ONE system in any view that was using @AllDescendants or @AllChildren. The documents did show in the embedded views because those views do not use parent child relationships for the display of children. They are tied to a specific unique ID.

The parent preview was working (scratching my head about this one) so I assumed that the parent child relationship was in tact. Contraire mon frère.  I opened the response document in Ytria tool and then tried to open the link to the parent from the response and I got this…

Error reading document (NoteID : 399134)
Invalid or nonexistent document (551) while opening by NoteID expand(0x6171e) (Y735)
[NotesDatabase]
Server = server/domain
Path = folder\database.nsf

I opened the document that I thought was the parent directly and it had a different NoteID than this invalid or nonexistent document.

I then used Ytria’s tool to delete the $REF field from all the response documents and then used the Ytria action Document – Set New Parent to Response to recreate the $REF field using the other parent’s Note ID. Note, you have to delete the existing $REF field first or you will be scratching your head as to why the process doesn’t work.

What happened? The user says “I was in the document.  I pasted the wrong folder in “Attachments or other details related to this document”. so I deleted the folder. After that I couldn’t access anything. When I refreshed the view the document was gone.”

I should note that the user doesn’t have access to delete the document.

I have no idea why the original parent document is Invalid or nonexistent. I cannot open it of course. I can only assume corruption and that this other document must be a replication conflict. Waiting to see if their are any other problems from this one.

The Trouble with Pickers

This really should not have been troublesome, but for me as a new XPage developer it was. So for any new XPage developers who think like me (backwards), and decide to blame the picker, here is potentially a solution to your trouble.

I created a new application for our production planning department based off of the Extension Library ToDo application. I liked the look and feel of the dashboard but needed additional workflow in the application.

One of the things that was needed was the ability to email out of the application for each of the ToDo documents. I utilized Tony McGuckin’s emailBean for this. Thank you Tony! It works great!

https://openntf.org/XSnippets.nsf/snippet.xsp?id=emailbean-send-dominodocument-html-emails-cw-embedded-images-attachments-custom-headerfooter

Initially I tried to email out without the picker, and it worked fine. I had a sendTo field, a simple edit box, and was able to type in multiple email addresses separated by comma or semi-colon and the recipient had no trouble receiving the email.

So my next step was to add a picker, and define type ahead for my field. Unfortunately then my emails stopped sending to multiple people and I blamed the picker.

Poor picker, it wasn’t his fault, but my assumption took me down the wrong road and I tried without success to find a solution. Time is a precious commodity, so I left the picker out and moved on to other projects deciding to come back to the picker problem when I had time. (after all the users are not even utilizing my production planning application)

Anyway long story short, when I finally did circle back to this project it didn’t take long for me to figure out what was wrong. There is a bug with Multi-Value fields

http://www.intec.co.uk/workaround-for-multi-value-fields-bug/

Had I enabled multipleSeparator on my edit box prior to adding the picker I would have run into the same issue and it would have made more sense to me and landed me at a solution earlier, but when things “work” for me I tend to accept them and move on to the next thing.

Extension Library Update Broke My Data View

OK well I really can’t blame it on Extension Library update. I broke my Data View but an Extension Library update revealed the folly of my ways. I wish I knew if it was update 15 or 16 that was the culprit, but what I do know is that my Data View controls were working fine before the update and not so much after.

The exception thrown was:

java.lang.NullPointerException
 at com.ibm.xsp.theme.bootstrap.renderkit.html.extlib.data.DataViewRenderer
.writeDataColumn(DataViewRenderer.java:319)

Turns out my problem was that I did not have a xe:viewSummaryColumn defined.

<xe:this.summaryColumn>
 <xe:viewSummaryColumn></xe:viewSummaryColumn>
 </xe:this.summaryColumn>

I have not used that xe:summaryColumn consistently in all my Data Views. Why? Well they worked fine without it. I am pretty sure I was breaking the rules. Me = Code Rebel. I had the summary information defined inside <this.facets> for the Data View.

Now I have to go back and in all my XPages and add xe:viewSummaryColumn. Don’t be like me.

Getting Connected

I just returned from IBM Connect 2016 and it was inspirational. I have been to Lotusphere, now IBM Connect, every year since 2004 (I think). Some years packed with content, other years not so much but every year I have left the conference knowing I would be back the next year. Last year (2015) I left the conference feeling like I had lost a friend. For years I had watched the IBM Champions and guest speakers present and interact with the community, and I had followed their wisdom in their blogs to the point where I also felt like I was part of their community, even if a silent part. Last year with the possibility that their would not be another conference I felt like that community was at a breaking point.

It made me re-evaluate the direction that I was going as a developer. I started concentrating on JavaScript, CSS, HTML, and Java. Which was really not a bad thing at all, but thank goodness I was wrong. If anything that threat has made the community stronger. I left the conference this year with renewed excitement about the wonderful products that are IBM Domino, IBM XPages, and IBM Connections. I also left with the feeling that I needed to try to become a more social part of that community.

Here goes nothing…