Showing posts with label random tip. Show all posts
Showing posts with label random tip. Show all posts

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.

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 6, 2012

Snippet to clear session for user

During testing, I sometimes log in as different user to test hide/whens/etc. I used to delete the SessionID cookie in the browser to clear session scoped beans/sessionScope variables. Today, I looked for a solution to automate this. This line will clear all objects related to a session:
facesContext.getExternalContext().getSession( false ).invalidate();
If you want to clear session when logged in user changes for the current "XPages" session, here's the snippet I use (put the code in afterPageLoad or beforePageLoad):
// Reset session when user changes
var currentUserName = sessionScope.currentUserName;
var userName = session.getEffectiveUserName();
if( currentUserName && userName !== currentUserName ){
 facesContext.getExternalContext().getSession( false ).invalidate();
}   
sessionScope.currentUserName = userName;
I would think this is better than deleting the cookie, as the server is immediately notified that it should flush the objects bound to the session. When I delete the cookie, I believe that the objects are kept in memory until a specified timeout.

Monday, August 20, 2012

Comprehensive guide to Design Definitions

I found this guide in IBM's Application Development wiki while looking for information on Design Definitions:
Native and Custom Control Custom Visualization Best Practices

So far it's the most comprehensive guide to Design Definitions I've found.

Monday, June 25, 2012

Multi value fields and Beans in XPages

I had an issue with multi value fields bound to bean fields in an XPages I worked on.

I got this error message on refresh:
java.lang.IllegalArgumentException: argument type mismatch

The issue turned out to be a somewhat inconsistent underlying API. When the field is empty, or has single value, it tries to set a string. When there are multiple values, it tries to set a list.

To work around the issue, have the getter return an Object, and the setter accept an object.
E.g.

public Object getInputMulti() {
 return this.inputMulti;
}
...
@SuppressWarnings( "unchecked" )
public void setInputMulti( Object inputMulti ) {
 if( inputMulti == null ){
  this.inputMulti = null;
 }
 
 if( inputMulti instanceof String ) {
  Vector inputNameList = new Vector();
  inputNameList.add( (String) inputMulti );
  this.inputMulti = inputNameList;  
 }
 if( inputMulti instanceof List ) {
  this.inputMulti = (Vector) inputMulti;
 }
}

You can have the translation for the setter be done in a utility method. E.g.
@SuppressWarnings("unchecked")
public static Vector translateToVector( Object object ){
 if( object instanceof String ){
  Vector list = new Vector();
  list.add( object );
  return list;
 }
 
 if( object instanceof List ){
  return (Vector)object;
 }
 
 return null;
}

Then, for the setter:

@SuppressWarnings( "unchecked" )
public void setInputMulti( Object inputMulti ) {
  this.inputMulti = UtilityClass.translateToVector( inputMulti );
}

Example of multi value fields: Checkbox group, multi value fields (fields with multipleSeparator), list boxes.

Thursday, May 31, 2012

Improving performance in Domino Designer when developing XPages

If the XPage has a view data source/the view name is a static value, it looks like Domino Designer is constantly polling the view for column info/etc.

If you are done dragging and dropping columns from the view to the view panel/etc. Go into source mode and compute the viewName.

Before

<xp:dominoView var="view1" viewName="MyView" />

After

<xp:dominoView var="view1" viewName="${javascript:return 'MyView'}" />

When the view name is computed, Domino Designer can't determine what view it should check -> No more lag.

I haven't tested this with Document Data source, but you might get a performance boost if you compute the formName as well, as Domino Designer won't have to check the fields for drag/drop.

Optimally I would wish the Designer team implemented a refresh fields/columns button for the data pane.

Share and enjoy!

Thursday, April 19, 2012

XPages Toolbox - Really nice profiling tool

If you feel that your XPage application is too slow, XPages Toolbox can help you to find the biggest bottlenecks in your code.

If you haven't tried it, I highly recommend that you give it a spin (it's free). If you like it, give it a good rating.

+1 to Philippe Riand for sharing it with the community :)

Thursday, March 15, 2012

Showing horizontal notes data as vertical in view

Today at work, I needed to transfer some data from a Notes application to SQL. The documents in question were horizontal.

An example of what I mean:
An order form in Notes with five order lines. For each line, there may be five fields that contains information about the order. Making it a total of 25 fields for five order lines.


Traditionally, if you want to show this data in a regular notes view, you have to have a column per field.


Thanks to the way the index is organized in a Notes view, you can show this data vertically using Show multiple values as separate entities.


A summary of the technique:
  • In each column, create a list of the field values that you want to show
  • Each column list has to have equal amount of values
  • Each column has to have Show multiple.. property enabled
  • Only the first column can be sorted (it can be categorized), or you end up with a lot of rows.
    This is probably due to how the index is organized/matching of multiple values

Here's the demoapp I took the screenshots from:
>> Download

Take a look at the Vertical view to see the technique I used.

Thanks to this technique, I can simply pull the data from a view using view entries/column values/send row by row to a stored procedure in SQL. The alternative would be to write code for each field.

Share and enjoy! :)

Thursday, January 26, 2012

Runtime optimized JavaScript and CSS - workaround for multiple stylesheets

Update: This workaround is only needed if you use "folders" in the image resource name.
E.g. backgrounds\home.png.

If you have multiple local stylesheets on a page, the CSS files are combined into a single file.

This changes the url to the stylesheet (adds xsp/.ibmmodres/.css after the path to the db).

If you have an image reference like url(image.png), the image can no longer be loaded, as the url is relative to the path of the stylesheet.

To work around this issue, add ../../../ to the image reference.

E.g.
url(../../../image.png)

Thursday, January 5, 2012

Useful tool when working with text files (CSV, source code, etc)

WinGrep is a tool that let's you search one/several folders for parts of strings. It supports searching in zip files, and lets you use Regular Expression (Perl syntax?) for searching strings.

The result pane shows all the matching lines in the file(s) you are searching.

Monday, January 2, 2012

Thing to be aware of when using "Generate unique keys.." in view

I had trouble with a couple of views today. The views had the option Generate unique keys in index checked.

When the views were replicated to other servers, they weren't built. When trying to open them I got the error message Entry not found in index

I found the solution on the Domino forums, add @IsUnavailable($Conflict) to the view selection.

Tuesday, December 13, 2011

ClassNotFoundException with the new Java design element

Last week Vince Shuurman blogged about having to recompile when opening an XPage app in Domino Designer.

I had the same issue. I was using some Java code in an XPage, and every time I opened the app in designer, I got ClassNotFoundException when opening the XPage. A build of the project fixed the issue.

My java code was in the new Java design element (new in Domino 8.5.3), so I suspected that it might have something to do with this.

I moved the code to a "custom" java source folder, and the error went away. Closing/opening the app in Designer did not result in ClassNotFoundException.

Friday, October 21, 2011

Java Debugging in Designer without hacks

I found this today: How can I enable Java debugging?.

Not sure if this is new in 8.5.3, but I never heard of it. It makes it a lot easier to debug than the using the two headed beast method which seemed like too much trouble.

The full instructions are in the Designer help. Search for java debugging.

Wednesday, September 28, 2011

Collecting data for HTTP hang or performance issues on a Lotus Domino server

We're currently having problems with one of our old Domino servers. The HTTP task randomly hangs.

In the process of looking for help to track down the reason, I found this document from IBM.

Collecting data for HTTP hang or performance issues on a Lotus Domino server

Monday, September 26, 2011

Using themeId for maintainability

In an application I'm currently working on, there are several categorized views with number-/totals columns. As the number of views/columns increased, I looked for a way to make styling of the columns more maintainable.

The solution I found was using themeId on the columns and calling a SSJS function in the theme, that generates the style classes.

I chose numberColumn as the name for the themeId.

In theme

<control>
<name>numberColumn</name>
<property>
<name>styleClass</name>
<value>#{javascript:return StyleHelper.getNumberColumnStyleClass( this );}</value>
</property>
</control>
this refers to the column object.


SSJS code

var StyleHelper = {
// Used to calculate styleClass for a number column
getNumberColumnStyleClass: function( column ){
try {
var entry = column.getViewRowData();
var styleClass = 'numberCell';
if( entry.isCategory() ){ styleClass += ' categoryCell'; }
if( entry.isTotal() ){ styleClass += ' totalsCell'; }
return styleClass;
} catch( e ){ /* Exception handling */ }
}
}

Regular column cells will get class="numberCell".
Totals column cells will get class="numberCell totalsCell".
Category column cells will get class="numberCell categoryCell".

All I have to do to add dynamic styling to future columns is to set themeId on the column to numberCell.

Wednesday, July 13, 2011

XPages: Styling required and invalid fields

Just discovered that in Domino 8.5.2 (not sure about previous releases), invalid fields get the attribute aria-invalid=true, and required fields aria-required=true.

That makes it easy to style in modern browsers (>IE6).

Simply add a couple of style rules (just an example):
[aria-required=true] { background-color: #ffe; }
[aria-invalid=true] { background-color: #fee; border-color: red; }

Valid - required fields "highlighted"


Invalid


+1 to IBM for implementing :)

Share and enjoy!

Tuesday, July 12, 2011

Small tip regarding optimizing FTSearches

Lately I've been working on SQL (MS). At work today, I had a talk about optimizing queries with a colleague more seasoned in the art of writing queries. We got into a talk about if the order of the filter statements (WHEN ..=..) and performance. Apparently, MS have optimized their engine so that the order of the filtering statements don't have much influence on the performance of the query.

This got me thinking about FTSearch. A year or so ago, I thought about doing some testing on how you could structure an FT query to get the best performance, but never got around to do it.

I did a little test today, and it seems like the order of the filters doesn't influence the result much. One thing that seems to heavily influence the result is if one of the query items alone results in a lot of documents.

If you search for "Tom", and the value "Tom" is in a field in a lot of documents, this will drag down the result, no matter if another query item in the query would result if only one document being returned from the query.

Example from test:
Searching for 'abigail AND abbott' - 2-5ms to get result.
Searching for '[Form=Person] AND abigail AND abbott' - 15-20ms to get result.

Conclusion from my test. Query items in a FTSearch that alone results in a lot of documents drags down the performance of the entire query. Order of query items doesn't seem to influence the performance of the query.

If you're building a search engine for databases with a lot of documents, try to avoid having general filters (Form/etc.) if possible.

Tuesday, June 21, 2011

Tip for those working with Database events in 8.5.x designer

If you're working with Open/Close events, it's quite cumbersome when you want to test your code. You have to close the app in both Domino Designer and Notes. I used to close the designer every time I wanted to test modified code.

During a chat, Tim Tripcony mentioned that you could close the apps in Designer from the Package Explorer. In Package Explorer, each app is shown as a project. To release the app from Designer, simply right click the project, and select close project. No need to remove the app from Designer or close Designer to release the app from memory.

Share and enjoy! :)

Creating your own keyboard shortcuts in Domino Designer

File -> Preferences --> General -> Keys

I currently have two custom keyboard shortcuts, Alt + b to build a single project, and Alt + c to close a project in Package Explorer.