Pages

Monday, April 11, 2011

Adding Custom Snippets to the WPF Picker

Like most websphere software, portlet factory is very customizable and contains several config files which enable the developer to do this. Right now I'm going to focus on the /WEB-INF/config/IndirectJavaExpressions.config file.

Add Your Own Code
I'm busy using dojo with WPF, and one of the things that I know will come up often is the ability to provide a URL to a model so it can display some HTML. I'll probably be using the reference chooser to this:


Now I could just select the replace with java expression item and then type in my code, but that would get tedious and I like things that snap into place (like WPF builders). I can quickly leverage WPF customization by appending some resuable code to the IndirectJavaExpressions.config in my project:

DsixE/AjaxPageURL=JSPSupport.getActionURL(webAppAccess, \
     webAppAccess.getBackchannelURLMapper(false), "keep_page:yourPageHere")

I save the file and go back to my model and now I see this:


I can add any number of shortcuts to this file and deploy to a team, instantly increasing their productivity and the quality of the applications they build.

Tuesday, April 5, 2011

Dynamically Changing dijit.TooltipDialog

I've spent the last week trying to use dijit.TooltipDialog to display widgets programmatically, and although I've found many examples of how to do this, none really addressed my particular case. In this blog entry I will provide a working example of how to manipulate a TooltipDialog using code.

Start Simple
Let's just create a dialog with a textbox on it, along with a simple onclick trigger:

<div onclick="showDialog()">clickme</div>   
<br>
<br>
<div id="dialogTarget">dialog appears here</div> 

<script type="text/javascript">   
    dojo.require("dijit.form.TextBox");        
    dojo.require("dijit.TooltipDialog");        
    
    var dialog;
     
    dojo.addOnLoad(function(){
        var tb = new dijit.form.TextBox({name:"tb1"});
    
        dialog = new dijit.TooltipDialog({
            content: tb,
            onBlur: function() { dijit.popup.close(dialog); }
        });
    });
     
    function showDialog(){
        dijit.popup.open({ popup: dialog, around: dojo.byId("dialogTarget") });
    } 
    
</script>    

A few things to note about this code - the content of a tooltip can be a dijit widget or HTML in quotes, and we can make the toolip appear on any element of our choice using the dijit.popup function. Most examples I could find showed content as HTML and the display of the tooltip triggered by a dijit.form.DropDownButton, neither of which fit my needs.

Change the Content
So what happens if the content of the tooltip dialog needs to be changed at runtime? This can be addressed using the attr() function:
<div onclick="showDialog(false)">clickme</div>   
<div onclick="showDialog(true)">clickme again</div>   
<br>
<br>
<div id="dialogTarget">dialog appears here</div> 

<script type="text/javascript">   
    dojo.require("dijit.form.TextBox");        
    dojo.require("dijit.form.NumberSpinner");        
    dojo.require("dijit.TooltipDialog");        
    
    var dialog;
     
    dojo.addOnLoad(function(){
        var tb = new dijit.form.TextBox({name:"tb1"});
    
        dialog = new dijit.TooltipDialog({
            content: tb,
            onBlur: function() { dijit.popup.close(dialog); }
        });
    });
     
    function showDialog(changeContents){
    
        if (changeContents){
           var mySpinner = new dijit.form.NumberSpinner({
                value: 1000,
                smallDelta: 10,
                constraints: {
                    min: 9,
                    max: 1550,
                    places: 0
                },
                style: "width:100px"
            });
    
            dialog.attr("content", mySpinner);
        }
           
        dijit.popup.open({ popup: dialog, around: dojo.byId("dialogTarget") });
    } 
</script>    
In this code I've made a few changes to support two options - clicking on one element (clickme) will show the dialog we created in the first example, and another (clickme again) will change the contents of the dialog with a dijit.form.NumberSpinner. The key line of code here is dialog.attr("content", mySpinner).

Try it here.

Loading Sametime Proxy Scripts

More useful insight on integrating sametime dojo widgets into a web application - this entry explains how scripts are loaded.

Why can't I find these scripts?

Inspecting the example HTML provided with the ST proxy, one can identify some scripts such as:

<script type="text/javascript" src="http://<YourServer>:9081/stwebclient/dojo_1.2.3/dojo/dojo.js"></script>
<script type="text/javascript" src="http://<YourServer>:9081/stbaseapi/baseComps.js"></script>
<script type="text/javascript" src="http://<YourServer>:9081/stwebclient/livename.js"></script>

but don't go looking for them in your filesystem because you won't find them. The HTTP requests are intercepted by a servlet that maps the filename in the URL to a physical filename in the stproxyweb.war. For example in the above case the request for livename.js is redirected to the physical file /dojo_1.2.3/sametime/LiveNameAll.js. This little bit of knowledge is very useful when debugging because many of the javascript files are also uncompressed, and loading that version makes life much easier.

So, we can replace our above example with this:

<script type="text/javascript" src="http://<YourServer>:9081/stwebclient/dojo_1.2.3/dojo/dojo.js"></script>
<script type="text/javascript" src="http://<YourServer>:9081/stbaseapi/baseComps.js"></script>
<script type="text/javascript" src="http://<YourServer>:9081/stwebclient/dojo_1.2.3/sametime/LiveNameAll.js.uncompressed.js"></script>

And now we can read the original code in firebug, enabling us to insert appropriate breakpoints.

Servlet mapping list

widgetsPart1.js >> stproxyWidgetsAllFirst.js
widgetsPart2.js >> stproxyWidgetsAllSecond.js
chatPart1.js >> stproxyChatAllFirst.js
chatPart2.js >> stproxyChatAllSecond.js
adderLoader.js >> stproxyAdder.js
meetingLoader.js >> stproxyMeeting.js
announcementLoader.js >> stproxyAnnouncement.js
widgets.js >> stproxyWidgetsAll.js
widgetsLight.js >> stproxyWidgetsAllNoDojo.js
livename.js >> LiveNameAll.js
livenameLight.js >>LiveNameAllNoDojo.js

Wednesday, March 30, 2011

Command Recall on AIX

One of the most frustrating things about working with unix is the lack of a user interface, everything is command line. Try explaining stuff like awk, grep, vi and ls to new users and the complaints start to roll in. What tops the list has to be the lack of command recall using the arrow keys. We've all been conditioned that pressing up-arrow will bring back the previous command so we can make edits instead of typing the whole thing over again.

No more. Below is a short series of commands that can be added to a .profile that will enable the arrow keys to behave in unix like they do in DOS:

set -o emacs
alias __A='^P'
alias __B='^N'
alias __C='^F'
alias __D='^B' 

Note that ^P refers to the keysequence control-p while editing the file using vi, so actually typing in the characters probably won't work.

Thursday, March 17, 2011

Debugging Dojo with Firebug

I've spent the last few weeks trying to integrate sametime dojo widgets into a portal theme and I used firebug extensively to debug my code. Dojo is difficult to debug because of the way it injects code using the requires function, everything shows up as an eval.

Firebug Extensions

I didn't know this, but there are quite a few firebug extensions out there, though none really for dojo. IBM has developed a dojo extension for use in their rational developer products, but since I use eclipse I was out of luck. Thankfully IBM has a history of participating in the open source community and appears to have contributed their code to the firebug community.

The code can be found at http://code.google.com/p/fbug/source/browse/#svn%2Fextensions%2Fdojofirebugextension

I downloaded from their SVN server and executed the build.xml, drag/dropped the resulting dojofirebugextension-1.0a6.xpi into firefox and now I have a nice dojo interface for firebug.

Thanks to Patricio Reyna Almandos and Fernando Gomez (IBM Argentina) for putting this together.

Wednesday, March 9, 2011

Vague Error Message with Sametime Proxy

More insight related to my work with the integration of sametime into a portal theme. If anyone runs into this error:

SystemOut.log:[3/7/11 12:41:01:852 EST] 00000022 STLoginServle W com.ibm.rtc.stproxy.servlet.STLoginServlet loginbyToken  CLFRX0055E: unable to retrieve login credentials

the message is a little misleading. Yes, it cannot retrieve the login credentials, but why exactly? The proxy will produce this error if it cannot find at least one of the following in the request:
  • password
  • LtpaToken
  • LtpaToken2
  • SametimeToken
 In my case I was using SSO through a Webseal reverse proxy and I failed to qualify my junction as an LTPA junction. Webseal wasn't sending the token causing the above error.

Wednesday, March 2, 2011

Race Condition with Sametime Proxy Server

I've spent the last few weeks integrating a web based sametime chat client into websphere portal and ran into a curious problem. It seemed that on occasion the buddy list would not populate, all I'd get is a dojo busy indicator, but if I refreshed the page everything would be fine.

Time to open up firebug.

I have to admit that dojo isn't the easiest javascript to debug, they've really stretched the capabilities of the language, but I finally tracked it down to a piece of code during the execution of:

ST_Client = new sametime.WebClient({}, "STClient");

At some point it tests if it should display the buddy list right away or add the task to a queue for later execution, and in this case it was adding to the queue. So who is supposed to deal with the queue, and why wasn't it being done? Turns out that there's some code executed in the login

stproxy.login.loginByPassword()

that iterates through the queue and displays the buddy list. I was running into a race condition because I was trying to log in to the samtime server before showing the buddy list, but in some cases the login was finishing before the call to create the WebClient was done.

The Fix?

Ensure that the code creates the WebClient before it tries to login. Go figure.