<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-31592724</id><updated>2011-11-27T20:05:02.581-05:00</updated><category term='portlet'/><category term='apache'/><category term='technology'/><category term='javascript'/><category term='unix'/><category term='twitter'/><category term='mac'/><category term='maven'/><category term='parenting'/><category term='music'/><category term='eclipse'/><category term='pluto'/><category term='review'/><category term='tivo'/><title type='text'>Marcus Christie's Blog</title><subtitle type='html'>Wherein I write about stuff that I find interesting.  Most of entries will probably be technology related (Java, Web development, Python, Flex, etc.).  But I will also write about: my adventures in homeschooling and parenting, reviews of books I've read, and anything else I've learned or seen that I think is cool enough to share.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>46</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-31592724.post-2429213810499808379</id><published>2011-07-09T13:20:00.006-04:00</published><updated>2011-07-09T17:39:42.324-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><title type='text'>How to dynamically change the Tweet Button's tweet text</title><content type='html'>Looked around on the internet for a way to dynamically change the tweet text of the &lt;a href="http://dev.twitter.com/pages/tweet_button"&gt;Tweet Button&lt;/a&gt;, but didn't find a good solution. Most of what I found involved setting the text when the page is being rendered server side or client side. But what I need for &lt;a href="http://fuelmyroute.com/"&gt;FuelMyRoute.com&lt;/a&gt; is a way to dynamically update the tweet text based on the user's activity in the page after it has rendered. (Specifically, based on the route provided by the user, I want to update the tweet text to say something specific about how much the user has saved per gallon of gas.)&lt;br /&gt;&lt;br /&gt;The solution I went with uses the iframe Tweet Button, and basically you just need a bit of javascript to manipulate the URL that configures the iframe Tweet Button. I went with the iframe Tweet Button over the javascript Tweet Button because the javascript one manipulates the DOM and replaces your anchor tag with an iframe, etc. You could theoretically dynamically change the tweet text for the javascript Tweet Button but it would be a little brittle, being dependent on how the javascript Tweet Button renders itself.&lt;br /&gt;&lt;br /&gt;Enough jibber jabber, on to the code! You start by adding an iframe Tweet Button to the page:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1073967.js?file=gistfile1.xml"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Then you need this function which updates the text parameter of the iframe Tweet Button's query string (which of course will cause the button to reload):&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1073778.js?file=gistfile1.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;You can try it out right here. Click on the Tweet Button below and preview the message, which should be "Replace Me":&lt;br /&gt;&lt;br /&gt;&lt;iframe id="tweet-button" allowtransparency="true" frameborder="0" scrolling="no" src="http://platform.twitter.com/widgets/tweet_button.html?via=marcus_christie&amp;amp;text=Replace%20Me&amp;amp;count=horizontal" style="width:110px; height:20px;"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Now click on the button below which will call &lt;code&gt;updateTweetButtonText('I just dynamically updated the text of a Tweet Button!');&lt;/code&gt; and then click on the Tweet Button again to see that the preview tweet has been updated:&lt;br /&gt;&lt;br /&gt;&lt;script type="text/javascript" src="https://raw.github.com/gist/1073778/f0c1148a17240a063dbbfc8983411a70e6cc99b7/gistfile1.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;input type="button" value="Update text" onclick="updateTweetButtonText('I just dynamically updated the text of a Tweet Button!');" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-2429213810499808379?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/2429213810499808379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=2429213810499808379' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2429213810499808379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2429213810499808379'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2011/07/how-to-dynamically-change-tweet-buttons.html' title='How to dynamically change the Tweet Button&apos;s tweet text'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-5765611681383303262</id><published>2009-12-08T10:26:00.012-05:00</published><updated>2009-12-09T21:09:10.844-05:00</updated><title type='text'>A Review of Homeschooling</title><content type='html'>Imagine you are a parent of a child attending a school. Your child brings home one of her exams and on this exam is a question the answer to which is marked incorrect. Your child asks you why it’s incorrect. To the best of your ability you can’t tell why it is incorrect. It seems plainly correct. So you tell her so and hope that this will help her feel better about her results. Normally, that would be it, but it just so happens that this mark has caused her to not make honor roll. Blissfully assuming the teacher just made a mistake you call the teacher to see about correcting the error. But you get stonewalled. Eventually you are granted an audience with the principal. You explain the situation, and, to your surprise, the principle replies:&lt;br /&gt;&lt;blockquote&gt;Yes, the answer is correct. But that answer is a fourth-grade answer, and your daughter is only in the second grade. She isn’t supposed to know that yet.&lt;/blockquote&gt; Stunned you say “Excuse me?” The principal continues: &lt;blockquote&gt;It wouldn’t be fair to the other children if we gave her credit for the answer. You see, you are a devoted couple, married, and you help your daughter study, and there are children in her class whose parents are divorced, or who don’t speak English. Your daughter is ahead of them because you work with her. It wouldn’t be fair to the others if we gave her credit for what she knows as a result of that advantage.&lt;/blockquote&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/158542661X?ie=UTF8&amp;tag=marchrsblo-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=158542661X"&gt;&lt;img border="0" style="float: right" src="http://3.bp.blogspot.com/_0lq8ah647ZM/SyBXWPtIBYI/AAAAAAAABBI/kU1V9gzy_ws/s320/51nkf4cBA0L._SL160_.jpg"&gt;&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=marchrsblo-20&amp;l=as2&amp;o=1&amp;a=158542661X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;Now, what would you do? For &lt;span style="font-weight: bold;"&gt;Gregory &lt;/span&gt;and &lt;span style="font-weight: bold;"&gt;Martine Millman&lt;/span&gt;, as they recount in their book, &lt;span style="font-style: italic;"&gt;Homeschooling: A Family’s Journey&lt;/span&gt;, this was their tipping point to take their child out of school and begin an experiment in homeschooling. Their book is part memoir of a homeschooling family and part defense of the legitimacy of homeschooling. They share and reflect on their personal philosophy towards homeschooling, a philosophy that encourages flexibility and spontaneity and that is grounded in the recognition of the importance of the relationship between a student and a teacher.&lt;br /&gt;&lt;br /&gt;They spend a considerable portion of the book defending their decision to homeschool their children while also decrying the current state of public schools. As a homeschooling parent, much of this felt like preaching to the choir. But I related quite well to the fact that they continually suffered from doubts as to whether they were doing the right thing, so it is very understandable that they spend so much effort making a case for homeschooling. There also went on a myth busting spree, and there were a few myths that surprised me. For example, they cite studies that show that there is no correlation between expertise in a subject area and the ability to teach it. Another &lt;a href="http://epaa.asu.edu/epaa/v7n8/"&gt;study they cite&lt;/a&gt; showed that whether a parent had a teacher’s license or not had no effect on a student’s test score. I looked up that study and found that it also found no correlation in test scores between families that use a “full service” curriculum (this is basically, I gather, a “school in a box” type thing with complete curriculum materials and even scripts for the “teacher”) and those that do not. I found this interesting because when I talk to other people about our decision to homeschool I’m often met with a response like “Oh, I couldn’t do that” and I explain, almost as if I’m making an excuse for myself, that my wife, Tracy, is a former, licensed teacher. But the Millman’s argue, and the studies show, that anyone who wants to homeschool can.&lt;br /&gt;&lt;br /&gt;Their philosophy on homeschooling is to create an environment where there is freedom to explore what pique’s the child’s interest. Of course, there is structure, but there is also the flexibility to take advantage of opportunities. For example, they mention a time when some workers came to their house to take away a tree that had fallen down in a storm. Since it was a fairly noisy undertaking, it would have been hard to stick to the schedule. So, they made a learning opportunity out of it. They looked at and noted not only the mechanics of the operation but also the social dynamics of the workers and their boss.&lt;br /&gt;&lt;br /&gt;Another important aspect of their philosophy is to provide personal attention and develop the whole child. They place a lot of emphasis on the relationship between the student and the teacher. This relationship is grounded in the practice of emulation; the student emulates the teacher in learning how to learn. The importance of relationship is manifold. For example, there is also the relationship to the subject matter being studied, to really appreciate it for its own sake and not as a means unto an end; in schools, that end is too often a standardized test. They point out that in schools the student learns how to relate to the institution, what its rules are and how to “work the system”, but this kind of relationship is obviously not academically sustaining.&lt;br /&gt;&lt;br /&gt;This is not a handbook on how to homeschool; they present a simple homeschooling philosophy that they have developed within their family which they illustrate with several anecdotes. But there is some concrete homeschooling advice. Chapter 3 contains some curriculum advice, materials they have used and found useful, for several academic subjects. But perhaps the most practical chapter is the one on choosing a college. They offer several insights into the admissions process from the perspective of homeschoolers. For example, colleges often require that they have a transcript with grades and such although ultimately they don’t trust the grades reported by homeschooling parents. There’s a list of 18 tips on how to better navigate the admissions process and when our children are reaching that stage of life I know that this chapter will be a handy reference. I also liked how they look at going to college as really “joining” a college, for life and as a family.&lt;br /&gt;&lt;br /&gt;Overall, it was a very inspirational book for me as a homeschooler. I was inspired by their adventurous spirit in seeking out educational opportunities wherever they may be. Their holistic approaches to education, their value of developing the whole child, and their emphasis on the importance of relationship have encouraged me to incorporate those same ideas in our own homeschooling.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-5765611681383303262?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/5765611681383303262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=5765611681383303262' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/5765611681383303262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/5765611681383303262'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2009/12/review-of-homeschooling.html' title='A Review of Homeschooling'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_0lq8ah647ZM/SyBXWPtIBYI/AAAAAAAABBI/kU1V9gzy_ws/s72-c/51nkf4cBA0L._SL160_.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-6566528696326659020</id><published>2009-10-04T08:38:00.005-04:00</published><updated>2009-10-08T17:44:51.375-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='music'/><title type='text'>New Music: Company of Thieves, Matisyahu and more</title><content type='html'>I listen to &lt;a href="http://www.wfpk.org/"&gt;WFPK&lt;/a&gt; radio online during the workday and All Songs Considered podcast during my work commute. They have both introduced me to some great music, and here are some of my recent favorites. Hope you enjoy them as much as I did.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:130%;" &gt;Pressure&lt;/span&gt;&lt;span style="font-size:130%;"&gt; by &lt;a href="http://www.companyofthieves.net/"&gt;Company of Thieves&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/bbAVPJjpXAY&amp;amp;color1=0xb1b1b1&amp;amp;color2=0xcfcfcf&amp;amp;hl=en&amp;amp;feature=player_embedded&amp;amp;fs=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/bbAVPJjpXAY&amp;amp;color1=0xb1b1b1&amp;amp;color2=0xcfcfcf&amp;amp;hl=en&amp;amp;feature=player_embedded&amp;amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" height="344" width="425"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-style: italic;"&gt;One Day&lt;/span&gt; by Matisyahu&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/k-aAZT15eHc&amp;amp;hl=en&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/k-aAZT15eHc&amp;amp;hl=en&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-style: italic;"&gt;Never Forget You&lt;/span&gt; by Noisettes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="480" height="295"&gt;&lt;param name="movie" value="http://www.youtube.com/v/a4dSEyaT6R8&amp;hl=en&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/a4dSEyaT6R8&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="295"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-style: italic;"&gt;Animal&lt;/span&gt; by Miike Snow&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/niKT-kJfUz4&amp;amp;hl=en&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/niKT-kJfUz4&amp;amp;hl=en&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-style: italic;"&gt;40 Day Dream&lt;/span&gt; by Edward Sharpe and the Magnetic Zeros&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="480" height="295"&gt;&lt;param name="movie" value="http://www.youtube.com/v/h0RQnGhxZzg&amp;hl=en&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/h0RQnGhxZzg&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="295"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-style: italic;"&gt;Border Reiver&lt;/span&gt; by Mark Knopfler&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="480" height="295"&gt;&lt;param name="movie" value="http://www.youtube.com/v/dzqNSAbE7Fo&amp;hl=en&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/dzqNSAbE7Fo&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="295"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-6566528696326659020?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/6566528696326659020/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=6566528696326659020' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/6566528696326659020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/6566528696326659020'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2009/10/new-music-company-of-thieves-matisyahu.html' title='New Music: Company of Thieves, Matisyahu and more'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-8319220499478554730</id><published>2009-06-06T09:24:00.003-04:00</published><updated>2009-06-06T14:40:05.068-04:00</updated><title type='text'>Combining blogs</title><content type='html'>&lt;blockquote&gt;Summary: I'm combining my personal and professional blogs.  All my posts will go into this blog.  If you only care to get my technology related posts, please update your feed reader to subscribe to just the &lt;a href="http://feeds2.feedburner.com/MarcusChristiesTechnologyBlog" rel="alternate" type="application/rss+xml"&gt;Technology Related Entries&lt;/a&gt;.&lt;/blockquote&gt;&lt;br /&gt;A couple of years ago, when I started blogging, I decided (as I had seen others doing) to create two blogs: one for blogging on work related things and one for blogging about everything else in my life. The main reason for having two blogs was so that people who are interested in my technology, work-related writings (i.e., coworkers and colleagues) could subscribe to and receive only those and likewise for my personal blog posts.  In the meantime, however, Blogger.com has added the labeling feature which allows me to &lt;a href="http://labnol.blogspot.com/2007/08/offer-rss-feeds-for-blogger-search.html"&gt;create feeds of subcategories&lt;/a&gt; of this blog.&lt;br /&gt;&lt;br /&gt;So going forward every technology related blog post will be tagged with the &lt;a href="http://marcus-christie.blogspot.com/search/label/technology"&gt;&lt;span style="font-style: italic;"&gt;technology&lt;/span&gt;&lt;/a&gt; label.  I've created &lt;a href="http://feeds2.feedburner.com/MarcusChristiesTechnologyBlog?format=xml"&gt;a feed just for these posts&lt;/a&gt;.  Otherwise, if you subscribe to this blog in the normal way, you'll get all entries.  Maybe I'll create other feeds for other sub-categories, but for now I'll leave it at&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://feeds2.feedburner.com/MarcusChristiesTechnologyBlog" rel="alternate" type="application/rss+xml"&gt;Technology Related Entries&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://feeds2.feedburner.com/MarcusChristiesBlog" rel="alternate" type="application/rss+xml"&gt;All Entries&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;What will I be writing about going forward?  Without making any firm commitments, here are some things that I would like to post about in the near term future&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Adobe Flex (which I've been learning about and using at my current job)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Homeschooling and parenting&lt;/li&gt;&lt;li&gt;Book and movie reviews and discussions&lt;/li&gt;&lt;li&gt;I've become interested lately in better code design and also software development processes, so I hope to blog on what I've learned and will be learning about these in the future&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Python, specifically the TurboGears framework&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Your feedback and comments are welcome.  Here's to writing more blog posts and writing them more regularly!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-8319220499478554730?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/8319220499478554730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=8319220499478554730' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/8319220499478554730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/8319220499478554730'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2009/06/combining-blogs.html' title='Combining blogs'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-3581935027329668410</id><published>2008-11-04T20:07:00.000-05:00</published><updated>2009-06-06T08:30:26.542-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>How to use custom ant tasks in a WTP generic ant publisher</title><content type='html'>Before creating the &lt;a href="http://code.google.com/p/pluto-server-plugin/"&gt;Eclipse Pluto Server Plug-in&lt;/a&gt;, I had an Ant script to publish my portlets to a Pluto server.  That Ant script used the &lt;a href="http://maven.apache.org/ant-tasks/index.html"&gt;Maven2 ant tasks&lt;/a&gt; to download the needed Pluto ant task jar and its dependencies.  This Pluto ant task is needed to rewrite the portlet's web.xml so that it contains the Pluto server's invoker of the portlet.  When I first created the plug-in and needed a way to get the Pluto ant task jar, I looked for how to include it with the plug-in jar but I couldn't figure out how to expose it to the Pluto ant publisher script I created as part of the &lt;a href="http://www.eclipse.org/webtools/community/tutorials/ServerDefinitionExplained/ServerDefinitionExplained.html"&gt;WTP generic server definition&lt;/a&gt;.  So, I used the Maven2 stuff I already had, and it worked pretty well for me.  However, it was never ideal.&lt;br /&gt;&lt;br /&gt;Recently, actually by accident, I figured out how to make ant tasks in a plug-in available to a WTP ant publisher.  I stumbled upon the Eclipse ant extension point documentation, specifically, the part about &lt;a href="http://help.eclipse.org/stable/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/extension-points/org_eclipse_ant_core_extraClasspathEntries.html"&gt;Extra Ant Classpath Entries&lt;/a&gt;.  Not sure how I missed this before, but it's basically all right there.  There's also the &lt;a href="http://help.eclipse.org/stable/topic/org.eclipse.platform.doc.isv/reference/extension-points/org_eclipse_ant_core_antTasks.html"&gt;org.eclipse.ant.core.antTasks&lt;/a&gt; extension point which allows you to expose ant tasks to your ant scripts in Eclipse.  Since it wasn't immediately obvious to me at first, I thought I would post how I got it working.  It's actually quite simple once you know what extension points to work with.&lt;br /&gt;&lt;br /&gt;Here's what I added to the Pluto Server Plug-in plugin.xml to define the Pluto ant task&lt;br /&gt;&lt;pre style="overflow: auto"&gt;&lt;br /&gt;  &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extension&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;point&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"org.eclipse.ant.core.antTasks"&lt;/span&gt;&lt;span style="color:#008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;antTask&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"pluto.assemble"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="color:#008080;"&gt;            &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"org.apache.pluto.ant.AssembleTask"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="color:#008080;"&gt;            &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/pluto-ant-tasks-1.1.6.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="color:#008080;"&gt;            &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#008080;"&gt;&amp;lt;/extension&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But of course this ant task has dependencies.  To make it's dependencies available to it, you'll just need to add extraClasspathEntries&lt;br /&gt;&lt;br /&gt;&lt;pre style="overflow: auto"&gt;&lt;br /&gt;  &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extension&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#008080;"&gt;        &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;id&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"pluto-assembletask-classpath"&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#008080;"&gt;        &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;point&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"org.eclipse.ant.core.extraClasspathEntries"&lt;/span&gt;&lt;span style="color:#008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/castor-1.1.1.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt; /&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/cglib-full-2.0.2.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt; /&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/commons-beanutils-1.7.0.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt; /&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/commons-cli-1.0.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt; /&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/commons-digester-1.8.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt; /&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/commons-io-1.3.1.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt; /&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/commons-lang-1.0.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/commons-logging-1.0.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/commons-logging-api-1.1.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/pluto-descriptor-api-1.1.6.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/pluto-descriptor-impl-1.1.6.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/pluto-util-1.1.6.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/xercesImpl-2.6.2.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;extraClasspathEntries&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;library&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"lib/xmlParserAPIs-2.6.2.jar"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"false"&lt;/span&gt;&lt;span style="color:#008080;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#008080;"&gt;&amp;lt;/extension&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I'm not quite sure why, but the &lt;code&gt;eclipseRuntime&lt;/code&gt; attribute needs to be set to false to get this to work.  The docs say&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;b&gt;eclipseRuntime&lt;/b&gt; - indicates whether this extra classpath entry should only be considered for builds run in the same VM as Eclipse. The implied value is true, when not specified.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;So I can only guess that this means that the WTP ant publisher doesn't run in the same VM as Eclipse?  Anyhow, I tried it both ways, and it only worked with the value of false.&lt;br /&gt;&lt;br /&gt;From my ant publisher script, nothing special, I just reference the &lt;code&gt;pluto.assemble&lt;/code&gt; task (I gave it that name).  Here's the snippet where I use it:&lt;br /&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;target&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;name&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"assemble"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"portletxml.exists"&lt;/span&gt;&lt;span style="color:#008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color:#008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#008080;"&gt;pluto&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;.&lt;/span&gt;&lt;span style="color:#008080;"&gt;assemble&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;webxml&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"${module.dir}/WEB-INF/web.xml"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="color:#008080;"&gt;                  &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;portletxml&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"${module.dir}/WEB-INF/portlet.xml"&lt;/span&gt;&lt;span style="color:#008080;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="color:#008080;"&gt;                  &lt;/span&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;destfile&lt;/b&gt;&lt;/span&gt;=&lt;span style="color:#ff00ff;"&gt;"${webxml.with.portlet.mapping.file}"&lt;/span&gt;&lt;span style="color:#008080;"&gt; /&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#008080;"&gt;&amp;lt;/target&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Previously I had to define the task with a &lt;code&gt;&amp;lt;taskdef&gt;&lt;/code&gt; tag, but I no longer need that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-3581935027329668410?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/3581935027329668410/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=3581935027329668410' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/3581935027329668410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/3581935027329668410'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2008/11/how-to-use-custom-ant-tasks-in-wtp.html' title='How to use custom ant tasks in a WTP generic ant publisher'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-7669922444788563944</id><published>2008-11-04T19:55:00.000-05:00</published><updated>2009-06-06T08:09:29.000-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='portlet'/><category scheme='http://www.blogger.com/atom/ns#' term='pluto'/><title type='text'>Pluto Server Plug-in 1st beta of 1.0.0 released</title><content type='html'>This past weekend I created a 1.0.0.b1 release of the &lt;a href="http://code.google.com/p/pluto-server-plugin/"&gt;Eclipse Pluto Server Plug-in&lt;/a&gt;.  Biggest change is that I got rid of the hack I had in there using Maven to download the Pluto ant task and dependencies needed to publish a portlet to Pluto.  I now bundle the ant task jar and its dependencies with the plug-in (a topic for a future post).  Having Maven do the download was something that would work most times but had problems.  For example, some users have not been able to get the plug-in to work with a proxy server setup (see &lt;a href="http://code.google.com/p/pluto-server-plugin/issues/detail?id=3"&gt;issue #3&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;It likely won't get picked up as an update in Eclipse; you'll need to go into the Update Manager and install it as a new feature.  And don't forget to use &lt;a href="http://pluto-server-plugin.googlecode.com/svn/trunk/pluto.server.update"&gt;http://pluto-server-plugin.googlecode.com/svn/trunk/pluto.server.update&lt;/a&gt; as your update site.  If you try it out, let me know.  I'd like to make the 1.0.0 release soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-7669922444788563944?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/7669922444788563944/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=7669922444788563944' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7669922444788563944'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7669922444788563944'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2008/11/pluto-server-plug-in-1st-beta-of-100.html' title='Pluto Server Plug-in 1st beta of 1.0.0 released'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-671973461041663018</id><published>2008-08-02T18:03:00.000-04:00</published><updated>2009-06-06T08:09:29.001-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='portlet'/><category scheme='http://www.blogger.com/atom/ns#' term='pluto'/><title type='text'>Could not publish to server NPE bug fixed!</title><content type='html'>I finally had some time to sit down and try to figure out the "Could not publish to server NPE bug".  Turns out to be a bug in WTP 2.0.2, &lt;a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=219627"&gt;bug #219627&lt;/a&gt;.  The WTP team released a patch and then later they made a &lt;a href="http://www.eclipse.org/webtools/releases/2.0.3/"&gt;full 2.0.3 release&lt;/a&gt;.  However, if you download the latest version of Eclipse Europa (for JEE), it &lt;span style="font-style: italic;"&gt;still has the older 2.0.2 version of WTP&lt;/span&gt;.  Which I believe explains why there have been so many reports of this problem.&lt;br /&gt;&lt;br /&gt;So the fix is to run the update manager in Eclipse and get the most recent updates for WTP.  I confirmed this by reverting my Eclipse config to WTP 2.0.2 and was able to reliably reproduce the issue.  Reverting back to WTP 2.0.3 got the deploy to Pluto working again.&lt;br /&gt;&lt;br /&gt;I added a &lt;a href="http://code.google.com/p/pluto-server-plugin/wiki/FrequentlyAskedQuestions"&gt;FAQ page&lt;/a&gt; for the project with a FAQ also explaining the issue.  I also verified that the Pluto server plug-in works in Ganymede.&lt;br /&gt;&lt;br /&gt;Many thanks to campi, by the way.  I basically &lt;a href="http://www.google.com/search?q=NullPointerException+at+ComponentUtilities.getDeployUriOfComponent&amp;amp;hl=en"&gt;ran a Google search&lt;/a&gt; based on the &lt;a href="http://marcus-christie.blogspot.com/2008/06/pluto-server-plug-in-could-not-publish.html?showComment=1216759680000#c1475274554528461010"&gt;stack trace campi posted&lt;/a&gt; to &lt;a href="http://forums.java.net/jive/thread.jspa?messageID=287798"&gt;find others who had run into the same issue but with a different plug-in&lt;/a&gt;.  And that eventually got me to the Eclipse bug and the resolution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-671973461041663018?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/671973461041663018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=671973461041663018' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/671973461041663018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/671973461041663018'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2008/08/could-not-publish-to-server-npe-bug.html' title='Could not publish to server NPE bug fixed!'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-2525867393698910475</id><published>2008-06-30T12:20:00.001-04:00</published><updated>2009-06-06T09:07:04.484-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tivo'/><category scheme='http://www.blogger.com/atom/ns#' term='review'/><title type='text'>Amazon Unbox Review</title><content type='html'>&lt;blockquote style="font-style: italic;"&gt;Synopsis: Amazon Unbox is too lacking in the convenience and features departments to justify the price.  But if they address some of the missing features and switched to a Netflix-style, all-you-can-eat subscription model, then they could really compete.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Recently had an excuse to try out Amazon Unbox on our Tivo.  The whole family was sick this past weekend and we had already watched our Netflix movie and everything Tivo had recorded for us :)  So we thought, why not download a movie from Amazon Unbox?&lt;br /&gt;&lt;br /&gt;I had already linked my Amazon account with our Tivo account, so ordering the movie just required that I enter a 5 digit pin number.  There was a snafu with the credit card I was using, but once I got that resolved, the movie started downloading almost immediately.  Only problem was that &lt;span style="font-weight: bold;"&gt;it took a LOOOONNNNGGGG time for it to download&lt;/span&gt; (we have a supposedly 10mbps cable DSL connection).  By long, I mean in the range of about 6-8 hours.  Since we started this just before dinner, there was no chance we could watch this that night.  We had to wait until the next day.&lt;br /&gt;&lt;br /&gt;The movie shows up in the Now Playing list as soon as it starts downloading.  There is no estimate of how long it will take to complete, but Tivo does tell you how many minutes of the movie have been downloaded.  The Amazon Unbox site doesn't tell you how many minutes total the movie is, but I was able to find this information via Netflix.  Thus, you can do back of the envelope calculation of how long the download will take.  (By the way, I believe the total download size was 2.4 GB).&lt;br /&gt;&lt;br /&gt;The way Amazon Unbox works is that you have 24 days to keep the downloaded rental, but once you start watching it, you have 24 hours before it will be deleted.  Tivo's provides a warning message when you start watching the movie and if you stop watching Tivo tells you exactly when the movie will be deleted.  So that's all very good.&lt;br /&gt;&lt;br /&gt;We started watching the movie, and &lt;span style="font-weight: bold;"&gt;the picture quality is top notch, easily DVD quality&lt;/span&gt;.  It's just like a recorded TV program; there are no chapters, no menus, just the movie from beginning to end.  So that's one strike against Amazon Unbox, that you don't get the bonus features or options or navigability of a DVD.  Since the characters in this particular movie speak with a Scottish accent, we wanted to put on subtitles.  Nope, can't do it.  How about closed captioning?  Amazingly, no, &lt;span style="font-weight: bold;"&gt;closed captioning doesn't work either&lt;/span&gt;.  This is pretty much a deal breaker for me.&lt;br /&gt;&lt;br /&gt;The movie cost $3.99, about the same as rental from a local video store.  Is the value worth the price?  No, I don't think so.  Speaking of the local video store, it would have been faster to have &lt;span style="font-style: italic;"&gt;walked &lt;/span&gt;to it to rent a DVD, and we would have had a richer viewing experience on top of it, for about the same price.  And it can't begin to compete with the tremendous value of the Netflix service.&lt;br /&gt;&lt;br /&gt;I have some advice for the Amazon Unbox team (they're waiting with bated breath for it, I know).  They really need to add support for closed captioning, at the very least, but if they could figure out a way to add in the other features that one typically expects with a DVD that would definitely bolster their offering.  The long download time could be mitigated if the download occurred automatically, in the background.  What I'm thinking of here is a subscription service and that one could have a Netflix like queue with their Amazon Unbox account and when they finish with one movie and delete it, the next movie could start downloading immediately.  This would mean a turnaround time measured in hours instead of the Netflix turnaround time which is measured in days.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-2525867393698910475?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/2525867393698910475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=2525867393698910475' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2525867393698910475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2525867393698910475'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2008/06/amazon-unbox-review_30.html' title='Amazon Unbox Review'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-4516239955435783638</id><published>2008-06-28T08:44:00.000-04:00</published><updated>2009-06-06T08:09:29.001-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Getting open square bullets in OpenOffice.org</title><content type='html'>Sometimes it's nice to create a bulleted list with a check box like bullet, e.g., creating a packing list.  Seems like in Word there's a quick option for selecting this style of bullets, but not so in OpenOffice.  To change a bulleted list to have a check box style bullet:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Select the bulleted list and in the menu go to &lt;span style="font-weight: bold;"&gt;Format &gt; Bullets and Numbering...&lt;/span&gt;&lt;/li&gt;&lt;li&gt;In the dialog that comes up, select the &lt;span style="font-weight: bold;"&gt;Options&lt;/span&gt; tab.&lt;/li&gt;&lt;li&gt;Click the &lt;span style="font-weight: bold;"&gt;...&lt;/span&gt; button labeled &lt;span style="font-weight: bold;"&gt;Character&lt;/span&gt;.  Under Ubuntu, the default font for my document is &lt;span style="font-style: italic;"&gt;DejaVu Sans&lt;/span&gt; and the subset of characters displayed is the &lt;span style="font-style: italic;"&gt;Geometric Shapes&lt;/span&gt;.  If you scroll up or down a bit, you can see a few different open square type bullets that can be used as check boxes.&lt;/li&gt;&lt;/ol&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_0lq8ah647ZM/SGY1SUW81RI/AAAAAAAAAgg/4pbY9ErVac0/s1600-h/openoffice_checkbox_bullets.png"&gt;&lt;img style="cursor: pointer;" src="http://2.bp.blogspot.com/_0lq8ah647ZM/SGY1SUW81RI/AAAAAAAAAgg/4pbY9ErVac0/s400/openoffice_checkbox_bullets.png" alt="" id="BLOGGER_PHOTO_ID_5216915807174186258" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-4516239955435783638?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/4516239955435783638/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=4516239955435783638' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4516239955435783638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4516239955435783638'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2008/06/getting-open-square-bullets-in.html' title='Getting open square bullets in OpenOffice.org'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_0lq8ah647ZM/SGY1SUW81RI/AAAAAAAAAgg/4pbY9ErVac0/s72-c/openoffice_checkbox_bullets.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-6381979954116157470</id><published>2008-06-22T16:07:00.000-04:00</published><updated>2009-06-06T08:09:29.001-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='pluto'/><title type='text'>Eclipse Pluto Server Plug-in, v. 0.2.5 (now on Google Code)</title><content type='html'>Just finished moving the Pluto Server Plug-in code over to its own project page, &lt;a href="http://code.google.com/p/pluto-server-plugin/"&gt;pluto-server-plugin&lt;/a&gt;, on Google Code.  I created a new minor release, v. 0.2.5, just to switch over the update site to the one on Google Code.  Switching over a plug-in's update site took some experimentation, but here's how I did it (for future reference and for anyone else needing to change a plug-in's update site)&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Change the Update Site URL for the Feature to the new update site. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Bump the Feature version and do a new release to the old site.  Users with an older release of the plug-in will get the update which will point them to the new update site for future releases.&lt;/li&gt;&lt;li&gt;Change the Update Site URL in the Update Site's site.xml file.  Publish the update site to the new update site location.&lt;/li&gt;&lt;/ol&gt;So hopefully it will be a seamless update for Pluto Server Plug-in users.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-6381979954116157470?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/6381979954116157470/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=6381979954116157470' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/6381979954116157470'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/6381979954116157470'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2008/06/eclipse-pluto-server-plug-in-v-025-now.html' title='Eclipse Pluto Server Plug-in, v. 0.2.5 (now on Google Code)'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-598397469526697447</id><published>2008-06-01T15:43:00.000-04:00</published><updated>2009-06-06T08:09:29.001-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='pluto'/><title type='text'>Pluto Server Plug-in: Could not publish to server NPE bug</title><content type='html'>Some users of the Pluto server plug-in have had trouble getting a simple plug-in to deploy.  They receive an error message:&lt;br /&gt;&lt;blockquote&gt;Could not publish to the server.&lt;br /&gt;java.lang.NullPointerException&lt;/blockquote&gt;&lt;br /&gt;Unfortunately, I've not been able to recreate the "Could not publish to the server" error.  I have created a new, clean Eclipse workspace and install, and went through the tutorial and it all still works.&lt;br /&gt;&lt;br /&gt;For those who are experiencing problems, I've added a &lt;a href="http://www.cs.indiana.edu/%7Emachrist/projects/pluto-server-plugin/test-portlet.zip"&gt;test portlet eclipse project&lt;/a&gt; that you can import and try to deploy to Pluto.  Some other troubleshooting ideas&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Make sure that you have a portlet.xml along with your portlet code.  That will be necessary.  See the eclipse project above for a simple example.&lt;/li&gt;&lt;li&gt;When first doing the deploy, you'll need to be connected to the internet so that the Maven ant tasks can download the pluto dependencies.  This is only required the first time you use the plug-in to deploy to a pluto server.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Check &lt;code&gt;ECLIPSE_WORKSPACE/.metadata/.log&lt;/code&gt;.  It may have more details regarding the exact nature of the error.  If you find anything, please do share it with me; I'd love to get to the bottom of this bug.&lt;/li&gt;&lt;/ul&gt;In other Pluto Server Plug-in related business, I hope to have the code moved over to Google Code sometime this month.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-598397469526697447?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/598397469526697447/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=598397469526697447' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/598397469526697447'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/598397469526697447'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2008/06/pluto-server-plug-in-could-not-publish.html' title='Pluto Server Plug-in: Could not publish to server NPE bug'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-7724549789050485223</id><published>2007-10-21T07:42:00.000-04:00</published><updated>2009-06-06T08:09:29.001-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='portlet'/><category scheme='http://www.blogger.com/atom/ns#' term='pluto'/><title type='text'>Pluto Server Plug-in Screencast Posted</title><content type='html'>Just finished the &lt;a href="http://www.cs.indiana.edu/%7Emachrist/projects/pluto-server-plugin/demo.htm"&gt;screencast&lt;/a&gt; promised for the Pluto Server Plug-in.  It's fairly simple, goes through installing the plug-in and then creating a simple "hello world" type portlet and deploying and displaying it in Pluto.&lt;br /&gt;&lt;br /&gt;&lt;s&gt;Unfortunately, the size of the screencast, produced with Wink, comes it at a little over 10MB.  I need to figure out how to keep these guys from getting so bloated.&lt;/s&gt; Using color palette now, has reduced the file size to just under 5MB.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-7724549789050485223?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/7724549789050485223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=7724549789050485223' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7724549789050485223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7724549789050485223'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/10/pluto-server-plug-in-screencast-posted.html' title='Pluto Server Plug-in Screencast Posted'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-3210697481504259681</id><published>2007-09-30T12:09:00.000-04:00</published><updated>2009-06-06T08:09:29.001-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='portlet'/><category scheme='http://www.blogger.com/atom/ns#' term='pluto'/><title type='text'>Eclipse Pluto Server Plug-in, v. 0.2.4</title><content type='html'>I've been working on an Eclipse Plug-in recently to provide a server definition for the Pluto portal driver.  Let me explain why.  To start with, I should say that I've been &lt;a href="http://marcus-christie.blogspot.com/2007/03/running-portlets-on-pluto-from-within.html"&gt;using Pluto 1.1.x with Eclipse for a while&lt;/a&gt;, since it comes bundled with Tomcat, it makes a nice, lightweight rapid development environment for working with portlets.  And Pluto keeps getting better.  In the latest release (v. 1.1.4), &lt;a href="https://issues.apache.org/jira/browse/PLUTO-382"&gt;changes to the portal pages and layouts are persisted across server restarts&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Alas, there has always been the annoyance that Eclipse wants to deploy your web application as-is to the server, including the web.xml, and Pluto, like all portal servers, expects special servlet mappings to be in place for portlets in your portlet application.  For me this has meant having to rewrite the web.xml for when I want to deploy to Pluto in Eclipse, but then changing it back for when I want to change a servlet definition (or deploy to a different portal server, e.g., GridSphere).  So that is the problem that this Eclipse plug-in solves.  The web.xml rewriting is taken care of by the plug-in at deployment time.&lt;br /&gt;&lt;br /&gt;I've put up a &lt;a href="http://www.extreme.indiana.edu/%7Emachrist/projects/pluto-server-plugin/"&gt;quick web page&lt;/a&gt; for those interested.  For the impatient, create a new remote site in the update manager with this url: &lt;a href="http://www.extreme.indiana.edu/%7Emachrist/projects/pluto-server-plugin/updates"&gt;http://www.extreme.indiana.edu/~machrist/projects/pluto-server-plugin/updates&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I've started work on a screencast to show how this thing works, and hopefully I'll get that posted next week.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-3210697481504259681?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/3210697481504259681/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=3210697481504259681' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/3210697481504259681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/3210697481504259681'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/09/eclipse-pluto-server-plug-in-v-024.html' title='Eclipse Pluto Server Plug-in, v. 0.2.4'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-7118486140448861471</id><published>2007-07-24T12:23:00.000-04:00</published><updated>2009-06-06T08:09:29.002-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>PURSe Portlets 1.1.0 Released</title><content type='html'>Just finished tagging and releasing a new version of the PURSe Portlets.  There are several great things in this release.  The one I am most proud of is also the one least apparent to the casual observer: the PURSe portlets are now synced up with the mainline PURSe codebase.  In PURSe Portlets 1.0.x, I had made modifications to the PURSe 1.0 release, but now I am a PURSe committer and I've committed some of those modifications and bugfixes into the PURSe trunk.  Also, I've developed an install script for PURSe that will install PURSe and it's dependencies, including a minimal deployment of Globus.  This should take a lot of the pain out of getting started with PURSe for the new user.&lt;br /&gt;&lt;br /&gt;Additional new features include:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Added an AJAX "Check availability of username" to registration portlet&lt;/li&gt;&lt;li&gt;Forgot password portlet now resets the user's password instead of revealing it&lt;/li&gt;&lt;li&gt;Administrative portlet has a paged table of users&lt;/li&gt;&lt;li&gt;Administrative portlet also allows to add a single user or multiple users at once&lt;/li&gt;&lt;li&gt;Portal/portlet "branding" greatly simplified and aligned with PURSe&lt;/li&gt;&lt;/ul&gt;See the &lt;a href="http://www.extreme.indiana.edu/portals/purse-portlets/release-notes.html"&gt;release notes&lt;/a&gt; for more information, or the &lt;a href="http://www.extreme.indiana.edu/portals/purse-portlets/downloads.html"&gt;download page&lt;/a&gt; to get it now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-7118486140448861471?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/7118486140448861471/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=7118486140448861471' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7118486140448861471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7118486140448861471'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/07/purse-portlets-110-released.html' title='PURSe Portlets 1.1.0 Released'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-6739936710825145775</id><published>2007-07-09T08:08:00.001-04:00</published><updated>2009-06-06T08:09:29.002-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><category scheme='http://www.blogger.com/atom/ns#' term='apache'/><title type='text'>Apache MaxClients reached, all connections in CLOSE_WAIT</title><content type='html'>Our Extreme Lab web server (Solaris running Apache 1.3) has recently developed a problem.  Twice yesterday it got into a state where it had hit its MaxClients limit (of 128, apparently) and then was unable to service any further requests.  Running &lt;code&gt;&lt;b&gt;netstat -f inet&lt;/b&gt;&lt;/code&gt; showed the all existing connections were in the CLOSE_WAIT stage.  I can't tell at this stage if there is some denial of service attack going on or just a problem with the server preventing it from finally closing these connections.&lt;br /&gt;&lt;br /&gt;Update: Googling around, and with some help from our local Unix guru, Rob Henderson, I found out that if you have connections stuck in the CLOSE_WAIT stage, this usually indicates that the server side is having trouble closing the connection.  Rob says that usually when he sees this problem it is because of an NFS server being down.  You get requests for something on that NFS mount, and the process hangs there for a long time.  With that NFS server remounted, things are much better.  Whereas before I was seeing steadily increasing numbers of CLOSE_WAIT connections, I now see none.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-6739936710825145775?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/6739936710825145775/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=6739936710825145775' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/6739936710825145775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/6739936710825145775'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/07/apache-maxclients-reached-all.html' title='Apache MaxClients reached, all connections in CLOSE_WAIT'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-6219928508816804457</id><published>2007-06-14T16:58:00.000-04:00</published><updated>2009-06-06T08:09:29.002-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>JSF Portlet Fun: Request Scoped Beans Don't Survive From Action to Render Phase</title><content type='html'>Not sure if this is Pluto specific, but request scoped beans basically don't work as expected since they get initialized on the action phase and then again on the render phase.  This is with MyFaces 1.1.4 and Pluto 1.1.3.  At least with GridSphere 2.1.5 and MyFaces 1.0.9, I know that request scoped beans do work.  See &lt;a href="http://issues.apache.org/jira/browse/MYFACES-788"&gt;http://issues.apache.org/jira/browse/MYFACES-788&lt;/a&gt; for more information.  The workaround is basic and actually standard from the Portlet API point of view.  The idea is that for any thing that you want to carry over from the action phase to the render phase, then just add this as a render parameter.  In this example, a field of the request scoped bean called "success" is a boolean.  So in the action method, I do this: &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    // add the success field to a render parameter so it will be available in&lt;br /&gt;    // the render phase.  See constructor as well.&lt;br /&gt;    ExternalContext extContext = FacesContext.getCurrentInstance().getExternalContext();&lt;br /&gt;    if (extContext.getResponse() instanceof ActionResponse) {&lt;br /&gt;        ActionResponse actionResponse = (ActionResponse) extContext.getResponse();&lt;br /&gt;        actionResponse.setRenderParameter("success", Boolean.toString(success));&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Then in the contructor for the bean I have:&lt;br /&gt;    // Pull success value from render parameter set in action phase, i.e., submit()&lt;br /&gt;    ExternalContext extContext = facesContext.getExternalContext();&lt;br /&gt;    Map params = extContext.getRequestParameterMap();&lt;br /&gt;&lt;br /&gt;    if (params.containsKey("success")) {&lt;br /&gt;        this.success = Boolean.parseBoolean((String)params.get("success"));&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-6219928508816804457?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/6219928508816804457/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=6219928508816804457' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/6219928508816804457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/6219928508816804457'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/06/jsf-portlet-fun-request-scoped-beans.html' title='JSF Portlet Fun: Request Scoped Beans Don&apos;t Survive From Action to Render Phase'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-1545075847884913074</id><published>2007-06-06T12:44:00.000-04:00</published><updated>2009-06-06T08:09:29.002-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>TeraGrid 2007, Day 3</title><content type='html'>In the Software Provider Forum, I gave a talk on PURSe (using slides provided to me by Rachana Anathakrishnan) and also about the PURSe portlets work I've been doing.&lt;br /&gt;&lt;br /&gt;&lt;object type="application/x-shockwave-flash" data="https://s3.amazonaws.com:443/slideshare/ssplayer.swf?id=60888&amp;doc=purse-and-the-purse-portlets-9375" width="425" height="348"&gt;&lt;param name="movie" value="https://s3.amazonaws.com:443/slideshare/ssplayer.swf?id=60888&amp;doc=purse-and-the-purse-portlets-9375" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;In the presentation I give a sketch of a roadmap for a PURSe portlets 1.1 release, which should be out within a month.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-1545075847884913074?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/1545075847884913074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=1545075847884913074' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/1545075847884913074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/1545075847884913074'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/06/teragrid-2007-day-3.html' title='TeraGrid 2007, Day 3'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-8991406026372558020</id><published>2007-06-06T12:34:00.001-04:00</published><updated>2009-06-06T08:09:29.002-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>TeraGrid 2007, Day 2</title><content type='html'>Stu Martin and I gave a talk on GRAM Auditing and integration of it with the LEAD Portal.&lt;br /&gt;&lt;br /&gt;&lt;object type="application/x-shockwave-flash" data="https://s3.amazonaws.com:443/slideshare/ssplayer.swf?id=60890&amp;doc=teragrids-gram-auditing-accounting-its-integration-with-the-lead-science-gateway-17521" width="425" height="348"&gt;&lt;param name="movie" value="https://s3.amazonaws.com:443/slideshare/ssplayer.swf?id=60890&amp;doc=teragrids-gram-auditing-accounting-its-integration-with-the-lead-science-gateway-17521" /&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-8991406026372558020?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/8991406026372558020/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=8991406026372558020' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/8991406026372558020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/8991406026372558020'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/06/teragrid-2007-day-2.html' title='TeraGrid 2007, Day 2'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-1296787247166012771</id><published>2007-06-05T09:26:00.000-04:00</published><updated>2009-06-06T08:09:29.002-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>TeraGrid 2007, Day 1</title><content type='html'>During most of the first day at &lt;a href="http://www.union.wisc.edu/teragrid07/"&gt;TeraGrid 07&lt;/a&gt;, I was involved in the TeraGrid Institute tutorial, a kind of "TeraGrid for beginners" tutorial.  We did a demo/tutorial using the LEAD Portal as a way of demonstrating how a science gateway can make effective use of TeraGrid, how the sum of TeraGrid is greater than it's individual parts.  A &lt;a href="https://portal.leadproject.org/gridsphere/screencasts/tg07_tutorial.htm"&gt;screencast we developed in support of the tutorial&lt;/a&gt; is available.&lt;br /&gt;&lt;br /&gt;Near the end of the day, I had a talk about the LEAD Portal for the "Build your own science gateway" tutorial.  It's titled &lt;i&gt;The LEAD Portal: An OGCE based weather science gateway&lt;/i&gt;, and you can see it below.&lt;br /&gt;&lt;br /&gt;&lt;object type="application/x-shockwave-flash" data="https://s3.amazonaws.com:443/slideshare/ssplayer.swf?id=59627&amp;doc=the-lead-portal-an-ogce-based-weather-science-gateway-3447" height="348" width="425"&gt;&lt;param name="movie" value="https://s3.amazonaws.com:443/slideshare/ssplayer.swf?id=59627&amp;amp;doc=the-lead-portal-an-ogce-based-weather-science-gateway-3447"&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;I talked with &lt;a href="http://www.tacc.utexas.edu/general/staff/milfeld/"&gt;Kent Milfeld&lt;/a&gt; briefly afterward about the difficulty in supporting and managing production and development deployments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-1296787247166012771?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/1296787247166012771/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=1296787247166012771' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/1296787247166012771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/1296787247166012771'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/06/teragrid-2007-day-1.html' title='TeraGrid 2007, Day 1'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-9153982621499398086</id><published>2007-05-22T15:02:00.001-04:00</published><updated>2009-06-06T08:09:29.002-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Pluto and creation of UserInfo Map</title><content type='html'>Pluto throws a NullPointerException if there is an attribute defined in your portlet.xml that it does not recognize.  Happened to me because I generally have the non-standard attribute "user.name" which is the way to get a GridSphere user's username (as opposed to PortletRequest.getRemoteUser()).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-9153982621499398086?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/9153982621499398086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=9153982621499398086' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/9153982621499398086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/9153982621499398086'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/05/pluto-and-creation-of-userinfo-map.html' title='Pluto and creation of UserInfo Map'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-5392337021115061223</id><published>2007-04-19T06:41:00.000-04:00</published><updated>2009-06-06T08:09:29.002-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Creating a Portlet Preferences JSF VariableResolver</title><content type='html'>One of the really cool things about JSF is that just about every piece of it is extensible.  One thing I've been playing with recently is the VariableResolver and PropertyResolver parts of the JSF API.  I want to create a VariableResolver that is specific to portlet development, so that, for example, when you want to create an EDIT page where a user can specify a preferred nickname, it would look something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; &amp;lt;h:inputText value="#{portletPreferences.nickname}"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And that's it, because custom Variable and Property resolvers take care of the getting and setting for us, no backing beans required.&lt;br /&gt;&lt;br /&gt;Turns out this is fairly easy to do.  I started with &lt;a href="http://www.jroller.com/page/cagataycivici?entry=how_to_write_your_own"&gt;Cagatay Civici's excellent blog/article on creating a custom VariableResolver and PropertyResolver&lt;/a&gt;.  The first thing to do was to create the VariableResolver.  The trick here is that VariableResolvers follow a "Chain of Responsibility" design pattern, and the parent resolver is passed in via the constructor of the child resolver.  This is an extremely important point.  I rushed ahead on the PortletPreferences part of the variable resolving and forgot to implement the chained part, and you get some interesting results when you do this.  Suddenly, your managed beans just silently are unresolvable.  No error messages, nothing in the logs, and in fact, it appears at first that they are working, but they do not.  So just a heads up, that if you create your own JSF resolvers, do the chaining part first and look out for disappearing managed beans.&lt;br /&gt;&lt;br /&gt;So here's how my initial PortletVariableResolver looked:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class PortletVariableResolver extends VariableResolver {&lt;br /&gt;&lt;br /&gt;    private static final org.apache.log4j.Logger log = org.apache.log4j.Logger&lt;br /&gt;            .getLogger(PortletVariableResolver.class);&lt;br /&gt;    &lt;br /&gt;    public static final String PORTLET_PREFERENCES = "portletPreferences";&lt;br /&gt;    private VariableResolver originalResolver;&lt;br /&gt;&lt;br /&gt;    public PortletVariableResolver(VariableResolver originalResolver) {&lt;br /&gt;        this.originalResolver = originalResolver;&lt;br /&gt;    }&lt;b&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public Object resolveVariable(FacesContext facesContext, &lt;br /&gt;                                  String variableName)&lt;br /&gt;            throws EvaluationException {&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            if (PORTLET_PREFERENCES.equals(variableName)) {&lt;br /&gt;                PortletRequest portletRequest = &lt;br /&gt;                  (PortletRequest)facesContext&lt;br /&gt;                  .getExternalContext().getRequest();&lt;br /&gt;                return portletRequest.getPreferences().getMap();&lt;br /&gt;            }&lt;br /&gt;        } catch (Exception e) {&lt;br /&gt;            throw new EvaluationException(&lt;br /&gt;              "Failed to resolve variable [" + &lt;br /&gt;               variableName + "]", e);&lt;br /&gt;        }&lt;br /&gt;        return originalResolver.resolveVariable(facesContext, &lt;br /&gt;           variableName);&lt;br /&gt;    }&lt;/b&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So here we're resolving the "portletPreferences" variable to the Map of the user's portlet preferences.  This is nice, but it only gets you read access to the portlet preferences.  For write access as well, we'll need a custom PropertyResolver.  First, let's change our variable resolver so that it returns the PortletPreferences object, instead of the map:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;            if (PORTLET_PREFERENCES.equals(variableName)) {&lt;br /&gt;                PortletRequest portletRequest = &lt;br /&gt;                  (PortletRequest)facesContext&lt;br /&gt;                  .getExternalContext().getRequest();&lt;br /&gt;                &lt;b&gt;return portletRequest.getPreferences();&lt;/b&gt;&lt;br /&gt;            }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now for the PropertyResolver.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class PortletPropertyResolver extends PropertyResolver {&lt;br /&gt;&lt;br /&gt;    private static final org.apache.log4j.Logger log = org.apache.log4j.Logger&lt;br /&gt;            .getLogger(PortletPropertyResolver.class);&lt;br /&gt;    &lt;br /&gt;    private PropertyResolver originalPropertyResolver;&lt;br /&gt;    &lt;br /&gt;    public PortletPropertyResolver(PropertyResolver propertyResolver) {&lt;br /&gt;        this.originalPropertyResolver = propertyResolver;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    @Override&lt;br /&gt;    public Class getType(Object obj, int index) throws EvaluationException,&lt;br /&gt;            PropertyNotFoundException {&lt;br /&gt;        if (obj instanceof PortletPreferences) {&lt;br /&gt;            throw new PropertyNotFoundException("Cannot reference PortletPreferences by index notation");&lt;br /&gt;        } else {&lt;br /&gt;            return this.originalPropertyResolver.getType(obj, index);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public Class getType(Object obj, Object obj1) throws EvaluationException,&lt;br /&gt;            PropertyNotFoundException {&lt;br /&gt;        if (obj instanceof PortletPreferences) {&lt;br /&gt;            return String.class;&lt;br /&gt;        } else {&lt;br /&gt;            return this.originalPropertyResolver.getType(obj, obj1);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public Object getValue(Object obj, int index) throws EvaluationException,&lt;br /&gt;            PropertyNotFoundException {&lt;br /&gt;        if (obj instanceof PortletPreferences) {&lt;br /&gt;            throw new PropertyNotFoundException("Cannot reference PortletPreferences by index notation");&lt;br /&gt;        } else {&lt;br /&gt;            return this.originalPropertyResolver.getValue(obj, index);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;b&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public Object getValue(Object obj, Object obj1)&lt;br /&gt;            throws EvaluationException, PropertyNotFoundException {&lt;br /&gt;        if (obj instanceof PortletPreferences) {&lt;br /&gt;            // TODO: support access to String[] preference values&lt;br /&gt;            PortletPreferences prefs = (PortletPreferences) obj;&lt;br /&gt;            String prefName = (String) obj1;&lt;br /&gt;            return prefs.getValue(prefName, null);&lt;br /&gt;        } else {&lt;br /&gt;            return this.originalPropertyResolver.getValue(obj, obj1);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public boolean isReadOnly(Object obj, int index)&lt;br /&gt;            throws EvaluationException, PropertyNotFoundException {&lt;br /&gt;        if (obj instanceof PortletPreferences) {&lt;br /&gt;            throw new PropertyNotFoundException("Cannot reference PortletPreferences by index notation");&lt;br /&gt;        } else {&lt;br /&gt;            return this.originalPropertyResolver.isReadOnly(obj, index);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public boolean isReadOnly(Object obj, Object obj1)&lt;br /&gt;            throws EvaluationException, PropertyNotFoundException {&lt;br /&gt;        if (obj instanceof PortletPreferences) {&lt;br /&gt;            PortletPreferences prefs = (PortletPreferences) obj;&lt;br /&gt;            String prefName = (String) obj1;&lt;br /&gt;            return prefs.isReadOnly(prefName);&lt;br /&gt;        } else {&lt;br /&gt;            return this.originalPropertyResolver.isReadOnly(obj, obj1);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void setValue(Object obj, int index, Object obj1)&lt;br /&gt;            throws EvaluationException, PropertyNotFoundException {&lt;br /&gt;        if (obj instanceof PortletPreferences) {&lt;br /&gt;            throw new PropertyNotFoundException("Cannot reference PortletPreferences by index notation");&lt;br /&gt;        } else {&lt;br /&gt;            this.originalPropertyResolver.setValue(obj, index, obj1);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;b&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void setValue(Object obj, Object obj1, Object value)&lt;br /&gt;            throws EvaluationException, PropertyNotFoundException {&lt;br /&gt;        if (obj instanceof PortletPreferences) {&lt;br /&gt;            PortletPreferences prefs = (PortletPreferences) obj;&lt;br /&gt;            String prefName = (String) obj1;&lt;br /&gt;            String prefValue = (String) value;&lt;br /&gt;            try {&lt;br /&gt;                prefs.setValue(prefName, prefValue);&lt;br /&gt;                prefs.store();&lt;br /&gt;            } catch (Exception e) {&lt;br /&gt;                log.error("Unable to set portlet preference [" + prefName + "] to value [" + prefValue + "]", e);&lt;br /&gt;            }&lt;br /&gt;        } else {&lt;br /&gt;            this.originalPropertyResolver.setValue(obj, obj1, value);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I've highlighted the main two methods here, getValue and setValue, and I think you'll find them fairly straightforward.  The other issue is that we have to implement the array index part of the property resolving, and we just throw an exception in this case (although, as a further exercise, we might want to implement this so that we can reference multi-valued preferences).&lt;br /&gt;&lt;br /&gt;At this point, you just need to register the VariableResolver and PropertyResolver in your faces-config.xml file, like so:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &amp;lt;application&gt;&lt;br /&gt;    &amp;lt;property-resolver&gt;&lt;br /&gt;      resolver.PortletPropertyResolver&lt;br /&gt;    &amp;lt;/property-resolver&gt;&lt;br /&gt;    &amp;lt;variable-resolver&gt;&lt;br /&gt;      resolver.PortletVariableResolver&lt;br /&gt;    &amp;lt;/variable-resolver&gt;&lt;br /&gt;  &amp;lt;/application&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-5392337021115061223?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/5392337021115061223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=5392337021115061223' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/5392337021115061223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/5392337021115061223'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/04/creating-portlet-preferences-jsf.html' title='Creating a Portlet Preferences JSF VariableResolver'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-6753582802186642150</id><published>2007-03-29T17:02:00.000-04:00</published><updated>2009-06-06T08:09:29.003-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Credential renewal with MyProxy and JGlobus</title><content type='html'>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 &lt;a href="http://dev.globus.org/wiki/CoG_JGlobus_1.4"&gt;JGlobus&lt;/a&gt; to this end.&lt;br /&gt;&lt;br /&gt;First of all, the MyProxy site has &lt;a href="http://grid.ncsa.uiuc.edu/myproxy/renew.html"&gt;an excellent page on various grid credential renewal issues and MyProxy&lt;/a&gt;.  So to begin, I want to set my credential renewer service as a "default renewer" in the MyProxy configuration.  I do this by adding&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;default_renewers "DN of my renewing service"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;myproxy-init -n -s myproxy-server.mydomain.org -l myusername&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The -n option says to store the proxy without a passphrase.  Now I can renew this proxy with&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;myproxy-logon -s myproxy-server.mydomain.org -a /tmp/aging_proxy \&lt;br /&gt;           -l myusername -o /tmp/refreshed_proxy&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;MyProxy myproxy = new MyProxy(myproxyHost, myproxyPort);&lt;br /&gt;GetParams getParams = new GetParams();&lt;br /&gt;getParams.setUserName(username);&lt;br /&gt;getParams.setLifetime(24*60*60);&lt;br /&gt;getParams.setAuthzCreds(userCred);&lt;br /&gt;&lt;br /&gt;GSSCredential renewedCredential = myproxy.get(serviceCred, getParams);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that you need a valid MyProxy username as well as a still valid proxy credential.  To load the service credential, do this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;GlobusCredential globusCred = new GlobusCredential(pathToServiceCert,&lt;br /&gt;                                                 pathToServiceKey);&lt;br /&gt;GSSCredential gssCred = new GlobusGSSCredentialImpl(globusCred,&lt;br /&gt;                                GSSCredential.INITIATE_AND_ACCEPT);&lt;br /&gt;&lt;/pre&gt;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 &lt;a href="http://grid.ncsa.uiuc.edu/myproxy/man/myproxy-store.1.html"&gt;grid credential storage feature&lt;/a&gt; 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:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;openssl rsa -in ~/.globus/userkey.pem -out ~/.globus/userkey1.pem&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then store your credential to MyProxy with this key:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;myproxy-store -s myproxy.mydomain.org -l myusername -y .globus/userkey1.pem&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now you'll be able to use this MyProxy credential for proxy renewal.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-6753582802186642150?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/6753582802186642150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=6753582802186642150' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/6753582802186642150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/6753582802186642150'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/03/credential-renewal-with-myproxy-and.html' title='Credential renewal with MyProxy and JGlobus'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-4612929441640970917</id><published>2007-03-28T05:42:00.000-04:00</published><updated>2009-06-06T08:09:29.003-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Setting the var attribute of dataTable in a facelet, part II</title><content type='html'>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 &lt;a href="http://marcus-christie.blogspot.com/2007/03/setting-var-attribute-of-datatable-in.html"&gt;previous post&lt;/a&gt;, 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.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package portletfacelets;&lt;br /&gt;&lt;br /&gt;import javax.faces.component.UIComponent;&lt;br /&gt;import javax.faces.component.html.HtmlDataTable;&lt;br /&gt;&lt;br /&gt;import com.sun.facelets.FaceletContext;&lt;br /&gt;import com.sun.facelets.tag.jsf.ComponentConfig;&lt;br /&gt;import com.sun.facelets.tag.jsf.html.HtmlComponentHandler;&lt;br /&gt;&lt;br /&gt;public class HtmlDataTableHandler extends HtmlComponentHandler {&lt;br /&gt;&lt;br /&gt;  public HtmlDataTableHandler(ComponentConfig config) {&lt;br /&gt;      super(config);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  protected void onComponentCreated(FaceletContext ctx,&lt;br /&gt;          UIComponent c, UIComponent parent) {&lt;br /&gt;      super.onComponentCreated(ctx, c, parent);&lt;br /&gt;      if (c instanceof HtmlDataTable) {&lt;br /&gt;          HtmlDataTable table = (HtmlDataTable) c;&lt;br /&gt;          if (table.getFooterClass() == null) {&lt;br /&gt;              table.setFooterClass("portlet-section-footer");&lt;br /&gt;          }&lt;br /&gt;          if (table.getHeaderClass() == null) {&lt;br /&gt;              table.setHeaderClass("portlet-section-header");&lt;br /&gt;          }&lt;br /&gt;          if (table.getRowClasses() == null) {&lt;br /&gt;              table.setRowClasses("portlet-section-body," +&lt;br /&gt;              "portlet-section-alternate");&lt;br /&gt;          }&lt;br /&gt;          if (table.getStyleClass() == null) {&lt;br /&gt;              table.setStyleClass("portlet-section-body");&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; &amp;lt;tag&gt;&lt;br /&gt;   &amp;lt;tag-name&gt;dataTable2&amp;lt;/tag-name&gt;&lt;br /&gt;   &amp;lt;component&gt;&lt;br /&gt;     &amp;lt;component-type&gt;javax.faces.HtmlDataTable&amp;lt;/component-type&gt;&lt;br /&gt;     &amp;lt;renderer-type&gt;javax.faces.Table&amp;lt;/renderer-type&gt;&lt;br /&gt;     &amp;lt;handler-class&gt;portletfacelets.HtmlDataTableHandler&amp;lt;/handler-class&gt;&lt;br /&gt;   &amp;lt;/component&gt;&lt;br /&gt; &amp;lt;/tag&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-4612929441640970917?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/4612929441640970917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=4612929441640970917' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4612929441640970917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4612929441640970917'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/03/setting-var-attribute-of-datatable-in_28.html' title='Setting the var attribute of dataTable in a facelet, part II'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-135317086180254199</id><published>2007-03-28T05:12:00.000-04:00</published><updated>2009-06-06T08:09:29.003-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Running Portlets on Pluto from within Eclipse</title><content type='html'>The Pluto team recently released version 1.1.0 and as part of that release they include &lt;a href="http://portals.apache.org/pluto/v11/getting-started.html"&gt;a very useful Pluto + Tomcat bundle&lt;/a&gt; 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.&lt;br /&gt;&lt;br /&gt;First, you need to register the Pluto 1.1/Tomcat 5.5.20 bundle with Eclipse as a Tomcat 5.5 server.  Select File &gt; New &gt; Other and select Server, then click Next (or, if in the J2EE perspective, right click in the Servers View and select New &gt; 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.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_0lq8ah647ZM/Rgo1wZrrnqI/AAAAAAAAAAg/zVZcoO1vM3I/s1600-h/new_server_dialog.PNG"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_0lq8ah647ZM/Rgo1wZrrnqI/AAAAAAAAAAg/zVZcoO1vM3I/s400/new_server_dialog.PNG" alt="" id="BLOGGER_PHOTO_ID_5046905438066155170" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;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 &gt; Show View &gt; 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.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_0lq8ah647ZM/Rgo2J5rrnrI/AAAAAAAAAAo/T06ElD_OIEE/s1600-h/config_server.PNG"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_0lq8ah647ZM/Rgo2J5rrnrI/AAAAAAAAAAo/T06ElD_OIEE/s400/config_server.PNG" alt="" id="BLOGGER_PHOTO_ID_5046905876152819378" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;Now we just need to get our application running on Pluto/Tomcat as before (right click on the Project, select Run As &gt; 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 &lt;span style="font-weight: bold;"&gt;pluto&lt;/span&gt;, password &lt;span style="font-weight: bold;"&gt;pluto&lt;/span&gt;.  In the upper left hand corner there is a label called "Navigation:".  Mouse over this label to get a popup menu.  Then select &lt;span style="font-weight: bold;"&gt;Pluto Admin&lt;/span&gt; from this list.  Under &lt;span style="font-weight: bold;"&gt;Pluto Pages&lt;/span&gt;, select &lt;span style="font-weight: bold;"&gt;Pluto Admin&lt;/span&gt; from the drop down list.  Then under &lt;span style="font-weight: bold;"&gt;Portlet Applications&lt;/span&gt;, select &lt;span style="font-weight: bold;"&gt;hello-world-jsf-facelets&lt;/span&gt; in the first drop down, and then in the second drop down select &lt;span style="font-weight: bold;"&gt;HelloWorldSamplePortlet&lt;/span&gt;, and click Add Portlet.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_0lq8ah647ZM/Rgo2lZrrnsI/AAAAAAAAAAw/obEpVXMXzh8/s1600-h/adding_portlet.PNG"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_0lq8ah647ZM/Rgo2lZrrnsI/AAAAAAAAAAw/obEpVXMXzh8/s400/adding_portlet.PNG" alt="" id="BLOGGER_PHOTO_ID_5046906348599221954" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now, the portlet should be there at the bottom of the page.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_0lq8ah647ZM/Rgo2v5rrntI/AAAAAAAAAA4/kPDr1nosDcM/s1600-h/porlet_added.PNG"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_0lq8ah647ZM/Rgo2v5rrntI/AAAAAAAAAA4/kPDr1nosDcM/s400/porlet_added.PNG" alt="" id="BLOGGER_PHOTO_ID_5046906528987848402" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;Now that our portlet is deployed to Pluto from within Eclipse, we can develop our portlet and have the changes immediately reflected in Pluto!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-135317086180254199?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/135317086180254199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=135317086180254199' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/135317086180254199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/135317086180254199'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/03/running-portlets-on-pluto-from-within.html' title='Running Portlets on Pluto from within Eclipse'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_0lq8ah647ZM/Rgo1wZrrnqI/AAAAAAAAAAg/zVZcoO1vM3I/s72-c/new_server_dialog.PNG' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-7171564556548736975</id><published>2007-03-22T06:32:00.000-04:00</published><updated>2009-06-06T08:09:29.003-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Setting the var attribute of dataTable in a facelet</title><content type='html'>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: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   &amp;lt;h:dataTable value="#{mybean.myData}" var="row"&lt;br /&gt;     styleClass="portlet-section-body"&lt;br /&gt;     rowClasses="portlet-section-body,portlet-section-alternate"&lt;br /&gt;     headerClass="portlet-section-header"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So, I'd like to replace that with a facelet instead, so that it looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   &amp;lt;p:dataTable value="#{mybean.myData}" var="row"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And the facelet would be defined once in a .xhtml file as:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;ui:composition&gt;&lt;br /&gt;    &amp;lt;h:dataTable value="#{value}" var="#{var}"&lt;br /&gt;      styleClass="portlet-section-body"&lt;br /&gt;      rowClasses="portlet-section-body,portlet-section-alternate"&lt;br /&gt;      headerClass="portlet-section-header"&gt;&lt;br /&gt;        &amp;lt;ui:insert /&gt;&lt;br /&gt;    &amp;lt;/h:dataTable&gt;&lt;br /&gt;&amp;lt;/ui:composition&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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 &lt;a href="https://facelets.dev.java.net/nonav/docs/dev/docbook.html#dev-taghandler"&gt; custom TagHandler&lt;/a&gt; that evaluates the value expression and then sets the var property of the dataTable component directly:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package portletfacelets;&lt;br /&gt;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;&lt;br /&gt;import javax.el.ELException;&lt;br /&gt;import javax.faces.FacesException;&lt;br /&gt;import javax.faces.component.UIComponent;&lt;br /&gt;import javax.faces.component.html.HtmlDataTable;&lt;br /&gt;&lt;br /&gt;import com.sun.facelets.FaceletContext;&lt;br /&gt;import com.sun.facelets.FaceletException;&lt;br /&gt;import com.sun.facelets.tag.TagAttribute;&lt;br /&gt;import com.sun.facelets.tag.TagConfig;&lt;br /&gt;import com.sun.facelets.tag.TagHandler;&lt;br /&gt;&lt;br /&gt;public class SetVarHandler extends TagHandler {&lt;br /&gt;&lt;br /&gt;    private final TagAttribute var;&lt;br /&gt;&lt;br /&gt;    public SetVarHandler(TagConfig config) {&lt;br /&gt;        super(config);&lt;br /&gt;        this.var = this.getAttribute("var");&lt;br /&gt;    }&lt;br /&gt;    public void apply(FaceletContext ctx, UIComponent parent)&lt;br /&gt;            throws IOException, FacesException, FaceletException, ELException {&lt;br /&gt;&lt;br /&gt;        System.out.println("var=" + this.var.getValue(ctx));&lt;br /&gt;        &lt;b&gt;&lt;br /&gt;        if (parent instanceof HtmlDataTable) {&lt;br /&gt;            HtmlDataTable table = (HtmlDataTable) parent;&lt;br /&gt;            table.setVar(this.var.getValue(ctx));&lt;br /&gt;        }&lt;br /&gt;        &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;        this.nextHandler.apply(ctx, parent);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I add this to my facelets taglib.xml file as such:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &amp;lt;tag&gt;&lt;br /&gt;    &amp;lt;tag-name&gt;setVar&amp;lt;/tag-name&gt;&lt;br /&gt;    &amp;lt;handler-class&gt;portletfacelets.SetVarHandler&amp;lt;/handler-class&gt;&lt;br /&gt;  &amp;lt;/tag&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And then use it like this in my facelet:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;ui:composition&gt;&lt;br /&gt;    &amp;lt;h:dataTable value="#{value}"&lt;br /&gt;      styleClass="portlet-section-body"&lt;br /&gt;      rowClasses="portlet-section-body,portlet-section-alternate"&lt;br /&gt;      headerClass="portlet-section-header"&gt;&lt;br /&gt;        &lt;b&gt;&amp;lt;p:setVar var="#{var}" /&gt;&lt;/b&gt;&lt;br /&gt;        &amp;lt;ui:insert /&gt;&lt;br /&gt;    &amp;lt;/h:dataTable&gt;&lt;br /&gt;&amp;lt;/ui:composition&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package portletfacelets;&lt;br /&gt;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.lang.reflect.Method;&lt;br /&gt;&lt;br /&gt;import javax.el.ELException;&lt;br /&gt;import javax.faces.FacesException;&lt;br /&gt;import javax.faces.component.UIComponent;&lt;br /&gt;&lt;br /&gt;import com.sun.facelets.FaceletContext;&lt;br /&gt;import com.sun.facelets.FaceletException;&lt;br /&gt;import com.sun.facelets.tag.TagAttribute;&lt;br /&gt;import com.sun.facelets.tag.TagConfig;&lt;br /&gt;import com.sun.facelets.tag.TagHandler;&lt;br /&gt;&lt;br /&gt;public class SetValueHandler extends TagHandler {&lt;br /&gt;&lt;br /&gt;    private final TagAttribute methodName;&lt;br /&gt;    private final TagAttribute value;&lt;br /&gt;&lt;br /&gt;    public SetValueHandler(TagConfig config) {&lt;br /&gt;        super(config);&lt;br /&gt;        this.methodName = this.getRequiredAttribute("methodName");&lt;br /&gt;        this.value = this.getRequiredAttribute("value");&lt;br /&gt;    }&lt;br /&gt;    public void apply(FaceletContext ctx, UIComponent parent)&lt;br /&gt;            throws IOException, FacesException, FaceletException, ELException {&lt;br /&gt;        try {&lt;br /&gt;            &lt;b&gt;&lt;br /&gt;            Method m = parent.getClass().getMethod(this.methodName.getValue(ctx), &lt;br /&gt;                    new Class[]{String.class});&lt;br /&gt;            m.invoke(parent, new Object[]{this.value.getValue(ctx)});&lt;br /&gt;            &lt;/b&gt;&lt;br /&gt;        } catch (Exception e) {&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        this.nextHandler.apply(ctx, parent);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;ui:composition&gt;&lt;br /&gt;    &amp;lt;h:dataTable value="#{value}"&lt;br /&gt;      styleClass="portlet-section-body"&lt;br /&gt;      rowClasses="portlet-section-body,portlet-section-alternate"&lt;br /&gt;      headerClass="portlet-section-header"&gt;&lt;br /&gt;        &lt;b&gt;&amp;lt;p:setValue methodName="setVar" value="#{var}" /&gt;&lt;/b&gt;&lt;br /&gt;        &amp;lt;ui:insert /&gt;&lt;br /&gt;    &amp;lt;/h:dataTable&gt;&lt;br /&gt;&amp;lt;/ui:composition&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-7171564556548736975?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/7171564556548736975/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=7171564556548736975' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7171564556548736975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/7171564556548736975'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/03/setting-var-attribute-of-datatable-in.html' title='Setting the var attribute of dataTable in a facelet'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-2193419255421050830</id><published>2007-03-22T05:44:00.000-04:00</published><updated>2009-06-06T08:09:29.004-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>How to watch Google Videos on your DivX compatible DVD player</title><content type='html'>Google has put videos of their &lt;a href="http://video.google.com/videosearch?q=user%3A%22Google+engEDU%22&amp;so=1&amp;amp;num=20"&gt;Tech Talks series online&lt;/a&gt; and I was interested in seeing if I could play these on my &lt;a href="http://www.amazon.com/Toshiba-SD-3990-Progressive-Scan-Player/dp/B000EBRLHK"&gt;SD-3990 Toshiba DVD player&lt;/a&gt; which is DivX compatible.  All you need to do is:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Find the video at Google Video.  Click the download link.&lt;/li&gt;&lt;li&gt;The Google Video Player comes up and starts buffering the video.  It saves the video into your &lt;code&gt;My Videos/Google Video&lt;/code&gt; directory, or perhaps in a different location, you can check the preferences to see where the location is.&lt;/li&gt;&lt;li&gt;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.&lt;/li&gt;&lt;li&gt;Burn this file to a CD-R disc.  And it's ready to play.&lt;/li&gt;&lt;/ol&gt;Last night I used this technique to watch part of Bram Moolenaar's (of &lt;a href="http://www.vim.org"&gt;Vim &lt;/a&gt;fame) talk on &lt;a href="http://video.google.com/videoplay?docid=2538831956647446078&amp;amp;q=user%3A%22Google+engEDU%22"&gt;7 Habits For Effective Text Editing 2.0&lt;/a&gt; on my DVD player from the comfort of my living room.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-2193419255421050830?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/2193419255421050830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=2193419255421050830' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2193419255421050830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/2193419255421050830'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/03/how-to-watch-google-videos-on-your-divx.html' title='How to watch Google Videos on your DivX compatible DVD player'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-5292752012176632599</id><published>2007-03-07T06:16:00.000-05:00</published><updated>2009-06-06T08:09:29.004-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Custom Tomcat Server Location coming in Eclipse WTP 2.0</title><content type='html'>&lt;a href="http://www.eclipse.org/webtools/development/news/2.0M5/server.php"&gt;Web Tools Platform 2.0 M5 News&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-5292752012176632599?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/5292752012176632599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=5292752012176632599' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/5292752012176632599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/5292752012176632599'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/03/custom-tomcat-server-location-coming-in.html' title='Custom Tomcat Server Location coming in Eclipse WTP 2.0'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-4430849264966624649</id><published>2007-02-20T08:59:00.000-05:00</published><updated>2009-06-06T08:09:29.004-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Double Submit Fix with Multiple Submit Buttons</title><content type='html'>In the &lt;a href="http://portal.leadproject.org/"&gt;LEAD Portal&lt;/a&gt; we have a portlet that allows users to submit weather forecast workflows.  When the user clicks the Launch button, a lot of things have to go on behind the scenes to setup and launch the workflow, and it's not atypical for a user to wonder if maybe something is amiss and attempt to click the Launch button again.  This double submit is quite problematic for us however.&lt;br /&gt;&lt;br /&gt;I searched the web for a double submit prevention JavaScript code, and found some good starts.  But our portlet has multiple submit buttons and I found that if I disabled the Launch button after it is clicked, for some reason, that buttons name and value are not passed in the POST to the server.  So I have to account for this.  Here's the JavaScript I used:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;form action="${actionURL}" method="POST" name="wfParamForm"&gt;&lt;br /&gt;&amp;lt;div align="right"&gt;&lt;br /&gt;      &amp;lt;input type="submit"&lt;br /&gt;              name="actionMethod_doExp_wiz" value="&lt;&gt;&lt;br /&gt;      &amp;lt;input type="submit"&lt;br /&gt;              name="actionMethod_doExp_wiz" value="Next &gt;" disabled="yes" /&gt;&lt;br /&gt;      &amp;lt;input type="submit"&lt;br /&gt;              name="actionMethod_doExp_wiz" value="Cancel" /&gt;&lt;br /&gt;&lt;br /&gt;      &amp;lt;!-- since we have multiple submit buttons, we need to add the&lt;br /&gt;      name value pair of this submit button to the form action.  It&lt;br /&gt;      seems that when the button is disabled that this also prevents&lt;br /&gt;      it from being present in the POST --&gt;&lt;br /&gt;      &amp;lt;input type="submit"&lt;br /&gt;             name="actionMethod_doExp_wiz" value="Launch"&lt;br /&gt;       &lt;b&gt;onClick="this.disabled=true; this.value='Please wait...'; this.form.action=this.form.action + '&amp;actionMethod_doExp_wiz=Launch'; this.form.submit()"&lt;/b&gt; /&gt;&lt;br /&gt;&amp;lt;/form&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This is from a Velocity Portlet, and it is creating a wizard like interface with Back, Next, Cancel, and Launch buttons on each page of the wizard.  Look at the JavaScript for the onClick for the Launch button.  Pretty standard stuff (sets the Launch button to disabled, displays "Please wait.." in the button), except that it is also adding the name value pair of the Launch button to the form action.  This works and has been tested with IE and Firefox.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-4430849264966624649?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/4430849264966624649/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=4430849264966624649' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4430849264966624649'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4430849264966624649'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/02/double-submit-fix-with-multiple-submit.html' title='Double Submit Fix with Multiple Submit Buttons'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-3290375478631178302</id><published>2007-01-25T15:25:00.000-05:00</published><updated>2009-06-06T08:09:46.976-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Scripting IFrames in IE and Firefox</title><content type='html'>&lt;b&gt;Update:&lt;/b&gt; Found out Safari requires iframeEl.contentWindow, iframeEl.contentDocument.defaultView doesn't work (or, at least, it doesn't work any more).  Turns out that this works for Firefox as well.  I've left the other branch for backwards compatibility and also because it is more standard.&lt;br /&gt;&lt;br /&gt;Here's how to get a reference to an iframe with JavaScript, in Firefox&lt;s&gt; and IE&lt;/s&gt;, IE and Safari:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;        var iframeEl = document.getElementById("iframeId");&lt;br /&gt;        &lt;s&gt;var iframeDoc = iframeEl.contentDocument&lt;/s&gt;&lt;br /&gt;        var iframeWin;&lt;br /&gt;        &lt;s&gt;if (iframeDoc) { // Firefox&lt;/s&gt;&lt;br /&gt;            &lt;s&gt;iframeWin = iframeDoc.defaultView&lt;/s&gt;&lt;br /&gt;        &lt;s&gt;} else { // IE&lt;/s&gt;&lt;br /&gt;            &lt;s&gt;iframeWin = iframeEl.contentWindow&lt;/s&gt;&lt;br /&gt;        &lt;s&gt;}&lt;/s&gt;&lt;br /&gt;        if (iframeEl.contentWindow) { // IE and Safari require, but works for Firefox too&lt;br /&gt;            iframeWin = iframeEl.contentWindow;&lt;br /&gt;        } else if (iframeEl.contentDocument) { // Works for Firefox, DOM level 2 standard&lt;br /&gt;            iframeWin = iframeEl.contentDocument.defaultView;&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And then you can use iframeWin to get access to JavaScript objects and the DOM of the iframe.&lt;br /&gt;&lt;br /&gt;Also, I learned that getElementById() in IE (version 7 tested) picks up elements by name attribute as well, so names and ids need to be unique for all elements on a page for IE.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-3290375478631178302?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/3290375478631178302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=3290375478631178302' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/3290375478631178302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/3290375478631178302'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2007/01/scripting-iframes-in-ie-and-firefox.html' title='Scripting IFrames in IE and Firefox'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-5265194390166803578</id><published>2006-12-25T21:52:00.001-05:00</published><updated>2009-06-06T09:07:04.484-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='parenting'/><title type='text'>Parenting Hack: Disabling the auto-flushing toilet</title><content type='html'>If you are a parent of small children like myself you can probably relate to a situation that I commonly find myself in.  I take our 4 year old girl to the public restroom because, well, she's gotta go.  And when we get there we see that the toilet is one of those auto-flushing models, you know, with a light sensor that can tell when an &lt;span style="font-style: italic;"&gt;adult&lt;/span&gt; has sat down and stood back up and hence flushes automatically.  I put emphasis on &lt;span style="font-style: italic;"&gt;adult&lt;/span&gt; because as you may know this doesn't always work so well with a child, especially squirmy ones.  Inevitably, the toilet flushes too soon, and these tend to not be wimpy flushers either.  The flushing action can remind one of Charlton Heston as Moses in the Ten Commandments parting the Red Sea.  And children find this very disturbing, obviously.&lt;br /&gt;&lt;br /&gt;Well, on a recent trip to the "facilities", I came up with a simple hack to get around this problem.  Simply take a piece of toilet paper (paper towel would probably work well too) and drape it over the light sensor.  The child can then safely use the toilet.  After the child has dismounted and everyone is ready for a flushing of biblical proportions, remove the toilet paper from the light sensor, which will activate the flushing, and drop it into the toilet.&lt;br /&gt;&lt;br /&gt;Happy parenting!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-5265194390166803578?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/5265194390166803578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=5265194390166803578' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/5265194390166803578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/5265194390166803578'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/12/parenting-hack-disabling-auto-flushing_25.html' title='Parenting Hack: Disabling the auto-flushing toilet'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-1768789482559926188</id><published>2006-12-21T12:39:00.000-05:00</published><updated>2009-06-06T08:09:46.977-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Evaluating Grid Portal Security Paper, Review</title><content type='html'>I just finished reading a paper titled &lt;a href="http://www.cs.virginia.edu/%7Ehumphrey/papers/EvaluatingGridPortalSecurity.pdf"&gt;Evaluating Grid Portal Security&lt;/a&gt;, by David Del Vecchio, Victor Hazelwood and Marty Humphrey.  In it they evaluate &lt;a href="http://www.gridsphere.org/"&gt;GridSphere&lt;/a&gt;, &lt;a href="http://www.ogce.org/"&gt;OGCE&lt;/a&gt; and Clarens against a standard set of security metrics.  The conclusion is that there is plenty of "room for improvement".  I found their recommendation section at the end particularly helpful.  It got me to thinking about things we can do in the projects I work with to make grid portals more secure, and here I try to capture my thoughts.&lt;br /&gt;&lt;br /&gt;First, I think in the &lt;a href="http://www.globus.org/solutions/purse/"&gt;PURSe&lt;/a&gt;/&lt;a href="http://www.extreme.indiana.edu/portals/purse-portlets/index.html"&gt;PURSe Portlets&lt;/a&gt; project, we should provide a way to configure the strength of the password required when a user creates a new registration, and we should provide a secure setting of this by default out of the box.  I created a &lt;a href="http://gf8.ucs.indiana.edu/ogcebugs/show_bug.cgi?id=90"&gt;bug report&lt;/a&gt; to track this.&lt;br /&gt;&lt;br /&gt;Second, I think one of the most difficult challenges for grid portals is in the area of creating, managing and processing auditing logs.  But the authors do provide a simple criterion, that all grid credential accesses be written to auditing logs.  However, is this sufficient?  It would seem that one would need to audit also all grid services requests (e.g., GRAM and GridFTP calls).  Then there is the problem of how to audit the auditing logs.  Perhaps there are general purpose tools to make this more feasible.  Nevertheless, we are seeing in TeraGrid a strong requirement for this functionality, so we need to come up with a solution.&lt;br /&gt;&lt;br /&gt;For the LEAD Portal that I work on, this is complicated by the fact that we do not have the user's grid credentials at the portal level, nor do we make calls to grid services from the portal.  Ours is a more distributed architecture, with services communicating asynchronously via a publish/subscribe notification broker.  So what we need is an auditing notification topic that all LEAD services could write to as a kind of auditing log.  A special auditing listener could be set up to listen to this topic and persist the messages to a file or database.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-1768789482559926188?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/1768789482559926188/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=1768789482559926188' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/1768789482559926188'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/1768789482559926188'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/12/evaluating-grid-portal-security-paper.html' title='Evaluating Grid Portal Security Paper, Review'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-116535439672521696</id><published>2006-12-05T15:43:00.000-05:00</published><updated>2009-06-06T08:09:46.977-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Upgrading MySQL 3.23 to 5.0</title><content type='html'>I recently had to upgrade a crufty old MySQL database on one of our Solaris machines (rainier) from 3.23 to 5.0.  Here's the process I came up with.  This is all in the MySQL documentation, but you have to hunt here and there for it, and what is outlined below allows you to do, or at least, test the upgrade while the original server is still running.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Preparation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Downloaded and installed latest 4.0, 4.1, and 5.0 into a directory.&lt;br /&gt;&lt;br /&gt;Copied data directory into /usr/local/mysql-data.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Upgrade from 3.23 to 4.0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Started 4.0 pointing at this data directory, on port 3307.&lt;br /&gt;&lt;br /&gt;Edit /usr/local/mysql-data/my.cnf to use port 3307 and socket file /tmp/mysql2.sock&lt;br /&gt;&lt;br /&gt;cd mysql-4.0&lt;br /&gt;export PATH=$PWD/bin:$PATH&lt;br /&gt;mysqld_safe  --defaults-file=/usr/local/mysql-data/my.cnf --user=emysql --datadir=/usr/local/mysql-data --basedir=$PWD --pid-file=/usr/local/mysql-data/rainier.pid&lt;br /&gt;&lt;br /&gt;Check the databases:&lt;br /&gt;&lt;br /&gt;mysqlcheck --all-databases -u root -p -h rainier -P 3307&lt;br /&gt;&lt;br /&gt;mysql_fix_privilege_tables --user=root --socket=/tmp/mysql2.sock --password=xxxxxx&lt;br /&gt;&lt;br /&gt;Lots of warnings and errors, but supposedly this is okay.&lt;br /&gt;&lt;br /&gt;Didn't need to upgrade ISAM to MyISAM storage engine.&lt;br /&gt;&lt;br /&gt;mysqladmin -u root -P 3307 -p -h rainier shutdown&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Upgrading from 4.0 to 4.1.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;cd ../mysql-4.1&lt;br /&gt;&lt;br /&gt;export PATH=$PWD/bin:$PATH&lt;br /&gt;mysqld_safe  --defaults-file=/usr/local/mysql-data/my.cnf --user=emysql --datadir=/usr/local/mysql-data --basedir=$PWD --pid-file=/usr/local/mysql-data/rainier.pid&lt;br /&gt;&lt;br /&gt;Check the databases:&lt;br /&gt;&lt;br /&gt;mysqlcheck --all-databases -u root -p -h rainier -P 3307&lt;br /&gt;&lt;br /&gt;mysql_fix_privilege_tables --user=root --socket=/tmp/mysql2.sock --password=xxxxxx --basedir=$PWD&lt;br /&gt;&lt;br /&gt;mysqladmin -u root -P 3307 -p -h rainier shutdown&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Upgrading from 4.1 to 5.0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;cd ../mysql-5.0&lt;br /&gt;&lt;br /&gt;export PATH=$PWD/bin:$PATH&lt;br /&gt;mysqld_safe  --defaults-file=/usr/local/mysql-data/my.cnf --user=emysql --datadir=/usr/local/mysql-data --basedir=$PWD --pid-file=/usr/local/mysql-data/rainier.pid&lt;br /&gt;&lt;br /&gt;mysql_upgrade didn't seem to work, but I think that's because I had run it in an earlier attempt to upgrade from 3.23 to 5.0.  So I did the individual steps:&lt;br /&gt;mysql_fix_privilege_tables --user=root --socket=/tmp/mysql2.sock --password=xxxxxxxxx --basedir=$PWD&lt;br /&gt;mysqlcheck --check-upgrade --all-databases --auto-repair -u root -p -h rainier -P 3307&lt;br /&gt;&lt;br /&gt;I ran upgrade again, anyways, this time with the force option&lt;br /&gt;mysql_upgrade -p -S /tmp/mysql2.sock --datadir=/usr/local/mysql-data --basedir=$PWD -u root --force&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Additional notes:&lt;br /&gt;&lt;br /&gt;Setting up the mysql init script.  I set the datadir and the basedir, and then I added a --defaults-extra-file=$datadir/my.cnf to the line that invokes mysqld_safe.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-116535439672521696?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/116535439672521696/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=116535439672521696' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/116535439672521696'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/116535439672521696'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/12/upgrading-mysql-323-to-50.html' title='Upgrading MySQL 3.23 to 5.0'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-116475062442548479</id><published>2006-11-28T16:30:00.000-05:00</published><updated>2009-06-06T08:09:46.977-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Integrated Google AJAX Search with LEAD Portal</title><content type='html'>First I created a LEAD Project custom search engine:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.google.com/coop/cse?cx=001503951656019931001%3Ag2lqfazq_ti"&gt;http://www.google.com/coop/cse?cx=001503951656019931001%3Ag2lqfazq_ti&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Then I signed up for a Google AJAX search key for portal-dev.leadproject.org.  Google gave me some stuff to add, and it worked just fine.  I set the web search site restriction to the custom search engine created above:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; var searchOptions = new GsearcherOptions();&lt;br /&gt; searchOptions.setExpandMode(GSearchControl.EXPAND_MODE_OPEN);&lt;br /&gt;&lt;br /&gt; var leadWebSearch = new GwebSearch();&lt;br /&gt; leadWebSearch.setSiteRestriction("001503951656019931001:g2lqfazq_ti");&lt;br /&gt; searchControl.addSearcher(leadWebSearch, searchOptions);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This all worked fairly well, but I wanted a couple of other things from it.  First I wanted to have the search control open up the results over the web page instead of within the web page and rearranging the layout.  I found &lt;a href="http://www.cjmillisock.com/2006/06/how-to-get-google-ajax-search-for-your.html"&gt;this blog entry&lt;/a&gt; at www.cjmillisock.com with a nice use of some simple CSS to get the right effect.  Secondly, by default the search results are limited to just one.  So I created a GsearcherOptions object with expanded mode set to OPEN (see the above code snippet and also the &lt;a href="http://code.google.com/apis/ajaxsearch/documentation/reference.html#_class_GsearcherOptions"&gt;api documentation&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;You can see the result at &lt;a href="http://portal-dev.leadproject.org/"&gt;http://portal-dev.leadproject.org&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-116475062442548479?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/116475062442548479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=116475062442548479' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/116475062442548479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/116475062442548479'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/11/integrated-google-ajax-search-with.html' title='Integrated Google AJAX Search with LEAD Portal'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-116239200388205312</id><published>2006-11-01T09:29:00.000-05:00</published><updated>2009-06-06T08:09:46.978-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Adding the portlet.xml schema to Eclipse</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Updated 2007-04-12:&lt;/span&gt; Fixed the instructions.  Seems the old ones don't work any longer.&lt;br /&gt;&lt;br /&gt;I finally figured out how to do this.  The inferred XML schema support in Eclipse is pretty nice and usually suffices, but sometimes I want to have completion based upon full schema knowledge.  Here's how to add the portlet.xml XSD file to Eclipse:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;First you need to have the JSR 168 code, so &lt;a href="http://www.jcp.org/en/jsr/detail?id=168"&gt;go there&lt;/a&gt; and get it.&lt;/li&gt;&lt;li&gt;For Eclipse you'll need WTP installed.  &lt;a href="http://www.eclipse.org/callisto/java.php"&gt;Get Eclipse 3.2 and use Callisto Discovery Site&lt;/a&gt; to download WTP as well.&lt;/li&gt;&lt;li&gt;Okay, now in Eclipse's preference window, go to Web and &lt;span style="font-weight: bold;"&gt;XML &gt; XML Catalog&lt;/span&gt;.  Click &lt;span style="font-weight: bold;"&gt;Add ...&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;In the &lt;span style="font-weight: bold;"&gt;URI &lt;/span&gt;field, click the little arrow and select the &lt;span style="font-style: italic;"&gt;portlet-app_1_0.xsd&lt;/span&gt; file that you downloaded in the JSR 168 release.&lt;/li&gt;&lt;li&gt;In &lt;span style="font-weight: bold;"&gt;Key Type&lt;/span&gt; field select &lt;span style="font-weight: bold;"&gt;Schema Location&lt;/span&gt;.  Then in the &lt;span style="font-weight: bold;"&gt;Key &lt;/span&gt;field, enter the schema location that you will be using in your portlet.xml files.  I entered &lt;span style="font-style: italic;"&gt;http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Click OK, OK.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Then you need to make sure you have the following entries in the root element (portlet-app)&lt;portlet-app&gt; in your portlet.xml file:&lt;/portlet-app&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ul&gt;&lt;ul&gt;&lt;li style="font-style: italic;"&gt;&lt;span&gt;[Added 2007-04-12]&lt;/span&gt;&lt;span style="font-style: italic;"&gt; &lt;/span&gt;xmlns="&lt;span style="font-style: italic;"&gt;http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"&lt;/span&gt;&lt;/li&gt;&lt;li style="font-style: italic;"&gt;  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;&lt;s&gt;xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/portlet"&lt;/s&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;[Updated 2007-04-12] xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;ol start="8"&gt;&lt;li&gt;Then if you already have a portlet.xml file loaded you'll need to go to &lt;span style="font-weight: bold;"&gt;XML &gt; Reload Dependencies&lt;/span&gt;.  Then you should have tag completion in your portlet.xml files.&lt;/li&gt;&lt;/ol&gt;For more information, here is the corresponding &lt;a href="http://help.eclipse.org/help32/index.jsp?topic=/org.eclipse.wst.xmleditor.doc.user/topics/txmlcat.html"&gt;entry from the Eclipse help documentation&lt;/a&gt;.  I should note that Eclipse seems to think there are errors in the portlet xsd file, but this doesn't seem to cause any problems, i.e., the tag completion works properly.&lt;br /&gt;&lt;br /&gt;I should note also that this approach works for other XSD files as well.  I recently also used these steps to get schema support for Maven2 pom.xml files.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-116239200388205312?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/116239200388205312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=116239200388205312' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/116239200388205312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/116239200388205312'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/11/adding-portletxml-schema-to-eclipse.html' title='Adding the portlet.xml schema to Eclipse'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-116198033567522537</id><published>2006-10-27T16:13:00.000-04:00</published><updated>2009-06-06T08:09:46.978-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>MyFaces JSF and GridSphere</title><content type='html'>Recently I received an email from someone who was trying to create a JSF portlet for GridSphere.  This person was looking for some advice.  I have only encountered one major problem with developing JSF portlets for GridSphere and that is that in GS 2.1.x MyFaces JSF portlets create invalid default id's for JSF components.  The problem is that in this version of GridSphere, RenderResponse.getNamespace() returns an identifier with a "#" character in it, which is an invalid character for JSF component ids.  Jason &lt;a href="http://www.gridlab.org/pipermail/gridsphere-dev/2006-July/003402.html"&gt;discusses this issue in the gridsphere-dev mailing list&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The simple workaround to this problem is provide id's for each of your JSF components.  Here's a snippet of the kind of JSF template that works with GS 2.1.x:&lt;br /&gt;&lt;br /&gt;&amp;lt;!--  FIXME: GridSphere "malformed autogenerated id" issue       Below several JSF components have been given unique id's to workaround       this issue in GridSphere 2.1.x.  This bug has been fixed in GridSphere       2.2.x, but we're not currently using 2.2.x.  Once we do move to 2.2.x we       can remove all id's that are prefixed with "gsid_" --&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;f:view&gt;&lt;br /&gt;&amp;lt;h:form id="gsid_wrapperForm"&gt;&lt;br /&gt;&amp;lt;h:outputtext id="gsid_greetingOT" value="Hello, #{Workspace.userFullName}, you are in your Personal Workspace"&gt;&lt;br /&gt;&amp;lt;/h:outputtext&gt;&amp;lt;/h:form&gt;&amp;lt;/f:view&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;However, that gets very tedious.  Fortunately this problem is fixed in GS 2.2.x, but we're not in a position in the LEAD Project to move to 2.2.x at this time (in fact, I'm holding out for GS 3.0).  So I've hacked myfaces 1.1.4 to change the "#" character to "_hash_" when it gets such a value in the returned namespace.  The &lt;a href="http://www.extreme.indiana.edu/dist/java-repository/org/apache/myfaces/core/myfaces-impl/1.1.4-gs/myfaces-impl-1.1.4-gs.jar"&gt;modified jar&lt;/a&gt; is available in the Extreme Lab maven repository.  Also, if you are using Maven 2, you can use:&lt;br /&gt;&lt;br /&gt;       &amp;lt;dependency&gt;&lt;br /&gt;           &amp;lt;groupId&gt;org.apache.myfaces.core&amp;lt;/groupId&gt;&lt;br /&gt;           &amp;lt;artifactId&gt;myfaces-impl&amp;lt;/artifactId&gt;&lt;br /&gt;           &amp;lt;version&gt;1.1.4-gs&amp;lt;/version&gt;&lt;br /&gt;       &amp;lt;/dependency&gt;&lt;br /&gt;&lt;br /&gt;to specify the dependency, and you'll need to add the extreme repo in your &amp;lt;repositories&gt; list:&lt;br /&gt;&lt;br /&gt;     &amp;lt;repository&gt;&lt;br /&gt;       &amp;lt;name&gt;Extreme Maven2&amp;lt;/name&gt;&lt;br /&gt;       &amp;lt;id&gt;extreme.repo.maven2&amp;lt;/id&gt;&lt;br /&gt;       &amp;lt;url&gt;http://www.extreme.indiana.edu/dist/java-repository&amp;lt;/url&gt;&lt;br /&gt;       &amp;lt;snapshots&gt;&lt;br /&gt;         &amp;lt;updatePolicy&gt;daily&amp;lt;/updatePolicy&gt;&lt;br /&gt;       &amp;lt;/snapshots&gt;&lt;br /&gt;     &amp;lt;/repository&gt;&lt;br /&gt;&lt;br /&gt;This has come in very handy now that I've begun working with &lt;a href="http://facelets.dev.java.net"&gt;Facelets&lt;/a&gt;, which I am very happy with.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-116198033567522537?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/116198033567522537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=116198033567522537' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/116198033567522537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/116198033567522537'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/10/myfaces-jsf-and-gridsphere.html' title='MyFaces JSF and GridSphere'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-115981319608097596</id><published>2006-10-02T14:18:00.000-04:00</published><updated>2009-06-06T08:09:46.978-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='maven'/><title type='text'>Using Maven's deploy:deploy-file to import 3rd party jars</title><content type='html'>&lt;a href="http://maven.apache.org/guides/mini/guide-3rd-party-jars-remote.html"&gt;Maven - Guide to deploying 3rd party JARs to remote repository&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Usually I just manually copy in third party jars to our Maven repository when they come by, but recently I decided to give Maven's own tools a try.  In this example, I'm deploying a MyLEAD jar Scott Jensen has sent my way:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mvn deploy:deploy-file -DgroupId=mylead  -DartifactId=mylead-crosscut-attr \&lt;br /&gt;-Dversion=1.0  -Dpackaging=jar -Dfile=./mylead_crosscut_attr-1.0.jar  \&lt;br /&gt;-Durl=scpexe://rainier.extreme.indiana.edu/l/extreme/java/repository&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And here, I deploy it again, but this time as a Maven1 type artifact, to support Maven1 clients:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mvn deploy:deploy-file -DgroupId=mylead  -DartifactId=mylead-crosscut-attr \&lt;br /&gt;-Dversion=1.0  -Dpackaging=jar -Dfile=./mylead_crosscut_attr-1.0.jar  \&lt;br /&gt;-Durl=scpexe://rainier.extreme.indiana.edu/l/extreme/java/repository \&lt;br /&gt;-DrepositoryLayout=legacy&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-115981319608097596?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/115981319608097596/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=115981319608097596' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115981319608097596'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115981319608097596'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/10/using-mavens-deploydeploy-file-to.html' title='Using Maven&apos;s deploy:deploy-file to import 3rd party jars'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-115921696380636602</id><published>2006-09-25T16:28:00.000-04:00</published><updated>2009-06-06T08:09:46.978-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Using service certificates with Globus Java APIs (jglobus)</title><content type='html'>Anne Wilson of Unidata recently contacted me about using grid credentials for a long running service.  I suggested that she use "service certificates" (&lt;a href="http://www.globus.org/toolkit/docs/4.0/security/key-index.html#svc-cert"&gt;definition&lt;/a&gt;), but I didn't know exactly how to use them from an application using Java CoG.  I looked it up but looks like Anne already has a way to do this or something similar, so I just want to make a quick note about how to do this for future reference.&lt;br /&gt;&lt;br /&gt;In jglobus there's the GlobusCredential class.  To create a GlobusCredential object from a service certificate (or, more generally, from a certificate/private key pair where the private key is not encrypted), the constructor you use is GlobusCredential(String certFile, String unencryptedKeyFile).  From there, it's a little unclear but it seems that you can get a GSSCredential from this by then creating a GlobusGSSCredentialImpl object with the arguments (GlobusCredential, int usage) where it seems a good value for usage would be GSSCredential.INITIATE_AND_ACCEPT.&lt;br /&gt;&lt;br /&gt;You would use this approach when you need a service with Globus credentials but you don't want to or can't create a proxy certificate for it over and over again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-115921696380636602?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/115921696380636602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=115921696380636602' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115921696380636602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115921696380636602'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/09/using-service-certificates-with-globus.html' title='Using service certificates with Globus Java APIs (jglobus)'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-115746779009031424</id><published>2006-09-05T10:39:00.000-04:00</published><updated>2009-06-06T08:09:46.978-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Getting commons-logging to behave in Tomcat</title><content type='html'>&lt;a href="http://jakarta.apache.org/commons/logging/"&gt;Commons-logging is the bane of my existence&lt;/a&gt;, and I only use log4j now in all of my new projects.  Unfortunately, I don't have the luxury of completely avoiding it since several projects I depend upon use it.  Hence, I've found a simple little way to get commons-logging out of my way when working with web applications in Tomcat.  The basis of the trick is to get commons-logging to stop trying to auto-discover the log4j configurations I'm using.  So I drop a &lt;span style="font-weight: bold;"&gt;commons-logging.properties&lt;/span&gt; file in the top-level of the classloader hierarchy ($CATALINA_HOME/common/classes) that directs commons-logging to use its own built in SimpleLog facility.&lt;br /&gt;&lt;br /&gt;&lt;pre style="overflow: auto"&gt;&lt;br /&gt;org.apache.commons.logging.Log = org.apache.commons.logging.impl.SimpleLog&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then I add a properties file, &lt;span style="font-weight: bold;"&gt;simplelog.properties&lt;/span&gt;, in the same directory to configure the SimpleLog logger.&lt;br /&gt;&lt;br /&gt;&lt;pre style="overflow: auto"&gt;&lt;br /&gt;org.apache.commons.logging.simplelog.defaultlog=warn&lt;br /&gt;org.apache.commons.logging.simplelog.log.org.apache.myfaces=debug&lt;br /&gt;org.apache.commons.logging.simplelog.log.org.globus.purse=debug&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here I've set MyFaces and PURSe, a Grid security library I use, logging levels to DEBUG.  Of course, I have to make sure that I have a &lt;span style="font-weight: bold;"&gt;commons-logging.jar&lt;/span&gt; in common/lib.  This setup has been working pretty well for me for some time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-115746779009031424?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/115746779009031424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=115746779009031424' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115746779009031424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115746779009031424'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/09/getting-commons-logging-to-behave-in.html' title='Getting commons-logging to behave in Tomcat'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-115713668524241127</id><published>2006-09-01T14:06:00.000-04:00</published><updated>2009-06-06T08:09:46.978-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Top 10 Coolest Things coming in JSR 286</title><content type='html'>A while back I posted on the availability of JSR 286 Early Draft 1 (just a reminder that today is the last day to get feedback to the JSR 286 group on this early version of the specification).  Recently I finished reviewing it and here is a list of what I found to be the most interesting new things coming in JSR 286.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Portlet Events&lt;/span&gt; - Yes, they are finally here.  Portlets can consume and produce events.  This is a very important addition because portals can only handle one action request from one portlet at a time, even though other portlets on the page might want to respond to that action.  With JSR 286 they will be able to do this.  One thing that is unclear from the specification is the scope of portlet events, i.e., are they broadcasted across all portlets in a page, all portlets within that portlet application, or across all of a user's portlets?&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;CSS Style Diagrams&lt;/span&gt; - Now we can &lt;span style="font-style: italic;"&gt;see&lt;/span&gt; what the standard CSS portlet styles are supposed to be used for.  Okay, it's not a fantastically cool thing, but I'm very happy to see that the JSR 286 group has addressed one of my pet annoyances with JSR 168, that the CSS portlet styles are described only with ambiguous text.  And ambiguity makes the standard styles hardly worth the trouble of using, but this is a very important aspect of portability and reusability for Java Portlets.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Shared Session Attributes&lt;/span&gt; - Finally, sessions with portal scope!  This seems like the most obvious thing to have in a Java Portlet specification I was dismayed to see if missing from JSR 168.  One obvious use case for this would be the loading of session objects that other portlets could use for the purpose of "single sign on" in the portal.  In the grid portals I've worked with, we load the user's grid proxy credential at log in and need a way to make it available to other portlets.  We had resorted to ad hoc singleton style services higher up in the classloader hierarchy in Tomcat.  Now we can have a real solution.  One interesting point here is that in Early Draft 1, the JSR members specifically ask for input on whether this feature is needed given that you can accomplish the same sort of thing with Portlet Events.  It's my opinion that it should be provided, because sometimes you want user attributes in the user's session that aren't necessarily event oriented.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Filters&lt;/span&gt; - Like their servlet cousins, portlets now have filters.  I've yet to think of a need I have for portlet filters, but now that we'll have them, I'm sure some ideas will come to mind.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Resource Serving&lt;/span&gt; - This is a nice feature.  This sort of thing is possible in JSR 168 by including servlets with your portlet application that could serve up things like images or JNLP (you know, those WebStart descriptors) documents.  But then things were a little bit trickier in that to parameterize those servlet requests you would have to add attributes to the APPLICATION_SCOPE session in your portlet that would later be read by the servlet.  Note also that JSR 286 mentions that this would be the way to service AJAX requests.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Use of Annotations&lt;/span&gt; - This Java 5 feature is being used to route Event requests to the appropriate event handling method in processEvent().  Oddly, Early Draft 1 doesn't mention that the same will be done for routing action requests to various action methods.  I've done this kind of routing in the VelocityPortlet bridge I wrote, using reflection.  The annotation idea looks pretty cool and probably cleaner.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;More Support for AJAX&lt;/span&gt; -  The focus of Early Draft 1 is "portlet coordination" and "WSRP 2.0 interoperation", so there isn't much that is AJAX specific here, but we are promised that more is on the way (such as state changing resource serving requests).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Shared Render Parameters&lt;/span&gt; - I didn't see this one coming, and I have to admit I'm still trying to figure out how I would best use this.  The idea is that when a portlet sets a render parameter this parameter could be shared with other portlets.  The outcome of this is that when you select an account to view in the "Accounts List" portlet (invoking a portlet action), the "Accounts List" could set the currently_selected_account render parameter which would cause that account to be highlighted in "Accounts List" (on the render phase).  If this render parameter is shared, then the "Account Detail" portlet on the same page could also see this parameter and, since its doView() but not it's processAction() method would be called, it could then update its display with details about that selected account.  You can do the same sort of thing with session objects, but this is probably a cleaner way of doing it.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Portlets aren't just for Portals anymore&lt;/span&gt; - I love this quote:&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-style: italic;"&gt;The predominant applications using portlets today are portals aggregating the portlet markup into portal pages, but the Java Portlet Specification and portlets itself are not restricted to portals.&lt;/span&gt;&lt;/blockquote&gt;With JSR 286, I think Java Portlets have the potential to really remake the Java web development scene.  Portlets can and in many cases should be applied to non-portal environment.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;JAXB&lt;/span&gt;! - Okay, I'm stretching this top ten list a bit.  JAXB is leverage in this specification as a way to define payload data for event and shared session attributes.  So it looks like I'll need to learn me some JAXB.  If you know a good tutorial, let me know.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-115713668524241127?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/115713668524241127/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=115713668524241127' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115713668524241127'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115713668524241127'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/09/top-10-coolest-things-coming-in-jsr.html' title='Top 10 Coolest Things coming in JSR 286'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-115618334032560548</id><published>2006-08-21T13:56:00.000-04:00</published><updated>2009-06-06T08:09:46.978-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><title type='text'>Fixing Out of Memory Errors with Eclipse 3.2, Mac OS X</title><content type='html'>I've recently been getting out of memory errors with Eclipse 3.2 on Mac OS X.  Initially, I bumped the maximum heap size to 512MB, but that wasn't sufficient.  I then saw that the problem was actually with the PermGen size.  So I bumped that up from the default 64MB to 128MB.  So far so good.&lt;br /&gt;&lt;br /&gt;On OS X, you change these settings by editing &lt;span style="font-style: italic;"&gt;Eclipse.app/Contents/MacOS/eclipse.ini&lt;/span&gt;.  There I set &lt;span style="font-weight: bold;"&gt;-Xmx&lt;/span&gt; to &lt;span style="font-weight: bold;"&gt;512m&lt;/span&gt; and I added a parameter, &lt;span style="font-weight: bold;"&gt;-XX:MaxPermSize&lt;/span&gt;, and set it to &lt;span style="font-weight: bold;"&gt;128m&lt;/span&gt;.  My complete eclipse.ini file is here:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;-vmargs&lt;br /&gt;-Xdock:icon=../Resources/Eclipse.icns&lt;br /&gt;-XstartOnFirstThread&lt;br /&gt;-Xbootclasspath/p:../../../plugins/org.eclipse.jdt.debug_3.2.0.v20060605/jdi.jar-Xms40m&lt;br /&gt;-Xmx512m&lt;br /&gt;-XX:MaxPermSize=128m&lt;br /&gt;-Dorg.eclipse.swt.internal.carbon.smallFonts&lt;br /&gt;-Dorg.eclipse.swt.internal.carbon.noFocusRing&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-115618334032560548?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/115618334032560548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=115618334032560548' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115618334032560548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115618334032560548'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/08/fixing-out-of-memory-errors-with.html' title='Fixing Out of Memory Errors with Eclipse 3.2, Mac OS X'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-115514832487859287</id><published>2006-08-09T14:32:00.000-04:00</published><updated>2009-06-06T08:09:46.979-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>PURSe Portlets v. 1.0.1 released</title><content type='html'>&lt;a href="http://www.extreme.indiana.edu/portals/purse-portlets/release-notes.html"&gt;PURSe Portlets 1.0.1 Release Notes&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Hot off the press, just put this release together.  I got a lot of feedback on the 1.0 release, from within the LEAD project and from folks outside the LEAD project.  All discovered bugs, more or less, have been fixed in this release.  Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-115514832487859287?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/115514832487859287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=115514832487859287' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115514832487859287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115514832487859287'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/08/purse-portlets-v-101-released.html' title='PURSe Portlets v. 1.0.1 released'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-4504862617745161143</id><published>2006-08-09T08:49:00.001-04:00</published><updated>2009-06-06T09:07:04.484-04:00</updated><title type='text'>Lost Production Resumes</title><content type='html'>&lt;a href="http://www.scifi.com/scifiwire/index.php?id=37431"&gt;Lost Production Resumes [Sci-Fi Wire]&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Lost returns on Wednesday, October 4th!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-4504862617745161143?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/4504862617745161143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=4504862617745161143' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4504862617745161143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4504862617745161143'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/08/lost-production-resumes_09.html' title='Lost Production Resumes'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-115504298271169748</id><published>2006-08-08T09:16:00.000-04:00</published><updated>2009-06-06T08:09:46.979-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>JSR-286 Portlet - Early Draft Review available now</title><content type='html'>&lt;a href="http://jcp.org/aboutJava/communityprocess/edr/jsr286/"&gt;JSR-000286 Portlet - Early Draft Review&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It's out.  Get it, read it, send feedback.  I'll be reading through it myself soon and writing about it here on this blog, so stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-115504298271169748?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/115504298271169748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=115504298271169748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115504298271169748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115504298271169748'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/08/jsr-286-portlet-early-draft-review.html' title='JSR-286 Portlet - Early Draft Review available now'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-115455313284123617</id><published>2006-08-02T17:08:00.000-04:00</published><updated>2009-06-06T08:09:46.979-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Using Ant with Maven 1 and Maven 2</title><content type='html'>I've been using &lt;a href="http://maven.apache.org"&gt;Maven&lt;/a&gt; 1 for well over a year now.  Not long after I had started using it and generally liking it, the Maven guys decided to drop support for it and came out with 2.0.  Everything changed again.  This time the directory layout conventions are different (which completes negates the benefits of having adopted a convention in the first place), and it's more difficult now to just use bits of Ant when you need to.  I do not look so kindly on such capriciousness; and there are other complaints about Maven besides.  Finally, I decided that although like most developers I get more excited about by build tools than I probably should, in the end, it's just a way to build code.  Whether it is Ant or Maven, it's really just overhead; at some point, after having constructed beautiful and clean works of code, you need to actually build it and publish an artifact that others can use.  And so, in order to lessen this overhead and get some &lt;span style="font-style: italic;"&gt;real work&lt;/span&gt; done, I decided to move to the more established, more well-known &lt;a href="http://ant.apache.org"&gt;Ant&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;However, I now have quite a few projects using Maven 1.  And eventually, I'll probably have to co-exist with Maven 2 projects.  What's more, I think the best part of Maven is the dependency management; and it gets better in Maven 2 with support for transitive dependencies.  Is there a way to have my cake and eat it too?  Indeed there is.  In a moment of brilliance, the Maven guys decided to take their golden dependency management code and make it available as &lt;a href="http://maven.apache.org/ant-tasks.html"&gt;Ant tasks&lt;/a&gt;.  Turns out this stuff actually works.  I've been able to&lt;br /&gt;&lt;ul&gt;&lt;li&gt;use Maven2 to manage dependencies for my Ant builds, with all of their transistive goodness&lt;br /&gt;&lt;/li&gt;&lt;li&gt;publish Maven2 artifacts to Maven2 repos&lt;/li&gt;&lt;li&gt;publish Maven1 artifacts to Maven1 repos&lt;/li&gt;&lt;li&gt;use either Maven1 or Maven2 artifacts&lt;/li&gt;&lt;li&gt;treat my Maven repository as both a Maven1 and a Maven2 repository&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;Getting Started&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The documentation on the &lt;a href="http://maven.apache.org/ant-tasks.html"&gt;Antlib for Maven 2.0&lt;/a&gt; page is decent.  Installing the Ant tasks is fairly straightforward.  You add an XML namespace declaration.&lt;br /&gt;&lt;br /&gt;&lt;pre size="smaller" style="border: 1px dashed rgb(153, 153, 153); overflow: auto; background-color: rgb(238, 238, 238);"&gt;&amp;lt;project name="ExpBuilder" basedir="." artifact="urn:maven-artifact-ant"&gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;/project&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Then what I wanted to do was to completely bootstrap the maven dependency by downloading it with the &lt;get&gt; task.  For this, I add the following to my "init" target:&lt;br /&gt;&lt;br /&gt;&lt;/get&gt;&lt;pre size="smaller" style="border: 1px dashed rgb(153, 153, 153); overflow: auto; background-color: rgb(238, 238, 238);"&gt;&lt;br /&gt;&amp;lt;mkdir dir="${lib}/maven" /&gt;&lt;br /&gt;&amp;lt;get src="${maven.artifact.ant.url}"&lt;br /&gt; dest="${lib}/maven/maven-artifact-ant-dep.jar" usetimestamp="true"&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;typedef resource="org/apache/maven/artifact/ant/antlib.xml"&lt;br /&gt;     uri="urn:maven-artifact-ant"&gt;&lt;br /&gt;&amp;lt;classpath&gt;&lt;br /&gt; &amp;lt;pathelement location="${lib}/maven/maven-artifact-ant-dep.jar" /&gt;&lt;br /&gt;&amp;lt;/classpath&gt;&lt;br /&gt;&amp;lt;/typedef&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Where ${maven.artifact.ant.url} is defined in the build.properties file and could be a remote url or a local "file:///" url.  Some people instead check this jar into CVS along with the code and use Maven to download the other dependencies, but I wanted something completely bootstrapped.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Defining Maven Repos&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here's what I used, again, in my "init" method, to define the needed maven repos.  Here's what I have:&lt;br /&gt;&lt;br /&gt;&lt;pre size="smaller" style="border: 1px dashed rgb(153, 153, 153); overflow: auto; background-color: rgb(238, 238, 238);"&gt;&lt;br /&gt;&lt;!-- repositories --&gt;&lt;br /&gt;&amp;lt;artifact:remoterepository id="extreme.http.maven1"&lt;br /&gt;url="http://www.extreme.indiana.edu/dist/java-repository" layout="legacy" /&gt;&lt;br /&gt;&amp;lt;artifact:remoterepository id="extreme.http.maven2"&lt;br /&gt;url="http://www.extreme.indiana.edu/dist/java-repository" /&gt;&lt;br /&gt;&amp;lt;artifact:remoterepository id="extreme.scp.maven1"&lt;br /&gt;url="scp://rainier.extreme.indiana.edu/l/extreme/java/repository" layout="legacy" /&gt;&lt;br /&gt;&amp;lt;artifact:remoterepository id="extreme.scpexe.maven1"&lt;br /&gt;url="scpexe://rainier.extreme.indiana.edu/l/extreme/java/repository" layout="legacy" /&gt;&lt;br /&gt;&amp;lt;artifact:remoterepository id="extreme.scp.maven2"&lt;br /&gt;url="scp://rainier.extreme.indiana.edu/l/extreme/java/repository" /&gt;&lt;br /&gt;&amp;lt;artifact:remoterepository id="extreme.scpexe.maven2"&lt;br /&gt;url="scpexe://rainier.extreme.indiana.edu/l/extreme/java/repository" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Basically I have one maven repository that I define 6 different mappings for.  This allows me to treat the same Maven repository as a Maven 1 and a Maven 2 repository.  The difference between Maven 1 and Maven 2 repository descriptions is in the layout="legacy" attribute.  I started by using the scp:// style remote repository deployment, but found that the scpexe:// style actually works better since it uses my local ssh environment, i.e., it uses my ssh-agent and I don't have to type in my password several times just to publish a single artifact.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Defining Dependencies&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This part is where Maven 2 comes in.  See the &lt;a href="http://maven.apache.org/guides/getting-started/index.html"&gt;getting started guide&lt;/a&gt; for help getting going with Maven 2 if you're unfamiliar with it.  Basically I created a very simple pom.xml file that contains only the basic info like groupId, artifactId, version, and then a list of dependencies.  The Maven Ant tasks provide a way to read in and reference your POM:&lt;br /&gt;&lt;br /&gt;&lt;pre size="smaller" style="border: 1px dashed rgb(153, 153, 153); overflow: auto; background-color: rgb(238, 238, 238);"&gt;&amp;lt;artifact:pom id="maven.project" file="pom.xml" /&gt;&lt;br /&gt;&lt;/pre&gt;That's it!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Pulling in the Dependencies&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One of the "gotchas" I discovered while putting this together was that using these tasks to retrieve artifacts from a Maven 1 repo is time consuming.  This is because it tries to retrieve the .pom file for all artifacts, even if the jar in question is already in cache.  Since my Maven 1 repository has a lot of artifacts in it that were deployed there with Maven and hence do not have .pom files, Maven spends a lot of extra time trying to download these files (on the order of a minute or two for about 20 dependencies).  Hence, I decided to create an Ant target, called &lt;span style="font-weight: bold;"&gt;maven-dependencies&lt;/span&gt;,  that would get the dependencies and copy them into ./lib directory.  That way I only have to run it occasionally.  The downside to this is that I have my compile target, for example, not depending on the maven-dependencies target, but it really should depend on it.  Here it is:&lt;br /&gt;&lt;br /&gt;&lt;pre size="smaller" style="border: 1px dashed rgb(153, 153, 153); overflow: auto; background-color: rgb(238, 238, 238);"&gt;&amp;lt;artifact:dependencies pathId="maven.compile.classpath"&lt;br /&gt;                     filesetId="maven.compile.fileset" usescope="compile"&gt;&lt;br /&gt;&amp;lt;remoteRepository refid="extreme.http.maven1" /&gt;&lt;br /&gt;&amp;lt;remoteRepository refid="extreme.http.maven2" /&gt;&lt;br /&gt;&amp;lt;pom refid="maven.project" /&gt;&lt;br /&gt;&amp;lt;/artifact:dependencies&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;artifact:dependencies pathId="maven.provided.classpath"&lt;br /&gt;                     filesetId="maven.provided.fileset" usescope="provided"&gt;&lt;br /&gt;&amp;lt;remoteRepository refid="extreme.http.maven1" /&gt;&lt;br /&gt;&amp;lt;remoteRepository refid="extreme.http.maven2" /&gt;&lt;br /&gt;&amp;lt;pom refid="maven.project" /&gt;&lt;br /&gt;&amp;lt;/artifact:dependencies&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;artifact:dependencies pathId="maven.runtime.classpath"&lt;br /&gt;                     filesetId="maven.runtime.fileset" usescope="runtime"&gt;&lt;br /&gt;&amp;lt;remoteRepository refid="extreme.http.maven1" /&gt;&lt;br /&gt;&amp;lt;remoteRepository refid="extreme.http.maven2" /&gt;&lt;br /&gt;&amp;lt;pom refid="maven.project" /&gt;&lt;br /&gt;&amp;lt;/artifact:dependencies&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;copy todir="${lib}"&gt;&lt;br /&gt;&amp;lt;fileset refid="maven.compile.fileset" /&gt;&lt;br /&gt;&amp;lt;mapper type="flatten" /&gt;&lt;br /&gt;&amp;lt;/copy&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;mkdir dir="${lib}/provided"/&gt;&lt;br /&gt;&amp;lt;copy todir="${lib}/provided"&gt;&lt;br /&gt;&amp;lt;fileset refid="maven.provided.fileset" /&gt;&lt;br /&gt;&amp;lt;mapper type="flatten" /&gt;&lt;br /&gt;&amp;lt;/copy&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;mkdir dir="${lib}/runtime" /&gt;&lt;br /&gt;&amp;lt;copy todir="${lib}/runtime"&gt;&lt;br /&gt;&amp;lt;fileset refid="maven.runtime.fileset" /&gt;&lt;br /&gt;&amp;lt;mapper type="flatten" /&gt;&lt;br /&gt;&amp;lt;/copy&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; Another gotcha is that although I have dependencies with scope "provided" (&lt;a href="http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html"&gt;more on dependency scope in Maven 2&lt;/a&gt;), those dependencies don't get translated into a fileSet or path.  The attribute "useScope" here means actually the set of dependencies needed at this scope.  So for example my "compile" scoped set of dependencies includes my "provided" scoped dependencies and my "compile" scoped dependencies, since dependencies from both of those scopes are needed to compile my code.  Likewise, my "runtime" scoped set of dependencies includes "compile" and "runtime" dependencies since those are needed at runtime (and "provided" dependencies are expected to be, well, provided).  I use "./lib/*.jar" as my default classpath in the rest of the build script.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Deploying to Maven 1 and Maven 2 repositories&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Again, I wanted to use the same repository for both Maven 1 and Maven 2 style artifacts.  Deploying is pretty straightforward; here are my targets:&lt;br /&gt;&lt;br /&gt;&lt;pre size="smaller" style="border: 1px dashed rgb(153, 153, 153); overflow: auto; background-color: rgb(238, 238, 238);"&gt;&amp;lt;target name="maven2-deploy" depends="jar"&gt;&lt;br /&gt;&amp;lt;artifact:install-provider artifactId="wagon-ssh-external"&lt;br /&gt;                             version="1.0-alpha-5" /&gt;&lt;br /&gt;&amp;lt;artifact:deploy file="${build}/${maven.project.artifactId}-${maven.project.version}.jar"&gt;&lt;br /&gt;   &amp;lt;remoteRepository refid="extreme.scpexe.maven2" /&gt;&lt;br /&gt;   &amp;lt;pom refid="maven.project" /&gt;&lt;br /&gt;&amp;lt;/artifact:deploy&gt;&lt;br /&gt;&amp;lt;/target&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="maven1-deploy" depends="jar"&gt;&lt;br /&gt;&amp;lt;artifact:install-provider artifactId="wagon-ssh-external"&lt;br /&gt;                             version="1.0-alpha-5" /&gt;&lt;br /&gt;&amp;lt;artifact:deploy file="${build}/${maven.project.artifactId}-${maven.project.version}.jar"&gt;&lt;br /&gt;   &amp;lt;remoteRepository refid="extreme.scpexe.maven1" /&gt;&lt;br /&gt;   &amp;lt;pom refid="maven.project" /&gt;&lt;br /&gt;&amp;lt;/artifact:deploy&gt;&lt;br /&gt;&amp;lt;/target&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;Again, I'm using scpexe as the install-provider because this picks up my ssh-agent environment on Mac and Linux workstations.  On Windows you might want the scp install-provider, although it should be possible to configure scpexe install-provider to use certain executables, such as &lt;a href="http://www.chiark.greenend.org.uk/%7Esgtatham/putty/"&gt;PuTTY&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Finally, let's build a portlet!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Building a portlet in Maven was pretty easy; just issue "maven war".  Okay, well, not that easy, because it probably wouldn't pick up the right things, and if you support deployment to multiple portals, then that typically means you need to have multiple web.xml files.  So, here's my &lt;span style="font-weight: bold;"&gt;war-gridsphere&lt;/span&gt; target for creating a portlet war for the &lt;a href="http://www.gridpshere.org"&gt;GridSphere&lt;/a&gt; portal server.&lt;br /&gt;&lt;br /&gt;&lt;pre size="smaller" style="border: 1px dashed rgb(153, 153, 153); overflow: auto; background-color: rgb(238, 238, 238);"&gt;&amp;lt;target name="war-gridsphere" depends="compile" description="Creates a web application resource file"&gt;&lt;br /&gt;&amp;lt;war destfile="${build}/${maven.project.artifactId}.war"&lt;br /&gt;   webxml="${webapp}/WEB-INF/web.xml.gridsphere" compress="true"&gt;&lt;br /&gt;   &amp;lt;fileset dir="${webapp}" excludes="**/web.xml"/&gt;&lt;br /&gt;   &amp;lt;fileset dir="${src.conf}"&gt;&lt;br /&gt;       &amp;lt;include name="*.properties"/&gt;&lt;br /&gt;   &amp;lt;/fileset&gt;&lt;br /&gt;   &amp;lt;lib dir="${lib}/runtime" includes="*.jar"/&gt;&lt;br /&gt;   &amp;lt;classes dir="${build}/classes"/&gt;&lt;br /&gt;&amp;lt;/war&gt;&lt;br /&gt;&amp;lt;/target&gt;&lt;br /&gt;&lt;/pre&gt; Well, that wasn't so bad.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-115455313284123617?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/115455313284123617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=115455313284123617' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115455313284123617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115455313284123617'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/08/using-ant-with-maven-1-and-maven-2.html' title='Using Ant with Maven 1 and Maven 2'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-115377236567536543</id><published>2006-07-24T16:16:00.000-04:00</published><updated>2009-06-06T08:09:46.979-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><title type='text'>Portals and Portlets 2006 Conference Recap</title><content type='html'>Just got back from a fantastic conference in  Edinburgh, Scotland called &lt;a href="http://www.grids.ac.uk/twiki/bin/view/EResearch/PortalsAndPortlets2006"&gt;Portals and Portlets 2006&lt;/a&gt;.  You can access the presentations given on &lt;a href="http://www.nesc.ac.uk/action/esi/contribution.cfm?Title=686"&gt;this page&lt;/a&gt;.  It was a great time to get together with fellow developers working on portals and portlets and related issues in the Grid community.  Of course, Edinburgh is one of the most beautiful places I've been to, and I stayed at the Radisson SAS right along the &lt;a href="http://en.wikipedia.org/wiki/Royal_Mile"&gt;Royal Mile&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here are some things that I've been thinking about since the conference, inspired by presentations and discussions I had there:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;More than a few times people expressed interest in "portlets without portals".  For example, Jason Novotny demonstrated some code he has been working on that would allow bringing a portlet into any web page with just a bit of JavaScript, using AJAX.  Previously Jason created the capability to bring a portlet into a JSP page with &lt;a href="http://ftp.gridsphere.org/browse/GPF-171"&gt;a custom JSP tag&lt;/a&gt;.  I've been thinking along these lines as well.  It seems the evolution of modern portals, from information aggregators (something akin to a personalized, internet newspaper) to application aggregators to standardized containers, has given us this cool ability to take a web application, treat it like a component, and stick it into a web page.  That is, portlets are the cool thing about portals, not the other way around.  Portals are now the baggage that portlets have inherited.  We now have several portals on the market that do pretty much the same thing, and we inherit their propensity for overbearing layout frameworks that like to cut everything up into rectangle and add lots of icons to them, like "maximize" and "minimize", which I'm pretty sure no user has every seriously used.&lt;br /&gt;The idea I've been toying around with is to take Pluto and wrap it with a custom JSF component, which would be similar to what Jason did with his JSP tag, but I wouldn't need a portal engine, just the portlet container.  JSF components are stateful so this component should be able to handle anything that Pluto would normally need a full portal engine to take care of.  Couple this with Facelets, and you would have a (nearly) pure XHTML way to create a website, sprinkling in portlets where you see fit.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;There was a lot of talk about WSRP.  I was unable to find out why anyone would want to use WSRP as it seems to be a solution in search of a problem, but that is just my personal opinion.  The consensus of the group seemed to be that WSRP is a good thing to have and that there currently is no decent community (i.e, open source) implementation of WSRP, since the WSRP4J project is still in incubation and it has several bugs besides.  Tim Rault-Smith of Sun was there and said that they will be open sourcing the Sun Portal product, including its WSRP stack, so hopefully the community will soon have a decent implementation.&lt;/li&gt;&lt;li&gt;There were several talks about security, which is a difficult problem in Grid environments.  Kurt Mueller talked about &lt;a href="http://grid-devel.sdsc.edu/gridsphere/gridsphere?cid=gama"&gt;GAMA&lt;/a&gt; 2, which will be available in the next month or so.  I talked about my work with the &lt;a href="http://www.extreme.indiana.edu/portals/purse-portlets/"&gt;PURSe portlets&lt;/a&gt;.  Jipu Jiang talked about using Shibboleth with GridSphere.  I had a discussion with Tim Rault-Smith about how we are doing authentication and authorization in the LEAD Portal.  Our authorization scheme in the LEAD Portal is based on SAML, using these things called capability tokens.  What I dislike about them is that they are time-limited just like Globus proxy certificates, and so we run into the same set of issues we experience with proxy certificates; in other words, they are always expiring at the worst moment.  What would be nice is either a more lightweight authorization scheme or perhaps if it were possible to grant a capability to a user limited not in time but in "space", that is, limited to only a particular instance of a service, or limited to a single invocation of the service (which of course implies that the service is somehow stateful).&lt;/li&gt;&lt;li&gt;Chuck was there, talking about all things Sakai, and it was good to see him again.  He wants to make Sakai a JSR 168 portlet container, and I think that's a great idea.  I would love to use Sakai this way, I've never been keen on running Sakai as a separate portal and linking into the LEAD portal via iframes.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-115377236567536543?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/115377236567536543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=115377236567536543' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115377236567536543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/115377236567536543'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/07/portals-and-portlets-2006-conference.html' title='Portals and Portlets 2006 Conference Recap'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31592724.post-4696030638407337752</id><published>2006-07-06T21:41:00.001-04:00</published><updated>2009-06-06T09:07:04.484-04:00</updated><title type='text'>Hello World - blogosphere style</title><content type='html'>I'm doing all things google today.  Created a gmail account, started using the &lt;a href="http://www.google.com/reader"&gt;google rss reader&lt;/a&gt;, playing with google earth, now a blog.  Oh yeah, and then there's this firefox extension that will sync up your firefox settings on multiple computers, called &lt;a href="http://www.google.com/tools/firefox/browsersync/"&gt;Google Browser Sync&lt;/a&gt;.  I'll install it on my work computer tomorrow and see how well it works.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31592724-4696030638407337752?l=marcus-christie.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcus-christie.blogspot.com/feeds/4696030638407337752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=31592724&amp;postID=4696030638407337752' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4696030638407337752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31592724/posts/default/4696030638407337752'/><link rel='alternate' type='text/html' href='http://marcus-christie.blogspot.com/2006/07/hello-world-blogosphere-style_06.html' title='Hello World - blogosphere style'/><author><name>Marcus Christie</name><uri>http://www.blogger.com/profile/02331634762593140064</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
