<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Object Partners Inc » Blog</title>
	
	<link>http://www.objectpartners.com</link>
	<description>Object Partners Inc.</description>
	<lastBuildDate>Fri, 30 Oct 2009 14:28:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/ObjectPartnersIncBlog" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Spring Security 3.0 with JSR-286 Liferay Portlet</title>
		<link>http://feedproxy.google.com/~r/ObjectPartnersIncBlog/~3/nNA3CtSBn24/</link>
		<comments>http://www.objectpartners.com/2009/10/30/spring-security-3-0-with-jsr-286-liferay-portlet/#comments</comments>
		<pubDate>Fri, 30 Oct 2009 14:28:33 +0000</pubDate>
		<dc:creator>Joel Crabb</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JSR-286]]></category>
		<category><![CDATA[Liferay]]></category>
		<category><![CDATA[portlet]]></category>
		<category><![CDATA[portletfilter]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[Spring3]]></category>
		<category><![CDATA[SpringSecurity]]></category>

		<guid isPermaLink="false">http://www.objectpartners.com/?p=1460</guid>
		<description><![CDATA[Overview
In the RC1 version of Spring Security 3.0 (SS3), the Portlet jar was dropped that was available in v2.0.5 (spring-security-portlet-2.0.x.jar).  That leaves us with a dilemma when it comes to securing portlets using SS3.  To implement security in a portlet in a JSR-168 context one would have to re-implement everything in the portlet jar to [...]]]></description>
			<content:encoded><![CDATA[<h2>Overview</h2>
<p>In the RC1 version of Spring Security 3.0 (SS3), the Portlet jar was dropped that was available in v2.0.5 (spring-security-portlet-2.0.x.jar).  That leaves us with a dilemma when it comes to securing portlets using SS3.  To implement security in a portlet in a JSR-168 context one would have to re-implement everything in the portlet jar to use an interceptor based way of adding an Authentication to the SecurityContext.</p>
<p>Rather than taking that path, Spring 3 supports JSR-286 portlet specification which allows for portlet filters.  Since a common way to implement security is through security filters, a portlet filter method seems like a viable alternative.  There is one main issue with using portlet filters in that Spring cannot be used to create or inject dependencies into the portlet filter.  (Maybe it can but I wasn’t able to get it to work).</p>
<p>Thus, I’ve created a PortletSecurityFilter filter that more or less follows the SS3 security process used in the Servlet side implementation (AbstractAuthenticationProcessingFilter).</p>
<p>What&#8217;s the point of doing this?  Well, we need to deploy our portlet to multiple portal containers.  Thus, if we use SS3 we can easily control our portlet roles and not have to rely on the portal implementation.</p>
<h2>Process</h2>
<p>The whole point of this exercise is to push an Authentication into the SecurityContext for SS3 to use later when verifying Role information.  We’ll create a PortletSecurityFilter to accomplish this push.</p>
<p>Warning, many might think of this as a hack to fool SS3.  If you’re okay with that then keep reading.</p>
<h2>Portlet Lifecycle Location</h2>
<p>The first question is in what portlet lifecycle should the filter live?  That depends but the best location is during the Action Phase.  Adding the filter at this point sets the SecurityContext early enough for both the Action and Render phases meaning SS3 will work for both annotation driven security as well as jsp rendering security.</p>
<h2>PortletSecurityFilter</h2>
<p>Below is the code for the PortletSecurityFilter.  Note that you will have to implement your own AuthenticationDetailsSource and AuthenticationManager for this to work.  You’ll notice this also throws the Authentication token onto the PortletSession for use in later requests. </p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">com.your.package.name</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.IOException</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.portlet.ActionRequest</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.portlet.ActionResponse</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.portlet.PortletException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.portlet.PortletSession</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.portlet.filter.ActionFilter</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.portlet.filter.FilterChain</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.portlet.filter.FilterConfig</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.portlet.filter.PortletFilter</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.log4j.Logger</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.security.authentication.AuthenticationDetailsSource</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.security.authentication.AuthenticationManager</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.security.core.Authentication</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.security.core.context.SecurityContextHolder</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * Implements security behavior for Spring Security 3.0.  Adds an &lt;tt&gt;Authentication&lt;/tt&gt; to the
 * &lt;tt&gt;SecurityContext&lt;/tt&gt; and to the &lt;tt&gt;PortletSession&lt;/tt&gt;.  Spring Security picks up the 
 * &lt;tt&gt;Authentication&lt;/tt&gt; when it meets annotated methods with the @Secured annotation.
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> PortletSecurityFilter <span style="color: #000000; font-weight: bold;">implements</span> PortletFilter, ActionFilter <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> Logger logger <span style="color: #339933;">=</span> Logger.<span style="color: #006633;">getLogger</span><span style="color: #009900;">&#40;</span>PortletSecurityFilter.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> SECURITY_TOKEN <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SECURITY_TOKEN&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> AuthenticationDetailsSource authenticationDetailsSource <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PortletAuthenticationDetailsSource<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> AuthenticationManager authenticationManager <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PortletAuthenticationManager<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    @Override
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Follow the Spring Security method for an AuthenticationFilter.
     * @see AbstractAuthenticationProcessingFilter
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> doFilter<span style="color: #009900;">&#40;</span>ActionRequest request, ActionResponse response, FilterChain chain<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span>, PortletException <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>request.<span style="color: #006633;">getUserPrincipal</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #666666; font-style: italic;">// If no UserPrincipal from Portal stop the chain here.</span>
	    <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	Authentication auth <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Authentication<span style="color: #009900;">&#41;</span> request.<span style="color: #006633;">getPortletSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getAttribute</span><span style="color: #009900;">&#40;</span>SECURITY_TOKEN<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>auth <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    PreAuthenticatedAuthenticationToken authToken <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PreAuthenticatedAuthenticationToken<span style="color: #009900;">&#40;</span>request.<span style="color: #006633;">getUserPrincipal</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, request.<span style="color: #006633;">getRemoteUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    setDetails<span style="color: #009900;">&#40;</span>request, authToken<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    auth <span style="color: #339933;">=</span> authenticationManager.<span style="color: #006633;">authenticate</span><span style="color: #009900;">&#40;</span>authToken<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>auth.<span style="color: #006633;">isAuthenticated</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    successfulAuthentication<span style="color: #009900;">&#40;</span>request, response, auth<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    chain.<span style="color: #006633;">doFilter</span><span style="color: #009900;">&#40;</span>request, response<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Default behavior for successful authentication.
     * &lt;ol&gt;
     * &lt;li&gt;Sets the successful &lt;tt&gt;Authentication&lt;/tt&gt; object on the {@link SecurityContextHolder}&lt;/li&gt;
     * &lt;li&gt;Sets the &lt;tt&gt;Authentication&lt;/tt&gt; onto the &lt;tt&gt;PortletSession&lt;/tt&gt;&lt;/li&gt;
     * &lt;/ol&gt;
     *
     * @see AbstractAuthenticationProcessingFilter
     * @param authResult the object returned from the &lt;tt&gt;attemptAuthentication&lt;/tt&gt; method.
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> successfulAuthentication<span style="color: #009900;">&#40;</span>ActionRequest request, ActionResponse response,
            Authentication authResult<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span>, PortletException <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>logger.<span style="color: #006633;">isDebugEnabled</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            logger.<span style="color: #006633;">debug</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Authentication success. Updating SecurityContextHolder to contain: &quot;</span> <span style="color: #339933;">+</span> authResult<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        SecurityContextHolder.<span style="color: #006633;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">setAuthentication</span><span style="color: #009900;">&#40;</span>authResult<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	PortletSession session <span style="color: #339933;">=</span> request.<span style="color: #006633;">getPortletSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	session.<span style="color: #006633;">setAttribute</span><span style="color: #009900;">&#40;</span>SECURITY_TOKEN, authResult<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Implementation of setDetails.
     *
     * @see UsernamePasswordAuthenticationFilter
     * @param request that an authentication request is being created for
     * @param authRequest the authentication request object that should have its details set
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> setDetails<span style="color: #009900;">&#40;</span>ActionRequest request, PreAuthenticatedAuthenticationToken authRequest<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        authRequest.<span style="color: #006633;">setDetails</span><span style="color: #009900;">&#40;</span>authenticationDetailsSource.<span style="color: #006633;">buildDetails</span><span style="color: #009900;">&#40;</span>request<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> destroy<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Action filter destroy.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> init<span style="color: #009900;">&#40;</span>FilterConfig arg0<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> PortletException <span style="color: #009900;">&#123;</span>
	<span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Action filter init.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>    
<span style="color: #009900;">&#125;</span></pre></div></div>

<h2>portlet.xml</h2>
<p>The next step is to add this portlet filter to the portlet.xml file.  After you have declared your portlets, insert the following filter declaration:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">    	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>	
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>PortletSecurityFilter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    com.your.package.name.PortletSecurityFilter
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>		
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;lifecycle<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>ACTION_PHASE<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/lifecycle<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>		
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>		
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>message<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Security Filter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>		
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>	
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
&nbsp;
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>PortletSecurityFilter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;portlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>your-portlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/portlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<h2>Spring Security 3.0 Configuration</h2>
<p>We have to enable SS3 by creating an applicationContext-security.xml file.  Basically, all we really have to do is enable secure annotations so if you don’t want to create a new file than just throw this into your current applicationContext.xml:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;beans</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://www.springframework.org/schema/beans&quot;</span></span>
<span style="color: #009900;"><span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span>
<span style="color: #009900;"><span style="color: #000066;">xmlns:security</span>=<span style="color: #ff0000;">&quot;http://www.springframework.org/schema/security&quot;</span> </span>
<span style="color: #009900;"><span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd</span>
<span style="color: #009900;">        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd&quot;</span></span>
<span style="color: #009900;">        <span style="color: #000000; font-weight: bold;">&gt;</span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;security:global-method-security</span> <span style="color: #000066;">secured-annotations</span>=<span style="color: #ff0000;">&quot;enabled&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;security:authentication-manager</span> <span style="color: #000066;">alias</span>=<span style="color: #ff0000;">&quot;authenticationManager&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>	
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/beans<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<h2>web.xml</h2>
<p>Finally, if you added a new applicationContext than you’ll need to add that to your web.xml as a new contextConfigLocation.  That path will depend on where you put the file but one path might be:</p>
<p>/WEB-INF/context/applicationContext-security.xml</p>
<h2>Add Security</h2>
<p>Now all you need to do is add @Secured notations to your protected services or &lt;security:authorize&gt; tags to your jsp.  Assuming you created an AuthenticationManager that added the proper GrantedAuthorities than your security should now work.</p>
<p>I did this with Liferay portal v5.2.3 and successfully secured my portlet outside of Liferay.  Of course Liferay provides you with methods to expose your portlet permissions and administer them through Liferay control panel but we did not want to use that method.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectpartners.com/2009/10/30/spring-security-3-0-with-jsr-286-liferay-portlet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.objectpartners.com/2009/10/30/spring-security-3-0-with-jsr-286-liferay-portlet/</feedburner:origLink></item>
		<item>
		<title>Default settings of svn:keywords property</title>
		<link>http://feedproxy.google.com/~r/ObjectPartnersIncBlog/~3/qnFjN6ylo94/</link>
		<comments>http://www.objectpartners.com/2009/10/28/default-settings-of-svnkeywords-property/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 14:07:18 +0000</pubDate>
		<dc:creator>amiller</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[cvs]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[netbeans]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[smartsvn]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://www.objectpartners.com/?p=1456</guid>
		<description><![CDATA[Keyword expansion is not the default for files added to an SVN repository.  And it&#8217;s done on a per file basis (with CVS we could configure an entire repository to turn on keyword expansion &#8212; .)  Some svn tools and plugins allow for defaulting properties when adding new files.  I&#8217;ve configured the two I use [...]]]></description>
			<content:encoded><![CDATA[<p>Keyword expansion is not the default for files added to an SVN repository.  And it&#8217;s done on a per file basis (with CVS we could configure an entire repository to turn on keyword expansion &#8212; .)  Some svn tools and plugins allow for defaulting properties when adding new files.  I&#8217;ve configured the two I use most often (eclipse and smartsvn) to the svn:keywords property for all new files:</p>
<pre style="padding-left: 30px;">svn:keywords : Date Revision Author URL Id</pre>
<p>You can see a file&#8217;s properties from the command line with</p>
<pre style="padding-left: 30px;">svn pl -v filename</pre>
<p>Some tool (like netbeans) don&#8217;t provide for defaulting properties when adding new files.  And there are probably some people (not gonna name names :^) who don&#8217;t configure their tools to default the svn:keywords property anyway.  So below is a little script that&#8217;ll do it for you.  The script is in ruby &#8217;cause Brian (who first sketched it out a few years ago for a project) wanted to do some ruby scripting.</p>
<p>You can run it from time to time from the command line or better yet, set up a cron job on the build server to do it once or twice a day.  Our cron job does something like this:</p>
<pre style="padding-left: 30px;">cd ~/tmp/scratch-dir
svn checkout https://opi.svn.cvsdude.com/xyzzy
add_svn_keywords.rb
svn commit -m \"Added svn:keywords property\"</pre>
<p>It&#8217;s up to you if you want to do a full checkout each time (an update would be faster.)</p>
<p>Here&#8217;s the script&#8230;</p>
<pre style="padding-left: 30px;">#!/usr/bin/ruby
#
# Adds svn:keywords property to source files.  Default to process the
# current directory.  Note: this does not commit the changes!
#
# Usage:
#   ruby add_svn_keywords.rb [src_dir]
#
# where
#   src_dir (Optional) The directory to process.
#
# for example
#   ruby add_svn_keywords.rb c:/mnscu/hr/code
#
require 'find'
require 'fileutils'
include FileUtils::Verbose
require 'ftools'
require 'optparse'

# -- functions --------------------------------------------------------------

def do_system(command)
    puts command
    system(command) or raise($?)
end

# -- vars -------------------------------------------------------------------

working_dir = "."
keywords = "Date Revision Author URL Id"
usage = "Usage: ruby add_svn_keywords.rb [src_dir]"

# -- options and svn checkout/update ----------------------------------------

opts = OptionParser.new
opts.parse(ARGV) rescue usage

unless ARGV[0].nil?
    working_dir = ARGV[0]
end

# -- svn properties ---------------------------------------------------------

num = 0
Find.find(working_dir) do |path|

    if FileTest.directory?(path)
        if File.basename(path) == '.svn'
            # allways skip the .svn dirs
            Find.prune
        else
            # don't bother setting properties on dirs
            next
        end
    else # must be a file...
        # quote spaces on paths that contain them (so svn wont fail)
        path.gsub!(/ /, '\ ')

        # add keywords property to some files...
        if File.file?(path) and path =~ /\.(ddl|bat|sh|css|dtd|el|groovy|gsp|html|java|js|jsp|properties|sql|txt|xml)$/
            keywordprop = `svn proplist --verbose #{path}`.to_a.find_all {|line| line.include? keywords  }
            if keywordprop.size == 0
                do_system("svn propset svn:keywords \"#{keywords}\" #{path}")
                num += 1
            end
        end
    end
end # find

# -- commit and cleanup -----------------------------------------------------

if num &gt; 0
    #do_system("svn commit -m \"Added svn:keywords property\" #{working_dir}");
    puts "Added svn:keywords property to: #{num} files"
else
    puts "No changes"
end

# -- end of file ------------------------------------------------------------</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.objectpartners.com/2009/10/28/default-settings-of-svnkeywords-property/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.objectpartners.com/2009/10/28/default-settings-of-svnkeywords-property/</feedburner:origLink></item>
		<item>
		<title>Twitter-like Load More Button</title>
		<link>http://feedproxy.google.com/~r/ObjectPartnersIncBlog/~3/O2fVJz6pPUA/</link>
		<comments>http://www.objectpartners.com/2009/10/20/twitter-like-load-more-button/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 19:42:36 +0000</pubDate>
		<dc:creator>Hiromi Suenaga</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Jquery]]></category>
		<category><![CDATA[MooTools]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.objectpartners.com/?p=1440</guid>
		<description><![CDATA[Here is a good example code for twitter like load more button in both jQuery and MooTools:
http://net.tutsplus.com/tutorials/javascript-ajax/create-a-twitter-like-load-more-widget/
I&#8217;ve tried MooTools version and worked fairly well (For IE, you need to remove the last comma in line 133 of mootools-version.php).  Very easy to customize and the effect is great!
]]></description>
			<content:encoded><![CDATA[<p>Here is a good example code for twitter like load more button in both jQuery and MooTools:</p>
<p><a href="http://net.tutsplus.com/tutorials/javascript-ajax/create-a-twitter-like-load-more-widget/">http://net.tutsplus.com/tutorials/javascript-ajax/create-a-twitter-like-load-more-widget/</a></p>
<p>I&#8217;ve tried MooTools version and worked fairly well (For IE, you need to remove the last comma in line 133 of mootools-version.php).  Very easy to customize and the effect is great!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectpartners.com/2009/10/20/twitter-like-load-more-button/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.objectpartners.com/2009/10/20/twitter-like-load-more-button/</feedburner:origLink></item>
		<item>
		<title>Delivering Business Value Through Polyglot Systems (part 4 / conclusion)</title>
		<link>http://feedproxy.google.com/~r/ObjectPartnersIncBlog/~3/06b-DUjqjbc/</link>
		<comments>http://www.objectpartners.com/2009/09/21/delivering-business-value-through-polyglot-systems-part-4-conclusion/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 14:30:52 +0000</pubDate>
		<dc:creator>Scott Hickey</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[polyglot]]></category>

		<guid isPermaLink="false">http://www.objectpartners.com/?p=1403</guid>
		<description><![CDATA[In my previous three posts, I described my experience with maintenance, refactoring, and installation on a large project that used both Java and Groovy. In this post, I will discuss the &#8220;support nightmare&#8221; raised by Bill Burke in his blog post &#8220;Polyglot programming is the worst idea I ever heard&#8221;. As I illustrate below, adding [...]]]></description>
			<content:encoded><![CDATA[<p>In my previous three posts, I described my experience with maintenance, refactoring, and installation on a large project that used both Java and Groovy. In this post, I will discuss the &#8220;support nightmare&#8221; raised by Bill Burke in his blog post <a href="http://bill.burkecentral.com/2009/07/20/polyglotism-is-the-worst-idea-i-ever-heard/">&#8220;Polyglot programming is the worst idea I ever heard&#8221;</a>. As I illustrate below, adding moving parts of any kind can make support difficult. But this shouldn&#8217;t scare us off from adding another language &#8211; most of us work with multiple languages like Javascript, CSS, SQL and XML already. </p>
<p>Mr. Burke&#8217;s describes the &#8220;support nightmare&#8221; as follows:</p>
<ul><font color="#3e7e9c">A support call comes in for your product or application. It&#8217;s obviously a bug, but where is the problem? Is it your application code? Your JVM? Your Ruby VM? Your Java library? Your Ruby gem?</font></ul>
<p>To paraphrase, adding a language will make it more difficult to track down bugs when support calls are made. Of course, with the decision to add any framework, runtime or library, we add complexity to our applications. In my experience, I think adding another language is no different. Even if I have an all Java stack, that doesn&#8217;t make it right to add any Java library that I want to the application environment. Too many times, I have seen frameworks injected into applications to solve problems that could have been coded by hand in less than fifty lines of Java. In situations like this, the conceptual complexity of learning a new framework doesn&#8217;t make sense. The critical aspect about the decision to add any toolset to an application is that it must be evaluated relative to its benefit.</p>
<p>In reality, we already deal with multiple runtimes when we resolve support calls. If a value doesn&#8217;t display correctly in a typical Java web application, the problem could be in any number of places. It might be a problem with HTML, a JSP tag library, a JavaScript function, a JavaScript library, server side controllers, business logic embedded in a service, a library utilized by these services, messaging to other systems, the ORM library or the database itself. This is why feel strongly that the decision to add anything to a system must be evaluated relative to its benefit. The expertise we utilize when evaluating a library can and should be applied when adding a language as well.</p>
<p>This final point about the &#8220;support nightmare&#8221; provides a nice segue to some concluding thoughts about building polyglot systems. The fact is we already use multiple runtimes and multiple languages. Even simple two-tier desktop systems will typically use SQL (the language), a SQL database runtime and whatever language the application is being built in. The reasons we already do it are so obvious, we rarely debate them. I remember the excitement I had when I was able to embed SQL in my C code instead of using Btrieve, an indexed record manager. Sure, the SQL based RDMS was more complex to install, hid more details under the covers, required a preprocessor for the C code and involved effort to setup and maintain. But the benefits easily out-weighed the effort for the applications I was building. In the same way, adding another language like Groovy or Python may require some effort, but the benefits in terms of a smaller, more expressible code base that directly reflects the problem domain can easily be worth it for the long run. Ultimately, we deliver greater business value to our customers with systems that are easier to comprehend, support, enhance and maintain. I&#8217;ve found that using the right language for the right job can help deliver such systems.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectpartners.com/2009/09/21/delivering-business-value-through-polyglot-systems-part-4-conclusion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.objectpartners.com/2009/09/21/delivering-business-value-through-polyglot-systems-part-4-conclusion/</feedburner:origLink></item>
		<item>
		<title>Relationships Matter</title>
		<link>http://feedproxy.google.com/~r/ObjectPartnersIncBlog/~3/Wl4gZHfCSGw/</link>
		<comments>http://www.objectpartners.com/2009/08/31/relationships-matter/#comments</comments>
		<pubDate>Mon, 31 Aug 2009 14:00:23 +0000</pubDate>
		<dc:creator>Travis Jenniges</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[consulting]]></category>
		<category><![CDATA[people skills]]></category>
		<category><![CDATA[personality]]></category>
		<category><![CDATA[relationships]]></category>

		<guid isPermaLink="false">http://www.objectpartners.com/?p=1373</guid>
		<description><![CDATA[Perhaps Minnesota politician Al Franken&#8217;s character on Saturday Night Live said it best when Stuart Smalley declared &#8220;I&#8217;m good enough, I&#8217;m smart enough, and doggone it, people like me!&#8221;  A good consultant is not just measured by their productivity, but by their professionalism and personality as well.  Building a rapport with decision makers [...]]]></description>
			<content:encoded><![CDATA[<p>Perhaps Minnesota politician Al Franken&#8217;s character on Saturday Night Live said it best when Stuart Smalley declared &#8220;I&#8217;m good enough, I&#8217;m smart enough, and doggone it, people like me!&#8221;  A good consultant is not just measured by their productivity, but by their professionalism and personality as well.  Building a rapport with decision makers at clients is what gets return business, along with the results of course.  Many developers are good enough and smart enough, but to be a good consultant, people should like you too!</p>
<h2>Building relationships</h2>
<p>To be a well rounded consultant, an individual should have the people skills necessary to integrate into all facets of the team he or she is joining.  This is even more important if this consultant is expected to lead the team and/or teach those he or she is working with.  In this context, people skills means more than just being able to look somebody in the eye while talking to them or not curling up into a ball, sucking a thumb when somebody attractive speaks to you.  We need to be, to borrow a phrase from a co-worker, socially capable geeks!  You want to get to know people on a personal level, it isn&#8217;t just business.  Get coffee with clients when you can. Go to lunch with people you are working with or, even better, those you are working FOR.  So much of the consulting business these days is built upon relationships.  When sales critters get wind of a project somewhere, the first order of business is finding somebody on staff who knows the people in charge of that project.  They want to leverage a relationship to first get on the radar and to later pitch their story.  Knowing somebody, not just working for them, is very important.</p>
<h2>Like me + remember me = return business</h2>
<p>Having the personality to be memorable goes a long way in todays market.  When a decision maker decides to enlist the help of a consultant, they will often seek out folks they have worked with before.  If you did great work, but nothing that was exceptional enough to be MEMORABLE work, chances are you will be forgotten.  However, if you had the personality that was memorable and/or forged a relationship with this person, then chances are you will be in the forefront of their mind and get the call.  Being a rock star at the keyboard isn&#8217;t always enough.  Sometimes, the fact that you are a rock star can even go unnoticed if all you do is hide in the corner writing code and reading developer forums while you eat lunch.  In today&#8217;s agile team environments, its very hard for a manager to keep tabs on which of the developers is keeping the project on track.  Finding ways to stand out from the crowd, in a positive light of course, becomes essential to obtaining return business.</p>
<p>In summation, if you call yourself a consultant and can&#8217;t look at your email address book, cell phone contacts or facebook friends and find at least a couple people from each client you have worked at in the past, you probably aren&#8217;t doing your best.  You haven&#8217;t forged those relationships that are of the utmost importance in today&#8217;s business climate.  Unless you write the greatest code in the world (in the eyes of your client, not your own opinion) or solved a monumental problem, you probably aren&#8217;t going to be remembered.  Start getting involved with your client and the people at the client personally, it&#8217;ll pay dividends down the road!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectpartners.com/2009/08/31/relationships-matter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.objectpartners.com/2009/08/31/relationships-matter/</feedburner:origLink></item>
		<item>
		<title>Delivering Business Value Through Polyglot Systems (part 3)</title>
		<link>http://feedproxy.google.com/~r/ObjectPartnersIncBlog/~3/4KGc2neNjTQ/</link>
		<comments>http://www.objectpartners.com/2009/08/26/delivering-business-value-through-polyglot-systems-part-3/#comments</comments>
		<pubDate>Wed, 26 Aug 2009 14:30:30 +0000</pubDate>
		<dc:creator>Scott Hickey</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[polyglot]]></category>

		<guid isPermaLink="false">http://www.objectpartners.com/?p=1378</guid>
		<description><![CDATA[In my previous two posts, I described my experience with maintenance and refactoring on a large project that used both Java and Groovy. In this post, I will discuss the installation concerns raised by Bill Burke in his blog post &#8220;Polyglot programming is the worst idea I ever heard&#8221;.
In describing the &#8220;installation nightmare&#8221;, Burke states:
But [...]]]></description>
			<content:encoded><![CDATA[<p>In my previous two posts, I described my experience with maintenance and refactoring on a large project that used both Java and Groovy. In this post, I will discuss the installation concerns raised by Bill Burke in his blog post <u><a href="http://bill.burkecentral.com/2009/07/20/polyglotism-is-the-worst-idea-i-ever-heard/">&#8220;Polyglot programming is the worst idea I ever heard&#8221;</a>.</u></p>
<p>In describing the &#8220;installation nightmare&#8221;, Burke states:</p>
<ul><font color="#3e7e9c">But you still need to package and install all the appropriate Java libraries, Ruby gems, and Python libraries on the appropriate places of your user’s machine. You also need to hope that all the desparate environments don’t conflict with anything the user has already installed on his machine. And that’s just with languages running in the JVM.</font></ul>
<p>These are valid concerns, but I don&#8217;t think they are exclusive to polyglot programming.</p>
<p>The problems of developing code that &#8220;works on my machine&#8221; but doesn&#8217;t work anywhere else are well documented. In my opinion, the first place to start with any project is a one-step build that provides for automated testing plus some form of continuous integration. This isn&#8217;t a particularly original idea these days. In our project, we used Ant to implement a one-step build using a clean checkout from version control. It took effort to get this working, but the effort involved would have been required whether Groovy was involved or not. In my experience, migrating from desktop Windows to Linux and then to AIX became a non-event once I had a one-step build in place.</p>
<p>In response to my previous blog posts on this topic, it has been pointed out that Groovy might be a special case. This is true to some degree in that Groovy was designed from the beginning for easy integration with Java. However, I think the concern about conflicts among libraries on different platforms is valid with or without Groovy. I&#8217;ve experienced first hand the unexpected differences in string truncation among IBM&#8217;s DB2 drivers running on different platforms. On Java projects, there is always a concern about a conflict with Antlr or ASM when using Hibernate and some other library that uses byte code generation. Adding Groovy is no different than adding any other library or framework to a project. There are always risks. Fortunately, one step builds and continuously integrating on all of your project platforms are tried and true strategies for mitigating this risk.</p>
<p>Finally, my thoughts with regards to non-JVM languages are different than those expressed by Mr. Burke:</p>
<ul><font color="#3e7e9c">Imagine if you used vanilla Ruby, Python and Java all as separate silos!</font></ul>
<p>I would encourage you to take your imagination out of the decision making process and base it instead on facts by testing things for yourself. For example, with Python, you might find that not only is it already installed on your test and production platforms, but your required libraries might be there as well. It also might be that installing the required libraries is trivial. Of course, it is possible that it is not trivial. The important point is to try it out and then evaluate the cost/benefit to your particular project. If the benefit is replacing 10,000 lines of the most complicated part of your project with 2,000 lines of code that is more readable and easier to &#8220;reason about&#8221;, then even the extra effort of engaging your infrastructure team to install a required Python library might be worth. Remember, the costs don&#8217;t exist in isolation but in relation to the benefit of adding another of language. The importance of this cannot be overstated.</p>
<p>At the end of the day, the business doesn&#8217;t exist for IT&#8217;s benefit and comfort. It is our job as developers to deliver systems that represent a good value to those making the investment. Where appropriate, we shouldn&#8217;t be afraid to utilize more than one language if it adds value to the project and take advantage of techniques like one-step builds and continuous integration to mitigate the risks.</p>
<p>In my next post, I&#8217;ll address the &#8220;support nightmare&#8221;. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectpartners.com/2009/08/26/delivering-business-value-through-polyglot-systems-part-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.objectpartners.com/2009/08/26/delivering-business-value-through-polyglot-systems-part-3/</feedburner:origLink></item>
		<item>
		<title>Floating DIV’s are tricky</title>
		<link>http://feedproxy.google.com/~r/ObjectPartnersIncBlog/~3/T263gh5_BlA/</link>
		<comments>http://www.objectpartners.com/2009/08/24/floating-divs-are-tricky/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 18:12:59 +0000</pubDate>
		<dc:creator>Hiromi Suenaga</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[div]]></category>
		<category><![CDATA[float]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[layout]]></category>
		<category><![CDATA[style]]></category>
		<category><![CDATA[web design]]></category>

		<guid isPermaLink="false">http://www.objectpartners.com/?p=1274</guid>
		<description><![CDATA[A page layout using DIV&#8217;s are much more flexible than a table layout.  However, I often went back to using tables because it seemed more stable across different browsers.  After spending some time researching how to use DIV&#8217;s effectively, I came up with a list of basics I wish I&#8217;ve known before.
1.  [...]]]></description>
			<content:encoded><![CDATA[<p>A page layout using DIV&#8217;s are much more flexible than a table layout.  However, I often went back to using tables because it seemed more stable across different browsers.  After spending some time researching how to use DIV&#8217;s effectively, I came up with a list of basics I wish I&#8217;ve known before.</p>
<p>1.  Is a container DIV not stretching accordingly to the size of content DIV&#8217;s?</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;container_div&quot;</span> <span style="color: #000066;">style</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;width: 500px;&quot;</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;left_column&quot;</span> <span style="color: #000066;">style</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;float: left; width: 200px&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;right_column&quot;</span> <span style="color: #000066;">style</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;float: left; width: 200px&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">style</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;clear: both;&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></pre></td></tr></table></div>

<p>The last DIV will make sure that container_div will stretch accordingly to the size of left_column and right_column.</p>
<p>2. IE 6 3px gap<br />
When I set the left_column and right_column&#8217;s width to 250px, it looked as though IE6 is completely ignoring the fact that these DIV&#8217;s are floating.  It turned out, IE 6 has a gap of width 3px and the contents of the right_column gets pushed underneath the left_column.<br />
<a href=" http://www.positioniseverything.net/explorer/floatIndent.html"><br />
http://www.positioniseverything.net/explorer/floatIndent.html</a></p>
<p>3. Peek-A-Boo bug in IE6<br />
Now all the DIV&#8217;s are positioned where I want them.  Surprise!  It seems as though the contents of the DIV is hiding behind the background image in IE 6.  You can sort of see it when you mouse over and try highlight it.  Setting z-index won&#8217;t do the trick because there is no z-indexing in IE6.  But do not worry.  Once again, http://www.positioniseverything.net came to a rescue.  </p>
<p><a href="http://www.positioniseverything.net/explorer/peekaboo.html">http://www.positioniseverything.net/explorer/peekaboo.html</a></p>
<p>His second solution of setting &#8216;position: relative;&#8217; usually does the trick for me.</p>
<p>Happy Web Development!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectpartners.com/2009/08/24/floating-divs-are-tricky/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.objectpartners.com/2009/08/24/floating-divs-are-tricky/</feedburner:origLink></item>
		<item>
		<title>Delivering Business Value Through Polyglot Systems (part 2)</title>
		<link>http://feedproxy.google.com/~r/ObjectPartnersIncBlog/~3/hn2cxhcoUPI/</link>
		<comments>http://www.objectpartners.com/2009/08/20/delivering-business-value-through-polyglot-systems-part-2/#comments</comments>
		<pubDate>Thu, 20 Aug 2009 14:32:22 +0000</pubDate>
		<dc:creator>Scott Hickey</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[polyglot]]></category>

		<guid isPermaLink="false">http://www.objectpartners.com/?p=1364</guid>
		<description><![CDATA[In part 1, I described how my experiences using both Groovy and Java delivered business value to the customer by letting the project team work with code that closely reflected the domain. We found the new system didn&#8217;t result in a &#8220;maintenance nightmare&#8221;, but rather made maintenance much easier than if only Java had been [...]]]></description>
			<content:encoded><![CDATA[<p>In part 1, I described how my experiences using both Groovy and Java delivered business value to the customer by letting the project team work with code that closely reflected the domain. We found the new system didn&#8217;t result in a &#8220;maintenance nightmare&#8221;, but rather made maintenance much easier than if only Java had been used.</p>
<p>In this post, I&#8217;ll address the &#8220;refactoring nightmare&#8221; as described by Bill Burke in <u><a href="http://bill.burkecentral.com/2009/07/20/polyglotism-is-the-worst-idea-i-ever-heard/">&#8220;Polyglotism is the worst idea I ever heard&#8221;</a></u>. In that post, he states:</p>
<ul><font color="#3e7e9c">So now your developers can use any one of these language to build out extensions to your Java app. But what happens when you want to refactor one of your re-used Java libraries? OOPS!!!</font></ul>
<p>I&#8217;ve seen these type of statements in blogs dating back to 2004. Let&#8217;s take the hypothetical one step further: What happens when I use Java to build out an extension to my Java app and the library doesn&#8217;t live in the same project or project workspace as my extension? OOPS!!! There are all kinds of hypothetical scenarios that we can imagine to scare ourselves into not using this or that technology. It is more insightful to see how actual project experience can substantiate or remove the fear, uncertainty and doubt.</p>
<p>I do think it is reasonable to expect refactoring could be different with a dynamic language in play. The lack of tooling was one of the major concerns introducing Groovy into our project. Personally, I was used to coding in Eclipse and was very comfortable with the tools it provides. I couldn&#8217;t imagine not working in Eclipse so I expected the worst. However, reality was different from expectations in ways I never anticpated.</p>
<p>When the project started out, I made sure all of my Groovy code always explicitly declared types. I also created interfaces following Java best practices. As a programmer who had been using Java since 1998, I was willing to accept Groovy but I was going to make sure our team followed &#8220;good&#8221; programming practices. I didn&#8217;t want our team to get too carried away with this dynamic stuff. I was quite pleased as the project proceeded quite well for almost nine months without any major refactoring required. Then, the inevitable unforeseen change in requirements appeared that was going to rip its way through most of our existing code. At the time, I only had JEdit, Ant and JUnit at my disposal. This change resulted in my spending a long, exhausting weekend refactoring the code. Luckily, our team had almost 100% code coverage between our unit tests and integration tests. Without those tests, I&#8217;m sure it would have taken weeks to make sure the new changes were correct.</p>
<p>The insight gained from this long refactoring weekend was completely unexpected. If I had not coded to interfaces and had not included types on all the method signatures, the coding changes would have been minimal. Our team did a really good job of writing lots of small methods that operated on a few properties at a time. It became obvious that the successful execution of these methods didn&#8217;t depend on the objects containing the properties.</p>
<p>Consider the following example: A method might look up a rate adjustment in an insurance rate table based on the gender and age of the insured. The only things that mattered were the the gender, the age and the lookup table. It didn&#8217;t really matter if age and gender were part of a Person object, an InsuredPerson object or a hash map. With Groovy and duck-typing, as long the object passed into the method had the properties &#8220;age&#8221; and &#8220;gender&#8221;, the method could do its job.</p>
<p>I kept my eye on this going forward and realized that as objects with properties flowed through the system, it didn&#8217;t really matter what the objects were. As long as the objects passed into the business calculations had the expected properties, we got the behavior we expected from the system. Thus, my experience for our system over the next two years was that we had an easy time of refactoring when we avoided specifying types in our system. Never again did I waste a whole weekend trying to refactor our system to accommodate a change in our object model.</p>
<p>I have given presentations about this project many times during the last two and half years and this concept is always the hardest thing for the audience to comprehend. I don&#8217;t think its something that a person can craft an argument for and expect to have everyone nod in an agreement. There are some things that just have be experienced to be understood. I am certainly willing to grant that I may be the lucky recipient of the perfect problem domain, programming languages, and programming team for this to happen. However, I have had similar experiences doing other, smaller projects in Groovy and Java.</p>
<p>In summary, on a large polyglot project using Groovy and Java, I didn&#8217;t experience a &#8220;refactoring nightmare&#8221;. I found that within a given coarse-grained component, if I (a) removed all types, (b) only used interfaces sparingly, and (c) had a dependable test suite, the time spent refactoring became a non-issue for my project. How does this relate to delivering business value? Time spent refactoring is time spent focusing on technical issues, not business issues. In our regular meetings with our business experts and project manager, the team stayed focused on working through the business logic and not getting sidetracked on technical issues that don&#8217;t deliver business value.</p>
<p>In the next segment, I will focus on my experiences as they relate to the &#8220;installation nightmare&#8221;. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectpartners.com/2009/08/20/delivering-business-value-through-polyglot-systems-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.objectpartners.com/2009/08/20/delivering-business-value-through-polyglot-systems-part-2/</feedburner:origLink></item>
		<item>
		<title>Defining the Role of the Agile Quality Analyst</title>
		<link>http://feedproxy.google.com/~r/ObjectPartnersIncBlog/~3/cGqxmgw3qEA/</link>
		<comments>http://www.objectpartners.com/2009/08/17/defining-the-role-of-the-agile-quality-analyst/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 14:39:42 +0000</pubDate>
		<dc:creator>Joel Crabb</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[methodology]]></category>
		<category><![CDATA[qa]]></category>
		<category><![CDATA[quality analyst]]></category>
		<category><![CDATA[quality assurance]]></category>
		<category><![CDATA[requirements]]></category>

		<guid isPermaLink="false">http://www.objectpartners.com/?p=1240</guid>
		<description><![CDATA[The third installment of the agile roles series looks at differences in the work of the Quality Analyst in an Agile environment.
The Quality Analyst (QA) role in an Agile environment has significant importance.  In Agile, the QA is part of the development team and included from the start of the project.  QA is expected to [...]]]></description>
			<content:encoded><![CDATA[<p>The third installment of the agile roles series looks at differences in the work of the Quality Analyst in an Agile environment.</p>
<p>The Quality Analyst (QA) role in an Agile environment has significant importance.  In Agile, the QA is part of the development team and included from the start of the project.  QA is expected to be as up-to-date on requirements and system state as any developer.  QA is also continuously reviewing completed tasks and stories to near real-time feedback.  If there is one concept in Agile it is fast and continuous feedback on all fronts, QA is essential for this to become reality.</p>
<p>When running a mixed Agile/Waterfall development environment it can be difficult to engage the QA resources at the correct moment.  Generally QA is accustomed to having some large period of time, say six weeks, at the end of development where they test the entire system.  The argument for this type of testing is that at this point the code is “locked down” and thus they can test the system in peace (not pieces) without worrying about pesky developers changing things on them.  While this is a fine notion, it rarely happens and development often runs over the QA cycle.  Or, more importantly, QA finds issues that simply must be fixed.  In standard QA parlance, the QA team should start their testing from scratch after the changes are made to the code.</p>
<h2>Agile QA</h2>
<p>Agile has the idea of production ready functionality at the end of every iteration.  To do that, QA must be involved at the iteration level and be testing functionality as it develops.  If done correctly, at the end of the iteration the stories and components are ready to deploy to production.  Thus, unless major changes occur, these items only need regression testing from this point forward.</p>
<h2>Embedded QA</h2>
<p>Since QA is part of the development team, they are often co-located with the development team as well.  This gives the QA person a significant advantage, they are present when requirements changes are taking place and can express their opinions in real-time rather than after the fact.  The QA person can also help refine requirements by providing the customer’s view of the application.</p>
<h2>Automated Testing</h2>
<p>Once components are production ready, automated test scripts are created to compile a full suite of regression tests.  These automated tests combined with the developers Unit and Integration tests help ensure that any changes made during the current and future iterations do not adversely affect the previously tested code.</p>
<h2>Deployment to Production</h2>
<p>As with any project, the final push to production is often a hectic and hurried endeavor.  QA is usually under pressure to certify that the application works.  While Agile projects are sometimes (but hopefully not) just as frenzied, the existence of thoroughly tested components, automated QA test and development unit tests help ease the burden on the QA team.  While a full system test is still advisable before deploying to production, since QA has been involved from the beginning and is aware of all requirements modifications that have occurred throughout the life of the project, this task is not as onerous as in non-Agile environments.  There is not a lot of back and forth between QA, development and BAs about requirements changes that were not adequately documented.</p>
<p>Often times the true QA cycle, where code is “frozen”, can be cut down to one to two weeks as the QA team feels very comfortable with where the application is at when the cycle begins.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectpartners.com/2009/08/17/defining-the-role-of-the-agile-quality-analyst/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.objectpartners.com/2009/08/17/defining-the-role-of-the-agile-quality-analyst/</feedburner:origLink></item>
		<item>
		<title>Delivering Business Value Through Polyglot Systems (part 1)</title>
		<link>http://feedproxy.google.com/~r/ObjectPartnersIncBlog/~3/CSCsMzSTVK0/</link>
		<comments>http://www.objectpartners.com/2009/08/10/delivering-business-value-through-ployglot-systems-part-1/#comments</comments>
		<pubDate>Mon, 10 Aug 2009 14:29:03 +0000</pubDate>
		<dc:creator>Scott Hickey</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[ployglot]]></category>

		<guid isPermaLink="false">http://www.objectpartners.com/?p=1300</guid>
		<description><![CDATA[My answer to Peter Ledbrooks&#8217;s blog post &#8220;Are polyglot systems a good idea?&#8221; is &#8220;Yes!&#8221;.
He wrote his post after reading &#8220;Polyglotism is the worst idea I ever heard&#8220; by Bill Burke. I don&#8217;t know Bill Burke personally but the post has a troll-like feel. However, beyond the rhetoric there are concerns that I see raised [...]]]></description>
			<content:encoded><![CDATA[<p>My answer to Peter Ledbrooks&#8217;s blog post <u><a href="http://www.cacoethes.co.uk/blog/software/are-polyglot-systems-a-good-idea">&#8220;Are polyglot systems a good idea?&#8221;</a></u> is &#8220;Yes!&#8221;.</p>
<p>He wrote his post after reading <u><a href="http://bill.burkecentral.com/2009/07/20/polyglotism-is-the-worst-idea-i-ever-heard/">&#8220;Polyglotism is the worst idea I ever heard</a>&#8220;</u> by Bill Burke. I don&#8217;t know Bill Burke personally but the post has a troll-like feel. However, beyond the rhetoric there are concerns that I see raised over and over again. These concerns are nothing new. Almost three years ago, they were the inspiration for developing my presentation &#8220;Real World Groovy&#8221;. In that presentation, I raise concerns about introducing Groovy into a Java project and I address each concern by relating my own <em>experience</em> having worked with Java and Groovy on paid projects.</p>
<p>Burke describes four &#8220;nightmares&#8221; in his post. These nightmares are based on the assumption that introducing another programming language into a project</p>
<ul><font color="#3e7e9c">&#8230;..is just a big excuse so the developer can learn and play with a new language, or for a language zealot/missionary to figure out a way to weasel in his pet language into a company. Plus, you&#8217;d probably end up being average or good at many languages but a master of none.</p></blockquote>
<p></font></ul>
<p>Personally, I never had trouble sleeping when using Groovy and Java on the same project. In this series of blog posts, I&#8217;ll examine these nightmares one at time.</p>
<p>The &#8220;Maintenance Nightmare&#8221; concerns staffing and training. He describes the <em>hypothetical</em> situation that after the polyglot programmer has left the team,</p>
<ul><font color="#3e7e9c">&#8230;your group is a bunch of Java developers. For any bug that needs to be fixed, these developers need to be retrained in Ruby, a new Ruby developer needs to be hired, and/or a Ruby consultant/contractor needs to be brought it. Multiply this by each language you’ve introduced to your project.</font></ul>
<p><strong><em>Hypothetically</strong></em>, this group of Java developers won&#8217;t be able to read and update the code written in another language without training. </p>
<p><strong><em>My experience</strong></em> is the exact opposite. The code written in Groovy was readable by the other developers on my team. No formal training was provided. The developers on my team were good, but they certainly weren&#8217;t language zealots. One had about 8 years of DB2 &#038; Cobol with less than one year of Java experience. Another developer had 10+ years in VB and various SQL databases, as well as some Java. The subject matter experts were insurance actuaries with programming experience in PL-SQL and Foxpro. On our project, all of these people were able to write and maintain the Groovy code <em>without formal training.</em></p>
<p>How is this possible? Groovy wasn&#8217;t added to the project because of some technical itch that needed scratching. The process of choosing an additional language involved taking a non-trivial piece of functionality and coding it in several languages, including Java. Each version was reviewed by those who would be developing and maintaining the new system. At that point in time, no one on the project had any experience with Groovy. If anything, there was prejudice against Groovy because of the uncertainty. Groovy was selected because it allowed us to easily express the algorithms and business logic in a way that reflected the business domain. The Groovy code was both concise and readable, with a very high signal-to-noise ratio.</p>
<p>Circling back to the maintenance concern, <strong><em>my experience</strong></em> has been that Groovy hasn&#8217;t made maintenance harder. In fact, it has made maintenance easier. Even with significant time passing between authoring and maintenance, the Groovy code has been easy to comprehend because it reflects the business domain. I try to write my Java code this way as well. However, Groovy doesn&#8217;t have a lot of ceremony around it, so it is accessible for developers with experience in other languages. My team did not struggle to decipher what was going on in a given piece of code because it was written in Groovy.</p>
<p>It is <strong><em>my experience</strong></em> that bugs can be resolved in minutes or hours that would have otherwise taken hours and days. The problems were solved quickly because those with domain expertise &#8211; my client&#8217;s developers and subject matter experts &#8211; could see at a glance what was wrong in the code. Note that none of this required them to be masters of Groovy. I have heard similar stories from others who had seen performance improvements rewriting C modules in Lisp or Smalltalk. The performance gains came because it was easier to implement logical efficiencies that just weren&#8217;t practical in C.</p>
<p>Based on what I&#8217;ve seen over the last 20+ years, technology issues are not what doom projects. I can&#8217;t tell you how many times I&#8217;ve heard developers say, &#8220;If the client could just decide what they want, I could build it. I just need to know what to build.&#8221; The hard part is getting systems to do what our client&#8217;s intend them to do. In order to bring a system into production, the team must be able to reason easily and quickly through the code to fix business logic errors.</p>
<p>In summary, the readability and expressiveness of languages like Groovy make maintenance of polyglot systems easier. There is less code to write and maintain and it is more readable. The benefit to less code isn&#8217;t in less effort typing at the keyboard. Rather, it is the ability to get one&#8217;s head around the various parts of the system. In addition, this enables a broader group of people with business expertise to be able to understand what the program is doing. All of this helps avoid creating <a href="http://www.laputan.org/mud/">a big ball of mud</a>. Keeping the code easy to read and understand is the key to avoiding the &#8220;maintenance nightmare&#8221;.</p>
<p>In the next post, I&#8217;ll address the &#8220;Refactoring Nightmare&#8221;. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectpartners.com/2009/08/10/delivering-business-value-through-ployglot-systems-part-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.objectpartners.com/2009/08/10/delivering-business-value-through-ployglot-systems-part-1/</feedburner:origLink></item>
	</channel>
</rss>
