Thursday, March 29, 2007

Credential renewal with MyProxy and JGlobus

I'm currently working on create a service as part of the LEAD project that will be responsible for kept grid credentials fresh for the duration of a workflow or some other user process. I've been experimenting with the capabilities of MyProxy and JGlobus to this end.

First of all, the MyProxy site has an excellent page on various grid credential renewal issues and MyProxy. So to begin, I want to set my credential renewer service as a "default renewer" in the MyProxy configuration. I do this by adding

default_renewers "DN of my renewing service"

to the myproxy-server.config file. Now my renewing service can renew credentials stored in this MyProxy server. Next, I store a proxy in MyProxy without a passphrase, so that MyProxy can use it for proxy renewal.

myproxy-init -n -s myproxy-server.mydomain.org -l myusername

The -n option says to store the proxy without a passphrase. Now I can renew this proxy with

myproxy-logon -s myproxy-server.mydomain.org -a /tmp/aging_proxy \
-l myusername -o /tmp/refreshed_proxy

In the previous command, -a specifies the proxy that we want to renew. For this to work, you either need to have loaded a proxy credential of the renewing service, or you need to set the X509_USER_CERT and X509_USER_KEY environment variables to the locations of the certificate and unencrypted key of your renewing service. And to do MyProxy renewal using the JGlobus API, it looks like this:

MyProxy myproxy = new MyProxy(myproxyHost, myproxyPort);
GetParams getParams = new GetParams();
getParams.setUserName(username);
getParams.setLifetime(24*60*60);
getParams.setAuthzCreds(userCred);

GSSCredential renewedCredential = myproxy.get(serviceCred, getParams);

Note that you need a valid MyProxy username as well as a still valid proxy credential. To load the service credential, do this:

GlobusCredential globusCred = new GlobusCredential(pathToServiceCert,
pathToServiceKey);
GSSCredential gssCred = new GlobusGSSCredentialImpl(globusCred,
GSSCredential.INITIATE_AND_ACCEPT);
An important thing to keep in mind (which I forgot halfway through this process) is that the credential stored in MyProxy cannot have a passphrase protecting it for it to be used to renew a proxy credential. We make use of the grid credential storage feature of MyProxy in the LEAD project, and for this to work with credential renewal, we first have to unencrypt the private key of the grid credential. Use openssl to do this:

openssl rsa -in ~/.globus/userkey.pem -out ~/.globus/userkey1.pem

Then store your credential to MyProxy with this key:

myproxy-store -s myproxy.mydomain.org -l myusername -y .globus/userkey1.pem

Now you'll be able to use this MyProxy credential for proxy renewal.

Wednesday, March 28, 2007

Setting the var attribute of dataTable in a facelet, part II

This time I take a completely different approach to this problem. The problem, by the way, is how to apply default Java Portlet API (JSR-168) CSS styles to the dataTable component. As shown in the previous post, this is complicated in Facelets by the fact that we can't just simply pass through a value for the var attribute of the dataTable component. But, this time that won't be an issue because we can simply extend the way Facelets handles the dataTable component and more directly apply the CSS styles we want.

After grepping through the Facelets source code, I discovered that HtmlComponentHandler is the TagHandler associated with the dataTable component (and all other HTML components as well). So I extended this with my own class, HtmlDataTableHandler:


package portletfacelets;

import javax.faces.component.UIComponent;
import javax.faces.component.html.HtmlDataTable;

import com.sun.facelets.FaceletContext;
import com.sun.facelets.tag.jsf.ComponentConfig;
import com.sun.facelets.tag.jsf.html.HtmlComponentHandler;

public class HtmlDataTableHandler extends HtmlComponentHandler {

public HtmlDataTableHandler(ComponentConfig config) {
super(config);
}

@Override
protected void onComponentCreated(FaceletContext ctx,
UIComponent c, UIComponent parent) {
super.onComponentCreated(ctx, c, parent);
if (c instanceof HtmlDataTable) {
HtmlDataTable table = (HtmlDataTable) c;
if (table.getFooterClass() == null) {
table.setFooterClass("portlet-section-footer");
}
if (table.getHeaderClass() == null) {
table.setHeaderClass("portlet-section-header");
}
if (table.getRowClasses() == null) {
table.setRowClasses("portlet-section-body," +
"portlet-section-alternate");
}
if (table.getStyleClass() == null) {
table.setStyleClass("portlet-section-body");
}
}
}

}


I check if the classes are null, to allow the user of the TagHandler to override the styles, but that's about it. The facelets taglib entry looks like this:


<tag>
<tag-name>dataTable2</tag-name>
<component>
<component-type>javax.faces.HtmlDataTable</component-type>
<renderer-type>javax.faces.Table</renderer-type>
<handler-class>portletfacelets.HtmlDataTableHandler</handler-class>
</component>
</tag>


I'm not sure which method I prefer, but I'm leaning toward the former, since it seems simpler and I like the idea of keeping things like CSS styles in a template file than in Java code, but in some sense this second approach also seems to be the cleaner one.

Running Portlets on Pluto from within Eclipse

The Pluto team recently released version 1.1.0 and as part of that release they include a very useful Pluto + Tomcat bundle that makes it very easy to get started. So I've been playing around with this and trying to figure out how to get it to work with Eclipse + WTP, and initially I ran into some issues. By default, WTP wants to take your application server and copy its files to a temporary location in which to deploy your webapp. However, this is fairly disastrous for portlet development because WTP doesn't copy everything and leaves behind important stuff like shared/lib, the portal webapp, etc. So I was trying to figure out what was left behind and manually copying the missing bits into the temporary location... aargh! And then I discovered a nice little feature of WTP. There is this "Run modules directly from the workspace" checkbox in the server settings for your app server, and unchecking this has the effect that Eclipse will deploy your web applications to the location of your app server and not some temporary location! So anyways, here are my notes on how to get this to work.

First, you need to register the Pluto 1.1/Tomcat 5.5.20 bundle with Eclipse as a Tomcat 5.5 server. Select File > New > Other and select Server, then click Next (or, if in the J2EE perspective, right click in the Servers View and select New > Server). Select a server type of "Tomcat v5.5", and click Next. Name it whatever you like, I call mine "Apache Tomcat v5.5 - Pluto". For "Tomcat installation directory:" browse to the location of where you installed the pluto bundle.




Click Finish. Now, we need to modify our Server definition for pluto just a bit, so go to the Servers view (if you don't have it, just switch to the J2EE perspective, or add the view with Window > Show View > Other..., then select Servers). Double click on your Pluto server defined there. Uncheck the "Run modules directly from the workspace" checkbox. We want Eclipse to run Pluto from the location of the pluto-bundle, so that it picks up the pluto webapp, shared/lib, and other bits that are needed because we are working with portlets.




Now, in order to run your portlet in Pluto from within Eclipse using WTP, you need to have your web.xml "pluto-ified". The Pluto guys have an Ant task called "assemble" which can do this for you, that's what I use. Just have it update your web.xml file (probably want to make a backup first). I've been working with a hello-world JSF Facelets sample portlet recently, here's how I get it running in Pluto:

Now we just need to get our application running on Pluto/Tomcat as before (right click on the Project, select Run As > Run on Server). The difference this time is that we will access our application through Pluto. In your web browser, go to http://localhost:8080/pluto. Login as user pluto, password pluto. In the upper left hand corner there is a label called "Navigation:". Mouse over this label to get a popup menu. Then select Pluto Admin from this list. Under Pluto Pages, select Pluto Admin from the drop down list. Then under Portlet Applications, select hello-world-jsf-facelets in the first drop down, and then in the second drop down select HelloWorldSamplePortlet, and click Add Portlet.



Now, the portlet should be there at the bottom of the page.



Note that the portlet pages configuration doesn't persist across restarts of the Pluto server. Consult the Pluto documentation if you want to persist the portal pages layout and configuration.

Now that our portlet is deployed to Pluto from within Eclipse, we can develop our portlet and have the changes immediately reflected in Pluto!

Thursday, March 22, 2007

Setting the var attribute of dataTable in a facelet

I'm currently working on a small little facelets suite to aid in portlet development. Initially, the idea is just to focus on making correct use of the portlet CSS styles implicit. So, for example, the following is the kind of code needed to set the portlet tables styles for the h:dataTable JSF component:


<h:dataTable value="#{mybean.myData}" var="row"
styleClass="portlet-section-body"
rowClasses="portlet-section-body,portlet-section-alternate"
headerClass="portlet-section-header">


So, I'd like to replace that with a facelet instead, so that it looks like this:


<p:dataTable value="#{mybean.myData}" var="row">


And the facelet would be defined once in a .xhtml file as:


<ui:composition>
<h:dataTable value="#{value}" var="#{var}"
styleClass="portlet-section-body"
rowClasses="portlet-section-body,portlet-section-alternate"
headerClass="portlet-section-header">
<ui:insert />
</h:dataTable>
</ui:composition>


However, this doesn't quite work. The problem is that it tries to set the var attribute of the dataTable component to a value expression, but dataTable requires a simple string for var. So we have to figure out some way of getting the var variable from the facelet into the dataTable component. What I came up with was a custom TagHandler that evaluates the value expression and then sets the var property of the dataTable component directly:


package portletfacelets;

import java.io.IOException;

import javax.el.ELException;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.component.html.HtmlDataTable;

import com.sun.facelets.FaceletContext;
import com.sun.facelets.FaceletException;
import com.sun.facelets.tag.TagAttribute;
import com.sun.facelets.tag.TagConfig;
import com.sun.facelets.tag.TagHandler;

public class SetVarHandler extends TagHandler {

private final TagAttribute var;

public SetVarHandler(TagConfig config) {
super(config);
this.var = this.getAttribute("var");
}
public void apply(FaceletContext ctx, UIComponent parent)
throws IOException, FacesException, FaceletException, ELException {

System.out.println("var=" + this.var.getValue(ctx));

if (parent instanceof HtmlDataTable) {
HtmlDataTable table = (HtmlDataTable) parent;
table.setVar(this.var.getValue(ctx));
}


this.nextHandler.apply(ctx, parent);
}

}


I add this to my facelets taglib.xml file as such:


<tag>
<tag-name>setVar</tag-name>
<handler-class>portletfacelets.SetVarHandler</handler-class>
</tag>


And then use it like this in my facelet:


<ui:composition>
<h:dataTable value="#{value}"
styleClass="portlet-section-body"
rowClasses="portlet-section-body,portlet-section-alternate"
headerClass="portlet-section-header">
<p:setVar var="#{var}" />
<ui:insert />
</h:dataTable>
</ui:composition>


Voila! However, seeing as this might come in handy in future instances, I wondered if I couldn't make something a bit more generic. So I created this TagHandler:


package portletfacelets;

import java.io.IOException;
import java.lang.reflect.Method;

import javax.el.ELException;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;

import com.sun.facelets.FaceletContext;
import com.sun.facelets.FaceletException;
import com.sun.facelets.tag.TagAttribute;
import com.sun.facelets.tag.TagConfig;
import com.sun.facelets.tag.TagHandler;

public class SetValueHandler extends TagHandler {

private final TagAttribute methodName;
private final TagAttribute value;

public SetValueHandler(TagConfig config) {
super(config);
this.methodName = this.getRequiredAttribute("methodName");
this.value = this.getRequiredAttribute("value");
}
public void apply(FaceletContext ctx, UIComponent parent)
throws IOException, FacesException, FaceletException, ELException {
try {

Method m = parent.getClass().getMethod(this.methodName.getValue(ctx),
new Class[]{String.class});
m.invoke(parent, new Object[]{this.value.getValue(ctx)});

} catch (Exception e) {
e.printStackTrace();
}

this.nextHandler.apply(ctx, parent);
}

}


So I'm using reflection to call any method on the parent JSF component and passing in the specified value. Then I use it in my facelet like so:


<ui:composition>
<h:dataTable value="#{value}"
styleClass="portlet-section-body"
rowClasses="portlet-section-body,portlet-section-alternate"
headerClass="portlet-section-header">
<p:setValue methodName="setVar" value="#{var}" />
<ui:insert />
</h:dataTable>
</ui:composition>


There you have it. Turns out there is more than one way to skin this cat, so I'll also share in a future blog post a different approach to this issue.

How to watch Google Videos on your DivX compatible DVD player

Google has put videos of their Tech Talks series online and I was interested in seeing if I could play these on my SD-3990 Toshiba DVD player which is DivX compatible. All you need to do is:
  1. Find the video at Google Video. Click the download link.
  2. The Google Video Player comes up and starts buffering the video. It saves the video into your My Videos/Google Video directory, or perhaps in a different location, you can check the preferences to see where the location is.
  3. The saved movie file has an extension .gvi (note, this is different than the saved Google Video Player, .gvp, file). Rename the extension to .avi.
  4. Burn this file to a CD-R disc. And it's ready to play.
Last night I used this technique to watch part of Bram Moolenaar's (of Vim fame) talk on 7 Habits For Effective Text Editing 2.0 on my DVD player from the comfort of my living room.

Wednesday, March 07, 2007

Custom Tomcat Server Location coming in Eclipse WTP 2.0

Web Tools Platform 2.0 M5 News

This looks very cool (scroll down to "Configure Tomcat's Paths"), especially for us portlet developers. It's been challenging using Eclipse WTP to run and debug portlets because WTP wants to take the Tomcat installation you provide, copy the server parts to a temporary location, and then deploy your webapp there. So it doesn't matter if the Tomcat installation you tell WTP to use has GridSphere or Pluto installed, they won't be there in the temporary location (neither the portal webapps nor shared/lib). Of course, you can manually copy the missing bits into the temp location, restart the server in Eclipse and get something working, but only after much consternation. So I happily welcome this new development and look forward to using WTP 2.0 when a final release is made.