<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Flaz Blog</title>
	<atom:link href="http://flaz.biz/feed/" rel="self" type="application/rss+xml" />
	<link>http://flaz.biz</link>
	<description>Consulente informatico e sviluppatore. Adoro la musica metal, le serie tv, la pizza e il mio cane Baxter!</description>
	<lastBuildDate>Sat, 12 Nov 2016 15:45:32 +0000</lastBuildDate>
	<language>it-IT</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.5.4</generator>
	<item>
		<title>Convert ANSI text file to UTF-8 with PowerShell</title>
		<link>http://flaz.biz/2016/06/convert-ansi-text-file-to-utf-8-with-powershell/</link>
		<comments>http://flaz.biz/2016/06/convert-ansi-text-file-to-utf-8-with-powershell/#respond</comments>
		<pubDate>Tue, 14 Jun 2016 12:05:21 +0000</pubDate>
		<dc:creator><![CDATA[Massimo]]></dc:creator>
				<category><![CDATA[Sistemi]]></category>
		<category><![CDATA[ansi]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[utf-8]]></category>

		<guid isPermaLink="false">http://flaz.biz/?p=194</guid>
		<description><![CDATA[Years ago, to riduce the size of a Domino database, I scheduled a simple export task to a text file in CSV format. Now, I need to import back those files in a RDBMS: PostgreSQL. I didn&#8217;t defined the file format (damn&#8230;), so all the files are, by default, in ANSI code and US-ASCII charset. [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Years ago, to riduce the size of a Domino database, I scheduled a simple export task to a text file in CSV format.</p>
<p>Now, I need to import back those files in a RDBMS: PostgreSQL.</p>
<p>I didn&#8217;t defined the file format (damn&#8230;), so all the files are, by default, in ANSI code and US-ASCII charset.</p>
<p>Before importing these files in PostgreSQL I needed to do some substitutions in regexp, but both using Notepad++ or bash I always get wrong characters, even converting the file to UTF-8. After spending <strike>some</strike> too much time using Notepad++, TextPad and bash, I finally found a very simple solution using <b>Windows PowerShell</b>:</p>
<p><code>Get-Content archive-2011.csv | Out-File -Encoding UTF8 -filepath archive-2011-utf8.csv</code></p>
<p>That&#8217;s it!</p>
<p>For unknown reasons, I had some duplicated lines in my files. And, again, PowerSheel can do the job with in one line only:</p>
<p><code>gc archive-2011-utf8.csv | sort | get-unique > archive-2011-utf8-unique.csv</code></p>
]]></content:encoded>
			<wfw:commentRss>http://flaz.biz/2016/06/convert-ansi-text-file-to-utf-8-with-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Coding the customizerBean in Dynamic View Panels</title>
		<link>http://flaz.biz/2016/04/coding-the-customizerbean-in-dynamic-view-panels/</link>
		<comments>http://flaz.biz/2016/04/coding-the-customizerbean-in-dynamic-view-panels/#respond</comments>
		<pubDate>Thu, 28 Apr 2016 10:10:06 +0000</pubDate>
		<dc:creator><![CDATA[Massimo]]></dc:creator>
				<category><![CDATA[Lotus]]></category>
		<category><![CDATA[Sviluppo]]></category>
		<category><![CDATA[customizerBean]]></category>
		<category><![CDATA[dynamic view panel]]></category>
		<category><![CDATA[extension library]]></category>
		<category><![CDATA[openntf]]></category>
		<category><![CDATA[xpages]]></category>

		<guid isPermaLink="false">http://flaz.biz/?p=189</guid>
		<description><![CDATA[I used for the first time the Dynamic View Panel from the OpenNTF Extension Library. You can get started watching this video (oldie but goldie). My need is to heavily customize the view rendered by the DVP, so the customizerBean is the way to go. This is the sample code described in the above video. [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I used for the first time the Dynamic View Panel from the OpenNTF <a href="https://extlib.openntf.org/">Extension Library</a>. You can get started watching <a href="https://www.youtube.com/watch?v=AQOGgVZpAcw">this video</a> (oldie but goldie).</p>
<p>My need is to heavily customize the view rendered by the DVP, so the <b>customizerBean</b> is the way to go.</p>
<p><a href="https://openntf.org/XSnippets.nsf/snippet.xsp?id=dynamic-view-panel-customizer-bean">This is the sample code</a> described in the above video. It only performs basic modifications, but is useful to understand the basis.<br />
While, <a href="https://github.com/jesse-gallagher/XPages-Scaffolding/blob/9e4e70e88b1a447524f7edb785c4218fc1209aa6/frostillicus.framework/frostillicus.framework.plugin/src/main/java/frostillicus/xsp/DynamicViewCustomizer.java">this Java class</a> is a goldmine to gather lots of useful information.</p>
<p>I won&#8217;t explain how to set up the DVP and the customizerBean (watch the video if that&#8217;s what you&#8217;re looking for), what follows is just a collection of notes with code samples.</p>
<h3>Using the Converter</h3>
<p>If you want to change a column value you have to write your own converter class (extending the <code>ViewColumnConverter</code>) and set it to the column.<br />
To work with properties in the converter class, you must serialize the parent class. Take in mind that the <code>ColumnDef</code> can&#8217;t be serialized anymore! So this (minimal) code <b>won&#8217;t work</b>:</p>
<pre class="prettyprint lang-java">public class DynamicViewCustomizer extends DominoViewCustomizer implements Serializable {
	private static final long serialVersionUID = -5126984721484501732L;

	private String panelId;

	@Override
	public IControl createColumn(final FacesContext context, final UIDynamicViewPanel panel, final int index, final ColumnDef colDef) {
		this.panelId = panel.getId();
		return super.createColumn(context, panel, index, colDef);
	}

	@Override
	public void afterCreateColumn(FacesContext context, int index, ColumnDef colDef, IControl column) {
		UIComponent columnComponent = column.getComponent();
		DynamicColumn dynamicColumn = (DynamicColumn) columnComponent;
		UIDynamicViewPanel panel = (UIDynamicViewPanel)FacesUtil.getComponentFor(context.getViewRoot(), this.panelId);
		dynamicColumn.setConverter(new ExtendedViewColumnConverter(null, colDef, panel));
	}

	public static class ExtendedViewColumnConverter extends ViewColumnConverter {
		private ColumnDef colDef;

		public ExtendedViewColumnConverter() {}

		public ExtendedViewColumnConverter(final ViewDef viewDef, final ColumnDef colDef, final UIDynamicViewPanel panel) {
			super(viewDef, colDef);
			this.colDef = colDef;
		}

		@Override
		public Object saveState(final FacesContext context) {
			Object[] superState = (Object[])super.saveState(context);
			Object[] state = new Object[2];
			state[0] = superState;
			state[1] = new Integer(this.colDef);
			return state;
		}

		@Override
		public void restoreState(final FacesContext context, final Object value) {
			Object[] state = (Object[])value;
			super.restoreState(context, state[0]);
			this.colDef= (ColumnDef)state[1];
		}
	}
}</pre>
<p>While this will work fine:</p>
<pre class="prettyprint lang-java">public class DynamicViewCustomizer extends DominoViewCustomizer implements Serializable {
	private static final long serialVersionUID = -5126984721484501732L;

	private String panelId;

	@Override
	public IControl createColumn(final FacesContext context, final UIDynamicViewPanel panel, final int index, final ColumnDef colDef) {
		this.panelId = panel.getId();
		return super.createColumn(context, panel, index, colDef);
	}

	@Override
	public void afterCreateColumn(FacesContext context, int index, ColumnDef colDef, IControl column) {
		UIComponent columnComponent = column.getComponent();
		DynamicColumn dynamicColumn = (DynamicColumn) columnComponent;
		UIDynamicViewPanel panel = (UIDynamicViewPanel)FacesUtil.getComponentFor(context.getViewRoot(), this.panelId);
		dynamicColumn.setConverter(new ExtendedViewColumnConverter(null, colDef, panel));
	}

	public static class ExtendedViewColumnConverter extends ViewColumnConverter {
		private int numberAttrib;
		private int numberDigits;
		private int numberFmt;
		private int timeDateFmt;
		private String name;

		public ExtendedViewColumnConverter() {}

		public ExtendedViewColumnConverter(final ViewDef viewDef, final ColumnDef colDef, final UIDynamicViewPanel panel) {
			super(viewDef, colDef);
			// all the properties needed in the getAsString method
			this.numberAttrib = colDef.getNumberAttrib();
			this.numberDigits = colDef.getNumberDigits();
			this.numberFmt = colDef.getNumberFmt();
			this.timeDateFmt = colDef.getTimeDateFmt();
			this.name = colDef.getName();
		}

		@Override
		public Object saveState(final FacesContext context) {
			Object[] superState = (Object[])super.saveState(context);
			Object[] state = new Object[6];
			state[0] = superState;
			state[1] = new Integer(this.numberAttrib);
			state[2] = new Integer(this.numberDigits);
			state[3] = new Integer(this.numberFmt);
			state[4] = new Integer(this.timeDateFmt);
			state[5] = this.name;
			return state;
		}

		@Override
		public void restoreState(final FacesContext context, final Object value) {
			Object[] state = (Object[])value;
			super.restoreState(context, state[0]);
			this.numberAttrib = ((Integer)state[1]).intValue();
			this.numberDigits = ((Integer)state[2]).intValue();
			this.numberFmt = ((Integer)state[3]).intValue();
			this.timeDateFmt = ((Integer)state[4]).intValue();
			this.name = (String)state[5];
		}
	}

}</pre>
<p>Or, even better, using a custom class, so that the <code>saveState</code> and <code>restoreState</code> methods will just have to save and restore one single object containing all the properties.</p>
<h3>Convert icon columns</h3>
<p>As shown on GitHub, you&#8217;d better use two converters: one for the icon columns and one for all the other types. Otherwise the converter will confuse itself, treating icon columns in categorized views as generic numeric/text columns.</p>
<p>The (minimal) code to arrange this:</p>
<pre class="prettyprint lang-java">public class MyViewBean extends DominoViewCustomizer implements Serializable {
	private static final long serialVersionUID = -5126984721484501732L;

	private String panelId;

	@Override
	public IControl createColumn(final FacesContext context, final UIDynamicViewPanel panel, final int index, final ColumnDef colDef) {
		this.panelId = panel.getId();
		return super.createColumn(context, panel, index, colDef);
	}

	@Override
	public void afterCreateColumn(FacesContext context, int index, ColumnDef colDef, IControl column) {
		UIComponent columnComponent = column.getComponent();
		DynamicColumn dynamicColumn = (DynamicColumn) columnComponent;
		UIDynamicViewPanel panel = (UIDynamicViewPanel)FacesUtil.getComponentFor(context.getViewRoot(), this.panelId);

		if (colDef.isIcon()) {
			dynamicColumn.setConverter(new MyIconColumnConverter(null, colDef, panel));
		} else {
			dynamicColumn.setConverter(new MyGenericColumnConverter(null, colDef, panel));
		}

	}
}</pre>
<h3>Replace icon columns with HTML</h3>
<p>My XPages application uses <a href="http://getbootstrap.com/">Bootstrap</a>, thus <a href="http://getbootstrap.com/components/#glyphicons">Glyphicons</a> is the way to go. The icons in my Notes application are all custom image resources, so I just have to identify the name, change the column content to HTML and fill it with the code to the display the proper icon. Here a minimal example (top class is not <code>Seralizable</code> since <code>MyIconColumnConverter</code> doesn&#8217;t use properties):</p>
<pre class="prettyprint lang-java">public class MyViewBean extends DominoViewCustomizer {
	private String panelId;

	@Override
	public IControl createColumn(final FacesContext context, final UIDynamicViewPanel panel, final int index, final ColumnDef colDef) {
		this.panelId = panel.getId();
		return super.createColumn(context, panel, index, colDef);
	}

	@Override
	public void afterCreateColumn(FacesContext context, int index, ColumnDef colDef, IControl column) {
		UIComponent columnComponent = column.getComponent();
		DynamicColumn dynamicColumn = (DynamicColumn) columnComponent;
		UIDynamicViewPanel panel = (UIDynamicViewPanel)FacesUtil.getComponentFor(context.getViewRoot(), this.panelId);

		if (colDef.isIcon()) {
			dynamicColumn.setIconSrc(null);
			dynamicColumn.setValueBinding("iconSrc", null);
			dynamicColumn.setDisplayAs("");
			dynamicColumn.setContentType("html");
			dynamicColumn.setConverter(new MyIconColumnConverter(null, colDef, panel));
		}

	}

	public static class MyIconColumnConverter extends ViewColumnConverter {
		
		public IntranetIconConverter() {}

		public IntranetIconConverter(ViewDef viewDef, ColumnDef colDef, UIDynamicViewPanel panel) {
			super(viewDef, colDef);
		}
		
		@Override
		public String getAsString(final FacesContext context, final UIComponent component, final Object value) {
			
			String ret = "&lt;span&gt;&amp;nbsp;&lt;/span&gt;"; // default
			
			try {

				String glyphicon = null;
				if (value instanceof java.lang.String) {
					if (((String)value).compareToIgnoreCase("vwWorkInProgress.gif") == 0) {
						glyphicon = "dashboard";
					} else if (((String)value).compareToIgnoreCase("vwLinks.gif") == 0) {
						glyphicon = "link";
					} else if (((String)value).compareToIgnoreCase("vwEdit.gif") == 0) {
						glyphicon = "pencil";
					} else if (((String)value).compareToIgnoreCase("vwSent.gif") == 0) {
						glyphicon = "envelope";
					}
				}
				
				if (glyphicon != null)
					ret = "&lt;span class=\"glyphicon glyphicon-" + glyphicon + "\"&gt;&lt;/span&gt;";
				
			} catch (Exception e) {
				ret = "&lt;span&gt;N/A&lt;/span&gt;";
			}
			
			return ret;
			
		}
		
	}
}</pre>
<p>If you need to replace default Domino icons, just check if <code>value instanceof Double</code> and compare the numeric values (take a look at the <code>IconColumnConverter</code> class on GitHub).</p>
<h3>Expand/collapse images</h3>
<p>It is very easy to change expand/collapse images in a categorized view:</p>
<pre class="prettyprint lang-java">public class MyViewBean extends DominoViewCustomizer {

	public void afterCreateColumn(FacesContext context, int index, ColumnDef colDef, IControl column) {
		UIComponent columnComponent = column.getComponent();
		DynamicColumn dynamicColumn = (DynamicColumn) columnComponent;

		if (colDef.isCategorized()) {
			dynamicColumn.setCollapsedImage("/collapsed.gif");
			dynamicColumn.setExpandedImage("/expanded.gif");
		}

	}
}</pre>
<p>Thanks to <a href="http://www.notesin9.com">David Leedy</a> and <a href="http://www.nnsu.com/">Paul T. Calhoun</a> for the video and <a href="http://frostillic.us">Jesse Gallagher</a> for sharing his wonderful converter class on GitHub.</p>
]]></content:encoded>
			<wfw:commentRss>http://flaz.biz/2016/04/coding-the-customizerbean-in-dynamic-view-panels/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>B-tree structure is invalid</title>
		<link>http://flaz.biz/2016/02/b-tree-structure-is-invalid/</link>
		<comments>http://flaz.biz/2016/02/b-tree-structure-is-invalid/#respond</comments>
		<pubDate>Sat, 27 Feb 2016 20:21:23 +0000</pubDate>
		<dc:creator><![CDATA[Massimo]]></dc:creator>
				<category><![CDATA[Lotus]]></category>
		<category><![CDATA[btree]]></category>
		<category><![CDATA[domino]]></category>

		<guid isPermaLink="false">http://flaz.biz/?p=185</guid>
		<description><![CDATA[I&#8217;m facing this problem when deleting a folder on three mail files. The server is a Domino 9.0.1 FP4 64-bit and the database ODS is 52. I&#8217;ve tryed almost everything, including: load compact -C -D mail\db.nsf load updall -R -C mail\db.nsf load fixup mail\db.nsf load convert mail\db.nsf * mail9.ntf -u No luck. The problem is [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;m facing this problem when deleting a folder on three mail files.</p>
<p>The server is a Domino 9.0.1 FP4 64-bit and the database ODS is 52.</p>
<p>I&#8217;ve tryed almost <b>everything</b>, including:</p>
<p><code>load compact -C -D mail\db.nsf<br />
load updall -R -C mail\db.nsf<br />
load fixup mail\db.nsf<br />
load convert mail\db.nsf * mail9.ntf -u</code></p>
<p>No luck. The problem is still there.<br />
After googling something more, I found <a href="http://www-10.lotus.com/ldd/nd8forum.nsf/4b9931b774db788c85256bf0006b5e6d/a4bfe2e340a8573b8525743d0049e943">this post in the Notes/Domino 8 Forum</a> that solved my problem.</p>
<p>So thank you very much <b>Mike Hayman</b>. I paste here the code as is, I only added the last line to remove the temporary document:</p>
<pre class="prettyprint lang-vb">Dim sess As New notessession
Dim dbThis As NotesDatabase
Dim docTemp As NotesDocument
Dim vViews As Variant

Set dbThis=sess.CurrentDatabase
Set docTemp=dbThis.CreateDocument
docTemp.Form="Memo"
docTemp.Subject="0. TidyUpFolders"
Call docTemp.ComputeWithForm( False, False)
docTemp.Save True, False, True

vViews=dbThis.Views
Forall f_vw In vViews
If f_vw.IsFolder Then
Print f_vw.Name
Call docTemp.PutInFolder (f_vw.Name )
f_vw.Refresh
Call docTemp.RemoveFromFolder ( f_vw.Name)
f_vw.Refresh
End If
End Forall
Print "Complete!"

Call docTemp.RemovePermanently(True)</pre>
]]></content:encoded>
			<wfw:commentRss>http://flaz.biz/2016/02/b-tree-structure-is-invalid/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bring NSF database back online after DBMT issues</title>
		<link>http://flaz.biz/2015/08/bring-nsf-database-back-online-after-dbmt-issues/</link>
		<comments>http://flaz.biz/2015/08/bring-nsf-database-back-online-after-dbmt-issues/#respond</comments>
		<pubDate>Thu, 27 Aug 2015 13:28:19 +0000</pubDate>
		<dc:creator><![CDATA[Massimo]]></dc:creator>
				<category><![CDATA[Lotus]]></category>

		<guid isPermaLink="false">http://flaz.biz/?p=169</guid>
		<description><![CDATA[If something goes wrong with DBMT you can experience problems accessing the database mainteined when the problem occurred: The only way to recover the database is using the NSFBringDatabaseOnline C API. Thus, create on the server a new database bringdbonline.nsf and an agent NSFBringDatabaseOnline with this code: Option Public Option Declare Declare Private Function NSFBringDatabaseOnline Lib [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>If something goes wrong with DBMT you can experience problems accessing the database mainteined when the problem occurred:</p>
<p><img class="alignnone size-full wp-image-170" src="http://flaz.biz/wp-content/uploads/2015/08/The-database-is-being-taken-off-line.png" alt="The database is being taken off-line" width="433" height="172" srcset="http://flaz.biz/wp-content/uploads/2015/08/The-database-is-being-taken-off-line.png 433w, http://flaz.biz/wp-content/uploads/2015/08/The-database-is-being-taken-off-line-300x119.png 300w" sizes="(max-width: 433px) 100vw, 433px" /></p>
<p>The only way to recover the database is using the <code>NSFBringDatabaseOnline</code> C API.<br />
Thus, create on the server a new database <code>bringdbonline.nsf</code> and an agent <code>NSFBringDatabaseOnline</code> with this code:</p>
<pre class="prettyprint lang-vb">Option Public
Option Declare

Declare Private Function NSFBringDatabaseOnline Lib "nnotes" Alias "NSFBringDatabaseOnline" (  ByVal dbPath As String, ByVal Z As Long) As Integer

Sub Initialize
	Call NSFBringDatabaseOnline("offlinedb.nsf", 0)
End Sub</pre>
<p>Agent&#8217;s trigger is <i>On Schedule</i> and the <i>Runtime security level</i> needs to be set to <i>3. Allow restricted operations with full administration rights</i>.<br />
Now simply run the agent from the Domino server console:</p>
<p><code>tell amgr run "bringdbonline.nsf" 'NSFBringDatabaseOnline'</code></p>
]]></content:encoded>
			<wfw:commentRss>http://flaz.biz/2015/08/bring-nsf-database-back-online-after-dbmt-issues/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache won&#8217;t start with a generic AH00016: Configuration Failed</title>
		<link>http://flaz.biz/2015/08/apache-wont-start-with-a-generic-ah00016-configuration-failed/</link>
		<comments>http://flaz.biz/2015/08/apache-wont-start-with-a-generic-ah00016-configuration-failed/#respond</comments>
		<pubDate>Fri, 07 Aug 2015 14:28:22 +0000</pubDate>
		<dc:creator><![CDATA[Massimo]]></dc:creator>
				<category><![CDATA[Sistemi]]></category>

		<guid isPermaLink="false">http://flaz.biz/?p=166</guid>
		<description><![CDATA[The setup is a fresh installation of a Debian with Apache 2.4.10 and OpenSSL 1.0.1k, configured as a reverse proxy with RapidSSL wildcard certificate. The apache2 service starts correctly but netstat -ant tells me that no service is listening on port 80 and 443. Disabling the SSL virtual host everything works fine. It&#8217;s not a syntax problem, [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>The setup is a fresh installation of a Debian with Apache 2.4.10 and OpenSSL 1.0.1k, configured as a reverse proxy with RapidSSL wildcard certificate.</p>
<p>The apache2 service starts correctly but <code>netstat -ant</code> tells me that no service is listening on port 80 and 443. Disabling the SSL virtual host everything works fine. It&#8217;s not a syntax problem, since <code>apachectl configtest</code> returns &#8220;Syntax OK&#8221;.</p>
<p>So, after stopping apache2 and enabling the SSL virtual host, I started the webserver with the control interface:</p>
<p><code>apache2ctl -e info -k start</code></p>
<p>The action fails, and I got bounced to the error log. Here I only find these lines:</p>
<p><code>[Fri Aug 07 15:27:49.535978 2015] [ssl:info] [pid 11844:tid 140686718781312] AH01883: Init: Initialized OpenSSL library<br />
AH00016: Configuration Failed</code></p>
<p>Fortunately, I have other Debian systems with the same version of Apache and OpenSSL working fine with a similar configuration, thus the problem could only be addressed to the certificate.</p>
<h3>Is the certificate trusted by the CA?</h3>
<p><code># openssl verify -CAfile rapidssl-intermediate.crt rapidssl-certificate.crt<br />
rapidssl-certificate.crt: OK</code></p>
<p>Positive response, no problem here.</p>
<h3>Does the private key match the certificate?</h3>
<p><code># openssl x509 -noout -modulus -in rapidssl-certificate.crt<br />
# openssl rsa -noout -modulus -in private.key</code></p>
<p>These commands should return the same value. If not, as in my case, you&#8217;re using the wrong private key!</p>
]]></content:encoded>
			<wfw:commentRss>http://flaz.biz/2015/08/apache-wont-start-with-a-generic-ah00016-configuration-failed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>@Usernameslist formula in XPages</title>
		<link>http://flaz.biz/2015/05/usernameslist-formula-in-xpages/</link>
		<comments>http://flaz.biz/2015/05/usernameslist-formula-in-xpages/#respond</comments>
		<pubDate>Fri, 22 May 2015 09:24:24 +0000</pubDate>
		<dc:creator><![CDATA[Massimo]]></dc:creator>
				<category><![CDATA[Lotus]]></category>
		<category><![CDATA[Sviluppo]]></category>
		<category><![CDATA[usernameslist]]></category>
		<category><![CDATA[xpages]]></category>

		<guid isPermaLink="false">http://flaz.biz/?p=164</guid>
		<description><![CDATA[@Usernameslist formula does not exists in SSJS, but you can write your own function to do the same job: function @Usernameslist() { var server:lotus.notes.addins.DominoServer = new lotus.notes.addins.DominoServer(session.getServerName()); var coll:java.util.Collection = server.getNamesList(session.getEffectiveUserName()); return coll.toArray(); } Thanks to Nathan T. Freeman.]]></description>
				<content:encoded><![CDATA[<p><code>@Usernameslist</code> formula does not exists in SSJS, but you can write your own function to do the same job:</p>
<pre class="prettyprint lang-js">function @Usernameslist() {
	var server:lotus.notes.addins.DominoServer = new lotus.notes.addins.DominoServer(session.getServerName());
	var coll:java.util.Collection = server.getNamesList(session.getEffectiveUserName());
	return coll.toArray();
}</pre>
<p>Thanks to <a href="http://stackoverflow.com/a/10287785/4555048">Nathan T. Freeman</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://flaz.biz/2015/05/usernameslist-formula-in-xpages/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Su FTSearch</title>
		<link>http://flaz.biz/2015/02/su-ftsearch/</link>
		<comments>http://flaz.biz/2015/02/su-ftsearch/#respond</comments>
		<pubDate>Sat, 14 Feb 2015 12:03:50 +0000</pubDate>
		<dc:creator><![CDATA[Massimo]]></dc:creator>
				<category><![CDATA[Lotus]]></category>
		<category><![CDATA[domino]]></category>
		<category><![CDATA[ftsearch]]></category>
		<category><![CDATA[xpages]]></category>

		<guid isPermaLink="false">http://flaz.biz/?p=158</guid>
		<description><![CDATA[Sto lavorando ad un progetto di migrazione su XPages di una vecchia applicazione di archiviazione documentale. C&#8217;è la presunzione di ottenere un risultato molto simile a quello di un motore di ricerca. Bing nello specifico, per il semplice fatto che graficamente è più accattivante dello scarno Google. Oltre ad un edit box generico è prevista una ricerca avanzata per [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Sto lavorando ad un progetto di migrazione su XPages di una vecchia applicazione di archiviazione documentale. C&#8217;è la presunzione di ottenere un risultato molto simile a quello di un motore di ricerca. Bing nello specifico, per il semplice fatto che graficamente è più <em>accattivante</em> dello scarno Google.</p>
<p>Oltre ad un edit box generico è prevista una ricerca avanzata per poter filtrare i risultati più precisamente agendo su campi specifici (categoria, cliente, autore, data, ecc.). C&#8217;è quindi una buona parte di logica dedicata alla produzione della query di ricerca che dovrà essere eseguita sull&#8217;indice full text per ottenere i risultati che rispettano i parametri di ricerca, presentati in uno stile comprensibile a lusers e power users:</p>
<p><img class="alignnone size-full wp-image-159" src="http://flaz.biz/wp-content/uploads/2015/02/Screenshot_1.png" alt="Google" width="555" height="85" srcset="http://flaz.biz/wp-content/uploads/2015/02/Screenshot_1.png 555w, http://flaz.biz/wp-content/uploads/2015/02/Screenshot_1-300x46.png 300w" sizes="(max-width: 555px) 100vw, 555px" /></p>
<p>Ovvero titolo del documento in blu (che è un link che apre il documento), categoria di archiviazione in verde, data creazione ed eventuale data di ultima modifica in grigio scuro. Navigazione a pagine di dieci elementi ciascuna (tutto lavoro assegnato al repeat control). Pur avendo ottenuto un prototipo funzionante e appagante, ci sono un po&#8217; di questioni da sottolineare.</p>
<h3>Discordanza con le query eseguite nella search bar del client Notes</h3>
<p>Per questa ho aperto una chiamata in IBM, perché ha davvero poco senso. Di primo acchito mi hanno suggerito di eseguire delle fuzzy search, ma è un inaffidabile palliativo.</p>
<p>Di fatto se un database (indicizzato) contiene un documento avente in un campo il valore <em>This is a document</em>, il client sarà in grado di trovarlo ricercando <em>this document</em>. Mentre il metodo <code>FTSearch</code> della <code>NotesDatabase</code> e della <code>NotesView</code> no. E nemmeno la proprietà <code>search</code> della view data source di una XPage. In questi casi la stringa viene trattata come se fosse scritta tra doppi apici, cioè come se le due parole fossero consecutive. Confido in un parametro non documentato che permetta di uniformare le cose, perché altrimenti è poco serio che, a parità di query e di database, il client restituisca risultati diversi rispetto alla XPage. Ed è anche sbagliato che vada io a inserire un <code>AND</code> in sostituzione ad ogni spazio dato che potrei potenzialmente invalidare una query complessa che alcuni utenti sono effettivamente in grado di fare.</p>
<h3>Ordinamento</h3>
<p>Che poi è strettamente collegato al punto precedente. Perché le ricerche eseguite da codice non possono essere ordinate come quelle eseguite dalla search bar? L&#8217;ottimo sarebbe poter eseguire una ricerca su una vista ordinata nello stesso modo in cui si vuole presentare i risultati, sfruttando quella che nel client è la modalità <em>Sorted like current view</em>. Dunque l&#8217;algoritmo di ricerca Domino lo prevede, perché non è stato reso disponibile anche via codice?</p>
<p>Ciascun documento archiviato dispone di due campi: data di creazione e data di ultima modifica. I risultati delle ricerche eseguite via XPage dovranno porre in testa i documenti più recenti, usando cioè la data di modifica (se presente) o in alternativa la data di creazione. Il metodo <code>FTSearch</code> della <code>NotesDatabase</code> prevede l&#8217;ordinamento ascendente o discendente per data di creazione (che è la proprietà del documento), quindi ordinare i risultati a proprio piacimento non è di fatto possibile!</p>
<p>L&#8217;omonimo metodo della <code>NotesView</code> dice invece che:</p>
<blockquote><p>If the database is not full-text indexed, the documents in the subset are in the same order as they are in the original view. However, if the database is full-text indexed, the documents in the subset are sorted into descending order of relevance.</p></blockquote>
<p>Quindi, senza indice full text i risultati sarebbero nello stesso ordine in cui si presentano nella vista. Mentre disponendo dell&#8217;indice sarebbero ordinati per rilevanza.</p>
<p>Fortunatamente esiste un workaround, che può funzionare solamente agendo sulla ricerca dalla <code>NotesDatabase</code> dato che nella <code>NotesView</code> non è prevista alcuna opzione sull&#8217;ordinamento dei risultati. Creando il campo <code>$Created</code> all&#8217;interno di ciascun documento, calcolato come segue:</p>
<p><code>@If(DataModifica = ""; DataCreazione; DataModifica)</code></p>
<p>E applicando il metodo di ordinamento <code>FT_DATECREATED_DESC</code> si ottiene un elenco ordinato in base al valore del campo <code>$Created</code> che sostituisce l&#8217;effettiva data di creazione del documento.</p>
<p>Ma se l&#8217;esigenza fosse stata quella di ordinare i risultati per un campo di tipo testo non ci sarebbe stata altra scelta che il solito <code>PutAllInFolder</code> che avrebbe complicato le cose e rallentato il processo di ricerca, che senza inutili spostamenti in cartelle temporanee è invece fulmineo pur trattando centinaia di migliaia di documenti.</p>
<h3>Occhio alla documentazione</h3>
<p>Lo farò presente al supporto (una cosa alla volta, ho troppe chiamate aperte contemporaneamente credo di essere a rischio blacklist): sul metodo <code>FTSearch</code> della <code>NotesDatabase</code> (JavaScript) c&#8217;è una <i>effe</i> di troppo sul parametro <code>FFT_DATECREATED_DES</code>:</p>
<p><img class="alignnone size-full wp-image-160" src="http://flaz.biz/wp-content/uploads/2015/02/FFT_DATECREATED_DES.png" alt="FFT_DATECREATED_DES" width="410" height="293" srcset="http://flaz.biz/wp-content/uploads/2015/02/FFT_DATECREATED_DES.png 410w, http://flaz.biz/wp-content/uploads/2015/02/FFT_DATECREATED_DES-300x214.png 300w" sizes="(max-width: 410px) 100vw, 410px" /></p>
]]></content:encoded>
			<wfw:commentRss>http://flaz.biz/2015/02/su-ftsearch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Riscrivere endpoint dei web service Domino dietro reverse proxy HTTPS</title>
		<link>http://flaz.biz/2015/01/riscrivere-endpoint-dei-web-service-domino-dietro-reverse-proxy-https/</link>
		<comments>http://flaz.biz/2015/01/riscrivere-endpoint-dei-web-service-domino-dietro-reverse-proxy-https/#respond</comments>
		<pubDate>Thu, 15 Jan 2015 20:24:56 +0000</pubDate>
		<dc:creator><![CDATA[Massimo]]></dc:creator>
				<category><![CDATA[Lotus]]></category>
		<category><![CDATA[Sistemi]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[mod_substitute]]></category>
		<category><![CDATA[reverse proxy]]></category>

		<guid isPermaLink="false">http://flaz.biz/?p=155</guid>
		<description><![CDATA[Un limite noto con cui convivevo da anni. Per riprodurre il problema è sufficiente un server Domino e un reverse proxy. Il reverse proxy dispone di certificato SSL, quindi il client si collega al reverse proxy in HTTPS mentre il reverse proxy a Domino in HTTP. Il problema consiste che nei web service esiste l&#8217;endpoint, ovvero l&#8217;indirizzo [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Un limite <a href="http://flaz.biz/2013/04/inotes-dietro-reverse-proxy-https/">noto</a> con cui convivevo da anni. Per riprodurre il problema è sufficiente un server Domino e un reverse proxy. Il reverse proxy dispone di certificato SSL, quindi il client si collega al reverse proxy in HTTPS mentre il reverse proxy a Domino in HTTP.</p>
<p>Il problema consiste che nei web service esiste l&#8217;<em>endpoint</em>, ovvero l&#8217;indirizzo a cui il client dovrà collegarsi per <em>consumare</em> il web service. Tale indirizzo è presente nell&#8217;attributo <code>location</code> dell&#8217;elemento <code>wsdlsoap:address</code>, che Domino genera dinamicamente in base alla richiesta HTTP che viene fatta al server, tenendo cioè conto del protocollo (HTTP/HTTPS) e dell&#8217;hostname.</p>
<p>Quando il client si collega al web service, Domino vedrà protocollo e hostname del <strong>reverse proxy</strong>, generando un endpoint potenzialmente errato. L&#8217;hostname è facilmente correggibile tramite il DNS interno, facendo in modo che l&#8217;hostname pubblico venga risolto dal DNS interno nell&#8217;indirizzo interno del server Domino. Ma per mantenere il protocollo non c&#8217;è alternativa che far collegare il reverse proxy a Domino in SSL.</p>
<p>Dopo aver interpellato anche IBM, e ottenuto una APAR a cui partecipiamo io e ben due altri clienti, mi viene confermato che l&#8217;unica possibile soluzione è installare un certificato SSL anche sul server web di Domino. Ma io non voglio installare il certificato anche su Domino!</p>
<p>Il reverse proxy è un server Apache che dispone del modulo <a href="http://httpd.apache.org/docs/2.2/mod/mod_substitute.html">mod_substitute</a>, in grado di manipolare il <strong>contenuto</strong> delle risposte che attraversano il proxy.</p>
<p>L&#8217;implementazione è semplice, purché ci si accorga subito che è necessario disattivare la compressione gzip altrimenti il mod_substitute tenterebbe di manipolare la risposta già compressa che è, chiaramente, indecifrabile.</p>
<p>Supponendo il caso che il client si collega al reverse proxy all&#8217;indirizzo <code>https://server.acme.com/app/ordini.nsf/elenco?WSDL</code> e il reverse proxy a Domino all&#8217;indirizzo <code>http://server.acme.com/app/ordini.nsf/elenco?WSDL</code>, per correggere il protocollo sarà necessario modificare la configurazione del Virtual Host gestito da Apache come segue:</p>
<pre class="prettify">&lt;Location /app/&gt;
	RequestHeader unset Accept-Encoding
	AddOutputFilterByType SUBSTITUTE text/xml
	Substitute "s|http://server.acme.com:80|https://server.acme.com|ni"
&lt;/Location&gt;</pre>
<p>Ho applicato la regola all&#8217;intera directory <code>/app/</code> dato che ho più applicazioni che dovranno essere soggette alla sostituzione, ma nel caso fosse stata solamente una avrei limitato la sostituzione a quella specifica applicazione specificandone il percorso esatto nella <code>Location</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://flaz.biz/2015/01/riscrivere-endpoint-dei-web-service-domino-dietro-reverse-proxy-https/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Di nuovo online</title>
		<link>http://flaz.biz/2015/01/di-nuovo-online/</link>
		<comments>http://flaz.biz/2015/01/di-nuovo-online/#comments</comments>
		<pubDate>Mon, 12 Jan 2015 18:08:52 +0000</pubDate>
		<dc:creator><![CDATA[Massimo]]></dc:creator>
				<category><![CDATA[Varie]]></category>

		<guid isPermaLink="false">http://flaz.biz/?p=151</guid>
		<description><![CDATA[Anno nuovo blog nuovo. Letteralmente: mi sono trasferito presso altro provider e dopo tanti anni sono tornato a WordPress. Che devo dire ha fatto passi da gigante rispetto al WordPress del 2007 che mi ricordavo io. Per il tema sono partito da Underscores che con un po&#8217; di pazienza ho personalizzato grazie alle sempre utili palette [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Anno nuovo blog nuovo. Letteralmente: mi sono trasferito presso altro provider e dopo tanti anni sono tornato a <a href="http://wordpress.org">WordPress</a>. Che devo dire ha fatto passi da gigante rispetto al WordPress del 2007 che mi ricordavo io. Per il tema sono partito da <a href="http://underscores.me">Underscores</a> che con un po&#8217; di pazienza ho personalizzato grazie alle sempre utili palette di <a href="http://www.colourlovers.com">Colour Lovers</a>.</p>
<p>Il 2014 è stato lavorativamente l&#8217;ennesimo anno di crescita. Ma a parte questo è stato un anno tremendo. Motivo per cui gli scorsi 12 mesi ero, di fatto, uscito di scena.</p>
<p>Ma con il 2015 ho deciso di riprendere in mano il blog. Principalmente perché spesso, dopo aver trovato la soluzione a quel problema su cui stai sbattendo la testa da ore o per quelle poche righe di codice che magari sono una banalità ma ci hai sudato sopra per farle funzionare, la voglia di scriverci sopra due righe era tanta. Il blog mi mancava.</p>
<p>Ecco che allora in mezza giornata il tema era pronto e finito (il più del tempo è andato perso per trovare la giusta palette). In un&#8217;altra mezza giornata ho scritto un agente che migrasse tutti i dati dal vecchio blog NSF (immagini comprese!). Ed eccomi qua, a combattere con gli ultimi postumi dell&#8217;influenza, senza la quale però dubito che sarei riuscito a ritagliarmi il tempo necessario per questi lavoretti.</p>
<p>Terminato il pistolotto veniamo al sodo.<br />
I temi su cui continuerò a scrivere saranno grossomodo sempre gli stessi. Lavoro ancora con IBM <span style="text-decoration: line-through;">Lotus</span> Notes/Domino. Sempre di più con le XPages, anche se non sono ancora ai livelli che vorrei. Lo sviluppo web rientra sempre nelle mie passioni, anche se l&#8217;ho un poco snobbato negli ultimi periodi. Di hardware, virtualizzazioni e attività sistemistiche non me ne occupo praticamente più ormai. Con GNU/Linux ci lavoro ancora, poco però.<br />
Continuano a piacermi la musica, le serie tv e le auto. Il tempo libero continua ad essere assorbito da <a href="http://flaz.biz/wp-content/uploads/2015/01/15176018115_29571ee85e_k.jpg">Baxter</a> (che a breve festeggerà i suoi sette anni) e dalla fotografia, attività a cui mi sono avvicinato dalla scorsa estate, che mi sta appassionando ma di cui sono ancora molto ignorante.</p>
]]></content:encoded>
			<wfw:commentRss>http://flaz.biz/2015/01/di-nuovo-online/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Svuotare l&#8217;elenco applicazioni nel Designer</title>
		<link>http://flaz.biz/2014/04/svuotare-l-elenco-applicazioni-nel-designer/</link>
		<comments>http://flaz.biz/2014/04/svuotare-l-elenco-applicazioni-nel-designer/#respond</comments>
		<pubDate>Wed, 02 Apr 2014 10:16:11 +0000</pubDate>
		<dc:creator><![CDATA[Massimo]]></dc:creator>
				<category><![CDATA[Lotus]]></category>

		<guid isPermaLink="false">http://2A04BFFB8E9A1EE6C1257CAE002D6D60</guid>
		<description><![CDATA[Chi come me lavora con diversi Clienti e su diversi progetti si trova presto ad avere la lista delle applicazioni piena al punto che è inutilizzabile. Eliminarle una alla volta è una seccatura, a maggior ragione se si riferiscono ad applicazioni on server a cui non si ha accesso nel preciso momento in cui si [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Chi come me lavora con diversi Clienti e su diversi progetti si trova presto ad avere la lista delle applicazioni piena al punto che è inutilizzabile.<br />
Eliminarle una alla volta è una seccatura, a maggior ragione se si riferiscono ad applicazioni on server a cui non si ha accesso nel preciso momento in cui si esegue l&#8217;operazione.</p>
<p>Una funzione <b>Clear</b> sarebbe stata apprezzata!</p>
<p>È tuttavia fattibile ma in modo manuale, svuotando cioè il contenuto del file <code>wsInfo.xml</code> contenuto nella directory <code>workspace\.metadata\.plugins\com.ibm.designer.domino.ide.resources</code> all&#8217;interno della <code>data</code> directory.</p>
<p>N.B. Non è possibile farlo <i>a caldo</i>, cioè con il Client aperto. Chiudere, dunque, Notes, modificare il file <code>wsInfo.xml</code> e quindi riaprirlo.</p>
]]></content:encoded>
			<wfw:commentRss>http://flaz.biz/2014/04/svuotare-l-elenco-applicazioni-nel-designer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
