Wednesday, December 30, 2009

Soirée de Noël

Les photos de la soirée de Noël chez Lucie et Jean sont ici:


Vidéos:


Noël chez Lucie from Frédéric Mauroy on Vimeo.

Wednesday, December 16, 2009

Commémoration de la bataille des Ardennes

Commémoration de la bataille des Ardennes, il y a 65 ans, à Bastogne, le dimanche 13 décembre 2009.

Photos ici:

Wednesday, November 4, 2009

Oracle WCI: Warning: couldn't access subscriber X, continuing;

All of a sudden, our Saved Search Mailer scripts stopped working, after several years without a glitch.

The error I could find in the log files was this one:
Warning: couldn't access subscriber X, continuing
I spent the day trying to figure this out, as I couldn't find any clue using the PTSpy tool, nor in the million other log files... I had to decompile the Java classes of the "externaloperations.jar" library to find out what the process was doing before spitting out that error message.

Here is the code where that error message is shown:
void prepareSubscriberList()
{
int userIds[] = m_ptSearch.RetrieveSubscribedUsers();
if(userIds == null)
throw new RuntimeException("Saved Search object failed to retrieve subscribers");

IPTProfileManager ptPM = (IPTProfileManager)m_ptSession.OpenGlobalObject(58, false);
m_subscribers = new Vector();
for(int i = 0; i < userIds.length; i++)
{
int userId = userIds[i];
try
{
IPTUserInfo ptUI = ptPM.GetUserInfo(userId);
String email = ptUI.GetEmail();
if(email == null)
throw new RuntimeException("no email");

String name = ptUI.GetFullName();
if(name == null)
{
IPTUser ptU = (IPTUser)m_ptSession.GetUsers().Open(userId, false);
name = ptU.GetName();
if(name == null)
name = ptU.GetLoginName();
if(name == null)
name = "User";
}
if(ptUI != null)
m_subscribers.addElement(new Subscriber(userId, name, email));
}
catch(Exception e)
{
Log.println((new StringBuilder()).append("Warning: couldn't access subscriber ").append(userId).append(", continuing.").toString());
}
}
}

So, I guessed there was an issue with the email address received from the Remote API service. I checked the "User Profile Manager" admin tool, under "User Information - Property Map" and found that the "Email Address" property was mapped to the "IMUser" attribute, instead of the usual "Email" attribute. I changed it back to the normal value and everything returned to normal :-) This also "repaired" a lot of Collaboration Server errors, stating that the email address was not passed to the portlet.

I still have no idea why this value was changed...

Wednesday, September 30, 2009

Commémoration de la libération de Lessines

Les photos de la commémoration de la libération de Lessines, ce samedi 26 septembre 2009, sont disponibles ici:

Tuesday, September 22, 2009

Error in ALUI Collaboration Server when subscriptions contain deleted users

Recently, we encountered a problem when a user wanted to register other users in Collaboration Server for notifications. The error message was not very helpful, and I could not find a lot of info in collaboration.log nor in the PTSpy trace. The Oracle support helped me find the culprit: there was a discrepancy between the subscribed users in the CNS database, and the current users in the Portal DB. Apparently, when a user is deleted from the portal, there are items that remain in the collab and notification databases, and they cause Collab to crash...

To clean the leftovers in this case:

DELETE FROM SUBSCRIBEDACCOUNT WHERE SUBSCRIBERID NOT IN
(SELECT UUID FROM Plumtree.dbo.PTMIGRATION)


This script is run on the CNS database, Plumtree is the name of the portal DB, and dbo is the owner of the table.

Tuesday, September 1, 2009

Joyce & Jérôme

Mariage de Joyce & Jérôme, des amis à Marie-Eve, le samedi 29 août 2009. Mais cette fois, je n'étais pas photographe, juste invité...

Mes photos sont ici:


En cadeau bonus, une petit vidéo lors du lancer de colombes...


Joyce & Jérôme - Lancer de colombes from Frédéric Mauroy on Vimeo.

Friday, August 28, 2009

Senda & Vincent

Les photos du mariage de Senda & Vincent, qui s'est déroulé le samedi 15 août 2009, sont en ligne ici:

Thursday, May 28, 2009

Caching portlets in ALUI 6.x

I've been developping portlets (gadgets) for nearly ten years now, starting with Plumtree Portal Server 3.5. A the time, there was a very nice document called "The Gadget Book" with all the details about the task of developping gadgets as they were called then. This PDF has been replaced by other versions since, but I still remember a few good practices for having a fast and reliable portal.

Among other things, there was the caching strategies to implement on the portlet side. The portal uses the standard HTTP mechanisms for calling content from the portlet server, as described in RFC 2616. Using the HTTP ETag and Last-Modified headers, we could prevent rendering a whole portlet when its content would remain unchanged. It proceeded like this:

- First call of the portlet by the portal. No special header is passed;
- The portlet returns the content to display, and sets the ETag and/or Last-Modified header;
- On the next access to the portlet, when the minimum cache time specified in the portlet configuration is over, and the maximum time not being reached, the portal calls the portlet giving back the content of the previous header;
- The portlet checks if the content has changed since the last call (in my case by comparing the timestamp passed in the Last-Modified header with a timestamp stored in a DB). If the content should be regenerated, I send the full content and give the new value for the headers. If not, I simply return an HTTP error 304 (Not Modified), and the portal would in that case display the content stored in its cache.

This worked perfectly for ages, until version 6.0 was released. On that version, when the 304 error was returned, the portal would display an error instead of displaying the cache (even when the setting "Suppress errors where possible (show cached content instead)" was checked.

I had several emails going back and forth with the Plumtree/BEA support and they finally acknowledge this as a bug. But in version 6.5, which is the one we are currently running (on http://www.myschool.lu/), that bug is still unresolved.

So, I disabled that part of my code, waiting for a solution to come eventually. I'm still waiting ;-) And my portlet is used in even more places than before (it displays content stored in a DB in many community pages) and the cache is key to allowing proper rendering times. The content would change once in a while, but hundreds of users would see the unchanged content in the meantime.

So, I tried to find a solution to this, and I have implemented the following workaround:

- Configure the portlet in this way (like in old times when caching worked):

- In my caching routine, I check the "CSP-Aggregation-Mode" header to see if I'm called as a portlet in a page, or as a standalone page (inside or outside of the gateway). This header can be empty (e.g. when called from outside of the gateway), can contain "Multiple" when displayed as a portlet in a page, or "Single" or "Hosted" when in an independent page accessed through the gateway.
- In the "Multiple" case, I do not return the 304 error but instead a Service Unavailable error (503). As per the setting above, the error is not displayed and the cached content is shown.
- In any other case, I return the 304 error, as a standalone page is properly processed by the browser. In such cases, the caching is done on the browser side and not the portal.

So far, so good. The performance has increased a lot, as could be expected, and the portlet server has more time to do other things than constantly rendering the same content...

Key lines of code:

Const c_sDateFormat As String = "yyyy-MM-dd HH:mm:ss"
Dim bFromPortal As Boolean = (Request.Headers("CSP-Aggregation-Mode") = "Multiple")

If dBrowserDate.ToString(c_sDateFormat) = dObjectDate.ToString(c_sDateFormat) Then
If bFromPortal Then
Response.StatusCode = System.Net.HttpStatusCode.ServiceUnavailable
Else
Response.StatusCode = System.Net.HttpStatusCode.NotModified
End If
Response.End()
End If

Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches)
Response.Cache.SetLastModified(dObjectDate)

Wednesday, May 27, 2009

IE8 not recognized in ASP.Net 1.1 applications

As always, I install the latest versions of anything when they become available (sometimes even betas). So did I for Internet Explorer 8.0 when it was released... And all of a sudden, my trusty applications made with ASP.Net 1.1 went berzerk. Things that used to work with IE7 and Firefox simply stopped working. This included external components we bought, like the ComponentArt suite. NavBars could not be clicked, drop-down menus behaved in strange ways, and so on.

I dug a bit and found the problem. My browser was not detected as it should. The
"Request.Browser.Browser" command returned "Unknown" instead of the expected "IE". But why?

I remarked that on my Vista x64 machine, the 32 bits browser would have these issues, but not the 64 bits version of IE. I compared the "User-Agent" HTTP header and saw these values:

32 bits:
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; GTB6; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; InfoPath.2; .NET CLR 1.1.4322; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618; FDM; OfficeLiveConnector.1.3; OfficeLivePatch.0.0)

64 bits:
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Win64; x64; Trident/4.0; .NET CLR 2.0.50727; SLCC1; Media Center PC 5.0; .NET CLR 3.5.30729)

I checked the browscap.ini and machine.config files on the server, but couldn't change them in any useful way.

Could the difference in length be the problem? In a Microsoft article on TechNet (http://technet.microsoft.com/en-us/library/bb496341.aspx) they say that the length of this header should remain shorter than 200 characters. In the first case, it is definitely longer...

So I dug further, looking for ways to shorten that User-Agent string. Many articles and blog talked about the following key to change in the registry:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\User Agent\Post Platform

I did this, but only the User-Agent of the 64 bits instance of IE seemed to care. I searched through the registry for the "OfficeLivePatch" key I can only see in the 32 bits instance, and found it it the following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\User Agent\Post Platform

As you can see, there is "Wow6432Node" in there, which corresponds to 32 bits applications running on a 64 bits OS. Exactly my case ;-)

I renamed the "Post Platform" key into "Post Platform-" and restarted the browser and... bingo :-) The browser is detected as IE 8.0 and everything works fine...

Now I need to find out why, when I open a new tab or a new instance of IE 8, the content is not loaded, as it continuously shows "Connecting...". I need to open one or more tabs before a connection can be made. It also happens when opening popup windows, which is even more annoying (in that case, I need to reopen the popup with Ctrl-N until it works).

To be continued...

Thursday, May 7, 2009

Monday, May 4, 2009

Les Compagnons du Champeau

Concert des 50 ans des Compagnons du Champeau, en l'église St Loup, à Namur, le samedi 2 mai 2009...

Wednesday, January 28, 2009

PPa Fest 2009

6ème édition du PPa Fest à Moustiers/Sambre, le samedi 24 janvier 2009.

Au programme, Mist, Vegas, Bikinians, Alpha 2.1 et the dIPLOMAT...