Tuesday, January 28, 2014

Dynamically pointing DomSQL to current database

I couldn't find a way to specify current database in the .jdbc file, so I dug around in the API.

When creating the connection to a DomSQL database, you can do it with getConnection and the name of a .jdbc config file:
public static Connection getConnection() throws SQLException {
    return JdbcUtil.getConnection( FacesContext.getCurrentInstance(), "nameOf.jdbc" );
}

Or use createConnection and specify the path for the connection:
public static Connection getConnection() throws SQLException {
    String dbPath = null;
    try {
        dbPath = ExtLibUtil.getCurrentDatabase().getFilePath().replaceAll( "\\\\", "/" );
    } catch( NotesException exception ){
        // Ignore
    }
  
    return JdbcUtil.createConnectionFromUrl( FacesContext.getCurrentInstance(), "jdbc:domsql:" + dbPath + "/nameOf.domsql" );
}


If you haven't heard of DomSQL: JDBC Access for IBM Domino

Monday, January 27, 2014

HTML5, script tags and partial refresh inside target area

I had some issues with a script tag not loading inside a panel. The panel was set to only be visible when a view scope variable was set.

It turns out that this is by design for HTML5.

When script tags are inserted into a document using Ajax/innerHTML, the spec states that the script tag should not execute.

HTML5 spec
"...script elements inserted using innerHTML do not execute when they are inserted..."

My workaround for this was to set full refresh for the event that refreshed the panel.

Tuesday, October 8, 2013

Configuring input field for DateTime picker with localized date/time format

In a new application a colleague of mine is working on, he wanted to let the user set date and time with Norwegian date and time format.

One would think it should be pretty straightforward, but it took me around three hours to figure out how to do it. I accidentally discovered the way to do it while making a custom control with one field for date and one field for time. The custom control was meant to combine the two values into a date/time value. Luckily there's a simpler solution.

Source for Norwegian Date/Time picker:
<xp:inputText id="dateTimePicker" value="#{document.date_time}">
 <xp:this.converter>
  <xp:convertDateTime pattern="dd.MM.yyyy HH:mm" type="both" />
 </xp:this.converter>
 <xp:dateTimeHelper>
  <xp:this.dojoAttributes>
   <xp:dojoAttribute name="constraints" value="{ datePattern : 'dd.MM.yyyy', locale: 'no', timePattern: 'HH:mm' }" />
  </xp:this.dojoAttributes>
 </xp:dateTimeHelper>
</xp:inputText>

I tested/this should work on Domino 8.5.3 and Domino 9.

Monday, September 23, 2013

Simple workaround for partial refresh issues with radio buttons

Update, 14.03.14: I had some issues with this technique when used inside a ExtLib dialog. I suspect this has something to do with the dialog having it's own form. To make it work inside the dialog, I added a parameter for the execId. If I remember correctly, execId specifies the part of the XPages tree that should be processed. It can be the same as the target of the refresh.

Example of use with execId:
XSP.partialRefreshPost( '#{id:targetOfRefresh}', { execId: '#{id:targetThatShouldBeProcessed}' } );

I had some issues getting partial refresh triggered by radio buttons to work as I wanted to across browsers. I found a simple workaround. Instead of specifying the partial refresh in the event handler, I set no submission for the server side part, and execute a slightly delayed XSP.partialRefreshPost from the client side event action:
<xp:radioGroup id="someId" value="#{document.someField}" defaultValue="yes">
 <xp:eventHandler event="onclick" submit="false">
   <xp:this.script><![CDATA[setTimeout( function(){
 XSP.partialRefreshPost( '#{id:targetOfRefresh}' );
}, 50 );]]></xp:this.script>
 </xp:eventHandler>
 <xp:selectItem itemValue="yes" itemLabel="Yes" />
 <xp:selectItem itemValue="no" itemLabel="No" />
</xp:radioGroup>

This seems to work nicely across the browsers I tested in, regardless of triggering the value change through the radio button or the label.

Thursday, September 19, 2013

Strange implementation of Document.setPreferJavaDates( true )

I wanted to try the Document.setPreferJavaDates today and see how it worked.

I called Document.setPreferJavaDates( true ); to ensure that no (Notes)DateTime objects were created as I didn't need them/didn't want to deal with recycling.

First I tried:
Document.getItemValueDateTimeArray( "fieldname" );
This returned a Vector of DateTime.

Then I tried:
Document.getItemValue( "fieldname" );
This also returned a Vector of DateTime.

The way that finally worked as expected (returned a Vector of java.util.Date) was this:
Document.firstItem( "fieldname" ).getValues();

I would imagine this is the least used method among developers wanting to get a date value from a field. This code was executed on a server running Domino 8.5.3FP2

Wednesday, July 3, 2013

Workaround for issues with XPage in iframe on external website

Update, 03.03.14: We had some further issues with Chrome and form submission. Code snippet updated with workaround.

A colleague of mine had some issues with an XPage running in an iframe on a customer's website. The customer notified us that some users with Chrome/Safari had issues with the page going blank.

When doing partial refresh, the page went into a reload loop. I did a quick check, and couldn't find anything wrong with the code. I believe it has something to do with cross domain cookies and Webkit.

My workaround was to have a script block that adds the SessionID parameter that was previously added in certain circumstances on earlier versions of XPages. The script block is only loaded for Chrome/Safari, and the code only runs when the XPage is in a frameset/iframe.

<xp:scriptBlock>
 <xp:this.loaded><![CDATA[${javascript:return ( context.getUserAgent().isChrome() || context.getUserAgent().isSafari() );}]]></xp:this.loaded>
 <xp:this.value><![CDATA[(function(){
// Fix for safari/chrome when page is in iframe. Cookie with SessionID seems to be discarded between requests
// Workaround: Set parameter for SessionID
var queryString = document.location.search;
var sessionIdParameter = 'SessionID=' + '#{javascript:return facesContext.getExternalContext().getRequest().getSession().getId();}';
if( self !== parent && queryString.indexOf( 'SessionID' ) === -1 ){
 if( queryString === '' ){
  document.location.search = sessionIdParameter;  
 } else {
  document.location.search = queryString + '&' + sessionIdParameter;
 } 
}

// Add SessionID parameter to form action if set in URL to preserve session
if( queryString.indexOf( 'SessionID' ) !== -1 ){ 
 var form = document.forms[0];
 if( !form ){
  return;
 }
 
 var formAction = form.action;
 var parameterDelimiter = '&';
 if( formAction.indexOf( '?' ) === -1 ){
  parameterDelimiter = '?';
 }
 form.action = form.action + parameterDelimiter + sessionIdParameter;  
}
})();]]></xp:this.value>
</xp:scriptBlock>