<?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-2976711854892236281</id><updated>2012-02-07T21:34:31.672+02:00</updated><category term='Personal'/><category term='rules'/><category term='Big-O'/><category term='JPA'/><category term='XSD'/><category term='Cargo'/><category term='Joda Time'/><category term='Cache'/><category term='ESB'/><category term='Review'/><category term='Code Snippet'/><category term='Hibernate'/><category term='Development Process'/><category term='Security'/><category term='Apple'/><category term='JaxB'/><category term='Testing'/><category term='Drools'/><category term='JNDI'/><category term='Git'/><category term='Hadoop'/><category term='Objective-C'/><category term='SpEL'/><category term='Hudson'/><category term='JMS'/><category term='Spring'/><category term='iOS'/><category term='JUnit'/><category term='Guice'/><category term='cocos2d'/><category term='JBoss'/><category term='General Info'/><category term='Open GL'/><category term='XML'/><category term='BRMS'/><category term='Java'/><category term='NetBeans'/><category term='Game Development'/><category term='XCode'/><category term='Web service'/><category term='LDAP'/><category term='Ehcache'/><category term='Hazelcast'/><category term='C#'/><category term='Tip'/><category term='GlassfishESB'/><category term='Maven'/><category term='Eclipse'/><category term='Weblogic'/><category term='Patterns'/><category term='Glassfish'/><category term='Solr'/><title type='text'>Zen in the art of IT</title><subtitle type='html'>Know more...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.briandupreez.net/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>75</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-6905317987888621310</id><published>2012-01-29T20:18:00.000+02:00</published><updated>2012-01-30T10:02:19.069+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web service'/><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='LDAP'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='JaxB'/><title type='text'>Spring 3, Spring Web Services 2 &amp; LDAP Security.</title><content type='html'>This year started on a good note, another one of those "the deadline won't change" / "skip all the red tape" / &lt;a href="http://www.briandupreez.net/2011/02/surviving-wild-west-development-process.html"&gt;"Wild West"&lt;/a&gt; type of projects in which I got to figure out and implement some functionality using some relatively new libraries and tech for a change, well Spring 3 ain't new but in the  Java 5, weblogic 10(.01), Spring 2.5.6 slow corporate kind of world it is all relative.&lt;br /&gt;Due to general time constraints I am not including too much "fluff" in this post, just the nitty gritty of creating and securing a Spring 3 , Spring WS 2 web service using multiple XSDs and LDAP security.&lt;br /&gt;&lt;b&gt;&lt;u&gt;The Code:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Service Endpoint: ExampleServiceEndpoint&lt;/b&gt;&lt;br /&gt;This is the class that will be exposed as web service using the configuration later in the post. &lt;script class="brush: java" type="syntaxhighlighter"&gt;package javaitzen.spring.ws;import org.springframework.ws.server.endpoint.annotation.Endpoint;import org.springframework.ws.server.endpoint.annotation.PayloadRoot;import org.springframework.ws.server.endpoint.annotation.RequestPayload;import org.springframework.ws.server.endpoint.annotation.ResponsePayload;import javax.annotation.Resource;@Endpointpublic class ExampleServiceEndpoint {    private static final String NAMESPACE_URI = "http://www.briandupreez.net";    /**     * Autowire a POJO to handle the business logic    @Resource(name = "businessComponent")    private ComponentInterface businessComponent;   */    public ExampleServiceEndpoint() {        System.out.println("&gt;&gt;  javaitzen.spring.ws.ExampleServiceEndpoint loaded.");    }    @PayloadRoot(localPart = "ProcessExample1Request", namespace = NAMESPACE_URI + "/example1")    @ResponsePayload    public Example1Response processExample1Request(@RequestPayload final Example1 request) {        System.out.println("&gt;&gt; process example request1 ran.");        return new Example1Response();    }    @PayloadRoot(localPart = "ProcessExample2Request", namespace = NAMESPACE_URI + "/example2")    @ResponsePayload    public Example2Response processExample2Request(@RequestPayload final Example2 request) {        System.out.println("&gt;&gt; process example request2 ran.");        return new Example2Response();    }}&lt;/script&gt;&lt;b&gt;The Code: CustomValidationCallbackHandler&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This was my bit of custom code I wrote to extend the AbstactCallbackHandler allowing us to use LDAP.As per the comments in the CallbackHandler below, it's probably a good idea to have a cache manager, something like Hazelcast or Ehcache to cache authenticated users, depending on security / performance considerations. &lt;br/&gt;The Digest Validator below can just be used directly from the Sun library, I was just wanted to see how it worked. &lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;package javaitzen.spring.ws;import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;import com.sun.xml.wss.impl.callback.PasswordValidationCallback;import com.sun.xml.wss.impl.misc.Base64;import org.springframework.beans.factory.InitializingBean;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;import org.springframework.security.core.Authentication;import org.springframework.util.Assert;import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;import javax.security.auth.callback.Callback;import javax.security.auth.callback.UnsupportedCallbackException;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.util.Properties;public class CustomValidationCallbackHandler extends AbstractCallbackHandler implements InitializingBean {    private Properties users = new Properties();    private AuthenticationManager ldapAuthenticationManager;    @Override    protected void handleInternal(final Callback callback) throws IOException, UnsupportedCallbackException {        if (callback instanceof PasswordValidationCallback) {            final PasswordValidationCallback passwordCallback = (PasswordValidationCallback) callback;            if (passwordCallback.getRequest() instanceof PasswordValidationCallback.DigestPasswordRequest) {                final PasswordValidationCallback.DigestPasswordRequest digestPasswordRequest =                        (PasswordValidationCallback.DigestPasswordRequest) passwordCallback.getRequest();                final String password = users                        .getProperty(digestPasswordRequest                                .getUsername());                digestPasswordRequest.setPassword(password);                passwordCallback                        .setValidator(new CustomDigestPasswordValidator());            }            if (passwordCallback.getRequest() instanceof PasswordValidationCallback.PlainTextPasswordRequest) {                passwordCallback                        .setValidator(new LDAPPlainTextPasswordValidator());            }        } else {            throw new UnsupportedCallbackException(callback);        }    }    /**     * Digest Validator.     * This code is directly from the sun class, I was just curious how it worked.     */    private class CustomDigestPasswordValidator implements PasswordValidationCallback.PasswordValidator {        public boolean validate(final PasswordValidationCallback.Request request) throws PasswordValidationCallback.PasswordValidationException {            final PasswordValidationCallback.DigestPasswordRequest req = (PasswordValidationCallback.DigestPasswordRequest) request;            final String passwd = req.getPassword();            final String nonce = req.getNonce();            final String created = req.getCreated();            final String passwordDigest = req.getDigest();            final String username = req.getUsername();            if (null == passwd)                return false;            byte[] decodedNonce = null;            if (null != nonce) {                try {                    decodedNonce = Base64.decode(nonce);                } catch (final Base64DecodingException bde) {                    throw new PasswordValidationCallback.PasswordValidationException(bde);                }            }            String utf8String = "";            if (created != null) {                utf8String += created;            }            utf8String += passwd;            final byte[] utf8Bytes;            try {                utf8Bytes = utf8String.getBytes("utf-8");            } catch (final UnsupportedEncodingException uee) {                throw new PasswordValidationCallback.PasswordValidationException(uee);            }            final byte[] bytesToHash;            if (decodedNonce != null) {                bytesToHash = new byte[utf8Bytes.length + decodedNonce.length];                for (int i = 0; i &lt; decodedNonce.length; i++)                    bytesToHash[i] = decodedNonce[i];                for (int i = decodedNonce.length;                     i &lt; utf8Bytes.length + decodedNonce.length;                     i++)                    bytesToHash[i] = utf8Bytes[i - decodedNonce.length];            } else {                bytesToHash = utf8Bytes;            }            final byte[] hash;            try {                final MessageDigest sha = MessageDigest.getInstance("SHA-1");                hash = sha.digest(bytesToHash);            } catch (final Exception e) {                throw new PasswordValidationCallback.PasswordValidationException(                        "Password Digest could not be created" + e);            }            return (passwordDigest.equals(Base64.encode(hash)));        }    }    /**     * LDAP Plain Text validator.     */    private class LDAPPlainTextPasswordValidator implements            PasswordValidationCallback.PasswordValidator {        /**         * Validate the callback against the injected LDAP server.         * Probably a good idea to have a cache manager - ehcache /  hazelcast injected to cache authenticated users.         *         * @param request the callback request         * @return true if login successful         * @throws PasswordValidationCallback.PasswordValidationException         *         */        public boolean validate(final PasswordValidationCallback.Request request) throws PasswordValidationCallback.PasswordValidationException {            final PasswordValidationCallback.PlainTextPasswordRequest plainTextPasswordRequest =                    (PasswordValidationCallback.PlainTextPasswordRequest) request;            final String username = plainTextPasswordRequest.getUsername();            final Authentication authentication;            final Authentication userPassAuth = new UsernamePasswordAuthenticationToken(username, plainTextPasswordRequest.getPassword());            authentication = ldapAuthenticationManager.authenticate(userPassAuth);            return authentication.isAuthenticated();        }    }    /**     * Assert users.     *     * @throws Exception error     */    public void afterPropertiesSet() throws Exception {        Assert.notNull(users, "Users is required.");        Assert.notNull(this.ldapAuthenticationManager, "A LDAP Authentication manager is required.");    }    /**     * Sets the users to validate against. Property names are usernames, property values are passwords.     *     * @param users the users     */    public void setUsers(final Properties users) {        this.users = users;    }    /**     * The the authentication manager.     *     * @param ldapAuthenticationManager the provider     */    public void setLdapAuthenticationManager(final AuthenticationManager ldapAuthenticationManager) {        this.ldapAuthenticationManager = ldapAuthenticationManager;    }}&lt;/script&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;The service config:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;The configuration for the Endpoint, CallbackHandler and the LDAP Authentication manager.&lt;br /&gt;&lt;b&gt;The Application Context - Server Side:&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: xml" type="syntaxhighlighter"&gt;&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns="http://www.springframework.org/schema/beans"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:sws="http://www.springframework.org/schema/web-services"              xmlns:s="http://www.springframework.org/schema/security"       xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd       http://www.springframework.org/schema/web-services       http://www.springframework.org/schema/web-services/web-services-2.0.xsd       http://www.springframework.org/schema/context       http://www.springframework.org/schema/context/spring-context.xsd              http://www.springframework.org/schema/security       http://www.springframework.org/schema/security/spring-security-3.0.xsd"&gt;    &lt;sws:annotation-driven/&gt;    &lt;context:component-scan base-package="javaitzen.spring.ws"/&gt;    &lt;sws:dynamic-wsdl id="exampleService"                      portTypeName="javaitzen.spring.ws.ExampleServiceEndpoint"                      locationUri="/exampleService/"                      targetNamespace="http://www.briandupreez.net/exampleService"&gt;        &lt;sws:xsd location="classpath:/xsd/Example1Request.xsd"/&gt;        &lt;sws:xsd location="classpath:/xsd/Example1Response.xsd"/&gt;        &lt;sws:xsd location="classpath:/xsd/Example2Request.xsd"/&gt;        &lt;sws:xsd location="classpath:/xsd/Example2Response.xsd"/&gt;    &lt;/sws:dynamic-wsdl&gt;    &lt;sws:interceptors&gt;        &lt;bean id="validatingInterceptor"              class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor"&gt;            &lt;property name="schema" value="classpath:/xsd/Example1Request.xsd"/&gt;            &lt;property name="validateRequest" value="true"/&gt;            &lt;property name="validateResponse" value="true"/&gt;        &lt;/bean&gt;        &lt;bean id="loggingInterceptor"              class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"/&gt;                  &lt;bean class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor"&gt;            &lt;property name="policyConfiguration" value="/WEB-INF/securityPolicy.xml"/&gt;            &lt;property name="callbackHandlers"&gt;                &lt;list&gt;                    &lt;ref bean="callbackHandler"/&gt;                &lt;/list&gt;            &lt;/property&gt;        &lt;/bean&gt;            &lt;/sws:interceptors&gt;    &lt;bean id="callbackHandler" class="javaitzen.spring.ws.CustomValidationCallbackHandler"&gt;        &lt;property name="ldapAuthenticationManager" ref="authManager" /&gt;    &lt;/bean&gt;    &lt;s:authentication-manager alias="authManager"&gt;        &lt;s:ldap-authentication-provider                user-search-filter="(uid={0})"                user-search-base="ou=users"                group-role-attribute="cn"                role-prefix="ROLE_"&gt;        &lt;/s:ldap-authentication-provider&gt;    &lt;/s:authentication-manager&gt;   &lt;!-- Example... (inmemory apache ldap service) --&gt;    &lt;s:ldap-server id="contextSource" root="o=example" ldif="classpath:example.ldif"/&gt;    &lt;!--    If you want to connect to a real LDAP server it would look more like:    &lt;s:ldap-server  id="contextSource" url="ldap://localhost:7001/o=example" manager-dn="uid=admin,ou=system" manager-password="secret"&gt;    &lt;/s:ldap-server&gt;--&gt;    &lt;bean id="marshallingPayloadMethodProcessor"          class="org.springframework.ws.server.endpoint.adapter.method.MarshallingPayloadMethodProcessor"&gt;        &lt;constructor-arg ref="serviceMarshaller"/&gt;        &lt;constructor-arg ref="serviceMarshaller"/&gt;    &lt;/bean&gt;    &lt;bean id="defaultMethodEndpointAdapter"          class="org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter"&gt;        &lt;property name="methodArgumentResolvers"&gt;            &lt;list&gt;                &lt;ref bean="marshallingPayloadMethodProcessor"/&gt;            &lt;/list&gt;        &lt;/property&gt;        &lt;property name="methodReturnValueHandlers"&gt;            &lt;list&gt;                &lt;ref bean="marshallingPayloadMethodProcessor"/&gt;            &lt;/list&gt;        &lt;/property&gt;    &lt;/bean&gt;    &lt;bean id="serviceMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"&gt;  &lt;property name="classesToBeBound"&gt;   &lt;list&gt;    &lt;value&gt;javaitzen.spring.ws.Example1&lt;/value&gt;    &lt;value&gt;javaitzen.spring.ws.Example1Response&lt;/value&gt;    &lt;value&gt;javaitzen.spring.ws.Example2&lt;/value&gt;    &lt;value&gt;javaitzen.spring.ws.Example2Response&lt;/value&gt;   &lt;/list&gt;  &lt;/property&gt;        &lt;property name="marshallerProperties"&gt;            &lt;map&gt;                &lt;entry key="jaxb.formatted.output"&gt;                     &lt;value type="java.lang.Boolean"&gt;true&lt;/value&gt;                &lt;/entry&gt;            &lt;/map&gt;        &lt;/property&gt; &lt;/bean&gt;&lt;/beans&gt;&lt;/script&gt;&lt;b&gt;The Security Context - Server Side:&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: xml" type="syntaxhighlighter"&gt;&lt;xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config"&gt;    &lt;xwss:RequireTimestamp maxClockSkew="60" timestampFreshnessLimit="300"/&gt;    &lt;!-- Expect plain text tokens from the client --&gt;    &lt;xwss:RequireUsernameToken passwordDigestRequired="false" nonceRequired="false"/&gt;    &lt;xwss:Timestamp/&gt;    &lt;!-- server side reply token --&gt;    &lt;xwss:UsernameToken name="server" password="server1" digestPassword="false" useNonce="false"/&gt;&lt;/xwss:SecurityConfiguration&gt;&lt;/script&gt;&lt;br /&gt;&lt;b&gt;The Web XML:&lt;/b&gt;&lt;br /&gt;Nothing really special here, just the Spring WS MessageDispatcherServlet.&lt;script class="brush: xml" type="syntaxhighlighter"&gt;   &lt;servlet&gt;        &lt;servlet-name&gt;spring-ws&lt;/servlet-name&gt;        &lt;servlet-class&gt;org.springframework.ws.transport.http.MessageDispatcherServlet&lt;/servlet-class&gt;     &lt;init-param&gt;        &lt;param-name&gt;transformWsdlLocations&lt;/param-name&gt;        &lt;param-value&gt;true&lt;/param-value&gt;     &lt;/init-param&gt;     &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;   &lt;/servlet&gt;   &lt;servlet-mapping&gt;        &lt;servlet-name&gt;spring-ws&lt;/servlet-name&gt;        &lt;url-pattern&gt;/*&lt;/url-pattern&gt;   &lt;/servlet-mapping&gt;&lt;/script&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;The client config:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;To test or use the service you'll need the following:&lt;br /&gt;&lt;b&gt;The Application Context - Client Side Test:&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: xml" type="syntaxhighlighter"&gt;&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"&gt;    &lt;bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/&gt;    &lt;bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate"&gt;        &lt;constructor-arg ref="messageFactory"/&gt;        &lt;property name="marshaller" ref="serviceMarshaller"/&gt;        &lt;property name="unmarshaller" ref="serviceMarshaller"/&gt;        &lt;property name="defaultUri" value="http://localhost:7001/example/spring-ws/exampleService"/&gt;        &lt;property name="interceptors"&gt;            &lt;list&gt;                &lt;ref local="xwsSecurityInterceptor"/&gt;            &lt;/list&gt;        &lt;/property&gt;    &lt;/bean&gt;    &lt;bean id="xwsSecurityInterceptor"          class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor"&gt;        &lt;property name="policyConfiguration" value="testSecurityPolicy.xml"/&gt;        &lt;property name="callbackHandlers"&gt;            &lt;list&gt;                &lt;ref bean="callbackHandler"/&gt;            &lt;/list&gt;        &lt;/property&gt;    &lt;/bean&gt;    &lt;!--  As a client the username and password generated by the server must match with the client! --&gt;    &lt;!-- a simple callback handler to configure users and passwords with an in-memory Properties object. --&gt;    &lt;bean id="callbackHandler"          class="org.springframework.ws.soap.security.xwss.callback.SimplePasswordValidationCallbackHandler"&gt;        &lt;property name="users"&gt;            &lt;props&gt;             &lt;prop key="server"&gt;server1&lt;/prop&gt;            &lt;/props&gt;        &lt;/property&gt;    &lt;/bean&gt;    &lt;bean id="serviceMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"&gt;  &lt;property name="classesToBeBound"&gt;   &lt;list&gt;    &lt;value&gt;javaitzen.spring.ws.Example1&lt;/value&gt;    &lt;value&gt;javaitzen.spring.ws.Example1Response&lt;/value&gt;    &lt;value&gt;javaitzen.spring.ws.Example2&lt;/value&gt;    &lt;value&gt;javaitzen.spring.ws.Example2Response&lt;/value&gt;   &lt;/list&gt;  &lt;/property&gt;        &lt;property name="marshallerProperties"&gt;            &lt;map&gt;                &lt;entry key="jaxb.formatted.output"&gt;                     &lt;value type="java.lang.Boolean"&gt;true&lt;/value&gt;                &lt;/entry&gt;            &lt;/map&gt;        &lt;/property&gt; &lt;/bean&gt;&lt;/script&gt;&lt;br /&gt;&lt;b&gt;The Security Context - Client Side:&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: xml" type="syntaxhighlighter"&gt;&lt;xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config"&gt;    &lt;xwss:RequireTimestamp maxClockSkew="60" timestampFreshnessLimit="300"/&gt;    &lt;!-- Expect a plain text reply from the server --&gt;    &lt;xwss:RequireUsernameToken passwordDigestRequired="false" nonceRequired="false"/&gt;    &lt;xwss:Timestamp/&gt;    &lt;!-- Client sending to server --&gt;    &lt;xwss:UsernameToken name="example" password="pass" digestPassword="false" useNonce="false"/&gt;&lt;/xwss:SecurityConfiguration&gt;&lt;/script&gt;&lt;br /&gt;As usual with Java there can be a couple little nuances when it comes to jars and versions so below is part of the pom I used.&lt;br /&gt;&lt;b&gt;The Dependencies:&lt;/b&gt;&lt;br /&gt;&lt;script class="brush: xml" type="syntaxhighlighter"&gt;    &lt;properties&gt;        &lt;spring-version&gt;3.0.6.RELEASE&lt;/spring-version&gt;        &lt;spring-ws-version&gt;2.0.2.RELEASE&lt;/spring-ws-version&gt;    &lt;/properties&gt;       &lt;dependencies&gt;        &lt;!-- This was required to use that example         .ldif file instead of a real external LDAP server --&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.apache.directory.server&lt;/groupId&gt;            &lt;artifactId&gt;apacheds-all&lt;/artifactId&gt;            &lt;version&gt;1.5.5&lt;/version&gt;            &lt;type&gt;jar&lt;/type&gt;            &lt;scope&gt;compile&lt;/scope&gt;        &lt;/dependency&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.springframework.ws&lt;/groupId&gt;            &lt;artifactId&gt;spring-ws-core&lt;/artifactId&gt;            &lt;version&gt;${spring-ws-version}&lt;/version&gt;        &lt;/dependency&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.springframework&lt;/groupId&gt;            &lt;artifactId&gt;spring-webmvc&lt;/artifactId&gt;            &lt;version&gt;${spring-version}&lt;/version&gt;        &lt;/dependency&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.springframework&lt;/groupId&gt;            &lt;artifactId&gt;spring-web&lt;/artifactId&gt;            &lt;version&gt;${spring-version}&lt;/version&gt;        &lt;/dependency&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.springframework&lt;/groupId&gt;            &lt;artifactId&gt;spring-context&lt;/artifactId&gt;            &lt;version&gt;${spring-version}&lt;/version&gt;        &lt;/dependency&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.springframework&lt;/groupId&gt;            &lt;artifactId&gt;spring-core&lt;/artifactId&gt;            &lt;version&gt;${spring-version}&lt;/version&gt;        &lt;/dependency&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.springframework&lt;/groupId&gt;            &lt;artifactId&gt;spring-beans&lt;/artifactId&gt;            &lt;version&gt;${spring-version}&lt;/version&gt;        &lt;/dependency&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.springframework&lt;/groupId&gt;            &lt;artifactId&gt;spring-oxm&lt;/artifactId&gt;            &lt;version&gt;${spring-version}&lt;/version&gt;        &lt;/dependency&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.springframework.ws&lt;/groupId&gt;            &lt;artifactId&gt;spring-ws-security&lt;/artifactId&gt;            &lt;version&gt;${spring-ws-version}&lt;/version&gt;        &lt;/dependency&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.springframework.security&lt;/groupId&gt;            &lt;artifactId&gt;spring-security-core&lt;/artifactId&gt;            &lt;version&gt;${spring-version}&lt;/version&gt;        &lt;/dependency&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.springframework.security&lt;/groupId&gt;            &lt;artifactId&gt;spring-security-ldap&lt;/artifactId&gt;            &lt;version&gt;${spring-version}&lt;/version&gt;        &lt;/dependency&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.springframework.ldap&lt;/groupId&gt;            &lt;artifactId&gt;spring-ldap-core&lt;/artifactId&gt;            &lt;version&gt;1.3.0.RELEASE&lt;/version&gt;        &lt;/dependency&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.apache.ws.security&lt;/groupId&gt;            &lt;artifactId&gt;wss4j&lt;/artifactId&gt;            &lt;version&gt;1.5.12&lt;/version&gt;        &lt;/dependency&gt;        &lt;dependency&gt;            &lt;groupId&gt;com.sun.xml.wss&lt;/groupId&gt;            &lt;artifactId&gt;xws-security&lt;/artifactId&gt;            &lt;version&gt;3.0&lt;/version&gt;        &lt;/dependency&gt;        &lt;!-- This is required when using multiple XSDs with the dynamic WSDL --&gt;        &lt;dependency&gt;            &lt;groupId&gt;org.apache.ws.commons.schema&lt;/groupId&gt;            &lt;artifactId&gt;XmlSchema&lt;/artifactId&gt;            &lt;version&gt;1.4.2&lt;/version&gt;        &lt;/dependency&gt;    &lt;/dependencies&gt;&lt;/project&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-6905317987888621310?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/6905317987888621310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2012/01/spring-3-string-web-services-2-ldap.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6905317987888621310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6905317987888621310'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2012/01/spring-3-string-web-services-2-ldap.html' title='Spring 3, Spring Web Services 2 &amp; LDAP Security.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-4551210706789078217</id><published>2012-01-28T07:30:00.000+02:00</published><updated>2012-01-28T07:30:38.393+02:00</updated><title type='text'>Wordballs Release</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Finally,&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="line-height: 14px;"&gt;Wordballs is live!&lt;/span&gt;&lt;span class="Apple-style-span" style="line-height: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span class="Apple-style-span" style="line-height: 14px;"&gt;My latest physics based word game. Please check it out if you have an iOS device, and let your friends know.&lt;/span&gt;&lt;span class="Apple-style-span" style="line-height: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span class="Apple-style-span" style="line-height: 14px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="line-height: 14px;"&gt;It's Free (with ads) and 16mb to download.&lt;/span&gt;&lt;span class="Apple-style-span" style="line-height: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="line-height: 14px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="line-height: 14px;"&gt;Please take a couple seconds to rate it as well, it will be much appreciated&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span class="Apple-style-span" style="line-height: 14px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;This game actually took me some time to do. Crazy deadlines and some nasty hours at work meant for some slow going and some very late nights at times.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I would just like to thank the teams from:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://chipmunk-physics.net/"&gt;Chipmunk Physics&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.cocos2d-iphone.org/"&gt;Cocos 2D&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Without their awesome libraries / code this Wordballs would have been impossible.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://www.wordballs.com/_/rsrc/1325964969714/home/Screenshot%202012.01.07%2017.43.21.png?height=320&amp;amp;width=213" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://www.wordballs.com/_/rsrc/1325964969714/home/Screenshot%202012.01.07%2017.43.21.png?height=320&amp;amp;width=213" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;Free Universal Version - In App Purchase available to remove ads&lt;br /&gt;&lt;a href="http://www.wordballs.com/"&gt;http://www.wordballs.com/&lt;/a&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://itunes.apple.com/us/app/wordballs/id483168068?ls=1&amp;amp;mt=8" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="65" src="http://4.bp.blogspot.com/-FY2pnaZ9KBs/Txrid2MSBkI/AAAAAAAAAX4/nhbL-6P5piw/s200/available_on_the_app_store.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-4551210706789078217?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/4551210706789078217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2012/01/wordballs-release.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4551210706789078217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4551210706789078217'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2012/01/wordballs-release.html' title='Wordballs Release'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-FY2pnaZ9KBs/Txrid2MSBkI/AAAAAAAAAX4/nhbL-6P5piw/s72-c/available_on_the_app_store.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-2216616905459489763</id><published>2011-12-17T08:30:00.000+02:00</published><updated>2011-12-17T08:30:25.945+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cocos2d'/><category scheme='http://www.blogger.com/atom/ns#' term='Game Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><title type='text'>ccColor3B constants.... A whole bunch of them.</title><content type='html'>This is bound to save everyone some time when looking at defining custom colors for cocos2d.Found this list on the cocos2d forums (thanks to a member there called Yeti):&lt;script class="brush: cpp" type="syntaxhighlighter"&gt;//! AliceBlue color (240,248,255)static const ccColor3B ccALICEBLUE={240,248,255};//! AntiqueWhite color (250,235,215)static const ccColor3B ccANTIQUEWHITE={250,235,215};//! Aqua color (0,255,255)static const ccColor3B ccAQUA={0,255,255};//! Aquamarine color (127,255,212)static const ccColor3B ccAQUAMARINE={127,255,212};//! Azure color (240,255,255)static const ccColor3B ccAZURE={240,255,255};//! Beige color (245,245,220)static const ccColor3B ccBEIGE={245,245,220};//! Bisque color (255,228,196)static const ccColor3B ccBISQUE={255,228,196};//! BlanchedAlmond color (255,235,205)static const ccColor3B ccBLANCHEDALMOND={255,235,205};//! BlueViolet color (138,43,226)static const ccColor3B ccBLUEVIOLET={138,43,226};//! Brown color (165,42,42)static const ccColor3B ccBROWN={165,42,42};//! BurlyWood color (222,184,135)static const ccColor3B ccBURLYWOOD={222,184,135};//! CadetBlue color (95,158,160)static const ccColor3B ccCADETBLUE={95,158,160};//! Chartreuse color (127,255,0)static const ccColor3B ccCHARTREUSE={127,255,0};//! Chocolate color (210,105,30)static const ccColor3B ccCHOCOLATE={210,105,30};//! Coral color (255,127,80)static const ccColor3B ccCORAL={255,127,80};//! CornflowerBlue color (100,149,237)static const ccColor3B ccCORNFLOWERBLUE={100,149,237};//! Cornsilk color (255,248,220)static const ccColor3B ccCORNSILK={255,248,220};//! Crimson color (220,20,60)static const ccColor3B ccCRIMSON={220,20,60};//! Cyan color (0,255,255)static const ccColor3B ccCYAN={0,255,255};//! DarkBlue color (0,0,139)static const ccColor3B ccDARKBLUE={0,0,139};//! DarkCyan color (0,139,139)static const ccColor3B ccDARKCYAN={0,139,139};//! DarkGoldenRod color (184,134,11)static const ccColor3B ccDARKGOLDENROD={184,134,11};//! DarkGray color (169,169,169)static const ccColor3B ccDARKGRAY={169,169,169};//! DarkGreen color (0,100,0)static const ccColor3B ccDARKGREEN={0,100,0};//! DarkKhaki color (189,183,107)static const ccColor3B ccDARKKHAKI={189,183,107};//! DarkMagenta color (139,0,139)static const ccColor3B ccDARKMAGENTA={139,0,139};//! DarkOliveGreen color (85,107,47)static const ccColor3B ccDARKOLIVEGREEN={85,107,47};//! Darkorange color (255,140,0)static const ccColor3B ccDARKORANGE={255,140,0};//! DarkOrchid color (153,50,204)static const ccColor3B ccDARKORCHID={153,50,204};//! DarkRed color (139,0,0)static const ccColor3B ccDARKRED={139,0,0};//! DarkSalmon color (233,150,122)static const ccColor3B ccDARKSALMON={233,150,122};//! DarkSeaGreen color (143,188,143)static const ccColor3B ccDARKSEAGREEN={143,188,143};//! DarkSlateBlue color (72,61,139)static const ccColor3B ccDARKSLATEBLUE={72,61,139};//! DarkSlateGray color (47,79,79)static const ccColor3B ccDARKSLATEGRAY={47,79,79};//! DarkTurquoise color (0,206,209)static const ccColor3B ccDARKTURQUOISE={0,206,209};//! DarkViolet color (148,0,211)static const ccColor3B ccDARKVIOLET={148,0,211};//! DeepPink color (255,20,147)static const ccColor3B ccDEEPPINK={255,20,147};//! DeepSkyBlue color (0,191,255)static const ccColor3B ccDEEPSKYBLUE={0,191,255};//! DimGray color (105,105,105)static const ccColor3B ccDIMGRAY={105,105,105};//! DodgerBlue color (30,144,255)static const ccColor3B ccDODGERBLUE={30,144,255};//! FireBrick color (178,34,34)static const ccColor3B ccFIREBRICK={178,34,34};//! FloralWhite color (255,250,240)static const ccColor3B ccFLORALWHITE={255,250,240};//! ForestGreen color (34,139,34)static const ccColor3B ccFORESTGREEN={34,139,34};//! Fuchsia color (255,0,255)static const ccColor3B ccFUCHSIA={255,0,255};//! Gainsboro color (220,220,220)static const ccColor3B ccGAINSBORO={220,220,220};//! GhostWhite color (248,248,255)static const ccColor3B ccGHOSTWHITE={248,248,255};//! Gold color (255,215,0)static const ccColor3B ccGOLD={255,215,0};//! GoldenRod color (218,165,32)static const ccColor3B ccGOLDENROD={218,165,32};//! GreenYellow color (173,255,47)static const ccColor3B ccGREENYELLOW={173,255,47};//! HoneyDew color (240,255,240)static const ccColor3B ccHONEYDEW={240,255,240};//! HotPink color (255,105,180)static const ccColor3B ccHOTPINK={255,105,180};//! IndianRed color (205,92,92)static const ccColor3B ccINDIANRED={205,92,92};//! Indigo color (75,0,130)static const ccColor3B ccINDIGO={75,0,130};//! Ivory color (255,255,240)static const ccColor3B ccIVORY={255,255,240};//! Khaki color (240,230,140)static const ccColor3B ccKHAKI={240,230,140};//! Lavender color (230,230,250)static const ccColor3B ccLAVENDER={230,230,250};//! LavenderBlush color (255,240,245)static const ccColor3B ccLAVENDERBLUSH={255,240,245};//! LawnGreen color (124,252,0)static const ccColor3B ccLAWNGREEN={124,252,0};//! LemonChiffon color (255,250,205)static const ccColor3B ccLEMONCHIFFON={255,250,205};//! LightBlue color (173,216,230)static const ccColor3B ccLIGHTBLUE={173,216,230};//! LightCoral color (240,128,128)static const ccColor3B ccLIGHTCORAL={240,128,128};//! LightCyan color (224,255,255)static const ccColor3B ccLIGHTCYAN={224,255,255};//! LightGoldenRodYellow color (250,250,210)static const ccColor3B ccLIGHTGOLDENRODYELLOW={250,250,210};//! LightGrey color (211,211,211)static const ccColor3B ccLIGHTGREY={211,211,211};//! LightGreen color (144,238,144)static const ccColor3B ccLIGHTGREEN={144,238,144};//! LightPink color (255,182,193)static const ccColor3B ccLIGHTPINK={255,182,193};//! LightSalmon color (255,160,122)static const ccColor3B ccLIGHTSALMON={255,160,122};//! LightSeaGreen color (32,178,170)static const ccColor3B ccLIGHTSEAGREEN={32,178,170};//! LightSkyBlue color (135,206,250)static const ccColor3B ccLIGHTSKYBLUE={135,206,250};//! LightSlateGray color (119,136,153)static const ccColor3B ccLIGHTSLATEGRAY={119,136,153};//! LightSteelBlue color (176,196,222)static const ccColor3B ccLIGHTSTEELBLUE={176,196,222};//! LightYellow color (255,255,224)static const ccColor3B ccLIGHTYELLOW={255,255,224};//! Lime color (0,255,0)static const ccColor3B ccLIME={0,255,0};//! LimeGreen color (50,205,50)static const ccColor3B ccLIMEGREEN={50,205,50};//! Linen color (250,240,230)static const ccColor3B ccLINEN={250,240,230};//! Maroon color (128,0,0)static const ccColor3B ccMAROON={128,0,0};//! MediumAquaMarine color (102,205,170)static const ccColor3B ccMEDIUMAQUAMARINE={102,205,170};//! MediumBlue color (0,0,205)static const ccColor3B ccMEDIUMBLUE={0,0,205};//! MediumOrchid color (186,85,211)static const ccColor3B ccMEDIUMORCHID={186,85,211};//! MediumPurple color (147,112,216)static const ccColor3B ccMEDIUMPURPLE={147,112,216};//! MediumSeaGreen color (60,179,113)static const ccColor3B ccMEDIUMSEAGREEN={60,179,113};//! MediumSlateBlue color (123,104,238)static const ccColor3B ccMEDIUMSLATEBLUE={123,104,238};//! MediumSpringGreen color (0,250,154)static const ccColor3B ccMEDIUMSPRINGGREEN={0,250,154};//! MediumTurquoise color (72,209,204)static const ccColor3B ccMEDIUMTURQUOISE={72,209,204};//! MediumVioletRed color (199,21,133)static const ccColor3B ccMEDIUMVIOLETRED={199,21,133};//! MidnightBlue color (25,25,112)static const ccColor3B ccMIDNIGHTBLUE={25,25,112};//! MintCream color (245,255,250)static const ccColor3B ccMINTCREAM={245,255,250};//! MistyRose color (255,228,225)static const ccColor3B ccMISTYROSE={255,228,225};//! Moccasin color (255,228,181)static const ccColor3B ccMOCCASIN={255,228,181};//! NavajoWhite color (255,222,173)static const ccColor3B ccNAVAJOWHITE={255,222,173};//! Navy color (0,0,128)static const ccColor3B ccNAVY={0,0,128};//! OldLace color (253,245,230)static const ccColor3B ccOLDLACE={253,245,230};//! Olive color (128,128,0)static const ccColor3B ccOLIVE={128,128,0};//! OliveDrab color (107,142,35)static const ccColor3B ccOLIVEDRAB={107,142,35};//! OrangeRed color (255,69,0)static const ccColor3B ccORANGERED={255,69,0};//! Orchid color (218,112,214)static const ccColor3B ccORCHID={218,112,214};//! PaleGoldenRod color (238,232,170)static const ccColor3B ccPALEGOLDENROD={238,232,170};//! PaleGreen color (152,251,152)static const ccColor3B ccPALEGREEN={152,251,152};//! PaleTurquoise color (175,238,238)static const ccColor3B ccPALETURQUOISE={175,238,238};//! PaleVioletRed color (216,112,147)static const ccColor3B ccPALEVIOLETRED={216,112,147};//! PapayaWhip color (255,239,213)static const ccColor3B ccPAPAYAWHIP={255,239,213};//! PeachPuff color (255,218,185)static const ccColor3B ccPEACHPUFF={255,218,185};//! Peru color (205,133,63)static const ccColor3B ccPERU={205,133,63};//! Pink color (255,192,203)static const ccColor3B ccPINK={255,192,203};//! Plum color (221,160,221)static const ccColor3B ccPLUM={221,160,221};//! PowderBlue color (176,224,230)static const ccColor3B ccPOWDERBLUE={176,224,230};//! Purple color (128,0,128)static const ccColor3B ccPURPLE={128,0,128};//! RosyBrown color (188,143,143)static const ccColor3B ccROSYBROWN={188,143,143};//! RoyalBlue color (65,105,225)static const ccColor3B ccROYALBLUE={65,105,225};//! SaddleBrown color (139,69,19)static const ccColor3B ccSADDLEBROWN={139,69,19};//! Salmon color (250,128,114)static const ccColor3B ccSALMON={250,128,114};//! SandyBrown color (244,164,96)static const ccColor3B ccSANDYBROWN={244,164,96};//! SeaGreen color (46,139,87)static const ccColor3B ccSEAGREEN={46,139,87};//! SeaShell color (255,245,238)static const ccColor3B ccSEASHELL={255,245,238};//! Sienna color (160,82,45)static const ccColor3B ccSIENNA={160,82,45};//! Silver color (192,192,192)static const ccColor3B ccSILVER={192,192,192};//! SkyBlue color (135,206,235)static const ccColor3B ccSKYBLUE={135,206,235};//! SlateBlue color (106,90,205)static const ccColor3B ccSLATEBLUE={106,90,205};//! SlateGray color (112,128,144)static const ccColor3B ccSLATEGRAY={112,128,144};//! Snow color (255,250,250)static const ccColor3B ccSNOW={255,250,250};//! SpringGreen color (0,255,127)static const ccColor3B ccSPRINGGREEN={0,255,127};//! SteelBlue color (70,130,180)static const ccColor3B ccSTEELBLUE={70,130,180};//! Tan color (210,180,140)static const ccColor3B ccTAN={210,180,140};//! Teal color (0,128,128)static const ccColor3B ccTEAL={0,128,128};//! Thistle color (216,191,216)static const ccColor3B ccTHISTLE={216,191,216};//! Tomato color (255,99,71)static const ccColor3B ccTOMATO={255,99,71};//! Turquoise color (64,224,208)static const ccColor3B ccTURQUOISE={64,224,208};//! Violet color (238,130,238)static const ccColor3B ccVIOLET={238,130,238};//! Wheat color (245,222,179)static const ccColor3B ccWHEAT={245,222,179};//! WhiteSmoke color (245,245,245)static const ccColor3B ccWHITESMOKE={245,245,245};//! YellowGreen color (154,205,50)static const ccColor3B ccYELLOWGREEN={154,205,50};&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-2216616905459489763?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/2216616905459489763/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/12/cccolor3b-constants-whole-bunch-of-them.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/2216616905459489763'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/2216616905459489763'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/12/cccolor3b-constants-whole-bunch-of-them.html' title='ccColor3B constants.... A whole bunch of them.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-3367976681971432865</id><published>2011-12-06T19:05:00.001+02:00</published><updated>2011-12-09T20:24:52.165+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Cached Property File Enum</title><content type='html'>We had a little need to dynamically enable and disable features on our current project and I sorta left it for the last day, came up with a simple little solution that ended up quite neat. &lt;br/&gt; &lt;p&gt;A cached property file enum:&lt;p&gt;&lt;br /&gt;&amp;nbsp;How it looks being used:&lt;br /&gt;Code:&lt;script class="brush: java" type="syntaxhighlighter"&gt;        if(Features.FEATUREA.isEnabled()){           //Perform some action.        }&lt;/script&gt;&lt;br /&gt;Test:&lt;script class="brush: java" type="syntaxhighlighter"&gt;        Assert.assertTrue(Features.FEATUREA.isEnabled());        Assert.assertFalse(Features.FEATUREB.isEnabled());        Assert.assertTrue(Features.FEATUREC.isEnabled());&lt;/script&gt;&lt;br /&gt;The .properties file:&lt;br /&gt;FEATUREA=true&lt;br /&gt;FEATUREB=false&lt;br /&gt;FEATUREC=true&lt;br /&gt;&lt;br /&gt;How it works:&lt;script class="brush: java" type="syntaxhighlighter"&gt;import java.util.Date;import java.util.Properties;public enum Features {    FEATUREA,    FEATUREB,    FEATUREC;    private static final String PATH = "/features.properties";    private final static long LOAD_INTERVAL = 5 * 60 * 1000;    private String value;    private long lastLoaded;    /**     * Check if the feature is enabled.     *     * @return true, if enabled.     */    public boolean isEnabled() {        if (value == null || ((new Date().getTime() - lastLoaded) &gt; LOAD_INTERVAL)) {            load();        }        return Boolean.parseBoolean(value);    }    /**     * Read the properties.     */    private void load() {      final Properties properties = new Properties();      try {         properties.load(Features.class.getResourceAsStream(PATH));      } catch (Exception e) {         System.out.println("Unable to load " + PATH + " file from classpath.");      }      value = (String) properties.get(this.toString());      lastLoaded = new Date().getTime();    }}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-3367976681971432865?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/3367976681971432865/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/12/cached-property-file-enum.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3367976681971432865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3367976681971432865'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/12/cached-property-file-enum.html' title='Cached Property File Enum'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-6155570653241703386</id><published>2011-12-06T14:34:00.001+02:00</published><updated>2011-12-06T19:03:47.724+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Review'/><category scheme='http://www.blogger.com/atom/ns#' term='Development Process'/><category scheme='http://www.blogger.com/atom/ns#' term='General Info'/><title type='text'>The Pragmatic Programmer - Review / Summary Notes.</title><content type='html'>I recently finished &lt;a href="http://pragprog.com/the-pragmatic-programmer"&gt;The Pragmatic Programmer&lt;/a&gt;, to be completely honest this had been the 3rd attempt to read it, although the book is good and well worth the read, I had unfortunetly learnt most of the lessons &lt;b&gt;the hard way&lt;/b&gt; on my own over the last decade or so of being a software developer, so I found often myself easily distracted.&lt;br /&gt;&lt;br /&gt;I have to add, had I read this when it was published it would have undoubtedly saved me some pain, but even with that it's always good to reaffirm some of your good habits, and keep your bad ones in check. It covers 46 sections with 70 different tips that are generally useful to any programmer.Jeff Atwood - coding horror made a list of all &lt;a href="http://www.codinghorror.com/blog/2004/10/a-pragmatic-quick-reference.html"&gt;70 tips&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;As with most things some tips are "more equal" than others, the ones that really stick out and probably can't be emphasized enough are:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;b&gt;Care About Your Craft&lt;/b&gt;&lt;br /&gt;Why spend your life developing software unless you care about doing it well?&lt;br /&gt;&amp;nbsp;&lt;b&gt;Think! About Your Work&lt;/b&gt;&lt;br /&gt;Turn off the autopilot and take control. Constantly critique and appraise your work.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Don't Live with Broken Windows&lt;/b&gt;&lt;br /&gt;Fix bad designs, wrong decisions, and poor code when you see them.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Invest Regularly in Your Knowledge Portfolio&lt;/b&gt;&lt;br /&gt;Make learning a habit.&lt;br /&gt;&amp;nbsp;&lt;b&gt;DRY - Don't Repeat Yourself&lt;/b&gt;&lt;br /&gt;Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Make It Easy to Reuse&lt;/b&gt;&lt;br /&gt;If it's easy to reuse, people will. Create an environment that supports reuse.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Prototype to Learn&lt;/b&gt;&lt;br /&gt;Prototyping is a learning experience. Its value lies not in the code you produce, but in the lessons you learn.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Don't Panic When Debugging&lt;/b&gt;&lt;br /&gt;Take a deep breath and THINK! about what could be causing the bug.&lt;br /&gt;&amp;nbsp;&lt;b&gt;"select" Isn't Broken.&lt;/b&gt;&lt;br /&gt;It is rare to find a bug in the OS or the compiler, or even a third-party product or library. The bug is most likely in the application.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Design with Contracts&lt;/b&gt;&lt;br /&gt;Use contracts to document and verify that code does no more and no less than it claims to do.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Crash Early&lt;/b&gt;&lt;br /&gt;A dead program normally does a lot less damage than a crippled one.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Minimize Coupling Between Modules&lt;/b&gt;&lt;br /&gt;Avoid coupling by writing "shy" code and applying the Law of Demeter.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Don't Program by Coincidence&lt;/b&gt;&lt;br /&gt;Rely only on reliable things. Beware of accidental complexity, and don't confuse a happy coincidence with a purposeful plan.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Refactor Early, Refactor Often&lt;/b&gt;&lt;br /&gt;Just as you might weed and rearrange a garden, rewrite, rework, and re-architect code when it needs it. Fix the root of the problem.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Design to Test&lt;/b&gt;&lt;br /&gt;Start thinking about testing before you write a line of code.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Some Things Are Better Done than Described&lt;/b&gt;&lt;br /&gt;Don't fall into the specification spiral at some point you need to start coding.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Don't Be a Slave to Formal Methods.&lt;/b&gt;&lt;br /&gt;Don't blindly adopt any technique without putting it into the context of your development practices and capabilities.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Don't Use Manual Procedures&lt;/b&gt;&lt;br /&gt;A shell script or batch file will execute the same instructions, in the same order, time after time.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Test Early. Test Often. Test Automatically&lt;/b&gt;&lt;br /&gt;Tests that run with every build are much more effective than test plans that sit on a shelf.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Coding Ain't Done 'Til All the Tests Run&lt;/b&gt;&lt;br /&gt;'Nuff said.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Test State Coverage, Not Code Coverage&lt;/b&gt;&lt;br /&gt;Identify and test significant program states. Just testing lines of code isn't enough.&lt;br /&gt;&amp;nbsp;&lt;b&gt;Find Bugs Once&lt;/b&gt;&lt;br /&gt;Once a human tester finds a bug, it should be the last time a human tester finds that bug. Automatic tests should check for it from then on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-6155570653241703386?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/6155570653241703386/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/12/pragmatic-programmer-review-summary.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6155570653241703386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6155570653241703386'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/12/pragmatic-programmer-review-summary.html' title='The Pragmatic Programmer - Review / Summary Notes.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-4769702720063849986</id><published>2011-11-25T19:19:00.001+02:00</published><updated>2011-12-06T13:37:46.756+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Game Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>Determining iOS Hardware / Device</title><content type='html'>I am currently working on my second iOS game in which I am creating dynamic Open GL ES reflections, and noticed on the older devices it would cause a drop in frames per second.It doesn't on the iPad 2, I do not have iPhone 4S yet, but I assume it won't have a visible effect there either with the new CPU.&lt;p&gt;So to not diminish the user experience I decided to remove those reflections, on the interactive CCSprite, on the older devices.&lt;p&gt;I went searching and found : &lt;a href="https://gist.github.com/1323251"&gt;UIDeviceHardware - Determine iOS device being used&lt;/a&gt;&lt;p&gt;I ended up just using:&lt;script class="brush: cpp" type="syntaxhighlighter"&gt;- (NSString *) platform{    size_t size;    sysctlbyname("hw.machine", NULL, &amp;size, NULL, 0);    char *machine = malloc(size);    sysctlbyname("hw.machine", machine, &amp;size, NULL, 0);    NSString *platform = [NSString stringWithUTF8String:machine];    free(machine);    return platform;}&lt;/script&gt;(platformString wasn't useful to me)I then just created a convenience method for myself to check for the version that have the Dual-core Apple A5 processor.&lt;script class="brush: cpp" type="syntaxhighlighter"&gt;- (BOOL) hasDualCoreCPU {    NSString *platform = [self platform];    if ([platform isEqualToString:@"iPhone4,1"] ||            [platform isEqualToString:@"iPad2,1"] ||            [platform isEqualToString:@"iPad2,2"] ||            [platform isEqualToString:@"iPad2,3"] ||            [platform isEqualToString:@"i386"] ||            [platform isEqualToString:@"x86_64"]) {        return YES;    }    return NO;}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-4769702720063849986?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/4769702720063849986/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/11/determining-ios-hardware-device.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4769702720063849986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4769702720063849986'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/11/determining-ios-hardware-device.html' title='Determining iOS Hardware / Device'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-7821069770067576079</id><published>2011-10-16T08:40:00.000+02:00</published><updated>2011-12-17T08:29:08.832+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cocos2d'/><category scheme='http://www.blogger.com/atom/ns#' term='Game Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Open GL'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS'/><title type='text'>Cocos2d CCSprite Reflection</title><content type='html'>With yet another 2 months of &lt;a href="http://www.briandupreez.net/2011/02/surviving-wild-west-development-process.html "&gt;Wild West Development&lt;/a&gt; behind me, I can hopefully get back to a somewhat normal life again, blogging, learning and a little iOS game development.&lt;p&gt;What I want to share today is my little hack to reflect a CCSprite used in to cocos2d. I say hack because it does feel a little dirty, i didn't go and learn about the details of Open GL and the like,  simply patched things together to get a working solution.&lt;p&gt;Below is the code for my ImageReflector, the basic idea and how it got it work was simple: &lt;p&gt;The best looking reflection example I found was Apples' &lt;a href="http://developer.apple.com/library/ios/#samplecode/Reflection/Introduction/Intro.html"&gt;example&lt;/a&gt;.So the methods&lt;b&gt; createBitmapContext, createGradientImage&lt;/b&gt; and &lt;b&gt;reflectedImage&lt;/b&gt; are directly from the above example.I wanted to use it in cocos2d so I used CCRenderTexture to create a UIImage, passed that to Apples' example code and then simply converted back to a CCSprite with the help of the CCTexture2D class.&lt;p&gt;&lt;b&gt;Usage:&lt;/b&gt;&lt;script class="brush: cpp" type="syntaxhighlighter"&gt;ImageReflector *imageReflector = [[ImageReflector alloc] init];CCSprite *game =  [CCSprite spriteWithFile:@"GameNameHD.png"];CCSprite *gameReflection = [imageReflector drawSpriteReflection:game withHeight:40];[imageReflector release];&lt;/script&gt;&lt;b&gt;Class:&lt;/b&gt;&lt;script class="brush: cpp" type="syntaxhighlighter"&gt;#import "ImageReflector.h"@implementation ImageReflector- (id)init{    self = [super init];    if (self) {        // Initialization code here.    }        return self;}- (UIImage *) convertSpriteToImage:(CCSprite *)sprite {    CGPoint p = sprite.anchorPoint;    [sprite setAnchorPoint:ccp(0,0)]; CCRenderTexture *renderer = [CCRenderTexture renderTextureWithWidth:sprite.contentSize.width height:sprite.contentSize.height]; [renderer begin]; [sprite visit]; [renderer end];    [sprite setAnchorPoint:p];    UIImage *newImage = [UIImage imageWithData:[renderer getUIImageAsDataFromBuffer:kCCImageFormatPNG]];    return newImage;}//Taken from the Apple Reflection example.- (CGContextRef) createBitmapContext:(int) pixelsWide pixelsHigh:(int) pixelsHigh {    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); // create the bitmap context CGContextRef bitmapContext = CGBitmapContextCreate (NULL, pixelsWide, pixelsHigh, 8,              0, colorSpace,              // this will give us an optimal BGRA format for the device:              (kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst)); CGColorSpaceRelease(colorSpace);    return bitmapContext;}- (CGImageRef) createGradientImage:(int) pixelsWide pixelsHigh:(int) pixelsHigh { CGImageRef theCGImage = NULL; // gradient is always black-white and the mask must be in the gray colorspace    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();  // create the bitmap context CGContextRef gradientBitmapContext = CGBitmapContextCreate(NULL, pixelsWide, pixelsHigh,                  8, 0, colorSpace, kCGImageAlphaNone);  // define the start and end grayscale values (with the alpha, even though // our bitmap context doesn't support alpha the gradient requires it) CGFloat colors[] = {0.0, 1.0, 1.0, 1.0}; // create the CGGradient and then release the gray color space CGGradientRef grayScaleGradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 2); CGColorSpaceRelease(colorSpace); // create the start and end points for the gradient vector (straight down) CGPoint gradientStartPoint = CGPointZero; CGPoint gradientEndPoint = CGPointMake(0, pixelsHigh); // draw the gradient into the gray bitmap context CGContextDrawLinearGradient(gradientBitmapContext, grayScaleGradient, gradientStartPoint,        gradientEndPoint, kCGGradientDrawsAfterEndLocation); CGGradientRelease(grayScaleGradient);  // convert the context into a CGImageRef and release the context theCGImage = CGBitmapContextCreateImage(gradientBitmapContext); CGContextRelease(gradientBitmapContext);  // return the imageref containing the gradient    return theCGImage;}- (UIImage *)reflectedImage:(UIImageView *)fromImage withHeight:(NSUInteger)height{    if(height == 0)  return nil;     // create a bitmap graphics context the size of the image CGContextRef mainViewContentContext = [self createBitmapContext:fromImage.bounds.size.width pixelsHigh:height];  // create a 2 bit CGImage containing a gradient that will be used for masking the  // main view content to create the 'fade' of the reflection.  The CGImageCreateWithMask // function will stretch the bitmap image as required, so we can create a 1 pixel wide gradient CGImageRef gradientMaskImage = [self createGradientImage:1 pixelsHigh:height];  // create an image by masking the bitmap of the mainView content with the gradient view // then release the  pre-masked content bitmap and the gradient bitmap CGContextClipToMask(mainViewContentContext, CGRectMake(0.0, 0.0, fromImage.bounds.size.width, height), gradientMaskImage); CGImageRelease(gradientMaskImage);  // In order to grab the part of the image that we want to render, we move the context origin to the // height of the image that we want to capture, then we flip the context so that the image draws upside down. CGContextTranslateCTM(mainViewContentContext, 0.0, height); CGContextScaleCTM(mainViewContentContext, 1.0, -1.0);  // draw the image into the bitmap context CGContextDrawImage(mainViewContentContext, fromImage.bounds, fromImage.image.CGImage);  // create CGImageRef of the main view bitmap content, and then release that bitmap context CGImageRef reflectionImage = CGBitmapContextCreateImage(mainViewContentContext); CGContextRelease(mainViewContentContext);  // convert the finished reflection image to a UIImage  UIImage *theImage = [UIImage imageWithCGImage:reflectionImage];  // image is retained by the property setting above, so we can release the original CGImageRelease(reflectionImage);  return theImage;}- (CCSprite*) drawSpriteReflection:(CCSprite *) sprite withHeight:(NSUInteger) height {        UIImage *theReflect = [self convertSpriteToImage:sprite];    UIImageView *imageView = [[UIImageView alloc] initWithImage:theReflect];    UIImage *reflect = [self reflectedImage:imageView withHeight:height];        CCTexture2D *texture=[[CCTexture2D alloc] initWithImage:reflect];    CCSprite *returnSprite = [CCSprite spriteWithTexture:texture];    [imageView release];    return returnSprite;}@end&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-7821069770067576079?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/7821069770067576079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/10/cocos2d-ccsprite-reflection.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/7821069770067576079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/7821069770067576079'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/10/cocos2d-ccsprite-reflection.html' title='Cocos2d CCSprite Reflection'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-1880849866755589683</id><published>2011-09-02T08:54:00.001+02:00</published><updated>2011-09-02T08:54:42.577+02:00</updated><title type='text'>iPhone Gmail Username / Password Error</title><content type='html'>This morning, I all of a sudden could not get my gmail mails on my iPhone, constantly got:&lt;br /&gt;&lt;b&gt;&lt;span&gt;Cannot Get Mail - The user name or password for imap.gmail.com is incorrect.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;After a bit of searching, I found the solution to be simple, logon and input the Captcha phrase.&lt;br /&gt;&lt;br /&gt;Link Below: &lt;br /&gt;&lt;a href="https://www.google.com/accounts/UnlockCaptcha"&gt;https://www.google.com/accounts/UnlockCaptcha&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-1880849866755589683?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/1880849866755589683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/09/iphone-gmail-username-password-error.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1880849866755589683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1880849866755589683'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/09/iphone-gmail-username-password-error.html' title='iPhone Gmail Username / Password Error'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-3293023155489450158</id><published>2011-08-31T22:44:00.000+02:00</published><updated>2011-08-31T22:44:47.583+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Git'/><category scheme='http://www.blogger.com/atom/ns#' term='XCode'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>Mac OSX Global Git Ignore - XCode Project and State Files.</title><content type='html'>With my recent switch to Mac, Objective C and XCode and XCode using Git as it's default VCS (Version control system), I figured it would probably be a good time to switch over to using Git. I registered with GitHub purchased the base 5 private repo plan and uploaded my projects and images. I didn't realize at the time then what pain I would cause myself.&lt;br /&gt;&lt;br /&gt;A little later, my wife joined me in working with those projects only to discover that under certain scenarios we could never actually merge or sync the branches from XCode. There were always couple files that would be "uncommited" in XCode. Nasty XCode project state files.&lt;br /&gt;&lt;br /&gt;I had not worked with Git before this actually, so after reading up a bit about project files and the like and how a ".ignore" file would do the trick. &lt;br /&gt;After I little bit of struggling, I realized that for ignore to work, the files needed to be removed from the repository first. Thankfully I did not have any important history so I could simply recreate them. You can also remove them from git with: &lt;i&gt;git rm --cached &lt;filename&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;To go about creating, editing configuring a global ignore file on OSX I did the following:&lt;br /&gt;&lt;br /&gt;First problem on a Mac, any "." files are seen as system files and those are automatically hidden from you.&lt;br /&gt;&lt;br /&gt;To get around that open "Terminal" and use the commands below to show and hide system files (you'll need to either restart or force quit Finder for the changes to take effect).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Show:&lt;/b&gt;&lt;br /&gt;&lt;i&gt;defaults write com.apple.finder AppleShowAllFiles -bool true&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Hide:&lt;/b&gt;&lt;br /&gt;&lt;i&gt;defaults write com.apple.finder AppleShowAllFiles -bool false&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Once I had done that I simply went searching for a couple example ignore files and combined them into the example below.&lt;br /&gt;&lt;br /&gt;Create a file in your user directory called ".gitignore_global", populate it with the contents required, (below is mine, that does take care of the XCode problem files)&lt;br /&gt;Then in Terminal run:&lt;br /&gt;&lt;i&gt;git config --global core.excludesfile ~/.gitignore_global&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;My global ignore file:&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;# Compiled source ####################*.com*.class*.dll*.exe*.o*.so# Packages #############*.7z*.dmg*.gz*.iso*.jar*.rar*.tar*.zip*.war*.ear# Logs and databases #######################*.log*.sql*.sqlite# OS generated files #######################.DS_Store?ehthumbs.dbIcon?Thumbs.db*.DS_Store# Xcode*.pbxuser*.mode1v3*.mode2v3*.perspectivev3*.xcuserstateproject.xcworkspace/xcuserdata/#Eclipse.classpath.project.settings# Generated files/web-app/WEB-INFbuild/*.[oa]*.pyc# Other source repository archive directories (protects when importing).hg.svnCVS# automatic backup files*~.nib*.swp*~*(Autosaved).rtfd/Backup[ ]of[ ]*.pages/Backup[ ]of[ ]*.key/Backup[ ]of[ ]*.numbers/&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-3293023155489450158?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/3293023155489450158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/08/mac-osx-global-git-ignore-xcode-project.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3293023155489450158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3293023155489450158'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/08/mac-osx-global-git-ignore-xcode-project.html' title='Mac OSX Global Git Ignore - XCode Project and State Files.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-5979530636765346189</id><published>2011-08-24T10:59:00.002+02:00</published><updated>2011-08-26T10:45:00.155+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='XSD'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><title type='text'>Java /  XML UTF-8  marshalling and validating pains</title><content type='html'>This is  a post on the little pains I am sure most people have endured while working with Java and XML from different sources, with 'funny' characters...&lt;br /&gt;&lt;br /&gt;If you use a FileWriter instead of a FileOutputStream it will use your OS encoding (So cp1252, ISO-8859-1 or US-ASCII and not UTF-8... ):&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;System.getProperty(file.encoding);&lt;/script&gt;&lt;br /&gt;A way to ensure that you are using UTF-8 is:&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(path),"UTF-8");&lt;/script&gt;&lt;br /&gt;If you are reading XML from a stream, it is probably safer to do something like:&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;new InputStreamReader(getInputStream(), "UTF-8");&lt;/script&gt;&lt;br /&gt;When validating a schema note the &lt;b&gt;.getBytes("UTF-8")&lt;/b&gt;:&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;	public void validate(final String requestXML) throws SAXException, IOException {		final SchemaFactory factory = SchemaFactory.newInstance(XML_SCHEMA);		final URL schemaUrl = this.getClass().getResource("/xsd/example.xsd");		final Schema schema = factory.newSchema(schemaUrl);		final Validator validator = schema.newValidator();		final StreamSource source = new StreamSource(new ByteArrayInputStream(requestXML.getBytes("UTF-8")));		validator.validate(source);	}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;When marshalling (Use a stream rather than a writer):&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;public String marshal(final Example request) {		final ByteArrayOutputStream baos = new ByteArrayOutputStream();		final Result result = new StreamResult(baos);		String xml;		try {			getMarshaller().marshal(request, result);			xml = baos.toString("UTF-8");			baos.close();		} catch (final IOException e) {			throw new RuntimeException("Could not marshall example XML.", e);		}        return xml;	}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Lastly if you are getting XML from some unknown source there are some chars that are outside the legal XML Unicode limits that you can not encode. To remove those:&lt;br /&gt;&lt;i&gt;Code below from another &lt;a href="http://benjchristensen.com/2008/02/07/how-to-strip-invalid-xml-characters/"&gt;blog&lt;/a&gt; &lt;/i&gt;:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;        String invalidXmlPattern = "[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF"                + "\\uE000-\\uFFFD\\u10000-\\u10FFFF]";        xml = xml.replaceAll(invalidXmlPattern, "");&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-5979530636765346189?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/5979530636765346189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/08/java-xml-utf-8-marshalling-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5979530636765346189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5979530636765346189'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/08/java-xml-utf-8-marshalling-and.html' title='Java /  XML UTF-8  marshalling and validating pains'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-3823182021341825997</id><published>2011-07-26T22:38:00.000+02:00</published><updated>2011-07-26T22:38:25.043+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>Mac Attack...</title><content type='html'>I have not created a blog entry in some time, for the last 2 months or so all my weekends and evenings have been spent on my latest addiction, iPhone development.&lt;br /&gt;&lt;br /&gt;A couple months back I spent some time deciding what programming language to learn, blogged about it &lt;a href="http://www.briandupreez.net/2011/02/selecting-new-programming-language-to.html"&gt;here&lt;/a&gt;. At the time I based on Tiobe, job stats, current interest and not taking the final step to actually buy a Mac, I choose C#. I spent a couple weeks messing with it, nothing serious, started a &lt;a href="http://en.wikipedia.org/wiki/Windows_Presentation_Foundation"&gt;WPF&lt;/a&gt; clone for one of my favorite tools of all time. &lt;a href="http://www.baremetalsoft.com/baretail/"&gt;Baretail&lt;/a&gt;, but it just didn't catch my imagination, so I lacked the drive to finish.&lt;br /&gt;&lt;br /&gt;I then got my iPhone, and that was all she wrote... I was hooked, coming from a lame excuse of a "smart phone" The HTC-Touch-Diamond-2-windows-mobile-thing, to the iPhone was a wonderful experience. It didn't take long before I could not resist the desire to program of my new toy... off to the iStore, out with the credit card, returning triumphantly with a single box, (iMac i5 quadcore 4gb 21.5"), inside the box there is a single cable,  plug in the power... (spend a couple minutes looking for the on switch)... basic OS config, user and such.... done.&lt;br /&gt;&lt;br /&gt;I had heard something about xCode, off go App Store... wait a day for the monster 4.5gb download. Stumble around hello world, and 2 or 3 other tutorials and that was that. I was hooked and with that 2 months of weekends and evenings were lost infront of the iMac. This last weekend my wife and I eventually submitted the game, and now we have to wait for probably 2 nerve wracking weeks for approval or rejection. &lt;br /&gt;&lt;br /&gt;I'll will discuss more specific details once it is released but For now I'll share some experiences and thoughts from the last 2 months.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Objective C&lt;/b&gt;&lt;br /&gt;I have to say, I like the language although coming for a Java / .Net background some of the intricacies of the syntax, lack of type enforcement and actually having to do your own memory management can be a little tedious when starting.&lt;br /&gt;All that aside but both my wife (a C# developer) and I (Java) didn't feel too uncomfortable picking it up.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Open Source and Other resources&lt;/b&gt;&lt;br /&gt;No. 1 most useful thing I found when writing a game for an iOS platform is:&lt;br /&gt;&lt;a href="http://www.cocos2d-iphone.org/"&gt;Cocos2D&lt;/a&gt;&lt;br /&gt;These guys have done an awesome job, and there is a decent size community / forum to help out if you do get stuck.&lt;br /&gt;I haven't looked at &lt;a href="http://www.sparrow-framework.org/"&gt;Sparrow&lt;/a&gt; as I only found it a couple days after implementing Cocos2D and decided to stick with that. Another blogger did a comparison &lt;a href="http://eddyl.com/blog/2010/08/ios_game_framework/"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Physics Engines, there are a couple out there, I figured I would gave it a skip for the first app, there would be enough to worry about without having to learn one of them either. &lt;br /&gt;The 2 Main contenders I can see are:&lt;br /&gt;&lt;a href="http://code.google.com/p/chipmunk-physics/"&gt;Chipmunk&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.box2d.org/"&gt;Box2D&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;XCode 4... &lt;/b&gt;&lt;br /&gt;ouch, XCode just feels behind the likes of Eclipse, Visual Studio and  IntelliJ. Little things we take for granted, are really missed. I am not going to go into the details, just know if you already use Eclipse, Visual Studio (with Resharper) or IntelliJ and start with XCode, you are going to be a little frustrated. To be fair, some of the frustrations were probably from a lack knowledge on my part and to top it off never having coded in the language before.&lt;br /&gt;&lt;br /&gt;After submitting my app I decided to try &lt;a href="http://www.jetbrains.com/objc/"&gt;App Code&lt;/a&gt; and loved it straight away. It's still in "beta", but using AppCode after coming from IntelliJ fells very natural. So thankfully there will be a real alternative once they release it officially.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;General&lt;/b&gt;&lt;br /&gt;I will try post useful Objective C/Game/Apple code and examples as I learn.  The first 2 quick things to start with:&lt;br /&gt;&lt;br /&gt;1. When Using Cocos2D.... and trying to incorporate UIScrollView from the SDK, prepare yourself for some pain. The &lt;a href="https://github.com/cocos2d/cocos2d-iphone-extensions/tree/develop/Extensions/CCScrollLayer"&gt;CCScrollLayer&lt;/a&gt; however, is completely painless. We extended it and completely customized it to our game look and feel, it was very simple to do.&lt;br /&gt;&lt;br /&gt;2. If you want to sort an array of integers in descending order use a NSSortDescriptor, very hand class actually:&lt;br /&gt;&lt;script class="brush: cpp" type="syntaxhighlighter"&gt;NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:NO selector:@selector(compare:)];sortedScores = [highscores sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-3823182021341825997?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/3823182021341825997/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/07/mac-attack.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3823182021341825997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3823182021341825997'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/07/mac-attack.html' title='Mac Attack...'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-4757451131548241879</id><published>2011-05-23T06:24:00.000+02:00</published><updated>2011-05-23T06:24:19.051+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Personal'/><category scheme='http://www.blogger.com/atom/ns#' term='General Info'/><title type='text'>1 Year and 70 000 views later, the stats...</title><content type='html'>So it has been just over a year, since my first blog post. Even though the whole work / life thing has kept me overly busy the last couple months, reducing me to 1-2 posts a month, it has been quite a pleasing experience blogging. I would recommend it to all developer types, it's an good way to keep you investigating, learning and having your work out there and visible to people makes you put in that little extra effort.&lt;br /&gt;&lt;br /&gt;The actual reason for this post is for some discussion on the stats... There were 1 or 2 interesting percentages I would not have expected.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Views By Country&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/A0ICSiDCMK" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="https://lh4.googleusercontent.com/_4oXSoLPl3uY/TdjiT_v44SI/AAAAAAAAAQQ/kspwDoWwuqs/s512/Country%20Stats.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;No big surprise that the US has the most views, this being a English technology based blog, it is however interesting that Germany is second, beating out the UK and India, both with larger populations. South Africa on the list is probably only there because I force my colleagues and friends to read it :)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Views By Browser&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/qzTXsJ9osM" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="https://lh6.googleusercontent.com/_4oXSoLPl3uY/Tdji1uC7KaI/AAAAAAAAAQc/A5IMzxCdWC8/s512/Browser%20Stats.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;With this being an Java-technical-open source oriented blog makes FireFox the obvious choice to lead the browser war. However with Chrome in 2nd by a such large percentage was a bit unexpected.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Views By OS&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/etUyaLITbO" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="https://lh5.googleusercontent.com/_4oXSoLPl3uY/Tdji_dVD7oI/AAAAAAAAAQg/2h7mZnoLaMg/s512/OS%20Stats.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;On OS Windows is still number one. Apple is competing nicely with Linux / Unix combined, this is probably due the large apple following in the US and the boom of the iPad.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-4757451131548241879?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/4757451131548241879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/05/1-year-and-70-000-views-later-stats.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4757451131548241879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4757451131548241879'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/05/1-year-and-70-000-views-later-stats.html' title='1 Year and 70 000 views later, the stats...'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh4.googleusercontent.com/_4oXSoLPl3uY/TdjiT_v44SI/AAAAAAAAAQQ/kspwDoWwuqs/s72-c/Country%20Stats.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-5075688311695129521</id><published>2011-05-16T05:58:00.001+02:00</published><updated>2011-05-22T12:09:15.466+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Java Compression.</title><content type='html'>In a recent project, we had to do something I had personally never really had to look at; Compression. We needed to take a couple files and images, zip them up and make them available for FTP, and yes somedays it does feel like we are back in the 90's. Besides the FTP trip into the past its was good opportunity to spend a little bit of time on the subject.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Compressing Files&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;So above the usual IO classes BufferedInputStream, FileOutputStream and File there are:&lt;br /&gt;&lt;b&gt;ZipInputStream&lt;/b&gt; - An input stream for reading files in the ZIP file format. Zip entries are not cached, unlike ZipFile.&lt;br /&gt;&lt;b&gt;ZipOutputStream&lt;/b&gt; - An output stream for writing files in the ZIP file format. This has a default internal buffer of 512, a BufferedOutputStream can be used to increase this.&lt;br /&gt;&lt;b&gt;ZipEntry&lt;/b&gt; - Represents an entry int a zip file.&lt;br /&gt;&lt;b&gt;ZipFile&lt;/b&gt; - Used to read entries from a zip file. The entries are cached.&lt;br /&gt;&lt;b&gt;CRC32&lt;/b&gt; - Used to compute the CRC-32 of a data stream.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Below is an example showing how to compress and decompress files in a folder, with and without a checksum:&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;package javaitzen.blog;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.util.Arrays;import java.util.List;import java.util.zip.CRC32;import java.util.zip.CheckedInputStream;import java.util.zip.CheckedOutputStream;import java.util.zip.ZipEntry;import java.util.zip.ZipInputStream;import java.util.zip.ZipOutputStream;/** * The Class FileCompressionUtil. */public class FileCompressionUtil { public static final int BUFFER = 2048; private FileCompressionUtil() {}  /**  * Zip files in path.  *   * @param zipFileName the zip file name  * @param filePath the file path  * @throws IOException Signals that an I/O exception has occurred.  */ public static void zipFilesInPath(final String zipFileName, final String filePath) throws IOException {  final FileOutputStream dest = new FileOutputStream(zipFileName);  final ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));  try {   byte[] data = new byte[BUFFER];   final File folder = new File(filePath);   final List&lt; String &gt; files = Arrays.asList(folder.list());   for (String file : files) {    final FileInputStream fi = new FileInputStream(filePath + File.pathSeparator + file);    final BufferedInputStream origin = new BufferedInputStream(fi, BUFFER);    out.putNextEntry(new ZipEntry(file));    int count;    while ((count = origin.read(data, 0, BUFFER)) != -1) {     out.write(data, 0, count);    }    origin.close();    fi.close();   }  } finally {   out.close();   dest.close();  } } /**  * Zip with checksum. CRC32  *   * @param zipFileName the zip file name  * @param folderPath the folder path  * @return the checksum  * @throws IOException Signals that an I/O exception has occurred.  */ public static long zipFilesInPathWithChecksum(final String zipFileName, final String folderPath) throws IOException {  final FileOutputStream dest = new FileOutputStream(zipFileName);  final CheckedOutputStream checkStream = new CheckedOutputStream(dest, new CRC32());  final ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(checkStream));  try {   byte[] data = new byte[BUFFER];   final File folder = new File(folderPath);   final List&lt; String &gt; files = Arrays.asList(folder.list());   for (String file : files) {    final FileInputStream fi = new FileInputStream(folderPath + File.pathSeparator + file);    final BufferedInputStream origin = new BufferedInputStream(fi, BUFFER);    out.putNextEntry(new ZipEntry(file));    int count;    while ((count = origin.read(data, 0, BUFFER)) != -1) {     out.write(data, 0, count);    }    origin.close();   }    } finally {   out.close();   checkStream.close();   dest.flush();   dest.close();  }  return checkStream.getChecksum().getValue(); } /**  * Unzip files to path.  *   * @param zipFileName the zip file name  * @param fileExtractPath the file extract path  * @throws IOException Signals that an I/O exception has occurred.  */ public static void unzipFilesToPath(final String zipFileName, final String fileExtractPath) throws IOException {  final FileInputStream fis = new FileInputStream(zipFileName);  final ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));  try {   ZipEntry entry;   while ((entry = zis.getNextEntry()) != null) {    int count;    byte[] data = new byte[BUFFER];    final FileOutputStream fos = new FileOutputStream(fileExtractPath + File.pathSeparator + entry.getName());    final BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);    while ((count = zis.read(data, 0, BUFFER)) != -1) {     dest.write(data, 0, count);    }    dest.flush();    dest.close();   }  } finally {   fis.close();   zis.close();  } } /**  * Unzip files to path with checksum. CRC32  *   * @param zipFileName the zip file name  * @param fileExtractPath the file extract path  * @param checksum the checksum  * @return true, if checksum matches;  * @throws IOException Signals that an I/O exception has occurred.  */ public static boolean unzipFilesToPathWithChecksum(final String zipFileName, final String fileExtractPath, final long checksum) throws IOException {  boolean checksumMatches = false;  final FileInputStream fis = new FileInputStream(zipFileName);  final CheckedInputStream checkStream = new CheckedInputStream(fis, new CRC32());  final ZipInputStream zis = new ZipInputStream(new BufferedInputStream(checkStream));  try {   ZipEntry entry = null;   while ((entry = zis.getNextEntry()) != null) {    int count;    byte[] data = new byte[BUFFER];    final FileOutputStream fos = new FileOutputStream(fileExtractPath + File.pathSeparator + entry.getName());    final BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);    while ((count = zis.read(data, 0, BUFFER)) != -1) {     dest.write(data, 0, count);    }    dest.flush();    dest.close();   }  } finally {   zis.close();   fis.close();   checkStream.close();  }  if(checkStream.getChecksum().getValue() == checksum) {   checksumMatches = true;  }    return checksumMatches; } }&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Compressing Objects&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;We didn't end up using object compression but I had a look at it anyways. I did a little generic compress / expand util, don't know if it will ever be useful. I left the input params as OutputStream and InputStream as this could theoretically be used with any stream implementation from socket communication to string manipulation.&lt;br /&gt;&lt;br /&gt;The compression related classes being used here:&lt;br /&gt;&lt;b&gt;GZIPInputStream&lt;/b&gt; - An input stream filter for reading compressed data in the GZIP file format.&lt;br /&gt;&lt;b&gt;GZIPOutputStream&lt;/b&gt; - An output stream filter for writing compressed data in the GZIP file format. Default internal buffer of 512, use BufferedOutputStream if you require more.&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;package javaitzen.blog;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.OutputStream;import java.io.Serializable;import java.util.zip.GZIPInputStream;import java.util.zip.GZIPOutputStream;/** * The Class ObjectCompressionUtil. *  * @param &lt;t&gt; the generic type of the serializable object to be compressed */public class ObjectCompressionUtil&lt;t extends Serializable&gt; { /**  * Compress object.  *   * @param objectToCompress the object to compress  * @param outstream the outstream  * @return the compressed object  * @throws IOException Signals that an I/O exception has occurred.  */ public T compressObject(final T objectToCompress, final OutputStream outstream) throws IOException {  final GZIPOutputStream gz = new GZIPOutputStream(outstream);  final ObjectOutputStream oos = new ObjectOutputStream(gz);    try {  oos.writeObject(objectToCompress);  oos.flush();  return objectToCompress;  }finally {   oos.close();   outstream.close();  } } /**  * Expand object.  *   * @param objectToExpand the object to expand  * @param instream the instream  * @return the expanded object  * @throws IOException Signals that an I/O exception has occurred.  * @throws ClassNotFoundException the class not found exception  */ public T expandObject(final T objectToExpand, final InputStream instream) throws IOException,   ClassNotFoundException {  final GZIPInputStream gs = new GZIPInputStream(instream);  final ObjectInputStream ois = new ObjectInputStream(gs);  try {   @SuppressWarnings("unchecked")   T expandedObject = (T) ois.readObject();   return expandedObject;  } finally {   gs.close();   ois.close();  } }}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-5075688311695129521?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/5075688311695129521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/05/java-compression.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5075688311695129521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5075688311695129521'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/05/java-compression.html' title='Java Compression.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-3143003732171505363</id><published>2011-04-05T14:34:00.000+02:00</published><updated>2011-04-05T14:34:32.934+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Little Spring Gem: ReflectionTestUtils</title><content type='html'>I have recently been slacking on content on my blog, between long stressful hours at work and to the wonderful toy that is an iPhone, I have taken a little break from anything "development" related after leaving the office to maintain my sanity. Now with the project delivered, and things quieting down again I can re-focus my excess neuron energy back to processing more IT related information. &lt;br /&gt;&lt;br /&gt;One little thing I discovered in my last project, which I am a little embarrassed about, being a Spring nut, is the little gem that is : &lt;a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/util/ReflectionTestUtils.html"&gt;ReflectionTestUtils&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I mostly try write unit tests that do not include Spring, for the reason, that you should be testing your code and not Spring config. However sometimes it's really useful and quite beneficial to have your test code wired up with Spring, be that for integration tests or just to extend your test suite.&lt;br /&gt;One issue was, I always found myself adding "setters" to my component interfaces,  I always hated doing it, but I would con myself by saying: "It was for more testing, and more testing is always a good thing", and move along. I eventually  (while procrastinating on work I didn't really want to do) went searching for a cleaner solution. &lt;br /&gt;&lt;br /&gt;1 search and 1 minute later, a little red faced, I kicked myself. I should have guessed straight away that Spring would have thought of this scenario From 2.5 Spring had the &lt;a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/util/ReflectionTestUtils.html"&gt;ReflectionTestUtils&lt;/a&gt; class, which simply lets you set your dependencies / mocks via reflection.&lt;br /&gt;&lt;br /&gt;So easy, tell it which object, the name of the field and set the mock / value you want to set. Neater interfaces, good times.&lt;br /&gt;Below is an example using &lt;a href="http://www.easymock.org/"&gt;EasyMock&lt;/a&gt; interfaces and inject them for my test.&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;BlobDAO blobDao = createMock(BlobDAO.class);expect(blobDao.create(anyObject(GenericBlob.class))).andReturn(1L);replay(blobDao);ReflectionTestUtils.setField(sim, "blobDao", blobDao);sim.simlulate();&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-3143003732171505363?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/3143003732171505363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/04/little-spring-gem-reflectiontestutils.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3143003732171505363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3143003732171505363'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/04/little-spring-gem-reflectiontestutils.html' title='Little Spring Gem: ReflectionTestUtils'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-7853439553696860988</id><published>2011-03-13T16:19:00.003+02:00</published><updated>2011-05-03T08:59:45.024+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Big-O'/><category scheme='http://www.blogger.com/atom/ns#' term='General Info'/><title type='text'>The simple Big-O Notation Post.</title><content type='html'>I make no claim to be a "computer scientist" or a software "engineer", those titles alone can spark some debate, I regard myself as a software developer and I generally don't study the math and science behind everything I do. I generally learn what is relevant and useful to my day to day functioning and only rarely go deeper and dabble in the theory behind it. This is one of those occasions, so I decided to scour the internet and see what I could pick up. I hope to keep this simple, practical and to the point.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Big-O:&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Describes how the algorithm scales and performs, in terms of either the execution time required or the space used.&lt;/li&gt;&lt;li&gt;Is relative representation of complexity. This allows you to reduce an  algorithm to a variable which in turn allows you to easily compare it to  another.&lt;/li&gt;&lt;li&gt;Describes an upper limit on the growth of a function, in the other words the "worst case scenario".&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;i&gt; There is also Big-Omega notation which looks at the&lt;/i&gt; &lt;i&gt;lower bound&amp;nbsp; / "best case scenario" stating that the algorithm will take at least X amount of time and Big-Theta which is&lt;/i&gt;&lt;i&gt; tight bound to both lower and upper / "average".&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b class="bbc"&gt;&lt;span class="bbc_underline"&gt;Some quick observations in determining Big-O:&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A Sequence of statements, or things like conditional checks are constant: O(1)&lt;/li&gt;&lt;li&gt;A loop of statements result in : O(n) n being the number of loop executions.&lt;/li&gt;&lt;li&gt;Nested loops are multiplied together: O(n&lt;sup&gt;2&lt;/sup&gt;) where n is the times the outer loop executes and m is the times the inner loop executes.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Comparing the common notation examples:&lt;/b&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="font-size: x-small;"&gt;(Thanks to &lt;a href="http://www.leepoint.net/notes-java/algorithms/big-oh/bigoh.html"&gt;Algorithms: Big-Oh Notation&lt;/a&gt;.)&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;table border="1" cellpadding="4" cellspacing="0" summary="example O(N) values"&gt;&lt;tbody&gt;&lt;tr valign="bottom"&gt;&lt;th&gt;n&lt;/th&gt;&lt;th&gt;Constant&lt;i&gt;&amp;nbsp;&lt;/i&gt;&lt;br /&gt;&lt;i&gt; &lt;/i&gt;O(1)&lt;/th&gt;     &lt;th&gt;&lt;table border="1" cellpadding="4" cellspacing="0" summary="example O(N) values"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Logarithmic&lt;br /&gt;O(log n)&lt;/th&gt;     &lt;th&gt;Linear&lt;br /&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;O(n)&lt;/th&gt;     &lt;th&gt;Linear Logarithmic&lt;br /&gt;O(n log n)&lt;/th&gt;     &lt;th&gt;Quadractic&lt;br /&gt;O(n&lt;sup&gt;2&lt;/sup&gt;)&lt;/th&gt;&lt;th&gt;Cubic&lt;br /&gt;O(n&lt;sup&gt;3&lt;/sup&gt;)&lt;/th&gt;&lt;/tr&gt;&lt;tr align="right"&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr align="right"&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;/tr&gt;&lt;tr align="right"&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;64&lt;/td&gt;&lt;/tr&gt;&lt;tr align="right"&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;64&lt;/td&gt;&lt;td&gt;512&lt;/td&gt;&lt;/tr&gt;&lt;tr align="right"&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;64&lt;/td&gt;&lt;td&gt;256&lt;/td&gt;&lt;td&gt;4,096&lt;/td&gt;&lt;/tr&gt;&lt;tr align="right"&gt;&lt;td&gt;1,024&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;1,024&lt;/td&gt;&lt;td&gt;10,240&lt;/td&gt;&lt;td&gt;1,048,576&lt;/td&gt;&lt;td&gt;1,073,741,824&lt;/td&gt;&lt;/tr&gt;&lt;tr align="right"&gt;&lt;td&gt;1,048,576&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;1,048,576&lt;/td&gt;&lt;td&gt;20,971,520&lt;/td&gt;&lt;td&gt;10&lt;sup&gt;12&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;10&lt;sup&gt;16&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Java code example:&lt;/b&gt;&lt;br /&gt;Show examples of notations in the table above.&amp;nbsp;&lt;b&gt; &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;/** * The Class BigOExamples. */public class BigOExamples { /**  * Constant. O(1)  *   * @param n the n  * @return the int  */ public int constant(int n) {  if (n &gt; 1) {   return n;  } else {   return 0;  } } /**  * Linear. O(n)  *   * @param n the n  * @return the int  */ public int linear(int n) {  int sum = 0;  for (int j = 0; j &lt; n; j++) {   sum += j;  }  return sum; } /**  * Quadratic. O(n^2)  *   * @param n the n  * @return the int  */ public int quadratic(int n) {  int sum = 0;  for (int j = 0; j &lt; n; j++) {   for (int k = 0; k &lt; n; k++) {    sum += j * k;   }  }  return sum; } /**  * Cubic. O(n^3)  *   * @param n the n  * @return the int  */ public int cubic(int n) {  int sum = 0;  for (int j = 0; j &lt; n; j++) {   for (int k = 0; k &lt; n; k++) {    for (int l = 0; l &lt; n; l++) {     sum += j * k / (l + 1);    }   }  }  return sum; } /**  * Logarithmic. O(log n). Binary Search.  *   * @param data the to search  * @param key the key  * @return the int  */ public int logarithmic(Integer[] data, int key) {  int startIndex = 0;  int endIndex = data.length - 1;  while (startIndex &lt; endIndex) {   int midIndex = (endIndex - startIndex / 2) + startIndex;   int midValue = data[midIndex];   if (key &gt; midValue) {    startIndex = midIndex++;   } else if (key &lt; midValue) {    endIndex = midIndex - 1;   } else {    return midIndex;   }  }  return -1; } /**  * Linear Logarithmic. O(n log n). Quick Sort.  *   * @param data the to search  * @param key the key  * @return the int  */ public Integer linearLogarithmic(Integer[] data) {  QuickSort&lt;Integer&gt; sorter = new QuickSort&lt;integer&gt;();  sorter.sort(data);  return data[0]; }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;/** * The Class QuickSort. *  * @param &lt;t&gt; the generic type */public class QuickSort&lt;t extends Comparable&lt;T&gt;&gt; { /**  * Sort.  *   * @param array the array  */ public void sort(T[] array) {  array = quicksort(array, 0, array.length - 1); } /**  * Quicksort.  *   * @param array the array  * @param lo the lo  * @param hi the hi  * @return the t[]  */ private T[] quicksort(T[] array, int lo, int hi) {  if (hi &gt; lo) {   int partitionPivotIndex = (int) (Math.random() * (hi - lo) + lo);   int newPivotIndex = partition(array, lo, hi, partitionPivotIndex);   quicksort(array, lo, newPivotIndex - 1);   quicksort(array, newPivotIndex + 1, hi);  }  return (T[]) array; } /**  * Partition.  *   * @param array the array  * @param lo the lo  * @param hi the hi  * @param pivotIndex the pivot index  * @return the int  */ private int partition(T[] array, int lo, int hi, int pivotIndex) {  T pivotValue = array[pivotIndex];  swap(array, pivotIndex, hi); // send to the back  int index = lo;  for (int i = lo; i &lt; hi; i++) {   if ((array[i]).compareTo(pivotValue) &lt;= 0) {    swap(array, i, index);    index++;   }  }  swap(array, hi, index);  return index; } /**  * Swap.  *   * @param array the array  * @param i the i  * @param j the j  */ private void swap(T[] array, int i, int j) {  T temp = array[i];  array[i] = array[j];  array[j] = temp; }}&lt;/script&gt;&lt;u&gt;&lt;b&gt;Common Data Structures and Relative functions:&lt;/b&gt;&lt;/u&gt;&lt;b&gt;Lists and Sets:&lt;/b&gt;&lt;table border="1" cellpadding="4" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr&gt; &lt;th&gt;Structure&lt;/th&gt;&lt;th&gt;get&lt;/th&gt;&lt;th&gt;add&lt;/th&gt;&lt;th&gt;remove&lt;/th&gt;&lt;th&gt;contains&lt;/th&gt; &lt;/tr&gt;&lt;tr align="Left"&gt; &lt;td&gt;ArrayList&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;b&gt;*&lt;/b&gt;&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt; &lt;/tr&gt;&lt;tr align="Left"&gt; &lt;td&gt;LinkedList&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt; &lt;/tr&gt;&lt;tr align="Left"&gt; &lt;td&gt;HashSet&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt; &lt;/tr&gt;&lt;tr align="Left"&gt; &lt;td&gt;LinkedHashSet&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt; &lt;/tr&gt;&lt;tr align="Left"&gt; &lt;td&gt;TreeSet&lt;/td&gt;&lt;td&gt;O(log n)&lt;/td&gt;&lt;td&gt;O(log n)&lt;/td&gt;&lt;td&gt;O(log n)&lt;/td&gt;&lt;td&gt;O(log n)&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&lt;b&gt;&lt;i&gt;* ArrayList Notes:&lt;/b&gt;&lt;p&gt;Thanks to reader comments, the add method on an ArrayList should be:O(1) amortized (and O(n) in worse case).Useful reference links:&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/200384/constant-amortized-time"&gt;Constant Amortized Time&lt;/a&gt;&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/322715/when-to-use-linkedlist-over-arraylist"&gt;Linked List vs ArrayList&lt;/a&gt;&lt;/i&gt;&lt;p&gt;&lt;b&gt;Maps:&lt;/b&gt;&lt;table border="1" cellpadding="4" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr&gt; &lt;th&gt;Structure&lt;/th&gt;&lt;th&gt;get&lt;/th&gt;&lt;th&gt;put&lt;/th&gt;&lt;th&gt;remove&lt;/th&gt;&lt;th&gt;containsKey&lt;/th&gt; &lt;/tr&gt;&lt;tr align="Left"&gt; &lt;td&gt;HashMap&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt; &lt;/tr&gt;&lt;tr align="Left"&gt; &lt;td&gt;LinkedHashMap&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt; &lt;/tr&gt;&lt;tr align="Left"&gt; &lt;td&gt;TreeMap&lt;/td&gt;&lt;td&gt;O(log n)&lt;/td&gt;&lt;td&gt;O(log n)&lt;/td&gt;&lt;td&gt;O(log n)&lt;/td&gt;&lt;td&gt;O(log n)&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&lt;b&gt;References:&lt;/b&gt;&lt;p&gt;&lt;a href="http://www.leepoint.net/notes-java/algorithms/big-oh/bigoh.html"&gt;Algorithms: Big-Oh Notation&lt;/a&gt;.&lt;p&gt;&lt;a href="http://science.slc.edu/%7Ejmarshall/courses/2002/spring/cs50/BigO/index.html"&gt;Algorithmic Complexity and Big-O Notation&lt;/a&gt;.&lt;p&gt;&lt;a href="http://www.dreamincode.net/forums/topic/125427-determining-big-o-notation/"&gt;Determining Big O Notation An easier way &lt;/a&gt;.&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Big_O_notation"&gt;Wikipedia&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-7853439553696860988?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/7853439553696860988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/03/simple-big-o-notation-post.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/7853439553696860988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/7853439553696860988'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/03/simple-big-o-notation-post.html' title='The simple Big-O Notation Post.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-4448937811650879567</id><published>2011-02-20T23:46:00.002+02:00</published><updated>2011-02-22T05:59:44.924+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Review'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Personal'/><title type='text'>Selecting a new programming language to learn.</title><content type='html'>I have been itching to learn a new language, but being a Java freak, I always end up convincing myself to spend the time and effort discovering, investigating or playing with something in the Java open source stable, Spring, Hadoop, Joda Time, Hibernate, Maven, Hazelcast, EhCache etc etc. Developing in Java these days is almost purely about knowing and wiring together frameworks, which is both a good and a bad thing. (&lt;i&gt;as well as a topic for another day&lt;/i&gt;).&lt;br /&gt;&lt;br /&gt;Now to get myself to not redirect the "new language" energy into Y.A.F (yet another framework) I decided to give the languages out there a proper look and see which would be the best fit and most beneficial to my work, marketability and just general 'IT Zen'.&lt;br /&gt;&lt;br /&gt;So what do I require from a language:&lt;br /&gt;&lt;b&gt;IDE...&lt;/b&gt; my number 1 thing is an IDE, if there isn't a decent IDE for a language it is frankly not worth the time and effort. I don't see myself as a  "scientist" where I feel the need to cause myself pain and inconvenience to be "pure". I want a comfortable productive working environment, and VI or Notepad with a command line utility ain't it.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Established...&lt;/b&gt; Every couple years someone somewhere tries to define some new language, and most of those die in obscurity for example &lt;a href="http://en.wikipedia.org/wiki/Brainfuck"&gt;brainf***&lt;/a&gt; or anything listed on &lt;a href="http://esolangs.org/wiki/Main_Page"&gt;Esolang&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Popular / In Demand...&lt;/b&gt; As with most things, popularity is good, it means:&lt;br /&gt;open source community, support and most importantly jobs. If you ever want to see the current popularity of a language &lt;a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;Tiobe&lt;/a&gt; is the site to visit.&lt;br /&gt;&lt;br /&gt;So who are the contenders out there?&lt;br /&gt;Based on Feb 2011 &lt;a href="http://www.tiobe.com"&gt;Tiobe&lt;/a&gt; index:&lt;br /&gt;Java is still the no.1 most popular, it has awesome IDEs and it's been around for just more than 15 years &lt;a href="http://en.wikipedia.org/wiki/Java_version_history"&gt;(January 23, 1996)&lt;/a&gt;, but thankfully I know Java reasonably well :)... so moving right along...  To narrow down the list quickly, I won't look at any languages that are losing popularity, for obvious reasons, so from the top 20 on the &lt;a href="http://www.tiobe.com"&gt;Tiobe&lt;/a&gt; list that excludes: C, C++, PHP, VB, JS, Perl, Ruby, Delphi, Go.&lt;br /&gt;(&lt;strike&gt;C, C++, PHP, VB, JS, Perl, Ruby, Delphi, Go.&lt;/strike&gt;)&lt;br /&gt;&lt;br /&gt;Which leaves behind: &lt;br /&gt;Python, C#, Objective-C, Lisp, NXT-G, Ada, Pascal, Lua, RPG&lt;br /&gt;&lt;br /&gt;Now there is a line between established and old, I am going to make a call that could offend some people and say Pascal and RPG are just old. (&lt;strike&gt;Pascal&lt;/strike&gt;, &lt;strike&gt;RPG&lt;/strike&gt;) &lt;br /&gt;&lt;br /&gt;Ada, don't know much about it, after reading &lt;a href="http://libre.adacore.com/home/ada_answers/ada_overview/"&gt;the ADA overview&lt;/a&gt;, it seems okay, going to exclude it based on popularity. (&lt;strike&gt;Ada&lt;/strike&gt;)&lt;br /&gt;&lt;br /&gt;Lua, from a quick read it is a scripting language. (&lt;strike&gt;Lua&lt;/strike&gt;)&lt;br /&gt;&lt;br /&gt;NXT-G has something to do with lego or some robotics, not very mainstream. (&lt;strike&gt;NXT-G&lt;/strike&gt;)&lt;br /&gt;&lt;br /&gt;Lisp again like Ada, at first glace seems fine, just not popular enough. (&lt;strike&gt;Lisp&lt;/strike&gt;)&lt;br /&gt;&lt;br /&gt;Then there are the "New, built on other platforms" functional languages: Scala, F#, Clojure. Although very temping being on the bleeding edge, it's not all that profitable or marketable yet. I'll give them some time to standardize, settle down and see if they are widely adopted. They do appeal greatly to my inner geek, so will always be keeping an eye on them.&lt;br /&gt;&lt;br /&gt;So this leaves me with:&lt;br /&gt;Python, C#, Objective-C, &lt;i&gt;(and Java)&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Straight away based on the above list we can Tick: IDE, Established and Popular / In demand. We all know they have decent IDEs: Eclipse, XCode, Visual Studio, (IntelliJ and Netbeans). They have also been around and are well known.&lt;br /&gt;&lt;br /&gt;Now looking at number of jobs:&lt;br /&gt;Found a site (&lt;a href="http://www.simplyhired.com"&gt;Simply hired&lt;/a&gt;) with a graph displays the percentage of jobs with your search terms anywhere in the job listing. Since June 2009, the following has occurred:&lt;br /&gt;&lt;br /&gt;Python jobs increased 72%&lt;br /&gt;C# jobs increased 77%&lt;br /&gt;Objective-c jobs increased 268%&lt;br /&gt;Java jobs increased 76%&lt;br /&gt;&lt;br /&gt;&lt;!-- BEGIN TREND GRAPH --&gt;&lt;div style="width: 540px;" class="chart"&gt;&lt;img src="http://www.simplyhired.com/a/jobtrends/graph/q-Python,+C%23,+Objective-c,+Java/t-line/embed" alt="Python, C#, Objective-c, Java trends" /&gt;&lt;table width="100%" style="font-size: 80%;"&gt;&lt;tr&gt;&lt;td width="2%"&gt;&amp;nbsp;&lt;/td&gt;&lt;td align="left"&gt;&lt;a href="http://www.simplyhired.com/a/jobtrends/trend/q-Python,+C%23,+Objective-c,+Java"&gt;Python, C#, Objective-c, Java trends&lt;/a&gt;&lt;/td&gt;&lt;td align="right"&gt;&lt;a href="http://www.simplyhired.com/a/jobs/list/q-Python"&gt;Python jobs&lt;/a&gt; | &lt;a href="http://www.simplyhired.com/a/jobs/list/q-C%23"&gt;C# jobs&lt;/a&gt; | &lt;a href="http://www.simplyhired.com/a/jobs/list/q-Objective-c"&gt;Objective-c jobs&lt;/a&gt; | &lt;a href="http://www.simplyhired.com/a/jobs/list/q-Java"&gt;Java jobs&lt;/a&gt;&lt;/td&gt;&lt;td width="2%"&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;!-- END TREND GRAPH --&gt;&lt;br /&gt;&lt;br /&gt;With the recent boom of iPads and iPhones the Objective-C percentage is not all that surprising. I do have a problem with Apple, Objective-C and XCode and that problem is you need a Mac to run it. Once you start down that road you end up having to change everything to Apple, and I am not ready to do that. So for now I am going to drop &lt;strike&gt;Objective-C&lt;/strike&gt; out of the running. Although if I ever do buy into the whole Apple thing, this will got back to the list.&lt;br /&gt;&lt;br /&gt;Leaving me with Python and C#, looking at their salaries compared with Java: &lt;br /&gt;(Data from &lt;a href="http://www.payscale.com/"&gt;Payscale&lt;/a&gt;).&lt;br /&gt;&lt;b&gt;&lt;u&gt;US Data&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Java&lt;/b&gt;&lt;br /&gt;&lt;a href="http://www.payscale.com/research/US/Skill=Java/Salary"&gt;PayScale - Java Skill Salary, Average Salaries by Years Experience&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background:white;color:#333;font:normal 11pt Verdana,Arial,sans-serif;text-align:center;border:1px solid #96b9d7;padding:5px;width:300px;"&gt;&lt;a href="http://www.payscale.com/research/US/Skill=Java/Salary/by_Years_Experience" style="color:#06C;text-decoration: none;font-weight:bold;"&gt;Median Salary by Years Experience - Skill: Java (United States)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.payscale.com/research/US/Skill=Java/Salary/by_Years_Experience"&gt;&lt;img src="http://www.payscale.com/research/US/Skill=Java/Salary/by_Years_Experience/300.png" alt="Median Salary by Years Experience" border="0" style="margin-top:10px;" /&gt;&lt;/a&gt;&lt;a href="http://www.payscale.com" border="0"&gt;&lt;img src="http://www.payscale.com/images/embed_upsell.jpg" alt="PayScale Salary Calculator" border="0" /&gt;&lt;/a&gt;&lt;p style="padding: 5px 2px;margin: 0;border-top: solid 1px #96b9d7;font:normal 10px Verdana,Arial,sans-serif;"&gt;&lt;strong&gt;CAREER TOOLS:&lt;/strong&gt; &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/salary-calculator"&gt;Salary Calculator&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/gigzig.aspx"&gt;Career Path Tool&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/cost-of-living-calculator"&gt;Cost of Living Calculator&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/meeting-miser"&gt;Meeting Miser&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Python&lt;/b&gt;&lt;br /&gt;&lt;a href="http://www.payscale.com/research/US/Skill=Python/Salary"&gt;PayScale - Python Skill Salary, Average Salaries by Years Experience&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background:white;color:#333;font:normal 11pt Verdana,Arial,sans-serif;text-align:center;border:1px solid #96b9d7;padding:5px;width:300px;"&gt;&lt;a href="http://www.payscale.com/research/US/Skill=Python/Salary/by_Years_Experience" style="color:#06C;text-decoration: none;font-weight:bold;"&gt;Median Salary by Years Experience - Skill: Python (United States)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.payscale.com/research/US/Skill=Python/Salary/by_Years_Experience"&gt;&lt;img src="http://www.payscale.com/research/US/Skill=Python/Salary/by_Years_Experience/300.png" alt="Median Salary by Years Experience" border="0" style="margin-top:10px;" /&gt;&lt;/a&gt;&lt;a href="http://www.payscale.com" border="0"&gt;&lt;img src="http://www.payscale.com/images/embed_upsell.jpg" alt="PayScale Salary Calculator" border="0" /&gt;&lt;/a&gt;&lt;p style="padding: 5px 2px;margin: 0;border-top: solid 1px #96b9d7;font:normal 10px Verdana,Arial,sans-serif;"&gt;&lt;strong&gt;CAREER TOOLS:&lt;/strong&gt; &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/salary-calculator"&gt;Salary Calculator&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/gigzig.aspx"&gt;Career Path Tool&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/cost-of-living-calculator"&gt;Cost of Living Calculator&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/meeting-miser"&gt;Meeting Miser&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;C#&lt;/b&gt;&lt;br /&gt;&lt;a href="http://www.payscale.com/research/US/Skill=C%2523/Salary"&gt;PayScale - C# Skill Salary, Average Salaries by Years Experience&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background:white;color:#333;font:normal 11pt Verdana,Arial,sans-serif;text-align:center;border:1px solid #96b9d7;padding:5px;width:300px;"&gt;&lt;a href="http://www.payscale.com/research/US/Skill=C%2523/Salary/by_Years_Experience" style="color:#06C;text-decoration: none;font-weight:bold;"&gt;Median Salary by Years Experience - Skill: C# (United States)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.payscale.com/research/US/Skill=C%2523/Salary/by_Years_Experience"&gt;&lt;img src="http://www.payscale.com/research/US/Skill=C%2523/Salary/by_Years_Experience/300.png" alt="Median Salary by Years Experience" border="0" style="margin-top:10px;" /&gt;&lt;/a&gt;&lt;a href="http://www.payscale.com" border="0"&gt;&lt;img src="http://www.payscale.com/images/embed_upsell.jpg" alt="PayScale Salary Calculator" border="0" /&gt;&lt;/a&gt;&lt;p style="padding: 5px 2px;margin: 0;border-top: solid 1px #96b9d7;font:normal 10px Verdana,Arial,sans-serif;"&gt;&lt;strong&gt;CAREER TOOLS:&lt;/strong&gt; &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/salary-calculator"&gt;Salary Calculator&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/gigzig.aspx"&gt;Career Path Tool&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/cost-of-living-calculator"&gt;Cost of Living Calculator&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/meeting-miser"&gt;Meeting Miser&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;South Africa Data&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Java&lt;/b&gt;&lt;br /&gt;&lt;a href="http://www.payscale.com/research/ZA/Skill=Java/Salary"&gt;PayScale - Java Skill Salary, Average Salaries by Years Experience&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background:white;color:#333;font:normal 11pt Verdana,Arial,sans-serif;text-align:center;border:1px solid #96b9d7;padding:5px;width:300px;"&gt;&lt;a href="http://www.payscale.com/research/ZA/Skill=Java/Salary/by_Years_Experience" style="color:#06C;text-decoration: none;font-weight:bold;"&gt;Median Salary by Years Experience - Skill: Java (South Africa)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.payscale.com/research/ZA/Skill=Java/Salary/by_Years_Experience"&gt;&lt;img src="http://www.payscale.com/research/ZA/Skill=Java/Salary/by_Years_Experience/300.png" alt="Median Salary by Years Experience" border="0" style="margin-top:10px;" /&gt;&lt;/a&gt;&lt;a href="http://www.payscale.com" border="0"&gt;&lt;img src="http://www.payscale.com/images/embed_upsell.jpg" alt="PayScale Salary Calculator" border="0" /&gt;&lt;/a&gt;&lt;p style="padding: 5px 2px;margin: 0;border-top: solid 1px #96b9d7;font:normal 10px Verdana,Arial,sans-serif;"&gt;&lt;strong&gt;CAREER TOOLS:&lt;/strong&gt; &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/salary-calculator"&gt;Salary Calculator&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/gigzig.aspx"&gt;Career Path Tool&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/cost-of-living-calculator"&gt;Cost of Living Calculator&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/meeting-miser"&gt;Meeting Miser&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Python&lt;/b&gt;&lt;br /&gt;&lt;a href="http://www.payscale.com/research/ZA/Skill=Python/Salary"&gt;PayScale - Python Skill Salary, Average Salaries by Years Experience&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background:white;color:#333;font:normal 11pt Verdana,Arial,sans-serif;text-align:center;border:1px solid #96b9d7;padding:5px;width:300px;"&gt;&lt;a href="http://www.payscale.com/research/ZA/Skill=Python/Salary/by_Years_Experience" style="color:#06C;text-decoration: none;font-weight:bold;"&gt;Median Salary by Years Experience - Skill: Python (South Africa)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.payscale.com/research/ZA/Skill=Python/Salary/by_Years_Experience"&gt;&lt;img src="http://www.payscale.com/research/ZA/Skill=Python/Salary/by_Years_Experience/300.png" alt="Median Salary by Years Experience" border="0" style="margin-top:10px;" /&gt;&lt;/a&gt;&lt;a href="http://www.payscale.com" border="0"&gt;&lt;img src="http://www.payscale.com/images/embed_upsell.jpg" alt="PayScale Salary Calculator" border="0" /&gt;&lt;/a&gt;&lt;p style="padding: 5px 2px;margin: 0;border-top: solid 1px #96b9d7;font:normal 10px Verdana,Arial,sans-serif;"&gt;&lt;strong&gt;CAREER TOOLS:&lt;/strong&gt; &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/salary-calculator"&gt;Salary Calculator&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/gigzig.aspx"&gt;Career Path Tool&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/cost-of-living-calculator"&gt;Cost of Living Calculator&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/meeting-miser"&gt;Meeting Miser&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;C#&lt;/b&gt;&lt;br /&gt;&lt;a href="http://www.payscale.com/research/ZA/Skill=C%2523/Salary"&gt;PayScale - C# Skill Salary, Average Salaries by Years Experience&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background:white;color:#333;font:normal 11pt Verdana,Arial,sans-serif;text-align:center;border:1px solid #96b9d7;padding:5px;width:300px;"&gt;&lt;a href="http://www.payscale.com/research/ZA/Skill=C%2523/Salary/by_Years_Experience" style="color:#06C;text-decoration: none;font-weight:bold;"&gt;Median Salary by Years Experience - Skill: C# (South Africa)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.payscale.com/research/ZA/Skill=C%2523/Salary/by_Years_Experience"&gt;&lt;img src="http://www.payscale.com/research/ZA/Skill=C%2523/Salary/by_Years_Experience/300.png" alt="Median Salary by Years Experience" border="0" style="margin-top:10px;" /&gt;&lt;/a&gt;&lt;a href="http://www.payscale.com" border="0"&gt;&lt;img src="http://www.payscale.com/images/embed_upsell.jpg" alt="PayScale Salary Calculator" border="0" /&gt;&lt;/a&gt;&lt;p style="padding: 5px 2px;margin: 0;border-top: solid 1px #96b9d7;font:normal 10px Verdana,Arial,sans-serif;"&gt;&lt;strong&gt;CAREER TOOLS:&lt;/strong&gt; &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/salary-calculator"&gt;Salary Calculator&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/gigzig.aspx"&gt;Career Path Tool&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/cost-of-living-calculator"&gt;Cost of Living Calculator&lt;/a&gt;, &lt;a style="color: #000;text-decoration: none;" href="http://www.payscale.com/meeting-miser"&gt;Meeting Miser&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;Based on the US data, I would have gone with Python, it's not as popular as C# but the pay is slightly better, I would also get to keep using Eclipse (&lt;a href="http://pydev.org/"&gt;PyDev&lt;/a&gt;) and Spring, but as soon as I looked at the South African data, I realized something, Python is really not big here. I manually went searching for Python positions advertised.. and found a grand total of 2 and the salaries were not good.&lt;br /&gt;&lt;br /&gt;(&lt;strike&gt;Python&lt;/strike&gt;)&lt;br /&gt;&lt;br /&gt;Leaving C# as the last language standing. &lt;br /&gt;&lt;br /&gt;It's got Visual Studio (even a free version &lt;a href="http://www.microsoft.com/express/Downloads/"&gt;Visual Studio Express&lt;/a&gt;), It has proven itself over the last couple years, it's out innovating Java at the moment, there's a ton of jobs, a whole range of certifications and the salaries have closed the gap on Java.&lt;br /&gt;Seems quite a logical choice to me.&lt;br /&gt;&lt;br /&gt;To top it off, I have also used C# many years back, so it won't not entirely new. Most of the successful Java open source projects (Spring, Hibernate etc etc) have been ported so all that knowledge is reusable, which also counted a little in my decision. Now I just need to stop working 12-14 hours a day, and I can focus on getting back to my Microsoft roots with little C# as a Java developer. Hopefully a couple months after that I can go through this process again, looking at Python, Objective-C, the mobile platforms (iOS, Android, windows) or maybe rather a concept change to functional with the likes of Clojure or Scala.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-4448937811650879567?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/4448937811650879567/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/02/selecting-new-programming-language-to.html#comment-form' title='24 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4448937811650879567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4448937811650879567'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/02/selecting-new-programming-language-to.html' title='Selecting a new programming language to learn.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>24</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-9206066488025361307</id><published>2011-02-14T07:09:00.000+02:00</published><updated>2011-02-14T07:09:56.148+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Code Snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='XSD'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><title type='text'>Validate XML against its XSD</title><content type='html'>Just a quick code snippet for possible future reference. How to validate a XML against it's XSD.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.blg.xml;import static org.junit.Assert.assertEquals;import static org.junit.Assert.assertNull;import static org.junit.Assert.fail;import java.io.File;import java.io.IOException;import java.net.URL;import javax.xml.transform.Source;import javax.xml.transform.stream.StreamSource;import javax.xml.validation.Schema;import javax.xml.validation.SchemaFactory;import javax.xml.validation.Validator;import org.junit.Before;import org.junit.Test;import org.xml.sax.SAXException;public class XMLXSDTest { private static final String XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; @Test public void testXSDDefaultXML() throws SAXException, IOException {         final SchemaFactory factory = SchemaFactory.newInstance(XML_SCHEMA);  final URL schemaUrl = XMLXSDTest.class.getClassLoader().getResource("test.xsd");  final URL xmlURL = XMLXSDTest.class.getClassLoader().getResource("test.xml");  final File schemaFile = new File(schemaUrl.getFile());  final File defaultXML = new File(xmlURL.getFile());    final Schema schema = factory.newSchema(schemaFile);  final Validator validator = schema.newValidator();  final Source source = new StreamSource(defaultXML);  try {   validator.validate(source);   System.out.println(defaultXML + " is valid.");  } catch (final SAXException ex) {   fail(defaultXML + " is not valid because: " + ex.getMessage());   ex.printStackTrace();  } }}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-9206066488025361307?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/9206066488025361307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/02/validate-xml-against-its-xsd.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/9206066488025361307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/9206066488025361307'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/02/validate-xml-against-its-xsd.html' title='Validate XML against its XSD'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-4027681552127444926</id><published>2011-02-07T07:32:00.001+02:00</published><updated>2011-02-07T08:14:26.806+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Development Process'/><category scheme='http://www.blogger.com/atom/ns#' term='General Info'/><title type='text'>Surviving the Wild West Development Process</title><content type='html'>Now in a perfect world, we all strive for a some kind of development process, be that: Waterfall development, Prototyping, all things Agile or whatever process the CIO / CTO /CEO got sold on by some consultancy.&lt;br /&gt;&lt;br /&gt;But in the real world what sometimes ("sometimes" being quite often actually) happens is:&lt;br /&gt;What I like to call the Wild West Development Process (WWDP)... the main principle is basically “promise first and ask questions later”.&lt;br /&gt;&lt;br /&gt;Getting started with WWDP is pretty simple:&lt;br /&gt;1. You need someone, somewhere in a place of power and influence in your organization to promise software by some unachievable date.&lt;br /&gt;2. Add in a eager marketing department and some press releases… &lt;br /&gt;3. stir and leave to simmer.&lt;br /&gt;4. After simmering for a while inform the software development department that they must have something, that does "stuff" and the release date can not change.&lt;br /&gt;&lt;br /&gt;I am not sure if this is a result of a immature IT industry in my country, but I have spent many years in environments like this. It even seems to find me in the most unlikely employers, the large corporate organizations like insurance and  banking institutions, where general red tape and corporate processes should limit this.  I started my career in one of those “startup-sell-information-tech-and-business-processes-to-anyone-cheaper-than -anyone-else-type-consultancies". Which means every project was driven by WWDP so I started in the deep end, and for about 4 years I knew no other way of developing software. I currently find myself in another one of those projects. I'd like to share some points that I found helpful in actually delivering some software in unimaginable unmovable deadlines.&lt;br /&gt;&lt;i&gt;(to be fair some of these are in the standard development processes mentioned earlier, maybe with just different priorities)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Pick the right developers&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;Not everyone can cope in this environment, knowing your staff / team is very important: late nights, constant crisis, constant changes and bucket loads of pressure and stress aren't for everyone. Some people thrive, some survive and run for the hills after, some just end up whimpering in the corner and need to be replaced (which is a disaster).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Have the developers involved.&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;Projects like these don't allow for the usual requirements / design / develop / test paradigm, all of these functions run concurrently. Having the developers know as much detail as the architect, analysts and testers is vital. Developers will have to make decisions affecting the architecture and business functionality constantly, if everyone has the same picture you'll save time.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;"Prototype" early&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;I say "Prototype" in quotes because unlike an actual prototype there won't be time to throw this code away. This "prototype" is to have the system in it's entirety up and running very early in the project. It can be a "shell" but having it up means testing can start early even if it's just the basics and no business functionality. Since there are no real requirements, make sure the design caters for adding them as they are defined.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Integrate early&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;If the system has any integration points, between systems, teams or external parties, make sure this is also in the "Prototype Shell", integration always takes longer than you think, having the interfaces up and available to test is crucial.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Keep track of communication&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;When the shock of not meeting an unachievable deadline kicks in, someone will always look for a scapegoat, always keep at least an email trail making sure you aren't that goat.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Automated builds and deploys&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;The standard agile practice of continuous integration is as important as ever, and even if you skip other parts of you software development cycle this is something that should not be dismissed.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Focus&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;With hundreds of things that need to happen a matter of days or weeks, it's very easy to try do 6 things at a time. Don't. Micro manage your time and tasks and focus. It's easy for us developers to start a task, see something, change something and lose a day which you don't have in the first place. If you have to, have someone keep an extensive list of "TODOs" that can be used in the cleanup phase.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Clean up&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;Once the unachievable deadline has been met, before starting the next phase, have at least one "cleanup" release. This cleanup phase should add very little or preferably no new functionality, but will allow for design and development decisions made in haste to be reviewed and refactored.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Pace Yourself&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;No matter how super human you may think you are, all of us have a limit to how many hours we can keep going. At some point you are actually being counter productive and a couple more hours sleep will actually help the project a lot more.&lt;br /&gt;Know your limits.&lt;br /&gt;&lt;br /&gt;I am sure there are a couple more, but currently being on a WWDP project I need to re-focus and leave that for the clean up phase later :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-4027681552127444926?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/4027681552127444926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/02/surviving-wild-west-development-process.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4027681552127444926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4027681552127444926'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/02/surviving-wild-west-development-process.html' title='Surviving the Wild West Development Process'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-6129932924129430185</id><published>2011-01-09T23:31:00.000+02:00</published><updated>2011-01-09T23:31:15.522+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Joda Time'/><title type='text'>Joda Time == Good Times</title><content type='html'>I heard about &lt;a href="http://joda-time.sourceforge.net/"&gt;Joda Time&lt;/a&gt; a couple months back, but finally got to use and implement it in a project.&lt;br /&gt;&lt;br /&gt;We all know the whole Java date thing is ugly, and I sure most people have the own "implementations" and extensions like Period objects and utility Date Diff classes. I know I've written my fair share over the years. I won't be doing that again... &lt;br /&gt;&lt;br /&gt;I am not going to go into too much detail as the Joda documentation is pretty good.&lt;br /&gt;I just wanna highlight some of the very usual functionality that won me over:&lt;br /&gt;&lt;br /&gt;Setting the "System" time, very useful. The financial systems I have worked on throughout my career always had some concept that required the "Current Date" mostly for data and rules with effective date periods.&lt;br /&gt;&lt;br /&gt;Joda lets you statically set the "Current Date" making it a pleasure to test with, ensuring that any new DateTime objects used will be based off the set date:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;/** * Setup. *  * @throws Exception the exception */@Beforepublic void setup() throws Exception { DateTimeUtils.setCurrentMillisFixed(    new DateTime(2010, 12, 30, 8, 0, 0, 0).getMillis());}/** * Teardown. */@Afterpublic void teardown() { DateTimeUtils.setCurrentMillisSystem(); }&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Intervals:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;final DateTime testDate = new DateTime();final DateTime eightAM = testDate.withTime(8, 0, 0, 0);final DateTime twelveAM = testDate.withTime(12, 0, 0, 0);final DateTime fivePM = testDate.withTime(17, 0, 0, 0);final DateTime sevenPM = testDate.withTime(19, 0, 0, 0);final Interval morning = new Interval(eightAM, twelveAM);final Interval afternoon = new Interval(twelveAM, fivePM);final Interval earlyEvening = new Interval(fivePM, sevenPM);System.out.println("Morning: " + morning.contains(testDate));System.out.println("Afternoon: " + afternoon.contains(testDate));System.out.println("Evening: " + earlyEvening.contains(testDate));System.out.println("Morning Before Evening: " + morning.isBefore(afternoon));&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The classic Date diff:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;final DateTime startDate = new DateTime(2010, 12, 30, 19, 30, 0, 0);final DateTime endDate = new DateTime();final Days days = Days.daysBetween(startDate, endDate);final Weeks weeks = Weeks.weeksBetween(startDate, endDate);final Hours hours = Hours.hoursBetween(startDate, endDate);final Interval theInterval= new Interval(eightAM, twelveAM);  final Hours hoursInInterval = Hours.hoursIn(theInterval);&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Working with "parts", just the date or the time:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;final LocalTime localTime = new LocalTime(11, 30, 0, 0);final LocalDate localDate = new LocalDate(2010, 12, 30);&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-6129932924129430185?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/6129932924129430185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2011/01/joda-time-good-times.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6129932924129430185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6129932924129430185'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2011/01/joda-time-good-times.html' title='Joda Time == Good Times'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-1064923948273332626</id><published>2010-12-31T08:48:00.000+02:00</published><updated>2010-12-31T08:48:37.318+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>The "all you need to know link" for tuning Hibernate</title><content type='html'>I stumbled across this awesome article today: &lt;a href="http://www.infoq.com/articles/hibernate_tuning"&gt;Revving Up Your Hibernate Engine&lt;/a&gt;.&lt;br /&gt;Well worth the read if you are or are planning to use Hibernate in the near future.&lt;br /&gt;&lt;br /&gt;To quote the summary of the article:&lt;i&gt;&lt;br /&gt;"This article covers most of the tuning skills you’ll find helpful for your Hibernate application tuning. It allocates more time to tuning topics that are very efficient but poorly documented, such as inheritance mapping, second level cache and enhanced sequence identifier generators.&lt;br /&gt;&lt;br /&gt;It also mentions some database insights which are essential for tuning Hibernate.&lt;br /&gt;Some examples also contain practical solutions to problems you may encounter."&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-1064923948273332626?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/1064923948273332626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/12/all-you-need-to-know-link-for-tuning.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1064923948273332626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1064923948273332626'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/12/all-you-need-to-know-link-for-tuning.html' title='The &quot;all you need to know link&quot; for tuning Hibernate'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-618178050469580433</id><published>2010-12-24T09:38:00.000+02:00</published><updated>2010-12-24T09:38:38.473+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Find all the classes in the same package</title><content type='html'>It's been a slow month for blogging, due to the release of a new World of Warcraft expansion, crazy year end software releases at work and the general retardation of the human collective consciousness that happens this time of year.&lt;br /&gt;&lt;br /&gt;With all of that I did however have some fun writing the following bit of code. We have a "generic" getter and setter test utility used to ensure a couple extra %'s of code coverage with minimal effort. That utility did however requires that you call it for every class you want to test, being lazy I wanted to just give it a class from a specific package and have that check all the classes.&lt;br /&gt;&lt;br /&gt;I initially thought there would have to be just a simple way to do it with the Java reflection API. Unfortunately I didn't find any, it seems a "Package" does not keep track of it's classes, so after a bit of digging on the net and feverish typing &lt;i&gt;(ignoring the actual project I am currently working on for a little)&lt;/i&gt; here is what I came up with. The tip is actually the just methods from the java.lang.Class object: "getProtectionDomain().getCodeSource().getLocation().toURI()", giving you the base to work from and I found that somewhere on &lt;a href="http://stackoverflow.com/"&gt;Stackoverflow&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There are 2 public methods: findAllClassesInSamePackage and findAllInstantiableClassesInSamePackage. &lt;i&gt;(For my purposes of code coverage I just needed the instantiable classes.)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Usage:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt; /**  * Test all getters and setters.  *   * @param clazz the package classes  * @throws Exception the exception  */ public static void testAllObjectsInPackage(final Class&lt; ? &gt; clazz) throws Exception {  for (String className : PackageClassInformationFinder.findAllInstantiableClassesInSamePackage(clazz)) {    GetterAndSetterTester.testAllGettersAndSetters(Class.forName(className).newInstance());  } }&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;PackageClassInformationFinder:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package za.co.discovery.health.medxpress.test;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.Enumeration;import java.util.jar.JarEntry;import java.util.jar.JarFile;/** * The Class PackageClassInformationFinder. */public final class PackageClassInformationFinder { private static final String DOT_CLASS = ".class"; private static final String DOT_JAR = ".jar"; private static final String SLASH = "/"; private static final String DOT = "."; private static final String SLASH2 = "\\"; /**  * Private constructor for static..  */ private PackageClassInformationFinder() { } /**  * Find all the classes from the package of the class given to it..  *   * @param clazz the class to check  * @return a list of class names  */ public static ArrayList&lt; String &gt; findAllClassesInSamePackage(final Class&lt; ? &gt; clazz) {  ArrayList&lt; String &gt; classes = new ArrayList&lt; String &gt;();  try {   final File fileToCheck = new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI());   final String absoluteFilePath = fileToCheck.getAbsoluteFile().toString();   final String packageName = clazz.getPackage().getName();   final String packagePath = packageName.replace(DOT, SLASH) + SLASH;   if (fileToCheck.isDirectory()) {    classes = findClassNamesFromDirectory(absoluteFilePath, packageName);   } else if (fileToCheck.isFile() &amp;&amp; fileToCheck.toString().endsWith(DOT_JAR)) {    classes = findClassNameFromJar(fileToCheck, packagePath, packageName);   }  } catch (final Exception e) {   e.printStackTrace();  }  return classes; } /**  * Find all the instantiable (Pretty sure instantiable isn't an actual word,  * it should be though) classes from the package of the class given to it...  *   * @param clazz the class to check  * @return a list of class names  */ public static ArrayList&lt; String &gt; findAllInstantiableClassesInSamePackage(final Class&lt; ? &gt; clazz) {  final ArrayList&lt; String &gt; validClasses = new ArrayList&lt; String &gt;();  for (String className : findAllClassesInSamePackage(clazz)) {   if (isInstantiableClass(className)) {    System.out.println(className);    validClasses.add(className);   }  }  return validClasses; } /**  * Checks if is valid class.  *   * @param className the class name  * @return true, if it is an instantiable class  */ private static boolean isInstantiableClass(final String className) {  Class&lt; ? &gt; clazz = null;  boolean instantiable = false;  try {   clazz = Class.forName(className);   if (!clazz.isEnum() &amp;&amp; !clazz.isInterface() &amp;&amp; !clazz.isPrimitive() &amp;&amp; !className.contains("package-info")) {    instantiable = true;   }  } catch (final Exception e) {   e.printStackTrace();  }  return instantiable; } /**  * Find class name from jar.  *   * @param file the file  * @param packagePath the package path  * @param packageName the package name  * @return the array list  */ private static ArrayList&lt; String &gt; findClassNameFromJar(final File file, final String packagePath, final String packageName) {  final ArrayList&lt; String &gt; classNames = new ArrayList&lt; String &gt;();  JarFile jarFile = null;  try {   jarFile = new JarFile(file);   final Enumeration&lt; JarEntry &gt; entries = jarFile.entries();   while (entries.hasMoreElements()) {    final JarEntry entry = entries.nextElement();    final String className = findClassNameFromPath(entry.getName(), packagePath);    final String absoluteClassName = packageName + DOT + className;    classNames.add(absoluteClassName);   }  } catch (final IOException e) {   throw new RuntimeException(e);  } finally {   try {    jarFile.close();   } catch (final IOException e) {    e.printStackTrace();   }  }  return classNames; } /**  * Find class name from path.  *   * @param filename the filename  * @param path the path  * @return the string  */ private static String findClassNameFromPath(final String filename, final String path) {  String classNameAfterPackage = null;  if (filename.startsWith(path) &amp;&amp; filename.endsWith(DOT_CLASS)) {   final String className = createClassNameFromFileName(filename);   classNameAfterPackage = className.substring(path.length());  }  return classNameAfterPackage; } /**  * Find class names from directory. - This is recursive.  *   * @param absolutePackagePath the absolute package path  * @param packageName the package name  * @param packageFolder the package folder  * @param classNames the class names  */ private static void findClassNamesFromDirectory(final String absolutePackagePath, final String packageName, final File packageFolder, final ArrayList&lt; String &gt; classNames) {  for (File file : packageFolder.listFiles()) {   if (file.isDirectory()) {    findClassNamesFromDirectory(absolutePackagePath, packageName, file, classNames);    continue;   }   final String classFileName = file.getAbsolutePath().substring(absolutePackagePath.length() + 1);   if (classFileName.endsWith(DOT_CLASS)) {    final String justClassName = createClassNameFromFileName(classFileName);    final String absoluteClassName = packageName + DOT + justClassName;    classNames.add(absoluteClassName);   }  } } /**  * Creates the absolute class name from path.  *   * @param absolutePath the absolute path (including ".class")  * @return the class name  */ private static String createClassNameFromFileName(final String absolutePath) {  final String classname = absolutePath.substring(0, absolutePath.length() - DOT_CLASS.length());  return classname.replace(SLASH, DOT).replace(SLASH2, DOT); } /**  * Find class names from directory.  *   * @param absolutePath the absolute path  * @param packageName the package name  * @return the array list  */ private static ArrayList&lt; String &gt; findClassNamesFromDirectory(final String absolutePath, final String packageName) {  final ArrayList&lt; String &gt; classNames = new ArrayList&lt; String &gt;();  final String packageFileName = absolutePath + SLASH + packageName.replace(DOT, SLASH);  final File workingFile = new File(packageFileName);  if (workingFile.exists() &amp;&amp; workingFile.isDirectory()) {   findClassNamesFromDirectory(workingFile.getAbsolutePath(), packageName, workingFile, classNames);  }  return classNames; }}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-618178050469580433?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/618178050469580433/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/12/find-all-classes-in-same-package.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/618178050469580433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/618178050469580433'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/12/find-all-classes-in-same-package.html' title='Find all the classes in the same package'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-8972088612918426222</id><published>2010-12-05T22:29:00.001+02:00</published><updated>2010-12-06T07:11:49.478+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Solr'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Hadoop'/><title type='text'>Enabling enterprise log searching -  Playing with Hadoop</title><content type='html'>Having a bunch of servers spewing out tons of logs is really a pain when trying to investigate an issue. A custom enterprise wide search would just be one of those awesome little things to have and literally save developers days of their lives not to mention their sanity. The "corporate architecture and management gestapo" will obviously be hard to convince, but the chance to write and setup my own "mini Google wannabe" MapReduce indexing is just too tempting. So this will be a personal little project for the next while. The final goal will be distributed log search, using &lt;a href="http://hadoop.apache.org/"&gt;Hadoop&lt;/a&gt; and &lt;a href="http://lucene.apache.org/solr/"&gt;Apache Solr&lt;/a&gt;. My environment this mostly consists of log files from: &lt;br /&gt;Weblogic Application server, legacy CORBA components, Apache, Tibco and then a mixture of JCAPS / OpenESB / Glasshfish as well.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Setting Up Hadoop and Cygwin&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;First thing to get up and running will be &lt;a href="http://hadoop.apache.org/"&gt;Hadoop&lt;/a&gt;, our environment runs on windows and there in lies the first problem. To run Hadoop on Windows you are going to need &lt;a href="http://www.cygwin.com/"&gt;Cygwin&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Download: &lt;a href="http://hadoop.apache.org/"&gt;Hadoop&lt;/a&gt; and &lt;a href="http://www.cygwin.com/"&gt;Cygwin&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Install Cygwin, just make sure to include the Openssh package.&lt;br /&gt;&lt;a href="http://goo.gl/photos/yNYhZl7BLo" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh6.ggpht.com/_4oXSoLPl3uY/TPuBDwUPPcI/AAAAAAAAAOk/NB8__YJPyrM/s512/Cygwin%20Install.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Once installed, using the Cygwin command prompt: ssh-host-config &lt;br /&gt;This is to setup the ssh configuration, reply yes to everything except if it asks&lt;br /&gt;"This script plans to use cyg_server, Do you want to use a different name?" Then  answer no.&lt;br /&gt;&lt;br /&gt;There seems to be a couple issues with regards to permissions between Windows (Vista in my case), Cygwin and sshd. &lt;br /&gt;&lt;b&gt;Note: Be sure to add your Cygwin "\bin" folder to your windows path&lt;/b&gt; &lt;i&gt;(else it will come back and bite you when trying to run your first map reduce job)&lt;/i&gt;&lt;br /&gt;and typical to Windows, a reboot is required to get it all working.&lt;br /&gt;&lt;br /&gt;So once that is done you should be able to start the ssh server:&lt;b&gt; cygrunsrv -S sshd&lt;/b&gt;&lt;br /&gt;Check that you can ssh to the localhost without a passphrase: &lt;b&gt;ssh localhost&lt;/b&gt;&lt;br /&gt;If that requires passphrase, run the following:&lt;br /&gt;&lt;b&gt;&lt;br /&gt;ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa&lt;br /&gt;cat ~/.ssh/id_dsa.pub &gt;&gt; ~/.ssh/authorized_keys &lt;br /&gt;&lt;/b&gt;&lt;br /&gt;Now back to the Hadoop configuration: &lt;br /&gt;Assuming that Hadoop was downloaded and unzipped into a working folder, ensure that the JAVA_HOME is set. Edit the [working folder]/conf/hadoop-env.sh.&lt;br /&gt;&lt;br /&gt;The go into [working folder]/conf, and add the following to core-site.xml:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;property&gt;  &lt;name&gt;hadoop.tmp.dir&lt;/name&gt;  &lt;value&gt;/tmp/hadoop-${user.name}&lt;/value&gt;&lt;/property&gt;&lt;property&gt;  &lt;name&gt;fs.default.name&lt;/name&gt;  &lt;value&gt;hdfs://localhost:54310&lt;/value&gt;&lt;/property&gt;&lt;property&gt;  &lt;name&gt;mapred.job.tracker&lt;/name&gt;  &lt;value&gt;hdfs://localhost:54311&lt;/value&gt;&lt;/property&gt;&lt;property&gt;   &lt;name&gt;dfs.replication&lt;/name&gt;  &lt;value&gt;8&lt;/value&gt;&lt;/property&gt;&lt;property&gt;  &lt;name&gt;mapred.child.java.opts&lt;/name&gt;  &lt;value&gt;-Xmx512m&lt;/value&gt;&lt;/property&gt;&lt;/script&gt;&lt;br /&gt;To mapred-site.xml add:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;   &lt;property&gt;     &lt;name&gt;mapred.job.tracker&lt;/name&gt;     &lt;value&gt;localhost:54311&lt;/value&gt;     &lt;description&gt;The host and port that the MapReduce job tracker runs     at.  If "local", then jobs are run in-process as a single map     and reduce task.     &lt;/description&gt;   &lt;/property&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Go to the hadoop folder: &lt;b&gt;cd /cygdrive/[drive]/[working folder]&lt;/b&gt;&lt;br /&gt;format the dfs: &lt;b&gt;bin/hadoop namenode -format&lt;/b&gt;&lt;br /&gt;Execute the following: &lt;b&gt;bin/start-all.sh&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;You should then have the following URLs available: &lt;br /&gt;&lt;a href="http://localhost:50070/"&gt;http://localhost:50070/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://localhost:50030/"&gt;http://localhost:50030/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A Hadoop application is made up of one or more jobs. A job&lt;br /&gt;consists of a configuration file and one or more Java classes, these will interact with the data that exists on the Hadoop distributed file system (HDFS).&lt;br /&gt;&lt;br /&gt;Now to get those pesky log files into the HDFS. I created a little HDFS Wrapper class to allow me to interact with the file system. I have defaulted to my values (in core-site.xml).&lt;br /&gt;&lt;br /&gt;HDFS Wrapper:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.hadoop.fileindex;import java.io.IOException;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.BlockLocation;import org.apache.hadoop.fs.FSDataOutputStream;import org.apache.hadoop.fs.FileStatus;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;/** * The Class HDFSWrapper. */public class HDFSWrapper { private Configuration config; private FileSystem hdfs; /**  * Instantiates a new hDFS wrapper.  *   * @param config  *            the config  * @throws IOException  *             Signals that an I/O exception has occurred.  */ public HDFSWrapper(final Configuration config) throws IOException {  this.config = config;  hdfs = FileSystem.get(this.config); } /**  * Creates the hdfs directory.  *   * @param dir  *            the dir  * @throws IOException  *             Signals that an I/O exception has occurred.  */ public void createHDFSDirectory(final String dir) throws IOException {  final Path src = new Path(hdfs.getWorkingDirectory() + "/" + dir);  hdfs.mkdirs(src); } /**  * Copy file to hdfs.  *   * @param srcFile  *            the src file  * @param dstFile  *            the dst file  * @throws IOException  *             Signals that an I/O exception has occurred.  */ public void copyFileToHDFS(final String srcFile, final String dstFile) throws IOException {  final Path srcPath = new Path(srcFile);  final Path dstPath = new Path(dstFile);  hdfs.copyFromLocalFile(srcPath, dstPath); } /**  * Copy file from hdfs.  *   * @param srcFile  *            the src file  * @param dstFile  *            the dst file  * @throws IOException  *             Signals that an I/O exception has occurred.  */ public void copyFileFromHDFS(final String srcFile, final String dstFile) throws IOException {  final Path srcPath = new Path(srcFile);  final Path dstPath = new Path(dstFile);  hdfs.copyToLocalFile(srcPath, dstPath); } /**  * Creates the file on hdfs.  *   * @param buff  *            the buff  * @param fileName  *            the file name  * @throws IOException  *             Signals that an I/O exception has occurred.  */ public void createFileOnHDFS(final byte[] buff, final String fileName) throws IOException {  final Path path = new Path(fileName);  FSDataOutputStream outputStream = hdfs.create(path);  outputStream.write(buff, 0, buff.length); } /**  * Delete file on hdfs.  *   * @param fileName  *            the file name  * @param recurs  *            the recurs  * @return true, if successful  * @throws IOException  *             Signals that an I/O exception has occurred.  */ public boolean deleteFileOnHDFS(final String fileName, final boolean recurs) throws IOException {  final Path path = new Path(fileName);  return hdfs.delete(path, recurs); } /**  * Determine file locations.  *   * @param fileName  *            the file name  * @return the list  * @throws IOException  *             Signals that an I/O exception has occurred.  */ public List&lt;string&gt; determineFileLocations(final String fileName) throws IOException {  final Path path = new Path(fileName);  final FileStatus fileStatus = hdfs.getFileStatus(path);  final BlockLocation[] blkLocations = hdfs.getFileBlockLocations(fileStatus, 0, fileStatus.getLen());  List&lt;string&gt; hosts = new ArrayList&lt;string&gt;();  int blkCount = blkLocations.length;  for (int i = 0; i &lt; blkCount; i++) {   hosts.addAll(Arrays.asList((blkLocations[i].getHosts())));  }  return hosts; }}&lt;/script&gt;I also found a quick way to start searching the log file uploaded, is the Grep example included with Hadoop, and included it my HDFS test case below.Simple Wrapper Test:&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.hadoop.fileindex;import static org.junit.Assert.assertEquals;import java.io.IOException;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.util.ToolRunner;import org.junit.After;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.junit.runners.BlockJUnit4ClassRunner;/** * The Class TestHDFSWrapper. */@RunWith(BlockJUnit4ClassRunner.class)public class TestHDFSWrapper { private static final String DIR_KEY = "fs.default.name"; private static final String DIR_HADOOP = "hdfs://localhost"; private static final int PORT_HADOOP = 54310; private Configuration config; private HDFSWrapper wrapper; @Before public void setup() throws IOException {  config = new Configuration();  config.set(DIR_KEY, DIR_HADOOP + ":" + PORT_HADOOP);  wrapper = new HDFSWrapper(config);  wrapper.createHDFSDirectory("testDir");  wrapper.createHDFSDirectory("testDirOut");  wrapper.copyFileToHDFS("a.log", "testDir/a.log"); } @Test public void testLocations() throws IOException {  assertEquals("192.168.1.101", wrapper.determineFileLocations("testDir/a.log").get(0)); } @Test public void testGrep() throws Exception {  String[] args = { "/user/newbob/user/testDir/a.log", "/user/newbob/user/testDirOut/out.log", "*a.*" };  int res = ToolRunner.run(config, new Grep(), args);  System.out.println(res); } @After public void teardown() throws IOException {  wrapper.deleteFileOnHDFS("testDir/a.log", true);  wrapper.deleteFileOnHDFS("testDirOut/out.log", true); }}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-8972088612918426222?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/8972088612918426222/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/12/enabling-enterprise-log-searching.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/8972088612918426222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/8972088612918426222'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/12/enabling-enterprise-log-searching.html' title='Enabling enterprise log searching -  Playing with Hadoop'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_4oXSoLPl3uY/TPuBDwUPPcI/AAAAAAAAAOk/NB8__YJPyrM/s72-c/Cygwin%20Install.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-3363713762402215634</id><published>2010-11-22T07:12:00.002+02:00</published><updated>2010-11-23T23:36:38.919+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><title type='text'>Design Patterns in the JDK.</title><content type='html'>I saw an article (well more of a rant) the other day, by Rob Williams&lt;br /&gt;&lt;a href="http://www.jroller.com/robwilliams/entry/brain_drain_in_enterprise_dev "&gt;Brain Drain in enterprise Dev&lt;/a&gt;. I have to say, I do agree with some of what he is saying. I know from my personal experience, I had spent a good 2 or so years just wallowing in the enterprise development world, not learning anything and actually losing my skills I developed before. The corporate confront zone is not conducive to eager technologists.&lt;br /&gt;&lt;br /&gt;In this article he also stated: &lt;br /&gt;"1 in 10 cant even pass a simple test like ‘which design pattern is used in the streams library that makes BufferedFileReader interchangeable with a FileReader?'"&lt;br /&gt;&lt;br /&gt;&lt;i&gt;I also tested it at work and I only had 1 out of the 8 people asked that got it right&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;Without much confidence, I had guessed Decorator based on "interchangeable". I then decided that was actually some worth sneaking into future interviews, and probably a good time to revise a little. &lt;br /&gt;&lt;br /&gt;So I went scouring the internet to find all I could on the topic and I didn't actually find as much as I thought I would. Most of it came from BalusC at &lt;a href="http://stackoverflow.com"&gt;Stackoverflow&lt;/a&gt;, the rest was very scattered between blog posts, java ranch, some old pdf's and articles I had. I didn't take every single example of every single pattern I found, but rather the common ones.&lt;br /&gt;This may be a good way for people to learn about patterns, quite often they are using them everyday without realizing.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Structural&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Adapter:&lt;/b&gt;&lt;br /&gt;This is used to convert the programming interface/class into that of another.&lt;br /&gt;&lt;br /&gt;-java.util.Arrays#asList()&lt;br /&gt;-javax.swing.JTable(TableModel)&lt;br /&gt;-java.io.InputStreamReader(InputStream)&lt;br /&gt;-java.io.OutputStreamWriter(OutputStream)&lt;br /&gt;-javax.xml.bind.annotation.adapters.XmlAdapter#marshal()&lt;br /&gt;-javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal()&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Bridge:&lt;/b&gt;&lt;br /&gt;This decouples an abstraction from the implementation of its abstract operations, so that the abstraction and its implementation can vary independently.&lt;br /&gt;&lt;br /&gt;-AWT (It provides an abstraction layer which maps onto the native OS the windowing support.)&lt;br /&gt;-JDBC &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Composite:&lt;/b&gt; &lt;br /&gt;Lets clients treat individual objects and compositions of objects uniformly. So in other words methods on a type accepting the same type.&lt;br /&gt;&lt;br /&gt;-javax.swing.JComponent#add(Component)&lt;br /&gt;-java.awt.Container#add(Component)&lt;br /&gt;-java.util.Map#putAll(Map)&lt;br /&gt;-java.util.List#addAll(Collection)&lt;br /&gt;-java.util.Set#addAll(Collection)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Decorator:&lt;/b&gt; &lt;br /&gt;Attach additional responsibilities to an object dynamically and therefore it is also an alternative to subclassing. Can be seen when creating a type passes in the same type. This is actually used all over the JDK, the more you look the more you find, so the list below is definitely not complete.&lt;br /&gt;&lt;br /&gt;-java.io.BufferedInputStream(InputStream)&lt;br /&gt;-java.io.DataInputStream(InputStream)&lt;br /&gt;-java.io.BufferedOutputStream(OutputStream)&lt;br /&gt;-java.util.zip.ZipOutputStream(OutputStream)&lt;br /&gt;-java.util.Collections#checked[List|Map|Set|SortedSet|SortedMap]() &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Facade:&lt;/b&gt; &lt;br /&gt;To provide a simplified interface to a group of components, interfaces, abstractions or subsystems.&lt;br /&gt;&lt;br /&gt;-java.lang.Class&lt;br /&gt;-javax.faces.webapp.FacesServlet&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Flyweight:&lt;/b&gt; &lt;br /&gt;Caching to support large numbers of smaller objects efficiently. I stumbled apon this a couple months back.&lt;br /&gt;&lt;br /&gt;-java.lang.Integer#valueOf(int)&lt;br /&gt;-java.lang.Boolean#valueOf(boolean)&lt;br /&gt;-java.lang.Byte#valueOf(byte)&lt;br /&gt;-java.lang.Character#valueOf(char)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Proxy:&lt;/b&gt; &lt;br /&gt;The Proxy pattern is used to represent with a simpler object an object that is complex or time consuming to create.&lt;br /&gt;&lt;br /&gt;-java.lang.reflect.Proxy&lt;br /&gt;-RMI&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Creational&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Abstract factory:&lt;/b&gt;&lt;br /&gt;To provide a contract for creating families of related or dependent objects without having to specify their concrete classes. It enables one to decouple an application from the concrete implementation of an entire framework one is using. This is also found all over the JDK and a lot of frameworks like Spring. They are simple to spot, any method that is used to create an object but still returns a interface or abstract class.&lt;br /&gt;&lt;br /&gt;-java.util.Calendar#getInstance()&lt;br /&gt;-java.util.Arrays#asList()&lt;br /&gt;-java.util.ResourceBundle#getBundle()&lt;br /&gt;-java.sql.DriverManager#getConnection()&lt;br /&gt;-java.sql.Connection#createStatement()&lt;br /&gt;-java.sql.Statement#executeQuery()&lt;br /&gt;-java.text.NumberFormat#getInstance()&lt;br /&gt;-javax.xml.transform.TransformerFactory#newInstance()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Builder:&lt;/b&gt;&lt;br /&gt;Used simplify complex object creation by defining a class whose purpose is to build instances of another class. The builder pattern also allows for the implementation of a &lt;a href="http://en.wikipedia.org/wiki/Fluent_interface"&gt;Fluent Interface&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;-java.lang.StringBuilder#append()&lt;br /&gt;-java.lang.StringBuffer#append()&lt;br /&gt;-java.sql.PreparedStatement&lt;br /&gt;-javax.swing.GroupLayout.Group#addComponent()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Factory method:&lt;/b&gt;&lt;br /&gt;Simply a method that returns an actual type.&lt;br /&gt;&lt;br /&gt;-java.lang.Proxy#newProxyInstance()&lt;br /&gt;-java.lang.Object#toString()&lt;br /&gt;-java.lang.Class#newInstance()&lt;br /&gt;-java.lang.reflect.Array#newInstance()&lt;br /&gt;-java.lang.reflect.Constructor#newInstance()&lt;br /&gt;-java.lang.Boolean#valueOf(String) &lt;br /&gt;-java.lang.Class#forName()&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Prototype:&lt;/b&gt; &lt;br /&gt;Allows for classes whose instances can create duplicates of themselves. This can be used when creating an instance of a class is very time-consuming or complex in some way, rather than creating new instances, you can make copies of the original instance and modify it.&lt;br /&gt;&lt;br /&gt;-java.lang.Object#clone() &lt;br /&gt;-java.lang.Cloneable&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Singleton:&lt;/b&gt;&lt;br /&gt;This tries to ensure that there is only a single instance of a class. I didn't find an example but another solution would be to use an Enum as Joshua Bloch suggests in Effective Java.&lt;br /&gt;&lt;br /&gt;-java.lang.Runtime#getRuntime()&lt;br /&gt;-java.awt.Toolkit#getDefaultToolkit()&lt;br /&gt;-java.awt.GraphicsEnvironment#getLocalGraphicsEnvironment() &lt;br /&gt;-java.awt.Desktop#getDesktop()&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Behavioral&lt;/u&gt;&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Chain of responsibility:&lt;/b&gt; &lt;br /&gt;Allows for the decoupling between objects by passing a request from one object to the next in a chain until the request is recognized. The objects in the chain are different implementations of the same interface or abstract class.&lt;br /&gt;&lt;br /&gt;-java.util.logging.Logger#log()&lt;br /&gt;-javax.servlet.Filter#doFilter()&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Command:&lt;/b&gt; &lt;br /&gt;To wrap a command in an object so that it can be stored, passed into methods, and returned like any other object.&lt;br /&gt;&lt;br /&gt;-java.lang.Runnable&lt;br /&gt;-javax.swing.Action&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Interpreter:&lt;/b&gt; &lt;br /&gt;This pattern generally describes defining a grammar for that language and using that grammar to interpret statements in that format.&lt;br /&gt;&lt;br /&gt;-java.util.Pattern&lt;br /&gt;-java.text.Normalizer&lt;br /&gt;-java.text.Format&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Iterator:&lt;/b&gt; &lt;br /&gt;To provide a consistent way to sequentially access items in a collection that is independent of and separate from the underlying collection.&lt;br /&gt;&lt;br /&gt;-java.util.Iterator &lt;br /&gt;-java.util.Enumeration&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Mediator:&lt;/b&gt; &lt;br /&gt;Used to reduce the number of direct dependencies between classes by introducing a single object that manages message distribution.&lt;br /&gt;&lt;br /&gt;-java.util.Timer&lt;br /&gt;-java.util.concurrent.Executor#execute()&lt;br /&gt;-java.util.concurrent.ExecutorService#submit()&lt;br /&gt;-java.lang.reflect.Method#invoke()&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Memento:&lt;/b&gt; &lt;br /&gt;This is a snapshot of an object’s state, so that the object can return to its original state without having to reveal it's content. Date does this by actually having a long value internally.&lt;br /&gt;&lt;br /&gt;-java.util.Date &lt;br /&gt;-java.io.Serializable&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Null Object:&lt;/b&gt;&lt;br /&gt;This can be used encapsulate the absence of an object by providing an alternative 'do nothing' behavior. It allows you to abstract the handling of null objects.&lt;br /&gt;&lt;br /&gt;-java.util.Collections#emptyList() &lt;br /&gt;-java.util.Collections#emptyMap()&lt;br /&gt;-java.util.Collections#emptySet()&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Observer:&lt;/b&gt; &lt;br /&gt;Used to provide a way for a component to flexibly broadcast messages to interested receivers.&lt;br /&gt;&lt;br /&gt;-java.util.EventListener&lt;br /&gt;-javax.servlet.http.HttpSessionBindingListener&lt;br /&gt;-javax.servlet.http.HttpSessionAttributeListener&lt;br /&gt;-javax.faces.event.PhaseListener&lt;br /&gt;&lt;br /&gt;&lt;b&gt;State:&lt;/b&gt; &lt;br /&gt;This allows you easily change an object’s behavior at runtime based on internal state.&lt;br /&gt;&lt;br /&gt;-java.util.Iterator&lt;br /&gt;-javax.faces.lifecycle.LifeCycle#execute() &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Strategy:&lt;/b&gt; &lt;br /&gt;Is intended to provide a means to define a family of algorithms, encapsulate each one as an object. These can then be flexibly passed in to change the functionality.&lt;br /&gt;&lt;br /&gt;-java.util.Comparator#compare()&lt;br /&gt;-javax.servlet.http.HttpServlet&lt;br /&gt;-javax.servlet.Filter#doFilter()&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Template method:&lt;/b&gt; &lt;br /&gt;Allows subclasses to override parts of the method without rewriting it, also allows you to control which operations subclasses are required to override.&lt;br /&gt;&lt;br /&gt;-java.util.Collections#sort()&lt;br /&gt;-java.io.InputStream#skip() &lt;br /&gt;-java.io.InputStream#read() &lt;br /&gt;-java.util.AbstractList#indexOf()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Visitor:&lt;/b&gt; &lt;br /&gt;To provide a maintainable, easy way to perform actions for a family of classes. Visitor centralizes the behaviors and allows them to be modified or extended without changing the classes they operate on.&lt;br /&gt;&lt;br /&gt;-javax.lang.model.element.Element and javax.lang.model.element.ElementVisitor&lt;br /&gt;-javax.lang.model.type.TypeMirror and javax.lang.model.type.TypeVisitor&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-3363713762402215634?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/3363713762402215634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/11/design-patterns-in-jdk.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3363713762402215634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3363713762402215634'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/11/design-patterns-in-jdk.html' title='Design Patterns in the JDK.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-1164260706893935471</id><published>2010-11-19T19:21:00.000+02:00</published><updated>2010-11-19T19:21:38.083+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Personal'/><title type='text'>Now with a new cleaner look...</title><content type='html'>I had a couple mails and comments stating that my blog theme made it hard to read, so for a complete reversal ... I went as clean as I could.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-1164260706893935471?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/1164260706893935471/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/11/now-with-new-cleaner-look.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1164260706893935471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1164260706893935471'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/11/now-with-new-cleaner-look.html' title='Now with a new cleaner look...'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-6809433838918824216</id><published>2010-11-15T07:14:00.000+02:00</published><updated>2010-11-15T07:14:00.351+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rules'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><category scheme='http://www.blogger.com/atom/ns#' term='BRMS'/><category scheme='http://www.blogger.com/atom/ns#' term='Drools'/><title type='text'>Learning to Drool... Part 2</title><content type='html'>In &lt;a href="http://www.briandupreez.net/2010/11/learning-to-drool-part-1.html"&gt;Part 1&lt;/a&gt; I went through the basic syntax and requirements to get a rule developed and tested.&lt;br /&gt;&lt;br /&gt;Now to extend that, the Drools documentation is actually quite good, there is just a ton of it, so I will try to just focus on some of the main topics.&lt;br /&gt;&lt;br /&gt;First a little thing I had to do to get the rules to run from your tests using maven, the .drls are not in the classpath by default, a simple way around that was to add the following to the POM:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;build&gt;  &lt;resources&gt;   &lt;resource&gt;    &lt;directory&gt;src/main/rules&lt;/directory&gt;   &lt;/resource&gt;  &lt;/resources&gt;&lt;/build&gt;&lt;/script&gt;&lt;br /&gt;Now more rules scenarios and usages:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Collections:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;Querying the contents of a can be done in 2 ways, contains and memberOf, the difference is that the collection used in conjunction with memberOf must be a variable.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The drl:&lt;/b&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;rule "Use a Collection" when  $vo : RoolVO( listValue contains  "items" ) then    $vo.setStringValue("Done.");  logger.log(Level.INFO,"Used a collection");end&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Regular Expressions:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;You can use a regex as a selection criteria as well with the key words Matches and Not Matches.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The drl:&lt;/b&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;rule "Use a Regular Expression"  when  $vo : RoolVO( stringValue matches  "(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/((19|20)\\d\\d)") then    $vo.setStringValue("Done.");  logger.log(Level.INFO,"Found the date with a regular expression dd/mm/yyyy");end&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Global Variables:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;You can define global variables, they should not be used as the are sometimes in code, to pass information between methods or in this case rules. They should rather be used to provide data or services that the rules use. An example would be something like an application specific logger, or perhaps constant lookup data loaded when the application starts.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The test:&lt;/b&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;public class TestBasicRules { private KnowledgeBase kbase; private Logger javaLogger = Logger.getLogger("testLogger"); @Test public void testGlobal() {  StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();  RoolVO vo = new RoolVO();  vo.setStringValue("Global");  ksession.insert(vo);  ksession.setGlobal("logger", javaLogger);  ksession.fireAllRules();  checkDone(ksession);     }&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The drl:&lt;/b&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.drools.rulesimport javaitzen.drools.RoolVOimport java.util.logging.Levelglobal java.util.logging.Logger logger;rule "Use a Global "  when  $vo : RoolVO( stringValue == "Global") then    $vo.setStringValue("Done.");  logger.log(Level.INFO,"Logging with a global"); end&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Rule Attributes:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;On a rule you can specify attribute, there are a number of these. I'll just mention a couple handy ones (quoting the official documentation):&lt;br /&gt;&lt;br /&gt;&lt;b&gt;no-loop&lt;/b&gt;&lt;br /&gt;default value: false&lt;br /&gt;type: Boolean&lt;br /&gt;When the rule's consequence modifies a fact it may cause the Rule to activate again, causing recursion. Setting no-loop to true means the attempt to create the Activation for the current set of data will be ignored.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;salience&lt;/b&gt;&lt;br /&gt;default value : 0&lt;br /&gt;type : integer&lt;br /&gt;Salience is a form of priority where rules with higher salience values are given higher priority when ordered in the Activation queue.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;dialect&lt;/b&gt;&lt;br /&gt;default value: as specified by the package&lt;br /&gt;type: String&lt;br /&gt;possible values: "java" or "mvel"&lt;br /&gt;The dialect species the language to be used for any code expressions in the LHS or the RHS code block. Currently two dialects are available, Java and MVEL. While the dialect can be specified at the package level, this attribute allows the package definition to be overridden for a rule.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;date-effective&lt;/b&gt;&lt;br /&gt;default value: N/A&lt;br /&gt;type: String, containing a date and time definition&lt;br /&gt;A rule can only activate if the current date and time is after date-effective attribute.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;date-expires&lt;/b&gt;&lt;br /&gt;default value: N/A&lt;br /&gt;type: String, containing a date and time definition&lt;br /&gt;A rule cannot activate if the current date and time is after the date-expires attribute.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Guided Rule:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;The guided rule editor seems to allow for everything you can do in code, just visually, and potentially more intuitively for those non developers. Only thing you need to do is make sure to have the objects you want to use imported in a .package in the same location as the created .brl file. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/2J0RokQaIi" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh5.ggpht.com/_4oXSoLPl3uY/TNw6pKtEfkI/AAAAAAAAAN0/BljQDr8CphE/s512/Guided%20Rule%20Example.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Decision Tables:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;In my opinion the world actually runs on spreadsheets. We all like to think that it only functions because of us and our fancy applications, but truth be told the world would miss spreadsheets more than any other single application.&lt;br /&gt;&lt;br /&gt;The business people giving us our requirements understand spread sheets, some of them better than us developers and this is the biggest single bonus on decision tables. The Drools decision table at first glance did look as if it would not be as simple to hand over to business users as the Quickrules one, but it is actually split quite clearly into "code" and "data"&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/bh0uxq0CU4" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh6.ggpht.com/_4oXSoLPl3uY/TN_zttsAgjI/AAAAAAAAAOM/RwQpE5zz2SY/s512/Decision%20Table.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now to breakdown a decision table into its parts...&lt;br /&gt;When creating  a decision table, the eclipse plugin gives you an example, I am going to work through that.&lt;br /&gt;&lt;br /&gt;C2: Keyword ruleset, just to state that this spread sheet is a ruleset (package).&lt;br /&gt;D2: The ruleset (package) name.&lt;br /&gt;Under this row you can specify the following optional keywords:&lt;br /&gt;Sequential - The cell to the right of this can be true or false. If true, then salience is used to ensure that rules fire from the top down.&lt;br /&gt;Import - The cell to the right contains a comma separated list of classes to import. &lt;br /&gt;Variables - The cell immediately to the right can contain global declarations which Drools supports. This is a type, followed by a variable name. (if multiple variables are needed, comma separate them).&lt;br /&gt;&lt;br /&gt;C3/D4: Notes heading and the actual notes.&lt;br /&gt;&lt;br /&gt;C5: The RuleTable keyword and name. The "RuleTable" keyword must appear on top of the first condition column. You can have multiple rule tables on a sheet, they must just be separated by a line.&lt;br /&gt;&lt;br /&gt;C6: Marks the column as a CONDITION column, G6, does this for the ACTION. You need at least one of each for a table to be valid. If there is no data in a CONDITION column, then that condition does not apply. &lt;br /&gt;Other column optional keywords are: &lt;br /&gt;PRIORITY - This states that this column's values will set the salience&lt;br /&gt;DURATION - This will set the duration values for the rule row.&lt;br /&gt;NO-LOOP - Same as in the drl, this specifies if rule is not allowed to loop. &lt;br /&gt;&lt;br /&gt;C7: This and subsequent columns in the row, define the actual variables referenced in the rule table.&lt;br /&gt;&lt;br /&gt;C8: This and subsequent columns in the row specifies where we are getting the data from.&lt;br /&gt;&lt;br /&gt;Row 9 and Column B are just labels / headings making the data simpler to understand, all the other fields and columns before there can be hidden as not to scare the "less technical". The table inside B9 is then were the specific rule data is defined, hopefully directly from the specification, by a non developer.&lt;br /&gt;&lt;br /&gt;I have uploaded this project to my Google code project, incase anyone wants it. I had a little issue with the decision table because I run OpenOffice at home and not Microsoft Office, the plugin expects Excel, so it leaves a ugly little red X in my project, but it opens fine outside the IDE and still compiles in maven.&lt;br /&gt;&lt;br /&gt;Part 3, I'll have a look at the Rule Flow, and start tackling the monster that is Guvnor&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-6809433838918824216?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/6809433838918824216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/11/learning-to-drool-part-2.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6809433838918824216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6809433838918824216'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/11/learning-to-drool-part-2.html' title='Learning to Drool... Part 2'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_4oXSoLPl3uY/TNw6pKtEfkI/AAAAAAAAAN0/BljQDr8CphE/s72-c/Guided%20Rule%20Example.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-3491487498454241256</id><published>2010-11-08T07:24:00.001+02:00</published><updated>2010-11-08T07:26:44.156+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rules'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><category scheme='http://www.blogger.com/atom/ns#' term='BRMS'/><category scheme='http://www.blogger.com/atom/ns#' term='Drools'/><title type='text'>Learning to Drool... Part 1</title><content type='html'>This series of posts will be about me getting to grips with &lt;a href="http://www.jboss.org/drools"&gt;JBoss Drools&lt;/a&gt;. The reasoning behind it is: SAP bought out my company's current rules engine and Drools is one alternative we will be looking into as soon as someone has the skills to get a proof of concept up.&lt;br /&gt;&lt;br /&gt;Although there seems to be a fair amount of documentation, I always find it helps having walked through examples, which is what I am going to do here.Drools on first glance can be quite daunting, it is made up of :&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.jboss.org/drools/drools-expert.html"&gt;Drools Expert&lt;/a&gt; (rule engine)&lt;br /&gt;Being a developer this is where I will begin, the actual rules and implementation of them.&lt;br /&gt;&lt;br /&gt;The other parts I'll get to later are:&lt;br /&gt;&lt;a href="http://www.jboss.org/drools/drools-guvnor.html"&gt;Drools Guvnor&lt;/a&gt; (BRMS/BPMS)&lt;br /&gt;&lt;a href="http://www.jboss.org/drools/drools-flow.html"&gt;Drools Flow&lt;/a&gt; (process/workflow)&lt;br /&gt;&lt;a href="http://www.jboss.org/drools/drools-fusion.html"&gt;Drools Fusion&lt;/a&gt; (event processing/temporal reasoning)&lt;br /&gt;&lt;a href="http://www.jboss.org/drools/drools-planner.html"&gt;Drools Planner&lt;/a&gt; (automated planning)&lt;br /&gt;&lt;br /&gt;So to begin.&lt;br /&gt;For part 1, I just want to get my feet wet, I download only the &lt;a href="http://www.jboss.org/drools/downloads.html"&gt;Eclipse plugin and the binaries &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Need to install the Eclipse plugin, used the &lt;a href="http://downloads.jboss.com/drools/updatesite3.5/"&gt;update site&lt;/a&gt;. Unzip the binaries to a directory and withing the Eclipse plugin settings point to that directory.&lt;br /&gt;&lt;br /&gt;The eclipse plugin will allow you to create a Drools Project and that includes the "Drools Library", but if you are using maven you need to point to the &lt;a href="http://repository.jboss.org/nexus/content/groups/public-jboss/"&gt;JBoss release repo&lt;/a&gt; for the Drools dependencies, The KnowledgeRuntimeLoggerFactory needs XStream which you can just get from the standard maven repo. Below is my POM:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&gt; &lt;modelversion&gt;4.0.0&lt;/modelVersion&gt; &lt;groupId&gt;javaitzen.drools&lt;/groupId&gt; &lt;artifactid&gt;LearningToDrool&lt;/artifactId&gt; &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt; &lt;build&gt;  &lt;plugins&gt;   &lt;plugin&gt;    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;    &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;    &lt;configuration&gt;     &lt;source&gt;1.6&lt;/source&gt;     &lt;target&gt;1.6&lt;/target&gt;    &lt;/configuration&gt;   &lt;/plugin&gt;  &lt;/plugins&gt; &lt;/build&gt; &lt;properties&gt;  &lt;drools.version&gt;5.1.1&lt;/drools.version&gt; &lt;/properties&gt; &lt;repositories&gt;  &lt;repository&gt;   &lt;name&gt;JBoss&lt;/name&gt;   &lt;id&gt;JBoss&lt;/id&gt;   &lt;url&gt;http://repository.jboss.org/nexus/content/groups/public-jboss/&lt;/url&gt;  &lt;/repository&gt; &lt;/repositories&gt; &lt;dependencies&gt;  &lt;dependency&gt;   &lt;groupId&gt;org.drools&lt;/groupId&gt;   &lt;artifactId&gt;drools-core&lt;/artifactId&gt;   &lt;version&gt;${drools.version}&lt;/version&gt;  &lt;/dependency&gt;  &lt;dependency&gt;   &lt;groupId&gt;org.drools&lt;/groupId&gt;   &lt;artifactid&gt;drools-compiler&lt;/artifactId&gt;   &lt;version&gt;${drools.version}&lt;/version&gt;  &lt;/dependency&gt;  &lt;dependency&gt;   &lt;groupId&gt;org.drools&lt;/groupId&gt;   &lt;artifactId&gt;drools-api&lt;/artifactId&gt;   &lt;version&gt;${drools.version}&lt;/version&gt;  &lt;/dependency&gt;  &lt;dependency&gt;   &lt;groupId&gt;com.thoughtworks.xstream&lt;/groupId&gt;   &lt;artifactId&gt;xstream&lt;/artifactId&gt;   &lt;version&gt;1.3.1&lt;/version&gt;  &lt;/dependency&gt;  &lt;dependency&gt;   &lt;groupId&gt;junit&lt;/groupId&gt;   &lt;artifactId&gt;junit&lt;/artifactId&gt;   &lt;version&gt;4.8.1&lt;/version&gt;   &lt;scope&gt;test&lt;/scope&gt;  &lt;/dependency&gt; &lt;/dependencies&gt;&lt;/project&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;To add a rule, on src/main/rules, Right click -&gt; New -&gt; Other... Drools/Rule Resource, be sure to choose the "individual rule". This leaves you with an empty drl file:&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.drools.rulesrule "A stand alone rule"  when  #conditions then   #actions  end&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;To understand and use the rule language, I read the &lt;a href="http://downloads.jboss.com/drools/docs/5.1.1.34858.FINAL/drools-expert/html/ch04.html"&gt;Drools Documentation&lt;/a&gt; and the examples project. &lt;br /&gt;What actually took me a little to grasp, was the basic syntax and how objects were handled in the rules and I did struggle to find anything that actually explains it simply so I will give it a shot.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;A note on variable names.. they do not need to have the '$' but it was used in the example and without it quickly gets quite confusing.&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Now to step through the parts of a rule:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.drools.rulesimport javaitzen.drools.RoolVOrule "Basic Rule"  when $vo : RoolVO( stringValue == "Learning to drool",                       $booleanVal : booleanValue ) eval( $booleanVal ) then         System.out.println( "First Rule" );  $vo.setStringValue("Done."); end&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The package, and import keyword are self explanatory, what happens after the when is not. &lt;br /&gt;What is happening in "$vo : RoolVO( stringValue == "Learning to drool", $booleanVal : booleanValue )" broken down actually is:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;stringValue == "Learning to drool" -&lt;/b&gt; This is a constraint that allows us to find all RoolVO objects known to the knowledge base that have the getStringValue() value equals to "Learning to drool". If there are multiple instances of RoolVO that comply we will run this rule more than once, these are also referred to as matched objects. You can also have multiple constraints separated by a ",".&lt;br /&gt;&lt;br /&gt;&lt;b&gt;$booleanVal : booleanValue -&lt;/b&gt; We are declaring a new local variable of type boolean called $booleanVal and gets it value from isBooleanValue.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;$vo : RoolVO -&lt;/b&gt; We are declaring a new local variable of type RoolVO called $vo.&lt;br /&gt;&lt;br /&gt;The next line:&lt;br /&gt;&lt;b&gt;"eval( $booleanVal )" -&lt;/b&gt; Evaluates the boolean variable, this needs to evaluate to true for the 'then' part of the rule to be called.&lt;br /&gt;Then:&lt;br /&gt;&lt;b&gt;System.out.println( "First Rule" ); -&lt;/b&gt; Standard sys out.&lt;br /&gt;&lt;b&gt;$vo.setStringValue("Done."); -&lt;/b&gt; Sets the String value on the current RoolVO object that matched the constraints to Done.&lt;br /&gt;&lt;br /&gt;The main classes / interfaces needed for a basic rule execution seem to be the following:&lt;br /&gt;org.drools.KnowledgeBase and it's factory &lt;br /&gt;org.drools.KnowledgeBaseFactory:&lt;br /&gt;This is the repository of all the relevant knowledge definitions; it contains rules, processes, functions, type models. &lt;br /&gt;&lt;br /&gt;org.drools.builder.KnowledgeBuilder and it's factory org.drools.builder.KnowledgeBuilderFactory:&lt;br /&gt;Transforms / parses a source file (.drl, .xsl) into a KnowledgePackage that a KnowledgeBase can understand. &lt;br /&gt;&lt;br /&gt;StatefulKnowledgeSession created by the KnowledgeBase .newStatefulKnowledgeSession();&lt;br /&gt;This session is used to communicate with the actual rules engine.&lt;br /&gt;&lt;br /&gt;To quote the drools JavaDocs:&lt;br /&gt;&lt;i&gt;StatefulKnowledgeSession is the most common way to interact with a rules engine. A StatefulKnowledgeSession allows the application to establish an iterative conversation with the engine, where the reasoning process may be triggered multiple times for the same set of data.&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I wrote a simple test for the rule I described earlier.&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.drools;import static org.junit.Assert.assertEquals;import org.drools.KnowledgeBase;import org.drools.KnowledgeBaseFactory;import org.drools.builder.KnowledgeBuilder;import org.drools.builder.KnowledgeBuilderError;import org.drools.builder.KnowledgeBuilderErrors;import org.drools.builder.KnowledgeBuilderFactory;import org.drools.builder.ResourceType;import org.drools.io.ResourceFactory;import org.drools.logger.KnowledgeRuntimeLogger;import org.drools.logger.KnowledgeRuntimeLoggerFactory;import org.drools.runtime.StatefulKnowledgeSession;import org.junit.Before;import org.junit.Test;public class TestBasicRules { private KnowledgeBase kbase;  @Before public void setup() {  KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();  kbuilder.add(ResourceFactory.newClassPathResource("basic.drl"), ResourceType.DRL);  KnowledgeBuilderErrors errors = kbuilder.getErrors();  if (errors.size() &gt; 0) {   for (KnowledgeBuilderError error: errors) {    System.err.println(error);   }   throw new IllegalArgumentException("Could not parse knowledge.");  }  kbase = KnowledgeBaseFactory.newKnowledgeBase();  kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());        }  @Test public void testBasic() {  StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();  KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");  RoolVO vo = new RoolVO();  vo.setStringValue("Learning to drool");  vo.setBooleanValue(true);  ksession.insert(vo);  ksession.fireAllRules();  for (Object o: ksession.getObjects()) {   if(o instanceof RoolVO) {    assertEquals("Done.", ((RoolVO) o).getStringValue());   }  }   logger.close();   }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;To be honest, Drools is not nearly as intuitive as Quickrules was from what I have seen in this first task. However, in Part 2, I will start looking at using the rule flows, decision table functionality as well as the guided rules:&lt;br /&gt;&lt;a href="http://goo.gl/photos/DjKPU3sXw0" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh4.ggpht.com/_4oXSoLPl3uY/TNXNqKrG3rI/AAAAAAAAANU/IUW6Y_aa1o0/s512/rule%20builder.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Those in partnership with the DSL (Domain Specific Language) construct hopefully do allow for more intuitive rules creation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-3491487498454241256?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/3491487498454241256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/11/learning-to-drool-part-1.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3491487498454241256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3491487498454241256'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/11/learning-to-drool-part-1.html' title='Learning to Drool... Part 1'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_4oXSoLPl3uY/TNXNqKrG3rI/AAAAAAAAANU/IUW6Y_aa1o0/s72-c/rule%20builder.jpg' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-2878998737379060721</id><published>2010-11-03T05:47:00.001+02:00</published><updated>2010-11-03T07:13:44.676+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rules'/><category scheme='http://www.blogger.com/atom/ns#' term='BRMS'/><title type='text'>Less code - More rules</title><content type='html'>Less code - More rules...  &lt;br /&gt;&lt;br /&gt;There I said it...Now before condemning me to the pits of hell let me add some context. &lt;br /&gt;&lt;br /&gt;In large corporate financial development where systems are comprised of thousands of business rules and run in production for many years... rules, rules, rules are the key... more specifically the management of rules with a Rules engine and/or a &lt;a href="http://en.wikipedia.org/wiki/Business_rule_management_syste"&gt;BRMS(Business Rule Management System)&lt;/a&gt;. Now I know, some people love them, some people hate them and some "wrote their own"... personally I think they add a huge amount of benefit when used within the correct context.&lt;br /&gt;&lt;br /&gt;I have worked in an environment where we have both successfully and unsuccessfully used a BRMS(Yasutech Quickrules) in implementing countless rules, flows, decision tables over a 5 year period. Unfortunately Quickrules is no longer actively supported, SAP has squished them into &lt;a href="http://www.sap.com/platform/netweaver/components/brm/index.epx"&gt;SAP Netweaver BRM&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I work in the health insurance industry, and there is a vast amount of analysis, risk management and business rules that go into the "simple" act of getting a stay in hospital paid. What makes it even worse is that these rules change, and they change often, there a constant stream of changes due to legislation changes, overly smart actuaries or overly zealous marketing department announcements. All this creates an environment where there are literally thousands of volitile rules, calculations, scenarios. Now add the fact that large corporate applications like these sometimes live for a decade or more and having business rules spread between code, store procedures, data tables and web pages and you have a recipe for disaster. (These are the systems we fortunately get to rewrite them from time to time.)&lt;br /&gt;&lt;br /&gt;Based on my experience over the last couple years; the biggest single benefit of a BRMS is simply "separation of concerns". &lt;br /&gt;What this separation allows for is:&lt;br /&gt;1. Rules to be developed, tested, and possibly even deployed on a different time &lt;br /&gt;line from the application itself.&lt;br /&gt;2. The use of different resources. We managed have both the architect and business analysts define, develop and test rules with very little effort from the developers. I know this is a scary concept, and we only did it after years of having everything in place but with the correct standards, peer review, testing and training it is a possibility.&lt;br /&gt;3. More business involvement and ownership, having the ability to simply let the business owners work with their own spreadsheets and import them directly (into development environment) helped cut down on the red tape and actually made them think about their requirements for a change.&lt;br /&gt;4. More quantifiable delivery segments and estimates for those pesky project managers.&lt;br /&gt;&lt;br /&gt;One very important thing to note is that even though rules can be handled separately, they still need to be part of the development and quality processes.  After all, the business rules (depending on system) are what it's all about in the end. Most of what we do in these financial corporate application is to facilitate the running of business rules. If anything there should be stricter control and quality assurance on the rules than on the code.&lt;br /&gt;&lt;br /&gt;The second thing worth mentioning (which is also actually a by-product of the separation) is visibility of business rules to people that understand them. To be able to print out and sit with either the business analysts or the actual business representatives and visually discuss the flow and structure of the rules proved to be very helpful.&lt;br /&gt;&lt;br /&gt;There are of course many other benefits to BRMSs auditing, performance and management, but to me the separation and visibility is were the real value lies.&lt;br /&gt;&lt;br /&gt;So with Quickrules gone and with &lt;a href="http://www-01.ibm.com/software/websphere/products/business-rule-management/"&gt;Ilog JRules&lt;/a&gt; and &lt;a href="http://www.fico.com/en/Products/DMTools/Pages/FICO-Blaze-Advisor-System.aspx"&gt;Blaze Advisor&lt;/a&gt; not available to the common man, I turn to &lt;a href="http://jboss.org/drools"&gt;Drools&lt;/a&gt;. &lt;br /&gt;Over the next couple weeks I need to spend some time ... Learning to Drool...&lt;br /&gt;&lt;br /&gt;On first glace Drools does seem a little daunting, split into :&lt;br /&gt;Drools Guvnor (BRMS/BPMS)&lt;br /&gt;Drools Expert (rule engine)&lt;br /&gt;Drools Flow (process/workflow)&lt;br /&gt;Drools Fusion (event processing/temporal reasoning)&lt;br /&gt;Drools Planner..&lt;br /&gt;&lt;br /&gt;Hopefully there is a simple, quick way to get to grips with it all as I would actually like to run a concurrent proof of concept on my next project to see how it compares.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-2878998737379060721?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/2878998737379060721/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/11/less-code-more-rules.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/2878998737379060721'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/2878998737379060721'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/11/less-code-more-rules.html' title='Less code - More rules'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-2502937523719838576</id><published>2010-10-25T08:59:00.001+02:00</published><updated>2010-11-13T08:01:24.809+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Review'/><title type='text'>Top 7 of 97 Things Every Software Architect Should Know</title><content type='html'>Last week I commented on the &lt;a href="http://www.briandupreez.net/2010/10/top-9-of-97-things-every-programmer.html"&gt;97 Things every programmer should know&lt;/a&gt;. I figured I would do the same for the &lt;a href="http://oreilly.com/catalog/9780596522704/"&gt;97 Things Every Software Architect Should Know&lt;/a&gt;. Initially I thought there may be some overlap between the 2, but they have done very well to focus each book on the targeted readers. I did however feel that quite a few of this "97 Things" were very similar in the principle they were trying to explain and so I grouped them under the relevant principle.&lt;br /&gt;&lt;br /&gt;Before I start I just need to comment on the first chapter of the book:&lt;br /&gt;&lt;b&gt;Don't put your resume ahead of the requirements - Nitin Borwankar&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I am not sure how I feel about this one. I understand the point and I do partially agree, but it also doesn't mean that the "latest shiny object in the latest shiny language or the latest shiny paradigm" isn't the best thing for the company or project. The choice of some new technology for a solution is a very difficult one and should not be taken lightly. Staying with what is already known is definitely the safer option and possibly the correct choice for a project or company in the short term, but when does this become something that actually does more harm than good?&lt;br /&gt;&lt;br /&gt;Moving along to my top 7 things:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. Understand The Business Domain - Mark Richards&lt;/b&gt;&lt;br /&gt;Us "systems" folk, often experts in our own field don't always spend the time to understand the actual business we are involved in e.g. insurance, finance, marketing. To be a more effective software architect appropriate industry knowledge is as important as staying up to date with tech.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. Before anything, an architect is a developer - Mike Brown&lt;/b&gt;&lt;br /&gt;"If you design it, you should be able to code it."&lt;br /&gt;I am a firm believer in the above statement. Architects sometimes don't have the time or the will to keep their developer skills current and over time let these skills atrophy. This can then lead to grand designs, with ugly implementations with unhappy developers&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. Dealing with Developers&lt;/b&gt;&lt;br /&gt;There were a couple topics on interaction with developers, I decided to group them into 1 point:&lt;br /&gt;&lt;i&gt;Find and retain passionate problem solvers - Chad LaVigne&lt;/i&gt;&lt;br /&gt;&lt;i&gt;Give developers autonomy - Philip Nelson&lt;/i&gt;&lt;br /&gt;&lt;i&gt;Empower developers - Timothy High&lt;/i&gt;&lt;br /&gt;An architect may be a developer, but he also needs to lead them, like it or not, architects by default have a leadership role to play when it comes to the developers on their project. Developers left to their own devices will run wild (we always do ;) ). So as with most things in software architecture it's all about balance:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;if (Too much control)&lt;br /&gt;developers = unhappy&lt;br /&gt;else if (Too little control)&lt;br /&gt;customers = unhappy&lt;br /&gt;&lt;br /&gt;if(developers or customers are unhappy)&lt;br /&gt;result = bad &lt;br /&gt;&lt;/blockquote&gt;I believe the relationship between developers and architects is one of the many crucial factors in the success of a project.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. Performance&lt;/b&gt;&lt;br /&gt;There are 2 topics about performance:&lt;br /&gt;&lt;i&gt;It's never too early to think about performance - Rebecca Parsons&lt;/i&gt;&lt;br /&gt;&lt;i&gt;Application architecture determines application performance - Randy Stafford&lt;/i&gt;&lt;br /&gt;In my current environment where transaction processing times are tightly monitored and contracted with SLAs that have financial implications, performance is always top priority. However in many other teams / projects / companies I have worked in the emphasis on system performance is almost always left to the end, and sometimes no amount of hardware is going to solve the problem.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5. Record your rationale - Timothy High&lt;/b&gt;&lt;br /&gt;This is something that I feel is often neglected. Quite recently a project that I had been involved in for a long time hit the spotlight for all the wrong reasons: customer, user and management dissatisfaction. The first thing to be questioned was not the analysis, requirements, testing, management or expectations, but rather the architecture. Documentation discussing all the decisions, options looked at and reason for options taken would have been valuable. When things go fine, no one will even know about the document, but when things turn bad as they sometimes do having justification and documentation for all the major decisions will be a lifesaver.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;6. Stand Up! - Udi Dahan&lt;/b&gt;&lt;br /&gt;&lt;i&gt;"The easiest way to more than double your effectiveness when communicating ideas is quite simply to stand up."&lt;/i&gt;&lt;br /&gt;This is more of a general point rather than one just for architects, anyone attempting to influence people and situations can benefit from this principle.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;7. Great software is not built, it is grown - Bill de hora&lt;/b&gt;&lt;br /&gt;&lt;i&gt;"The single biggest predictor of software failure is size; on reflection there's almost no benefit to be had from starting with a large system design."&lt;/i&gt;&lt;br /&gt;&lt;i&gt;"Have a grand vision, but not a grand design."&lt;/i&gt;&lt;br /&gt;It is all too tempting to jump in and design the total solution. By starting with a basic, small, solid system implementation and growing from that base over the life of the project always with a grand vision in mind, you allow the software to evolve rather than just stuck together. Evolution turned out ok for us, no reason it shouldn't be the same for software.&lt;br /&gt;This approach should not be confused with prototyping, there shouldn't be any quality shortcuts taken and it shouldn't be thrown away.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;All the contributions for both books are actually available on the O'reilly site:&lt;br /&gt;&lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/Contributions_Appearing_in_the_Book"&gt;&lt;b&gt;Programmer&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://97things.oreilly.com/wiki/index.php/97_Things_Every_Software_Architect_Should_Know_-_The_Book"&gt;&lt;b&gt;Architect&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There are also a number of "things" not included in the books available on the wiki.&lt;br /&gt;&lt;br /&gt;//ignore the next bit&lt;br /&gt;Technorati claim:987BEU5BKS8H&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-2502937523719838576?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/2502937523719838576/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/10/top-7-of-97-things-every-software.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/2502937523719838576'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/2502937523719838576'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/10/top-7-of-97-things-every-software.html' title='Top 7 of 97 Things Every Software Architect Should Know'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-5176684245469426779</id><published>2010-10-18T08:28:00.002+02:00</published><updated>2010-10-18T13:55:31.868+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Review'/><category scheme='http://www.blogger.com/atom/ns#' term='General Info'/><title type='text'>Top 9 of 97 Things every programmer should know</title><content type='html'>I recently finished &lt;a href="http://oreilly.com/catalog/9780596809485/"&gt;&lt;b&gt;97 Things every programmer should know&lt;/b&gt;&lt;/a&gt;. Well to be completely honest I did skim over a couple of the 97, but all and all this was a very nice compilation of thoughts and topics about software development from very experienced authors. Well worth a read.&lt;br /&gt;&lt;br /&gt;A couple of the "97 Things" discussed, stood out more than the others, the following would be the ones I rank as my top 9. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. The Boy Scout Rule - Robert C. Martin (Uncle Bob)&lt;/b&gt;&lt;br /&gt;&lt;i&gt;"You don’t have to make every module perfect before you check it in. You simply have to make it a little bit better than when you checked it out."&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;To be honest this is not something I have followed throughout my career, and although I certainly try improve code where I can, I never did it per check-in.  I do however feel that it is an awesome principle and should be something that is actually part of a code review process. It is all to easy to just say: &lt;br /&gt;"It was like that already" &lt;br /&gt;"that nasty code was there for years, I am not going to touch it."&lt;br /&gt;"It never had any tests"&lt;br /&gt;&lt;br /&gt;I work in a corporate environment were applications often last for 4-10 years. If part of the process is always to just make something a little better, everything from deleting unused code to writing a single extra unit test, year after year... it will end up with saving a lot of people a lot of time and money.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. Beauty Is in Simplicity - Jørn Ølmheim&lt;/b&gt;&lt;br /&gt;&lt;i&gt;"The bottom line is that beautiful code is simple code."&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Over the years this has become particularly important to me. Earlier in my career, especially when starting somewhere new I would design the crap out of something. &lt;br /&gt;It would be: "Welcome to the school of over-engineering", everything would be abstracted to the nth degree, there would be patterns for the patterns, interfaces on interfaces for the abstractions and a huge amount of code and components catering for every "what if" that ever existed, that only I understood. All of this would lead to very "fancy" code, and me stroking my ego, but at what cost? &lt;br /&gt;Only the minor little one: an utter nightmare to maintain. I have for a while now favored the simplest implementation of almost any solution, even if it is not necessarily the prefect technical implementation. In the world of long living software, maintainability should quite often outweigh other concerns.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. Step Back and Automate, Automate, Automate - Cay Horstmann&lt;/b&gt;&lt;br /&gt;I believe in automating everything possible: builds, deploys, code analysis, unit testing, functional testing, integration testing. None of us actually want to look at that stuff everyday and automation is the only way to get away from that. Can't say automate enough. Automate, Automate, Automate.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. Continuous Learning - Clint Shank&lt;/b&gt;&lt;br /&gt;This is a very important topic, we are in a industry that is constantly growing, changing, shifting and as a programmer you need to be learning and improving yourself wherever you can. It's very easy to get into a comfort zone and just rest on your laurels, I did that for a couple years, and I do regret it now. &lt;br /&gt;Things I am trying to do to keep up and would recommend:&lt;br /&gt;1. Get a Kindle... then buy &amp; read books.&lt;br /&gt;2. Use &lt;a href="http://www.google.com/reader/"&gt;Google Reader&lt;/a&gt; add the popular blogs and website RSS feeds for your specific field as well as a couple outside your field that interest you.&lt;br /&gt;3. Start a blog, by putting my code and thoughts out there, I put in more effort knowing that it's going to visible than if I just wrote the code/article for myself. I also force myself to do 1 - 2 posts a week, ensuring that I must always find new content to learn about.&lt;br /&gt;4. Join an open source community, we generally don't get to do enough "technical" development in our corporate environments. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5. Check Your Code First Before Looking to Blame Others - Allan Kelly&lt;/b&gt;&lt;br /&gt;Exactly what it the title says, we all look to put the blame on anything other than our "perfect" code. Everything from the OS to the network guys, the DBAs to the JVM, 3rd party libraries to other teams' interfaces are always blamed first. This often leads to countless hours of wasted effort, or completely avoiding the issue that eventually comes back to bite you in the butt. Most of us can mention moments where we have done this, it's frighteningly common. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;6. Hard Work Does Not Pay Off - Olve Maudal&lt;/b&gt;&lt;br /&gt;&lt;i&gt;"truth is that by working less, you might achieve more"&lt;br /&gt;&lt;br /&gt;"If you are trying to be focused and “productive” for more than 30 hours a week, you&lt;br /&gt;are probably working too hard."&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I couldn't agree more with Olve Maudal. A lot of us have been there, we have spent the days, weeks, months at work, but we often don't see the negative sides of what happens when you work 50-70 hours a week. Everything from common logic to motivation and team dynamics go out the window. Even if the short term goals are achieved, quite often the long term repercussions are a lot worse. No one goes back and see's why they have to re-write a system 4 years down the line because the architecture or code is failing. I'd love to know how many of those were because of ludicrous hours and impossible time lines. I can think of at least 2 "re-writes" that I was involved in where you could see it was the result of long hours. People you know to write great code end up hacking solutions at 1am in the morning.&lt;br /&gt;There are times and there always will be, where a couple extra hours are required,  just try keep them down to a minimum.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;7. Comment Only What the Code Cannot Say - Kevlin Henney&lt;/b&gt;&lt;br /&gt;Exactly that... Don't tell another programmer what he can see in the code. Comments stating the business reason or requirement behind a particular complex algorithm is a lot more useful than //loop through the outcomes and add 1.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;8. Know Your IDE - Heinz Kabutz&lt;/b&gt;&lt;br /&gt;Something a lot of us are guilty of, we spend a couple hours a day in our IDE, learn the shortcuts, learn the features, we probably couldn't begin to calculate the time that would be saved if everyone used their IDE to it's full potential.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;9. Learn to Estimate - Giovanni Asproni&lt;/b&gt;&lt;br /&gt;I feel this is something that comes with experience, I pride myself on my estimates and over the years I have tried to nurture this "skill". I have a couple points I would like to share on how I get better estimates:&lt;br /&gt;1. Be honest with yourself, make sure you know what you think you know, and openly admit what you don't. This is the quickest way to end up in trouble.&lt;br /&gt;2. Keep track of what you do and how long it, not necessarily for the project manager, but for yourself, see point 1.&lt;br /&gt;3. Don't rely on other peoples perceived skills and timing, see point 1.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Will try get through the rest of &lt;a href="http://oreilly.com/catalog/9780596522698/"&gt;&lt;b&gt;97 Things Every Software Architect Should Know&lt;/b&gt;&lt;/a&gt; in the next week or so, will be interesting to see how it compares to the programmer one and how much overlaps.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-5176684245469426779?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/5176684245469426779/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/10/top-9-of-97-things-every-programmer.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5176684245469426779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5176684245469426779'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/10/top-9-of-97-things-every-programmer.html' title='Top 9 of 97 Things every programmer should know'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-5925468792945614090</id><published>2010-10-11T00:19:00.001+02:00</published><updated>2010-10-11T13:03:25.481+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='Hazelcast'/><title type='text'>Creating your own custom Spring configuration.</title><content type='html'>Recently I volunteered myself to do some of the Spring integration for &lt;a href="http://www.hazelcast.com/"&gt;Hazelcast&lt;/a&gt;, for one main reason actually.. I had always wondered how to actually do that. It is something you don't get to do often in a corporate working environment. As with most things Spring related it actually turned out to be very simple.&lt;br /&gt;&lt;br /&gt;First thing I needed to do was define a schema for the Hazelcast xml config. If you want to add your custom XML configuration into Springs', it will require that you have a schema for the specific XML.&lt;br /&gt;&lt;br /&gt;So what is the quickest way to get started on a schema?  &lt;a href="http://www.altova.com/xmlspy.html"&gt;Altova XML Spy&lt;/a&gt;, it generates a basic XSD form a sample XML which takes care of about 40% of the actual work. Then it's all about the details, min / max constraints, enumerations, defaults, attributes and documentation. I believe XSDs should be verbose, so the version below is not 100% complete but it is a good starting point.&lt;br /&gt;I am not going to add the XSD to this post as is quite long and doesn't add much with regards to the actual Spring integration. If interested, it is available &lt;b&gt;&lt;a href="https://code.google.com/p/hazelcast/source/browse/trunk/hazelcast/src/main/resources/hazelcast-basic.xsd"&gt;here...&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;On the Spring side you need the following:&lt;br /&gt;&lt;b&gt;1. &lt;/b&gt;An implementation of: NamespaceHandlerSupport, this basically tells Spring when it finds "hazelcast" use the "HazelcastBeanDefinitionParser".&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package com.hazelcast.spring;import org.springframework.beans.factory.xml.NamespaceHandlerSupport;public class HazelcastNamespaceHandler extends NamespaceHandlerSupport {    public void init() {        registerBeanDefinitionParser("hazelcast", new HazelcastBeanDefinitionParser());    }  }&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. &lt;/b&gt;An implementation of: AbstractSimpleBeanDefinitionParser. This implementation actually processes the XML from the Spring application config. You need to override&lt;br /&gt;getBeanClass and doParse methods, to specify what type of object and how to create it respectively.&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package com.hazelcast.spring;import org.springframework.beans.factory.support.BeanDefinitionBuilder;import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;import org.springframework.beans.factory.xml.ParserContext;import org.w3c.dom.Element;import com.hazelcast.config.Config;import com.hazelcast.config.XmlConfigBuilder;import com.hazelcast.config.XmlConfigBuilder.IterableNodeList;public class HazelcastBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser {    @Override    protected Class&lt;config&gt; getBeanClass(Element element) {        return Config.class;    }    @Override    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {        super.doParse(element, parserContext, builder);                XmlConfigBuilder util = new XmlConfigBuilder();        Config config = util.build();        try {            for (org.w3c.dom.Node node : new IterableNodeList(element.getChildNodes())) {                final String nodeName = util.cleanNodeName(node.getNodeName());                               if ("network".equals(nodeName)) {                    util.handleNetwork(node);                } else if ("group".equals(nodeName)) {                    util.handleGroup(node);                } else if ("properties".equals(nodeName)) {                    util.handleProperties(node, config.getProperties());                } else if ("executor-service".equals(nodeName)) {                    util.handleExecutor(node);                } else if ("queue".equals(nodeName)) {                    util.handleQueue(node);                } else if ("map".equals(nodeName)) {                    util.handleMap(node);                } else if ("topic".equals(nodeName)) {                    util.handleTopic(node);                } else if ("merge-policies".equals(nodeName)) {                    util.handleMergePolicies(node);                }            }        } catch (Exception e) {            throw new IllegalStateException("Configuration failed due to:" + e.getMessage(), e);        }        builder.addPropertyValue("networkConfig", config.getNetworkConfig());        builder.addPropertyValue("groupConfig", config.getGroupConfig());        builder.addPropertyValue("properties", config.getProperties());        builder.addPropertyValue("executorConfigMap", config.getExecutorConfigMap());        builder.addPropertyValue("mapConfigs", config.getMapConfigs());        builder.addPropertyValue("qConfigs", config.getQConfigs());            }&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. &lt;/b&gt;2 files in the META-INF&lt;br /&gt;3.1. A &lt;b&gt;spring.handlers&lt;/b&gt; file containing the namespace and the NamespaceHandlerSupport implementation (in my case):&lt;br /&gt;http\://www.hazelcast.com/schema/config=com.hazelcast.spring.HazelcastNamespaceHandler&lt;br /&gt;&lt;br /&gt;3.2. A &lt;b&gt;spring.schemas&lt;/b&gt; file containing the location of the schema:&lt;br /&gt;http\://www.hazelcast.com/schema/config/hazelcast-basic.xsd=hazelcast-basic.xsd&lt;br /&gt;&lt;br /&gt;and that is it...&lt;br /&gt;&lt;br /&gt;The XML you described in your XSD is now available to be used within your the Spring config.&lt;br /&gt;&lt;br /&gt;The example below is a Hazelcast map cache config, which can then be injected where required as ref="config".&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:cache="http://www.hazelcast.com/schema/config" xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.hazelcast.com/schema/confighttp://www.hazelcast.com/schema/config/hazelcast-basic.xsd"&gt; &lt;cache:hazelcast id="config"&gt;  &lt;cache:map name="testCache" &gt; &lt;cache:backup-count&gt;2&lt;/cache:backup-count&gt; &lt;cache:eviction-policy&gt;NONE&lt;/cache:eviction-policy&gt; &lt;cache:max-size&gt;0&lt;/cache:max-size&gt; &lt;cache:eviction-percentage&gt;30&lt;/cache:eviction-percentage&gt; &lt;cache:merge-policy&gt;hz.ADD_NEW_ENTRY&lt;/cache:merge-policy&gt;  &lt;/cache:map&gt; &lt;/cache:hazelcast&gt;&lt;/beans&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The source and tests for this are available in the Hazelcast code project &lt;a href="https://code.google.com/p/hazelcast/source/browse/#svn/trunk/hazelcast-spring"&gt;&lt;b&gt;here.&lt;/b&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-5925468792945614090?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/5925468792945614090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/10/creating-your-own-custom-spring.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5925468792945614090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5925468792945614090'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/10/creating-your-own-custom-spring.html' title='Creating your own custom Spring configuration.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-4328401643912998299</id><published>2010-10-05T00:21:00.002+02:00</published><updated>2010-10-05T07:25:15.746+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='SpEL'/><title type='text'>Spring 3: Spring Expression Language - SpEL</title><content type='html'>I realized that I have covered most of the major functions in the Spring 3 release, but completely overlooked SpEL. Now even though I am a huge Spring fan, all this functionality does actually scare me a little bit. To often have I seen people hang themselves with awesome, innocent looking ropes just like this one. Soon there will be some project that needs to be "dynamic" and some person/consultant/architect/developer will have this amazing idea and place code somewhere they can edit it externally. Then this SpEL can read this and "dynamically do stuff"... &lt;br /&gt;&lt;i&gt;(I am pretty sure that I have been that "person" somewhere in my career, it all feels horribly familiar.)&lt;/i&gt;&lt;br /&gt;And all of that only comes at the price of some poor developers' sanity trying to maintain it. To be fair, this view is purely based on personal experiences and maybe slightly unjustified, but I have seen my share of good ideas gone bad in my time and it feels like SpEL is wide open for misuse.&lt;br /&gt;&lt;br /&gt;Putting my concerns aside and refocusing on: it's something new , it's shiny and Spring-made so I obviously can't resist trying it out. &lt;br /&gt;First I go digging for information to answer: "What is SpEL, Spring Expression Language?" &lt;br /&gt;A quick summary of what I find:&lt;br /&gt;It is an expression language that supports querying and manipulating objects at runtime. It can be used as part of the standard configuration, XML or annotation based, but can also be evaluated directly by the application code. It allows you to overcome the limitation of using only fixed values. It can be used for bean definitions in both XML- and annotation-based configurations. There is a facility to access system, environment and context parameters.&lt;br /&gt;&lt;br /&gt;I have just covered thing that I would generally need or have run into... there is however quite a bit more information within the &lt;a href="http://static.springsource.org/spring/docs/3.0.3.RELEASE/spring-framework-reference/html/expressions.html"&gt;Spring documentation&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So using Maven first thing I needed was to add following:&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;dependency&gt; &lt;groupId&gt;org.springframework&lt;/groupId&gt; &lt;artifactId&gt;spring-expression&lt;/artifactId&gt; &lt;version&gt;3.0.3.RELEASE&lt;/version&gt;&lt;/dependency&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Using SpEL in Code:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Below I have examples code of: Setting a value, Calling a constructor, creating variables, calling a static function, all the basic operators, the instanceof operator and even the ternary if.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.spel;import static org.junit.Assert.assertEquals;import static org.junit.Assert.assertFalse;import static org.junit.Assert.assertNotNull;import static org.junit.Assert.assertSame;import static org.junit.Assert.assertTrue;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.expression.Expression;import org.springframework.expression.ExpressionParser;import org.springframework.expression.spel.standard.SpelExpressionParser;import org.springframework.expression.spel.support.StandardEvaluationContext;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = { "applicationContext.xml"})public class TestSpEL {          @Test    public void checkSimpleStringParser() {               ExpressionParser parser = new SpelExpressionParser();              Expression expre = parser.parseExpression("'bob'");        String value = expre.getValue(String.class);        assertEquals("bob", value);    }        @Test    public void checkConstructorsParser() {        ExpressionParser parser = new SpelExpressionParser();        TestObject object = parser.parseExpression("new javaitzen.spring.spel.TestObject()").getValue(TestObject.class);        assertNotNull(object);                parser = new SpelExpressionParser();        TestObject o2 = parser.parseExpression("new  javaitzen.spring.spel.TestObject('a String value')").getValue(TestObject.class);        assertEquals(o2.getStringValue(), "a String value");            }        @Test    public void testStateAndFunctionCreation() throws Exception{        ExpressionParser parser = new SpelExpressionParser();        StandardEvaluationContext context = new StandardEvaluationContext();        context.setVariable("bob", "string");        String bob = parser.parseExpression("#bob").getValue(context, String.class);        assertEquals("string", bob);                context.registerFunction("staticStringValue", TestObject.class.getDeclaredMethod("staticStringValue", String.class));        String added = parser.parseExpression("#staticStringValue(#bob)").getValue(context, String.class);        assertEquals("static string", added);            }        @Test    public void checkOperators() {        StandardEvaluationContext context = new StandardEvaluationContext();        context.setVariable("bob", "true");                ExpressionParser parser = new SpelExpressionParser();        //can use variables        assertTrue(parser.parseExpression("#bob ==#bob").getValue(boolean.class));        assertFalse(parser.parseExpression("#bob != #bob").getValue(boolean.class));                //can use numbers        assertTrue(parser.parseExpression("5 == 5").getValue(boolean.class));        assertFalse(parser.parseExpression("5 &lt; 5").getValue(boolean.class));                //can't use the variable as a boolean in this case, but can use it to create a boolean result.        assertTrue(parser.parseExpression("true and #bob == #bob").getValue(boolean.class));        assertTrue(parser.parseExpression("false or true").getValue(boolean.class));        assertTrue(parser.parseExpression("true and not false").getValue(boolean.class));        // can use + - ^ * / and even + on string values note the '        assertSame(100, parser.parseExpression("10*10").getValue(int.class));        assertEquals("added-together", parser.parseExpression("'added' + '-' + 'together'").getValue(String.class));                // instanceof        assertTrue(parser.parseExpression("0 instanceof T(Integer)").getValue(boolean.class));                // and now for some logic and null checks        assertEquals("true answer", parser.parseExpression("true ? 'true answer' : 'false answer'").getValue(String.class));    }}&lt;/script&gt;&lt;b&gt;Using SpEL in XML Config:&lt;/b&gt;As with the Java code, here is the same functionality within you Spring application XML.&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;bean id="testObject" class="javaitzen.spring.spel.TestObject" &gt; &lt;property name="theDate" value="#{new java.util.Date()}" /&gt; &lt;property name="intValue" value="#{10 * 10}"/&gt; &lt;property name="stringValue" value="#{'added' + '-' + 'together'}"/&gt; &lt;property name="stringValue2" value="#{testObject.theDate instanceof T(java.util.Date) ? 'yes' : 'no'}"/&gt;&lt;/bean&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Using SpEL in Annotations:&lt;/b&gt;&lt;br /&gt;And then again will the @Value annotation.&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt; //The @Value value needs to be a constant value so no: //@Value("#{new java.util.ComplexType("+ stringValue +")}")    @Value("#{'String Annotation Value'}")    private String stringValue;    @Value("#{10 * 10}")    private int intValue;    @Value("#{new java.util.Date()}")    private Date theDate;    @Value("#{10 == 10}")    private boolean booleanValue;    @Value("#{new javaitzen.spring.spel.ComplexType('a value')}")    private ComplexType complexObjectValue;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-4328401643912998299?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/4328401643912998299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/10/spring-3-spring-expression-language.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4328401643912998299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4328401643912998299'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/10/spring-3-spring-expression-language.html' title='Spring 3: Spring Expression Language - SpEL'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-3663186721956330249</id><published>2010-09-23T00:21:00.004+02:00</published><updated>2010-09-23T01:04:07.750+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cache'/><category scheme='http://www.blogger.com/atom/ns#' term='Guice'/><category scheme='http://www.blogger.com/atom/ns#' term='Hazelcast'/><title type='text'>Guice &amp; Hazelcast.... Method Caching Interceptor</title><content type='html'>A couple days back I did &lt;a href="http://www.briandupreez.net/2010/09/spring-aspectj-hazelcast-method-caching.html"&gt;&lt;b&gt;Spring, AspectJ, Hazelcast Method Caching Aspect&lt;/b&gt;&lt;/a&gt; and I received an anonymous question on how to do the same thing in &lt;a href="http://code.google.com/p/google-guice/"&gt;&lt;b&gt;Guice&lt;/b&gt;&lt;/a&gt; I had heard of Guice, I knew what it was, but... I have been a Spring zealot for many years now, so my first reaction was:&lt;br /&gt;What???  Guice? me?? ... Not use Spring? ... why would you ever &lt;b&gt;not&lt;/b&gt; do this is Spring?... after a bit more whining I finally found myself saying "Oh ok, let me do it in this Spring wannabe "Juice" framework, just to prove that Spring is better."&lt;br /&gt;&lt;br /&gt;All I can say is dammit! I hate being wrong ... the Guice is sweet. It took me about an hour to go from never using it before to having this AOP Method Cache Interceptor project done. A lot of that time was me being a typical developer and playing rather than actually reading the docs. In other words, it's simple, and that is always a good thing. &lt;br /&gt;Now before someone takes this the wrong way: I know Spring does a lot more, Guice is focused on DI, Spring integrates with more, most of the popular Google apps run on Guice so it is rock solid etc. etc... I am not doing this as a comparison and definitely don't want to choose sides, but rather just showing another way of doing something.&lt;br /&gt;&lt;br /&gt;I will only be posting the interesting bits of this project here, the full source is available here : &lt;br /&gt;&lt;a href="http://code.google.com/p/itzen/source/browse/#svn/trunk/HazelGuice"&gt;&lt;b&gt; Source Code&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;First thing, Guice is available in the Maven repo and they recommend using that rather than the google.code site. The POM for this project:&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt; &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;  &lt;groupId&gt;HazelGuice&lt;/groupId&gt; &lt;artifactId&gt;HazelGuice&lt;/artifactId&gt; &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt; &lt;packaging&gt;jar&lt;/packaging&gt; &lt;name&gt;HazelGuice&lt;/name&gt;  &lt;build&gt;  &lt;plugins&gt;   &lt;plugin&gt;    &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;    &lt;configuration&gt;     &lt;source&gt;1.6&lt;/source&gt;     &lt;target&gt;1.6&lt;/target&gt;    &lt;/configuration&gt;   &lt;/plugin&gt;  &lt;/plugins&gt; &lt;/build&gt; &lt;dependencies&gt;  &lt;dependency&gt;   &lt;groupId&gt;junit&lt;/groupId&gt;   &lt;artifactId&gt;junit&lt;/artifactId&gt;   &lt;version&gt;4.8.1&lt;/version&gt;   &lt;scope&gt;test&lt;/scope&gt;  &lt;/dependency&gt;  &lt;dependency&gt;   &lt;groupId&gt;com.google.inject&lt;/groupId&gt;   &lt;artifactId&gt;guice&lt;/artifactId&gt;   &lt;version&gt;2.0&lt;/version&gt;  &lt;/dependency&gt;  &lt;dependency&gt;   &lt;groupId&gt;com.hazelcast&lt;/groupId&gt;   &lt;artifactId&gt;hazelcast&lt;/artifactId&gt;   &lt;version&gt;1.9&lt;/version&gt;  &lt;/dependency&gt; &lt;/dependencies&gt; &lt;/project&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Guice (as they say in their documentation) takes full advantage of annotations and generics. So for this project I created a @Cacheable interface to allow me to annotate the methods I wanted cached.&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD)@interface Cacheable {}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;To configure Guice you need to extend an AbstractModule, this is where you configure what gets injected where by what. In the example below I use a construct called a Provider to allow me to use the Hazelcast factory to inject and instance. One other important thing to note in the code below is the "requestInjection(cache)" when injecting into interceptors you need to specify that in order to that injection before actually using the interceptor.&lt;br /&gt;&lt;br /&gt;The AbstractModule:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.gg.interceptors;import com.google.inject.AbstractModule;import com.google.inject.Provider;import com.google.inject.matcher.Matchers;import com.hazelcast.core.Hazelcast;import com.hazelcast.core.HazelcastInstance;public class CacheModule extends AbstractModule{        /* (non-Javadoc)     * @see com.google.inject.AbstractModule#configure()     */    protected void configure() {        HazelcastMethodCacheInterceptor cache = new HazelcastMethodCacheInterceptor();        requestInjection(cache);        //To use a factory.        bind(HazelcastInstance.class).toProvider(new Provider&lt;hazelcastinstance&gt;() {                @Override                public HazelcastInstance get() {                   return Hazelcast.getDefaultInstance();                }        });        bind(CacheKeyStrategy.class).to(DefaultCacheKeyStrategy.class);        bindConstant().annotatedWith(HazelcastMethodCacheInterceptor.CacheName.class).to("testCache");        bindInterceptor(Matchers.only(MyLittleTestObject.class), Matchers.annotatedWith(Cacheable.class), cache);            }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;And lastly for the actual interceptor. Right at the bottom of the source below you will see the @CacheName interface, this is one of a number of ways to map configuration values to be injected. The interceptor implements MethodInterceptor and you get all the required information about the method execution from the MethodInvocation parameter.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.gg.interceptors;import java.io.Serializable;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import java.util.LinkedList;import java.util.List;import java.util.logging.Level;import java.util.logging.Logger;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import com.google.inject.BindingAnnotation;import com.google.inject.Inject;import com.hazelcast.core.HazelcastInstance;import com.hazelcast.core.IMap;import com.hazelcast.core.MapEntry;public class HazelcastMethodCacheInterceptor implements MethodInterceptor {    private Logger logger = Logger.getLogger(HazelcastMethodCacheInterceptor.class.getName());    private HazelcastInstance hazelcastInstance;    private String cacheName;    private CacheKeyStrategy defaultKeyStrat;        private List&lt;cachekeystrategy&gt; keyStrategies = new LinkedList&lt;cachekeystrategy&gt;();        public void setCacheKeyStrategies(final List&lt;cachekeystrategy&gt; cacheKeys) {        this.keyStrategies = cacheKeys;    }    public void addCacheKeyStrategy(final CacheKeyStrategy cacheKey) {        this.keyStrategies.add(cacheKey);    }    @Override    public Object invoke(MethodInvocation invocation) throws Throwable {        Object[] arguments = invocation.getArguments();        Object result;        StringBuilder cacheKey = new StringBuilder();        defaultKeyStrat = new DefaultCacheKeyStrategy(invocation);        if (!keyStrategies.isEmpty()) {            logger.log(Level.FINE, "Have a Key Strategy to use...");            for (CacheKeyStrategy strat : keyStrategies) {                if ((arguments != null) &amp;&amp; (arguments.length != 0)) {                    logger.log(Level.FINE, "Have Arguments...");                    for (Object arg : arguments) {                        logger.log(Level.FINE, "Class for Strategy: " + strat.classForStrategy());                        logger.log(Level.FINE, "Arguments: " + arg);                        if (Class.forName(strat.classForStrategy()).isInstance(arg)) {                            strat.setObject(arg);                            logger.log(Level.FINE, "Using Strategy...");                            cacheKey.append(strat.generateKey());                        }                    }                }            }        }        if (cacheKey.length() == 0) {            logger.log(Level.FINE, "Using Default...");            cacheKey.append(defaultKeyStrat.generateKey());        }        MapEntry&lt;String, Serializable&gt; entry = getCache().getMapEntry(cacheKey.toString());                // not in cache        if (entry == null) {            result = invocation.proceed();            if (result != null &amp;&amp; !(result instanceof Serializable)) {                throw new RuntimeException("[" + result.getClass().getName() + "] is not Serializable");            }            logger.log(Level.INFO, "&gt;&gt;&gt; caching result - " + cacheKey);            getCache().put(cacheKey.toString(), (Serializable) result);        } else {            logger.log(Level.INFO, "&gt;&gt;&gt; returning result from cache");            return entry.getValue();        }        return result;    }    private IMap&lt;String, Serializable&gt; getCache() {        return hazelcastInstance.getMap(getCacheName());    }        @Inject    public final void setHazelcastInstance(HazelcastInstance hazelcastInstance) {        this.hazelcastInstance = hazelcastInstance;    }    private final String getCacheName() {        return cacheName;    }    @Inject    public final void setCacheName(@CacheName String cacheName) {        this.cacheName = cacheName;    }    @Retention(RetentionPolicy.RUNTIME)    @Target({ElementType.FIELD, ElementType.PARAMETER})    @BindingAnnotation    public @interface CacheName {}    }&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;So there you go Mr Anonymous, hope it helps.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-3663186721956330249?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/3663186721956330249/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/09/guice-hazelcast-method-caching.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3663186721956330249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3663186721956330249'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/09/guice-hazelcast-method-caching.html' title='Guice &amp; Hazelcast.... Method Caching Interceptor'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-660906115836980032</id><published>2010-09-20T08:52:00.000+02:00</published><updated>2010-09-20T08:52:35.479+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cache'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='Hazelcast'/><title type='text'>Spring, AspectJ, Hazelcast  Method Caching Aspect</title><content type='html'>After my recent discovery of &lt;a href="http://www.hazelcast.com/"&gt;Hazelcast&lt;/a&gt;, I decided to update my caching aspect project to include a Hazelcast implementation.&lt;br /&gt;&lt;br /&gt;The source code for this project is available &lt;a href="http://code.google.com/p/itzen/source/browse/#svn/trunk/MethodCacheAspect"&gt;&lt;b&gt; here &lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For more information please refer to the actual source or my original Ehcache &lt;a href="http://www.briandupreez.net/2010/06/spring-aspectj-ehcache-method-caching.html"&gt;post&lt;/a&gt;. The main difference here is that the Hazelcast implementation is by default a distributed cache, and takes advantage of all the other functionality that Hazelcast provides. &lt;br /&gt;The main points of interest for this implementation are:&lt;br /&gt; - The actual aspect class. See code below.&lt;br /&gt; - The application context. See xml below.&lt;br /&gt; - The Hazelcast configuration. I am using the default Hazelcast configuration, located in the hazelcast-version.jar. To use a custom one, you can define a hazelcast.xml and inject it via Spring. &lt;br /&gt; - The CacheKeyStrategy in the code below is an interface defined to allow key generation for the cache for specific requirements. There is a default implementation that simply sorts and uses hashcodes of the values in the class. You can define a strategy per type you want to cache.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;note: java docs only removed for size of post&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The aspect:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.interceptors;import java.io.Serializable;import java.util.LinkedList;import java.util.List;import java.util.logging.Level;import java.util.logging.Logger;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Aspect;import com.hazelcast.core.HazelcastInstance;import com.hazelcast.core.IMap;import com.hazelcast.core.MapEntry;/** * The Class HazelcastMethodAspect. *  * @author Brian Du Preez */@Aspectpublic class HazelcastMethodAspect {    private Logger logger = Logger.getLogger(HazelcastMethodAspect.class.getName());    private HazelcastInstance hazelcastInstance;    private String cacheName;    private CacheKeyStrategy defaultKeyStrat;    private List&lt; CacheKeyStrategy &gt; keyStrategies = new LinkedList&lt; CacheKeyStrategy &gt;();    public void setCacheKeyStrategies(final List&lt; CacheKeyStrategy &gt; cacheKeys) {        this.keyStrategies = cacheKeys;    }    public void addCacheKeyStrategy(final CacheKeyStrategy cacheKey) {        this.keyStrategies.add(cacheKey);    }    public Object aroundAdvice(final ProceedingJoinPoint pjp) throws Throwable {        Object[] arguments = pjp.getArgs();        Object result;        StringBuilder cacheKey = new StringBuilder();        defaultKeyStrat = new DefaultCacheKeyStrategy(pjp);        if (!keyStrategies.isEmpty()) {            logger.log(Level.FINE, "Have a Key Strategy to use...");            for (CacheKeyStrategy strat : keyStrategies) {                if ((arguments != null) &amp;&amp; (arguments.length != 0)) {                    logger.log(Level.FINE, "Have Arguments...");                    for (Object arg : arguments) {                        logger.log(Level.FINE, "Class for Strategy: " + strat.classForStrategy());                        logger.log(Level.FINE, "Arguments: " + arg);                        if (Class.forName(strat.classForStrategy()).isInstance(arg)) {                            strat.setObject(arg);                            logger.log(Level.FINE, "Using Strategy...");                            cacheKey.append(strat.generateKey());                        }                    }                }            }        }        if (cacheKey.length() == 0) {            logger.log(Level.FINE, "Using Default...");            cacheKey.append(defaultKeyStrat.generateKey());        }        MapEntry&lt;String, Serializable&gt; entry = getCache().getMapEntry(cacheKey.toString());                // not in cache        if (entry == null) {            result = pjp.proceed();            if (result != null &amp;&amp; !(result instanceof Serializable)) {                throw new RuntimeException("[" + result.getClass().getName() + "] is not Serializable");            }            logger.log(Level.INFO, "&gt;&gt;&gt; caching result - " + cacheKey);            getCache().put(cacheKey.toString(), (Serializable) result);        } else {            logger.log(Level.INFO, "&gt;&gt;&gt; returning result from cache");            return entry.getValue();        }        return result;    }    private IMap&lt;String, Serializable&gt; getCache() {        return hazelcastInstance.getMap(getCacheName());    }            private final HazelcastInstance getHazelcastInstance() {        return hazelcastInstance;    }    public final void setHazelcastInstance(HazelcastInstance hazelcastInstance) {        this.hazelcastInstance = hazelcastInstance;    }    private final String getCacheName() {        return cacheName;    }    public final void setCacheName(String cacheName) {        this.cacheName = cacheName;    }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The application context:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt; &lt;bean id="hazelTestObject" class="javaitzen.spring.interceptors.MyLittleTestObject" /&gt; &lt;bean id="hazelcastCacheAspect" class="javaitzen.spring.interceptors.HazelcastMethodAspect"&gt;  &lt;property name="cacheName" value="methodCache" /&gt;  &lt;property name="hazelcastInstance"  ref="hazInstance" /&gt;    &lt;/bean&gt;  &lt;aop:config proxy-target-class="true"&gt;  &lt;aop:aspect ref="hazelcastCacheAspect"&gt;   &lt;aop:pointcut id="around" expression="execution(* theOtherBusinessMethod(..))" &gt;&lt;/aop:pointcut&gt;   &lt;aop:around pointcut-ref="around" method="aroundAdvice" &gt;&lt;/aop:around&gt;  &lt;/aop:aspect&gt; &lt;/aop:config&gt; &lt;bean id="hazInstance" class="com.hazelcast.core.Hazelcast" factory-method="getDefaultInstance" /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The test case:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.interceptors;import static org.junit.Assert.assertEquals;import java.util.Date;import java.util.logging.Level;import java.util.logging.Logger;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = { "applicationContext-hazelcast.xml" })public class TestHazelcastCacheAspect {    private Logger logger = Logger.getAnonymousLogger();        @Autowired    private MyLittleTestObject hazelTestObject;        @Test    public void checkHazelcastAspect() {        long starttime = new Date().getTime();        String returnstr = hazelTestObject.theOtherBusinessMethod("test");        logger.log(Level.INFO, "Ran the Hazelcast method: " + returnstr);        long donetime = new Date().getTime();        long totalTime1 = donetime - starttime;        logger.log(Level.INFO, "theOtherBusinessMethod()&gt; 1 done - time:" + totalTime1);        assertEquals(returnstr, "Returning from other business method with value: test 1000000");    }    /**     * Cached time test. Times out after 5 milliseconds, meaning that the cache     * didn't work.     */    @Test(timeout = 5)    public void cachedHazelcastTimeTest() {        long starttime = new Date().getTime();        String returnstr = hazelTestObject.theOtherBusinessMethod("test");        logger.log(Level.INFO, "Ran the Hazelcast method: " + returnstr);        long donetime = new Date().getTime();        long totalTime1 = donetime - starttime;        logger.log(Level.INFO, "theOtherBusinessMethod()&gt; 2 done - time:" + totalTime1);        // check that we got the same result with actually entering the        // function.        assertEquals(returnstr, "Returning from other business method with value: test 1000000");    }}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-660906115836980032?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/660906115836980032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/09/spring-aspectj-hazelcast-method-caching.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/660906115836980032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/660906115836980032'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/09/spring-aspectj-hazelcast-method-caching.html' title='Spring, AspectJ, Hazelcast  Method Caching Aspect'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-5224409000902897960</id><published>2010-09-13T00:13:00.002+02:00</published><updated>2011-09-04T10:03:57.757+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cache'/><category scheme='http://www.blogger.com/atom/ns#' term='Hazelcast'/><title type='text'>Hazelcast - a simple distributed caching alternative</title><content type='html'>I have over the last couple years used EhCache either via &lt;a href="http://www.briandupreez.net/2010/06/spring-aspectj-ehcache-method-caching.html"&gt;&lt;b&gt;Spring (with AOP)&lt;/b&gt;&lt;/a&gt; or having it configured as hibernates' cache. I have never had the time or the need to look into the whole distributed caching available with Terracotta. However I recently stumbled on to &lt;a href="http://www.hazelcast.com/"&gt;&lt;b&gt;Hazelcast&lt;/b&gt;&lt;/a&gt; and read the following:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;"Hazelcast is pure Java. JVMs that are running Hazelcast will dynamically cluster. Although by default Hazelcast will use multicast for discovery, it can also be configured to only use TCP/IP for environments where multicast is not available or preferred. Communication among cluster members is always TCP/IP with Java NIO beauty. Default configuration comes with 1 backup so if one node fails, no data will be lost. It is as simple as using java.util.{Queue, Set, List, Map}. Just add the hazelcast.jar into your classpath and start coding."&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I was instantly intrigued. So it sounds simple enough...Open IDE...jump in... being a maven fan, I figure, why download and manually "install" when you can just use maven, so I search around a little and add the following to a pom.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Edit: 1.8.4 is now outdated check &lt;a href="http://www.hazelcast.com/downloads.jsp"&gt;http://www.hazelcast.com/downloads.jsp&lt;/a&gt; for the latest.&lt;/b&gt;&lt;script class="brush: xml" type="syntaxhighlighter"&gt;    &lt;dependency&gt;      &lt;groupid&gt;com.hazelcast&lt;/groupid&gt;      &lt;artifactid&gt;hazelcast&lt;/artifactid&gt;      &lt;version&gt;1.8.4&lt;/version&gt;    &lt;/dependency&gt;    &lt;dependency&gt;      &lt;groupid&gt;com.hazelcast&lt;/groupid&gt;      &lt;artifactid&gt;hazelcast-client&lt;/artifactid&gt;      &lt;version&gt;1.8.4&lt;/version&gt;    &lt;/dependency&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;From the online documentation, I saw there was an InstanceListener interface. I create a simple Main class, that implements that and lists the instances.&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;package javaitzen.cache.hazelcast;import java.util.Collection;import com.hazelcast.core.Hazelcast;import com.hazelcast.core.Instance;import com.hazelcast.core.InstanceEvent;import com.hazelcast.core.InstanceListener;public class HCListener implements InstanceListener {    public static void main(String[] args) {        HCListener main = new HCListener();        Hazelcast.addInstanceListener(main);        Collection&lt;instance&gt; instances = Hazelcast.getInstances();        for (Instance instance : instances) {            System.out.println("ID: [" + instance.getId() + "] Type: [" + instance.getInstanceType() + "]");        }    }    @Override    public void instanceCreated(InstanceEvent event) {        Instance instance = event.getInstance();        System.out.println("Created instance ID: [" + instance.getId() + "] Type: [" + instance.getInstanceType() + "]");    }    @Override    public void instanceDestroyed(InstanceEvent event) {        Instance instance = event.getInstance();        System.out.println("Destroyed isntance ID: [" + instance.getId() + "] Type: [" + instance.getInstanceType() + "]");    }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;So running this just adds a listener to the Hazelcast instance. According to the documentation Hazelcast allows for the following (and lots more):&lt;br /&gt;# Distributed java.util.{Queue, Set, List, Map}&lt;br /&gt;# Querying distributed data&lt;br /&gt;&lt;br /&gt;I created a couple Main classes to run these separately, so that I could see if they are usable across different JVM executions. &lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;package javaitzen.cache.hazelcast;import java.io.Serializable;public class ObjectToCache implements Serializable{    private static final long serialVersionUID = -4702483501497968870L;    private String objectName;    private String objectValue;    private Integer objectID;    public ObjectToCache() {            }        public ObjectToCache(String objectName, String objectValue, Integer objectID) {        super();        this.objectName = objectName;        this.objectValue = objectValue;        this.objectID = objectID;    }    public final String getObjectName() {        return objectName;    }    public final void setObjectName(String objectName) {        this.objectName = objectName;    }    public final String getObjectValue() {        return objectValue;    }    public final void setObjectValue(String objectValue) {        this.objectValue = objectValue;    }    public final Integer getObjectID() {        return objectID;    }    public final void setObjectID(Integer objectID) {        this.objectID = objectID;    }    @Override    public String toString() {        return "ObjectToCache [objectID=" + objectID + ", objectName=" + objectName + ", objectValue=" + objectValue + "]";    }    }&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;package javaitzen.cache.hazelcast;import java.util.List;import java.util.Map;import com.hazelcast.core.Hazelcast;import com.hazelcast.core.HazelcastInstance;public class AddThingsToCache {    private HazelcastInstance haz;        public AddThingsToCache() {        haz = Hazelcast.getDefaultInstance();    }        public void addListData() {        List&lt;objecttocache&gt; list = haz.getList("testlist");        for (int i = 0; i &lt; 10000; i++) {            list.add(new ObjectToCache("example: " + i, "value" + i,i));        }    }    public void addMapData() {        Map&lt;Integer, ObjectToCache&gt; map = haz.getMap("testmap");        for (int i = 0; i &lt; 10000; i++) {            map.put(i, new ObjectToCache("example: " + i, "value" + i,i));        }    }    public static void main(String[] args) {        AddThingsToCache adder = new AddThingsToCache();        adder.addListData();        adder.addMapData();           }   }&lt;/script&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;package javaitzen.cache.hazelcast;import java.util.List;import java.util.Map;import java.util.Set;import com.hazelcast.core.Hazelcast;import com.hazelcast.core.HazelcastInstance;import com.hazelcast.core.IMap;import com.hazelcast.query.EntryObject;import com.hazelcast.query.Predicate;import com.hazelcast.query.PredicateBuilder;public class QueryTheCache {    private HazelcastInstance haz;    public QueryTheCache() {        haz = Hazelcast.getDefaultInstance();    }    @SuppressWarnings("unchecked")    public void queryMap() {        IMap map = Hazelcast.getMap("testmap");        EntryObject e = new PredicateBuilder().getEntryObject();        Predicate predicate = e.get("objectName").in("example: 1","example: 2","example: 3").and(e.get("objectID").lessThan(4));        Set&lt;objecttocache&gt; objects = (Set&lt;objecttocache&gt;) map.values(predicate);        for(ObjectToCache o : objects ) {            System.out.println("Map Query Result :" + o);        }    }    public static void main(String[] args) {        QueryTheCache use = new QueryTheCache();        use.queryMap();    }    }&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;package javaitzen.cache.hazelcast;import java.util.List;import java.util.Map;import com.hazelcast.core.Hazelcast;import com.hazelcast.core.HazelcastInstance;public class UseTheCache {    private HazelcastInstance haz;    public UseTheCache() {        haz = Hazelcast.getDefaultInstance();    }    public void readList() {        List&lt;objecttocache&gt; list = haz.getList("testlist");        System.out.println("List has " + list.size() + " items.");    }    public void readMap() {        Map&lt;Integer, ObjectToCache&gt; map = haz.getMap("testmap");        System.out.println("Map has " + map.size() + " items.");    }    public static void main(String[] args) {        UseTheCache use = new UseTheCache();        use.readList();        use.readMap();    }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;So within minutes... I have a distributed cache across 4 applications, that I can monitor, control, query... (and btw. Hazelcast allows you to add indexes to the caches, same as a database to optimize queries).&lt;br /&gt;If I was to place these 4 applications on 4 different machines, they will by default cluster (multicast for discovery) and have built in failover, monitoring and even persistence if required.&lt;br /&gt;&lt;br /&gt;Coming from an environment where we have dozens of servers all caching data, this has got to be one of the most exciting open source products I have come across. Now I just need to convince the powers that be to prototype this and this may be the first open source project I actually try get involved in. The possibilities I am seeing for this type of functionality and then integrating it with the Spring Framework may actually make my brain explode.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-5224409000902897960?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/5224409000902897960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/09/hazelcast-simple-distributed-caching.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5224409000902897960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5224409000902897960'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/09/hazelcast-simple-distributed-caching.html' title='Hazelcast - a simple distributed caching alternative'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-9015082252909051778</id><published>2010-09-07T20:28:00.001+02:00</published><updated>2010-09-07T20:31:12.095+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General Info'/><title type='text'>Developer / Architect interviews, looking at it from both sides. Part 2</title><content type='html'>Part 2, The Interviewer...&lt;br /&gt;&lt;br /&gt;In &lt;b&gt;&lt;a href="http://www.briandupreez.net/2010/09/developer-architect-interviews-looking.html"&gt;Part 1&lt;/a&gt;&lt;/b&gt;, I covered things that would possibly aid you as an interviewee, now onto the other side. I will be the first to say, I still have lots to learn about interviewing people, and some of what I list below, I need to practice as well.&lt;br /&gt;&lt;br /&gt;All companies have their general interview process, being certain technical tests, standard questionnaires and particular processes. Going beyond those -because they are a necessary evil- other things I feel important when interviewing a developer are:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1.&lt;/b&gt; Probably the most important thing I look for in a developer, being a developer, is a passion for development. Sadly this has also proven to be the hardest thing to find. There was only one candidate out of the 20 something interviewed that showed some passion for development and he ended up accepted an architecture role, where he probably won't get to develop. I feel if someone shows passion for what they do, they will learn faster, be more focused, be more positive and generally a much safer bet to employ. Judging a developers' passion in an interview can be difficult, the best way I can think of is to explore an area of their expertise. Taking myself as an example all you would need to say is: "So I see you worked with the Spring Frame..." and that would be the rest of the interview. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;2.&lt;/b&gt; When you receive a candidate's CV, read it, make notes, add specific questions. Do this before the interview as once you are in the actual interview it is far more important to pay attention to the candidate. During this preparation look for discrepancies, these creep in, things like someone rates themselves 4/5 in say JavaScript or some application server for example... but then none of the jobs / projects they mention used that specific technology. Make sure to find out the detail, as this could be a miss communication somewhere between the candidate, recruiter, HR department and you, or actually something alluding to a "creative" CV. Always check for job hopping, in areas where there are large systems running it generally takes a developer 3-6 months to become really productive, if someone leaves within a year it's actually a huge loss.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3.&lt;/b&gt; Try get the candidate to relax, people do not show their actual personality under stress. So begin the interview with light personal questions, none that will get you in trouble with the HR department, but just enough to allow the candidate loosen up before jumping into the technical stuff.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4.&lt;/b&gt; Make sure everything required for the interview is available and ready. A clean whiteboard and markers or paper and pens if the candidate needs to draw or describe anything. Having both available is preferable as some people are really not comfortable drawing on a board.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5.&lt;/b&gt; People sometimes don't feel very comfortable asking the interviewer questions, specially in the case of panel interviews. Prepare a standard list of points that would answer questions the candidate didn't ask. I mentioned some in Part 1 and some examples as an interviewer may be:&lt;br /&gt;&lt;br /&gt;The regular day /week in the life of a developer here looks like: weekly dev meetings, daily meetings close to deadline, multiple tasks, tech specs, code reviews and unit tests, etc etc.&lt;br /&gt;We support 15 different application on a 24/7 basis every couple weeks.&lt;br /&gt;The team size and structure is as follows: 12 people, 1 team lead, 1 architect, 6 developers... &lt;br /&gt;The career path here is defined as follows Developer - Senior Developer - Architect - etc.&lt;br /&gt;We supply you with a choice of laptop or desktop, duel monitors, 4gb RAM, IDE is up to you.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;6.&lt;/b&gt; 'Go with your gut'; the general interview process is actually too short to be able to completely assess someones skills and compatibility. We work in a very high stress environment, with hundreds of different scenarios everyday and I don't think we can determine if the candidate will cope or excel within a 1 - 2 hour period. There are no hard and fast tests that will determine if the candidate will take responsibly for their work. If they will complete things in a timely manner under pressure. If they will boost the morale of those in the team, or will they turn out to be a complainer that will to jump ship at the earliest opportunity.&lt;br /&gt;&lt;br /&gt;My final point to end off -something I heard from my wife's boss- which appealed to me greatly. This will probably get some reactions from people and unfortunately my current boss did not allow me to actually do this... but... In a perfect world, where you get a fair amount of high quality CVs, I would personally love to divide the large stack of applications in half and toss 1 half of them directly into recycle bin. If you are unlucky, it's probably better you find work somewhere else.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-9015082252909051778?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/9015082252909051778/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/09/developer-architect-interviews-looking_07.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/9015082252909051778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/9015082252909051778'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/09/developer-architect-interviews-looking_07.html' title='Developer / Architect interviews, looking at it from both sides. Part 2'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-1305221734146965433</id><published>2010-09-06T08:17:00.001+02:00</published><updated>2010-09-07T20:33:48.237+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General Info'/><title type='text'>Developer / Architect interviews, looking at it from both sides. Part 1</title><content type='html'>Part 1, The Interviewee...&lt;br /&gt;&lt;br /&gt;Firstly let me say, I am by no means an expert interviewer, I have just recently been included in the whole interview process. I originally wanted nothing to do with it actually, but now several months and 20ish interviews later I quite enjoy it. The only frustrating thing is how people actually come to an interview, in one word: &lt;b&gt;Unprepared&lt;/b&gt;. This may be a South African thing, where the demand way out strips the supply when it comes to software developers, but sadly the quality of the candidates coming for interviews is really disappointing. I am going to try keep this technology agnostic, as it is not only limited to Java, my wife -a dev team manager in a .Net technology company- goes through the same frustrations when looking for new staff.&lt;br /&gt;&lt;br /&gt;So out of the 20ish candidates I have interviewed in the past months only 3 potentially had the skills we required, 1 was hired, 1 accepted an architect position at another company rather than the senior developer we were offering and the other's personality was not a match for the team. The other 17-20 people were either unprepared, unskilled or incorrectly represented by a recruitment agency.&lt;br /&gt;&lt;br /&gt;I personally have not been for an interview in about 4 years, so my own interview skills may be a little rusty. However if I had to apply some of my experiences of being the interviewer into being the interviewee. I would do the following, above and beyond the standard interview success practices of being presentable, on time, professional, confident and having a self sales pitch. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;1.&lt;/b&gt; If you are going through a recruitment agency, make sure that they show you the CV (Curriculum Vitae / Resume) they will be sending to their clients. Make sure you are happy with it. I would say about half the CVs we get really do not accurately describe the candidate. When this happens it immediately changes the tone of the interview and your chances diminish greatly. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;2.&lt;/b&gt; Find out upfront what kind of tests the company makes candidates do, and prepare for those.&lt;br /&gt;In the case of my current employer:&lt;br /&gt;2.1 There is a general "aptitude" test, which I personally don't agree with, but it generally covers classic word sum, riddle, trick and what's the next in the sequence type questions. There seems to be a lot of companies doing this kind of test these days. So it is well worth searching the web and practising this kind of test. One site I did find quickly &lt;a href="http://www.indiabix.com/"&gt;&lt;b&gt;India Bix&lt;/b&gt;&lt;/a&gt;, would be a good way to prepare.&lt;br /&gt;2.2 A &lt;a href="http://techcheck.com/"&gt;&lt;b&gt;Tech Check&lt;/b&gt;&lt;/a&gt;, which is a scaled down version of the official certifications and as such the same preparation can be done for those.&lt;br /&gt;2.3 Finally after the initial interview there is a long &lt;a href="http://en.wikipedia.org/wiki/Psychometrics"&gt;Psychometric&lt;/a&gt; Test. Which you can't really prepare for.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3.&lt;/b&gt; Find out who is interviewing you, and just to a quick web search on them. They may have a blog, a book, a twitter feed, public facebook account all of which can give you vital information that can drastically alter the entire interview. Take myself for example, if you knew I was interviewing you and you found my blog, you would find this article along with a whole bunch of technical stuff about the environment / company that can give you a very nice advantage in the interview.&lt;br /&gt;I Google all the candidates, only fair that they do the same.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4.&lt;/b&gt; Stay Current, we are in a ever changing industry, companies and your current employer may not be able to keep up with the changing technology environment, but this doesn't mean we as IT professionals shouldn't. As an interviewer I often ask the questions, "how do you stay current?", "what do you read?". How I try stay current, is this blog and Google Reader, I follow and read many Java, development and architectural related websites and blogs. I also plan to get the new Kindle in the next week or so, as there are quite a number of books that I need to get through.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5.&lt;/b&gt; Make sure that you read and know the common interview questions for your technical specialities. There are a lot of resources online to help with that. You don't want to show up to an interview as a Hibernate, Spring, Oracle or Asp.net 'expert' and then get put on the spot by a relatively simple well known interview question.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;6.&lt;/b&gt; Ask questions, from the interviews I have done very few people have even asked the basic questions. It is important to ask questions, firstly there are things you should know about your working environment and you to engage the interviewer. Some example questions I would ask are in no particular order:&lt;br /&gt;6.1. What does a regular day in the life of a developer or architect here look like?&lt;br /&gt;6.2. What applications are you supporting? What are the support hours like?&lt;br /&gt;6.3. What is the team size and structure?&lt;br /&gt;6.4. What is the career path and policies on training?&lt;br /&gt;6.5. What IDE, and what kind of hardware will be supplied?&lt;br /&gt;6.6. Why are you hiring? Is it because the team is growing? (or are people jumping ship... don't ask that :) their answer will imply that.)&lt;br /&gt;6.7. What are the greatest challenges facing the new person in this position? &lt;br /&gt;6.8. What is the management style of my direct manager?&lt;br /&gt;6.9. Who will evaluate my performance? When? How?&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;On a side note:&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;If I was to find new employment I would firstly research companies I want to work for and see if I could directly deal with them, as I stated before recruitment agencies can sometimes do you more harm than good. Search the top 100 companies to work for in your country / city, check the technologies they use, their culture, their location. I would also use social networks, a candidate that comes recommended from a current employee already has a huge advantage to just some random Joe Smith off the street.&lt;br /&gt;&lt;br /&gt;In &lt;b&gt;&lt;a href="http://www.briandupreez.net/2010/09/developer-architect-interviews-looking_07.html"&gt;Part 2&lt;/a&gt;&lt;/b&gt;, I will discuss some of my experiences on the other side of the table as a interviewer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-1305221734146965433?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/1305221734146965433/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/09/developer-architect-interviews-looking.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1305221734146965433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1305221734146965433'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/09/developer-architect-interviews-looking.html' title='Developer / Architect interviews, looking at it from both sides. Part 1'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-2440484303550457384</id><published>2010-09-01T19:04:00.001+02:00</published><updated>2010-09-02T07:16:34.528+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Chunking a List into parts.</title><content type='html'>Needed to batch up the contents of a list into groups of 4 today. Spent a little more time than I would have liked on it, but I think it's a pretty neat bit of code now, and I actually got to use java.util.concurrent.CopyOnWriteArrayList for the first time.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.blog.misc;import java.util.ArrayList;import java.util.List;import java.util.concurrent.CopyOnWriteArrayList;public class Main {    public static void main(String[] args) {        List&lt;string&gt; testList = new ArrayList&lt;string&gt;();        testList.add("1");        testList.add("2");        testList.add("3");        testList.add("4");        testList.add("5");        testList.add("6");        testList.add("7");        testList.add("8");        testList.add("9");                List&lt;List&lt;string&gt;&gt; returnLists = chunkList(testList, 4);        int count = 0;        for(List&lt;string&gt; list : returnLists) {            System.out.println("Top level list " + ++count + " contains:");            for(String val : list) {                System.out.println(" " + val);            }        }    }        /**     * Chunk list.     * @param &lt;t&gt;     *      * @param &lt;t&gt; the generic type     * @param originalList the original list     * @param chunkSize the chunk size     * @return the list     */    public static &lt;t&gt; List&lt;List&lt;t&gt;&gt; chunkList(List&lt;t&gt; originalList, int chunkSize ){      if(chunkSize &lt;= 0) {        throw new IllegalArgumentException("chunkSize must be greater than 0.");      }      List&lt;List&lt;t&gt;&gt; result = new ArrayList&lt;List&lt;t&gt;&gt;();      int index = 0;      while(originalList.size() &gt; 0) {        int count = originalList.size() - index &gt;= chunkSize ? chunkSize : originalList.size() - index;        List&lt;t&gt; sublist =  new CopyOnWriteArrayList&lt;t&gt;(originalList.subList(0, count));        result.add(sublist);        originalList.removeAll(sublist);      }      return result;    }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The result of running this:&lt;br /&gt;&lt;br /&gt;Top level list 1 contains:&lt;br /&gt;1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;br /&gt;Top level list 2 contains:&lt;br /&gt;5&lt;br /&gt;6&lt;br /&gt;7&lt;br /&gt;8&lt;br /&gt;Top level list 3 contains:&lt;br /&gt;9&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-2440484303550457384?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/2440484303550457384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/09/chunking-list-into-parts.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/2440484303550457384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/2440484303550457384'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/09/chunking-list-into-parts.html' title='Chunking a List into parts.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-6635610301129557298</id><published>2010-08-28T10:01:00.000+02:00</published><updated>2010-08-28T10:01:37.524+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cargo'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Cargo, Maven and the benefits of integrated functional testing</title><content type='html'>I little while back an ex-colleague mentioned that I should have a look at an open source project called &lt;a href="http://cargo.codehaus.org/"&gt;Cargo&lt;/a&gt;. So what is Cargo, their mission statement states "Cargo is a thin wrapper that allows you to manipulate Java EE containers in a standard way." and that is exactly what they do.&lt;br /&gt;&lt;br /&gt;In 2 of my previous posts:&lt;br /&gt;&lt;a href="http://www.briandupreez.net/2010/07/some-useful-maven-configurations.html"&gt;Some useful Maven configurations&lt;/a&gt;&lt;br /&gt;and &lt;br /&gt;&lt;a href="http://www.briandupreez.net/2010/07/so-your-poms-quite-nice-now-what.html"&gt;Your POM is quite nice&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I went through some maven configurations and practices along with the concept of continuous integration. This article and Cargo make a logical "Part 3". In the above 2 articles there is a lot of emphasis on continuous testing, but with some very large / legacy systems total unit test coverage is something of a luxury and quite often neglected. Depending on the size, type and deployment of the application there will be certain circumstances where to quickly gain, promote and gauge system stability, integration or functional testing will be a much faster and more beneficial practice than retro fitting unit test coverage.&lt;br /&gt;&lt;br /&gt;Tools like &lt;a href="http://seleniumhq.org/"&gt;Selenium&lt;/a&gt;, &lt;a href="https://h10078.www1.hp.com/cda/hpms/display/main/hpms_content.jsp?zn=bto&amp;cp=1-11-127-24^1352_4000_100__"&gt;QTP (QuickTestPro)&lt;/a&gt; a number of others, allow you to simply record, playback and validate the application. In my current environment and I am sure in a lot of other places, these types of tests are run by people outside the development team, namely testing teams, clients or even business analysts. I personally feel to gain the most benefit out of functional testing and automation tools these need to happen at build time. Having these tests run outside of the standard development environment add extra unneeded iterations, and more external dependencies that can delay a software project. Bringing these type of tests into you build process allow you detect, maintain and repair system issues before influencing the world outside the development environment.&lt;br /&gt;&lt;br /&gt;Like everything else surrounding the "continuous integration" philosophy, automation is key. This is were Cargo helps you out. If you already have the other tools like Maven and Hudson setup it is very quick to integrate and benefit from Cargo.&lt;br /&gt;&lt;br /&gt;My environment runs on Weblogic, so that is what I will be using as my example, but Cargo supports about all the major web and application servers used. So this should work for anyone.&lt;br /&gt; &lt;br /&gt;Maven has the concept of phases which can be thought of like a collection of goals. A full list of the phases of Maven is available here: &lt;a href="http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html?PHPSESSID=5f73f4b3f0ed14f13498fae9ccc33c3a#Lifecycle_Reference"&gt;Lifecycle Reference&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The 3 we are interesting in with regards to Cargo are:&lt;br /&gt;&lt;b&gt;pre-integration-test&lt;/b&gt;&lt;br /&gt;perform actions required before integration tests are executed. This may involve things such as setting up the required environment.&lt;br /&gt;&lt;b&gt;integration-test &lt;/b&gt;&lt;br /&gt;Process and deploy the package if necessary into an environment where integration tests can be run.&lt;br /&gt;&lt;b&gt;post-integration-test&lt;/b&gt; &lt;br /&gt;Perform actions required after integration tests have been executed. This may including cleaning up the environment.&lt;br /&gt;&lt;br /&gt;So any phase higher than ’pre-integration-test’ will trigger the deployment to your application server.&lt;br /&gt;&lt;br /&gt;Cargo can only stop and start local application servers, deployments can take place remotely, not all application servers have "deployers", detail for these are on the Cargo site. The one feature I am very happy with is the server properties. You can from within you POM configure all the required, JDBC, JMS, and JVM settings you require for your application server to function, which is awesome. In my examples I just needed JVM and JDBC settings, but theoretically you should be able to configure most things you may require.&lt;br /&gt;&lt;br /&gt;You could integrate the Cargo plugin into your existing POMs, I prefer to keep it separate. I am not including any Selenium configuration to keep this post about Cargo. However here is a very nice &lt;a href="http://wiki.foochal.org/index.php/Maven_Selenium"&gt;Maven Selenium Guide&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So for the local server configuration, this will startup the application server, create the JDBC configuration and deploy the war.&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&gt;&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;&lt;groupId&gt;javaitzen&lt;/groupId&gt;&lt;artifactId&gt;Cargo&lt;/artifactId&gt;&lt;packaging&gt;jar&lt;/packaging&gt;&lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;&lt;name&gt;Cargo&lt;/name&gt;&lt;url&gt;http://maven.apache.org&lt;/url&gt;&lt;build&gt; &lt;plugins&gt; &lt;plugin&gt;  &lt;groupId&gt;org.codehaus.cargo&lt;/groupId&gt;  &lt;artifactId&gt;cargo-maven2-plugin&lt;/artifactId&gt;  &lt;version&gt;1.0.2&lt;/version&gt;  &lt;configuration&gt;                 &lt;container&gt;    &lt;containerId&gt;weblogic10x&lt;/containerId&gt;     &lt;home&gt;D:\Java\bea10\wlserver_10.0&lt;/home&gt;    &lt;/container&gt;    &lt;configuration&gt;     &lt;properties&gt;       &lt;cargo.jvmargs&gt;-XX:MaxPermSize=128M -Xmx512m&lt;/cargo.jvmargs&gt;        &lt;cargo.datasource.datasource&gt;cargo.datasource.url=jdbc:oracle:thin:@dev:1523:db|cargo.datasource.driver=oracle.jdbc.driver.OracleDriver|cargo.datasource.username=dev|cargo.datasource.password=dev|cargo.datasource.jndi=devdb&lt;/cargo.datasource.datasource&gt;                   &lt;/properties&gt;    &lt;/configuration&gt;     &lt;deployer&gt;   &lt;type&gt;installed&lt;/type&gt;   &lt;deployables&gt;    &lt;deployable&gt;     &lt;groupId&gt;javaitzen.spring&lt;/groupId&gt;     &lt;artifactId&gt;RestWS&lt;/artifactId&gt;     &lt;type&gt;war&lt;/type&gt;            &lt;properties&gt;      &lt;context&gt;RestWS&lt;/context&gt;     &lt;/properties&gt;     &lt;pingURL&gt;http://localhost:7001/&lt;/pingURL&gt;     &lt;pingTimeout&gt;10000&lt;/pingTimeout&gt;    &lt;/deployable&gt;   &lt;/deployables&gt;      &lt;/deployer&gt;     &lt;/configuration&gt;   &lt;executions&gt;    &lt;execution&gt;     &lt;id&gt;start-container&lt;/id&gt;     &lt;phase&gt;pre-integration-test&lt;/phase&gt;     &lt;goals&gt;      &lt;goal&gt;deployer-deploy&lt;/goal&gt;      &lt;goal&gt;start&lt;/goal&gt;     &lt;/goals&gt;    &lt;/execution&gt;    &lt;execution&gt;     &lt;id&gt;stop-container&lt;/id&gt;     &lt;phase&gt;post-integration-test&lt;/phase&gt;     &lt;goals&gt;      &lt;goal&gt;deployer-undeploy&lt;/goal&gt;      &lt;goal&gt;stop&lt;/goal&gt;     &lt;/goals&gt;    &lt;/execution&gt;   &lt;/executions&gt;  &lt;/plugin&gt; &lt;/plugins&gt;&lt;/build&gt;&lt;dependencies&gt; &lt;dependency&gt;  &lt;groupId&gt;javaitzen.spring&lt;/groupId&gt;  &lt;artifactId&gt;RestWS&lt;/artifactId&gt;  &lt;type&gt;war&lt;/type&gt;  &lt;version&gt;1.0.0&lt;/version&gt; &lt;/dependency&gt;&lt;/dependencies&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-6635610301129557298?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/6635610301129557298/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/08/cargo-maven-and-benefits-of-integrated.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6635610301129557298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6635610301129557298'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/08/cargo-maven-and-benefits-of-integrated.html' title='Cargo, Maven and the benefits of integrated functional testing'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-1768419973706575740</id><published>2010-08-17T07:26:00.000+02:00</published><updated>2010-08-17T07:26:45.254+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Pimp your Eclipse, a collection of darker colour schemes</title><content type='html'>Since my recent disappointment with &lt;a href="http://www.briandupreez.net/2010/08/netbeans-69-and-691-find-usages-not.html"&gt;NetBeans&lt;/a&gt;, I figured I would make myself feel a bit better by customizing my Eclipse to almost look a little like one of the themes that come with Netbeans. Now Eclipse doesn't really cater for "Themes", more just colour schemes that you can import. There are 2 basic ways to import bulk settings...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Firstly, make a backup!&lt;/b&gt; (I don't wanna be blamed for lost hours :))&lt;br /&gt;To do that in Eclipse, go to File &gt; Export &gt; Preferences and export all the preferences. This will export all your settings so you can quickly roll back.&lt;br /&gt;&lt;br /&gt;Now the 2 ways to update (besides changing every setting manually) are:&lt;br /&gt;1. Import.&lt;br /&gt;If you have or download a *.epf file you can import. In Eclipse through File &gt; Import &gt; Preferences.&lt;br /&gt;&lt;br /&gt;Or&lt;br /&gt;2. Manual.&lt;br /&gt;The settings for the basic and java editors are stored in the following 2 files:&lt;br /&gt;[workspace]\.metadata\.plugins\org.eclipse.core.runtime\.settings\org.eclipse.jdt.ui.prefs&lt;br /&gt;[workspace]\.metadata\.plugins\org.eclipse.core.runtime\.settings\org.eclipse.ui.editors.prefs&lt;br /&gt;&lt;br /&gt;The problem with the import is that it can contain ALL the settings of the person that exported it, there is no option to only export the UI bits, so I personally prefer the Manual route, but both work fine. &lt;br /&gt;&lt;br /&gt;So to begin, my theme, Dark Blue Eclipse:&lt;br /&gt;&lt;a href="http://goo.gl/photos/TBww" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh6.ggpht.com/_4oXSoLPl3uY/TGZLxUDe4fI/AAAAAAAAAKg/KtSOQg53pQI/s512/Eclipse%20Dark%20Blue%20Theme.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The 2 perfs files can be downloaded from, and copied the manual way:&lt;br /&gt;&lt;a href="http://code.google.com/p/itzen/downloads/list"&gt;&lt;b&gt;Download List&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I tried the following theme, and quite liked it, however I did miss blue:&lt;br /&gt;&lt;a href="http://blog.prabir.me/post/Dark-Eclipse-Theme.aspx"&gt;&lt;b&gt;Prabir's Blog&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/0P5w" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh3.ggpht.com/_4oXSoLPl3uY/TGZSvQO_i-I/AAAAAAAAAKw/r7wHmoy15rU/s512/prabir%20dark.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I also came across the following collection of themes and what is nice with the links here is that srand did it the manual way, and the other is a clean *.epf import ( I checked the files, no unrelated settings):&lt;br /&gt;&lt;a href="http://srand2.blogspot.com/2009/08/eclipse-color-themes.html"&gt;&lt;b&gt;srand's blog&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;Which actually come from:&lt;br /&gt;&lt;a href="http://eclipsecolorthemes.jottit.com/"&gt;&lt;b&gt;Eclipse color themes&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Inkpot:&lt;br /&gt;&lt;a href="http://goo.gl/photos/adRv" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh5.ggpht.com/_4oXSoLPl3uY/TGZTOp78SbI/AAAAAAAAALA/DwN8lbte6FY/s512/inkpot.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Sula:&lt;br /&gt;&lt;a href="http://goo.gl/photos/CIpr" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh5.ggpht.com/_4oXSoLPl3uY/TGZTh7yToSI/AAAAAAAAALQ/OJU9U_H6_p8/s512/sula.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Vibrant Ink:&lt;br /&gt;&lt;a href="http://goo.gl/photos/6vvs" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh3.ggpht.com/_4oXSoLPl3uY/TGZTvXqnI3I/AAAAAAAAALU/NHxjUwflj3M/s512/vibrantink.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Wombat:&lt;br /&gt;&lt;a href="http://goo.gl/photos/Oitw" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh6.ggpht.com/_4oXSoLPl3uY/TGZUBAKrGoI/AAAAAAAAALs/FzMlKuIta54/s512/wombat.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I have not actually tried the following site but it should be very useful if you are looking to create your own colour scheme:&lt;br /&gt;&lt;a href="http://blog.edwards-research.com/files/eclipse-gen/"&gt;Edwards research Eclipse Gen&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-1768419973706575740?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/1768419973706575740/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/08/pimp-your-eclipse-collection-of-darker.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1768419973706575740'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1768419973706575740'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/08/pimp-your-eclipse-collection-of-darker.html' title='Pimp your Eclipse, a collection of darker colour schemes'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_4oXSoLPl3uY/TGZLxUDe4fI/AAAAAAAAAKg/KtSOQg53pQI/s72-c/Eclipse%20Dark%20Blue%20Theme.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-2614423397053245982</id><published>2010-08-16T00:13:00.001+02:00</published><updated>2010-08-16T09:22:42.675+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMS'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Spring, JMS, Weblogic, and FizzBuzz</title><content type='html'>There are 2 reasons for me posting this example:&lt;br /&gt;I have not looked at anything Spring related for about a month, and last week I got to show someone new to Spring all the joy that it can bring, I couldn't shut up for about a hour. One of the reasons he is looking into using Spring happens to involve JMS, something I had not yet covered in my blog. &lt;br /&gt;The other reason is:&lt;br /&gt;I was &lt;a href="http://passif.blogspot.com/2010/08/fizzbuzz-rules-engines-and-some-fun.html"&gt;&lt;b&gt;challenged&lt;/B&gt;&lt;/a&gt; by a work colleague to come up with a more complex FizzBuzz implementation than his monster rule implementation and not being a person to back down on a challenge.&lt;br /&gt;&lt;br /&gt;Here it is. Spring, JMS, Weblogic and FizzBuzz&lt;br /&gt;&lt;br /&gt;All the code for this example will be available &lt;a href="http://code.google.com/p/itzen/source/browse/#svn/trunk/SpringJMS"&gt;&lt;b&gt;--Here--&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There are a couple JMS examples out there using ActiveMQ, and either JMS "client type" implementations or Message Driven POJOs but not together. For this example I will show both methods and will use Weblogic, those that have worked with Weblogic know there are always little nuances. The first thing is to have a standalone client for Weblogic, you need the weblogic.jar (Full Client), I have uploaded this into my local maven repo so that I can just place this within my POM.&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt; &lt;dependency&gt;  &lt;groupid&gt;bea&lt;/groupId&gt;  &lt;artifactid&gt;weblogic&lt;/artifactId&gt;  &lt;version&gt;10.3&lt;/version&gt; &lt;/dependency&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;In the Weblogic admin console I set up the JMS modules as follows (5 Queues and a Connection Factory):&lt;br /&gt;&lt;a href="http://goo.gl/photos/GNQi" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh6.ggpht.com/_4oXSoLPl3uY/TGg2W1JCcXI/AAAAAAAAAL8/rvd0bUFXyiE/s512/FizzBuzzQueues.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now for what this example does:&lt;br /&gt;* It creates 100 messages... &lt;br /&gt;* It reads 100 messages... while reading, it checks the content, depending on the value it creates a message to a fizz queue or a buzz queue or a fizzbuzz queue and a result queue.&lt;br /&gt;* There is message driven POJO on the result queue that prints out the content.&lt;br /&gt;&lt;br /&gt;How it does this:&lt;br /&gt;The Spring application context below is pretty straight forward but it does have a couple things to note:&lt;br /&gt;1. The jndiTemplate, jmsQueueConnectionFactory, jmsDestinationResolver, jmsTemplate are all used in combination to get to the application server, and connect to the actual JMS queues.&lt;br /&gt;2. The "messageDrivenListener" and "queue" beans are the configuration for the message driven POJO. In that config is "concurrentConsumers", this allows you to specify how many listeners will be created to process the messages on the queue. For this example I only require 1.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jms="http://www.springframework.org/schema/jms" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd&gt; &lt;context:component-scan base-package="javaitzen.spring.jms" /&gt; &lt;bean name="main" class="javaitzen.spring.jms.Main" /&gt;  &lt;bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"&gt; &lt;property name="connectionFactory" ref="jmsQueueConnectionFactory" /&gt; &lt;property name="destinationResolver" ref="jmsDestinationResolver" /&gt; &lt;/bean&gt; &lt;bean id="jmsQueueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"&gt; &lt;property name="jndiTemplate"&gt;  &lt;ref bean="jndiTemplate" /&gt; &lt;/property&gt; &lt;property name="jndiName"&gt;  &lt;value&gt;jms/FizzBuzzConnectionFactory&lt;/value&gt; &lt;/property&gt; &lt;/bean&gt; &lt;bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate"&gt; &lt;property name="environment"&gt;  &lt;props&gt;         &lt;prop key="java.naming.factory.initial"&gt;weblogic.jndi.WLInitialContextFactory&lt;/prop&gt;  &lt;prop key="java.naming.provider.url"&gt;t3://localhost:7001&lt;/prop&gt;  &lt;prop key="java.naming.security.principal"&gt;weblogic&lt;/prop&gt;  &lt;prop key="java.naming.security.credentials"&gt;weblogic&lt;/prop&gt;         &lt;/props&gt; &lt;/property&gt; &lt;/bean&gt; &lt;bean id="messageConsumer " class="javaitzen.spring.jms.MessageConsumer"&gt; &lt;property name="jmsTemplate" ref="jmsTemplate" /&gt; &lt;/bean&gt; &lt;bean id="jmsDestinationResolver"  class="org.springframework.jms.support.destination.JndiDestinationResolver"&gt; &lt;property name="jndiTemplate"&gt;  &lt;ref bean="jndiTemplate" /&gt; &lt;/property&gt; &lt;property name="cache" value="true" /&gt; &lt;/bean&gt; &lt;bean id="numberSender" class="javaitzen.spring.jms.MessageSender"&gt; &lt;property name="queue" value="jms/NumberQueue" /&gt; &lt;property name="jmsTemplate" ref="jmsTemplate" /&gt; &lt;/bean&gt; &lt;bean id="buzzSender" class="javaitzen.spring.jms.MessageSender"&gt; &lt;property name="queue" value="jms/BuzzQueue" /&gt; &lt;property name="jmsTemplate" ref="jmsTemplate" /&gt; &lt;/bean&gt; &lt;bean id="fizzSender" class="javaitzen.spring.jms.MessageSender"&gt; &lt;property name="queue" value="jms/FizzQueue" /&gt; &lt;property name="jmsTemplate" ref="jmsTemplate" /&gt; &lt;/bean&gt; &lt;bean id="fizzBuzzSender" class="javaitzen.spring.jms.MessageSender"&gt; &lt;property name="queue" value="jms/FizzBuzzQueue" /&gt; &lt;property name="jmsTemplate" ref="jmsTemplate" /&gt; &lt;/bean&gt; &lt;bean id="resultSender" class="javaitzen.spring.jms.MessageSender"&gt; &lt;property name="queue" value="jms/ResultQueue" /&gt; &lt;property name="jmsTemplate" ref="jmsTemplate" /&gt; &lt;/bean&gt; &lt;bean id="numberReader" class="javaitzen.spring.jms.MessageConsumer"&gt; &lt;property name="queue" value="jms/NumberQueue" /&gt; &lt;property name="jmsTemplate" ref="jmsTemplate" /&gt; &lt;/bean&gt; &lt;bean name="jmsListener" class="javaitzen.spring.jms.JmsMessageListener" /&gt; &lt;bean id="queue" class="org.springframework.jndi.JndiObjectFactoryBean"&gt; &lt;property name="jndiTemplate"&gt;  &lt;ref bean="jndiTemplate" /&gt; &lt;/property&gt; &lt;property name="jndiName" value="jms/ResultQueue" /&gt; &lt;/bean&gt; &lt;bean id="messageDrivenListener"  class="org.springframework.jms.listener.DefaultMessageListenerContainer"&gt; &lt;property name="concurrentConsumers" value="1" /&gt; &lt;property name="connectionFactory" ref="jmsQueueConnectionFactory" /&gt; &lt;property name="destination" ref="queue" /&gt; &lt;property name="messageListener" ref="jmsListener" /&gt; &lt;/bean&gt;&lt;/beans&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;I have created just a simple example message structure for this, with a generic content which looks like:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.jms.message;import java.io.Serializable;public class ExampleMessage implements Serializable {        private static final long serialVersionUID = 4759716828378650012L;    private Header header;    private Content&lt; ? &gt; content;        public final Header getHeader() {        return header;    }        public final void setHeader(Header header) {        this.header = header;    }        @SuppressWarnings("unchecked")    public final Content getContent() {        return content;    }        @SuppressWarnings("unchecked")    public final void setContent(Content content) {        this.content = content;    }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.jms.message;import java.io.Serializable;public class Header implements Serializable {    private static final long serialVersionUID = 1201985581526142757L;    private String someHeader;    public Header(){    }        public Header(final String someHeader) {        super();        this.someHeader = someHeader;    }    public final String getSomeHeader() {        return someHeader;    }    public final void setSomeHeader(final String someHeader) {        this.someHeader = someHeader;    }     }&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.jms.message;import java.io.Serializable;public class Content&lt;t&gt; implements Serializable {    private static final long serialVersionUID = 3008805001429324011L;       private T content;    public Content(){     }        public Content(final T content) {        super();        this.content = content;    }        public String getContentString() {        return content.toString();    }    public T getContentValue() {        return content;    }        public void setContentValue(T content) {        this.content = content;    }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The message driven POJO is just the standard javax.jms.MessageListener interface implementation:&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.jms;import javaitzen.spring.jms.message.ExampleMessage;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.ObjectMessage;import org.springframework.stereotype.Component;public class JmsMessageListener implements MessageListener {     public void onMessage(final Message message) {        try {                           if (message instanceof ObjectMessage) {                ObjectMessage oMessage = (ObjectMessage) message;                ExampleMessage tehMessage = (ExampleMessage) oMessage.getObject();                System.out.println("Message Listener: Result Queue:" + tehMessage.getContent().getContentString());                oMessage.acknowledge();            }        } catch (Exception e) {            e.printStackTrace();        }    }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The client classes to read and create messages, make use of Springs JMSTemplate to simplify your interaction with the JMS server:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.jms;import javaitzen.spring.jms.message.ExampleMessage;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.ObjectMessage;import org.springframework.jms.core.JmsTemplate; public class MessageConsumer {    private JmsTemplate jmsTemplate;    private String queue;    public MessageConsumer() {}    public MessageConsumer(final String queue) {        this.queue = queue;    }        public ExampleMessage receiveMessage() throws JMSException  {        final Message message = jmsTemplate.receive(queue);                ExampleMessage tehMessage  = null;        if (message instanceof ObjectMessage) {          ObjectMessage oMessage = (ObjectMessage) message;            tehMessage = (ExampleMessage) oMessage.getObject();                    oMessage.acknowledge();        }        return tehMessage;    }    public final void setQueue(final String queue) {        this.queue = queue;    }    public final void setJmsTemplate(final JmsTemplate jmsTemplate) {        this.jmsTemplate = jmsTemplate;    }}&lt;/script&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.jms;import javaitzen.spring.jms.message.ExampleMessage;import javax.jms.Message;import javax.jms.Session;import javax.jms.ObjectMessage;import org.springframework.jms.core.JmsTemplate;import org.springframework.jms.core.MessageCreator;public class MessageSender {    private JmsTemplate jmsTemplate;    private String queue;    public MessageSender() { }    public void sendMessage(final ExampleMessage message) {        MessageCreator creator = new MessageCreator() {            public Message createMessage(Session session) {                ObjectMessage objectMessage = null;                try {                    objectMessage = session.createObjectMessage(message);                } catch (Exception e) {                    e.printStackTrace();                }                return objectMessage;            }        };        jmsTemplate.send(queue, creator);    }    public final void setQueue(final String queue) {        this.queue = queue;    }    public final void setJmsTemplate(final JmsTemplate jmsTemplate) {        this.jmsTemplate = jmsTemplate;    }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;And the finally the Main class, that creates the 100 messages, then reads them, publishing messages to 4 different queues. The reading of the results queue is triggered by the application server and handled by Springs "DefaultMessageListenerContainer"&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.jms;import javaitzen.spring.jms.message.Content;import javaitzen.spring.jms.message.ExampleMessage;import javaitzen.spring.jms.message.Header;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main {        @Autowired    private MessageSender   numberSender;    @Autowired    private MessageConsumer numberReader;    @Autowired    private MessageSender   fizzSender;    @Autowired    private MessageSender   buzzSender;    @Autowired    private MessageSender   fizzBuzzSender;    @Autowired    private MessageSender   resultSender;        public static void main(String[] args) {        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml", Main.class);        Main main = (Main)context.getBean("main");        try {            main.runExample();        }catch (Exception e) {            e.printStackTrace();        }finally {            System.exit(0);        }    }        @SuppressWarnings("unchecked")    public void runExample() throws Exception{              for (int i = 1; i &lt;= 100; i++) {            ExampleMessage message = new ExampleMessage();            message.setHeader(new Header("I am a Number"));            message.setContent(new Content&lt;integer&gt;(i));            numberSender.sendMessage(message);        }                for (int i = 1; i &lt;= 100; i++) {                        ExampleMessage  message = numberReader.receiveMessage();            Content&lt;integer&gt; messageInt = message.getContent();            Integer val = messageInt.getContentValue();            if (val % 15 == 0) {                message.setContent(new Content&lt;string&gt;("FizzBuzz"));                fizzBuzzSender.sendMessage(message);            } else if (val % 3 == 0) {                message.setContent(new Content&lt;string&gt;("Fizz"));                fizzSender.sendMessage(message);            } else if (val % 5 == 0) {                 message.setContent(new Content&lt;string&gt;("Buzz"));                buzzSender.sendMessage(message);            }            //send all to the result queue            resultSender.sendMessage(message);        }           }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Note: if you constantly run this example, you will end up with a ton of messages on the Fizz, Buzz and FizzBuzz queues as there is nothing reading those messages to clean it up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-2614423397053245982?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/2614423397053245982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/08/spring-jms-weblogic-and-fizzbuzz.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/2614423397053245982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/2614423397053245982'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/08/spring-jms-weblogic-and-fizzbuzz.html' title='Spring, JMS, Weblogic, and FizzBuzz'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_4oXSoLPl3uY/TGg2W1JCcXI/AAAAAAAAAL8/rvd0bUFXyiE/s72-c/FizzBuzzQueues.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-9222521873505478400</id><published>2010-08-11T07:40:00.000+02:00</published><updated>2010-08-11T07:40:26.177+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><category scheme='http://www.blogger.com/atom/ns#' term='General Info'/><title type='text'>NetBeans 6.9 and 6.9.1 find usages not working.</title><content type='html'>Yesterday I was investigating an issue, during my investigation I started following the code trail, I finally get to a place where the when calling "Find Usages" on a method returns me nothing... I think great... Delete, Delete, Delete... cleaning up unused code always takes me to a happy place, so after this I just check with someone that had originally worked on this bit of functionality which goes a bit pale, stating that there has to be something wrong and that code must run...&lt;br /&gt;&lt;br /&gt;I quickly revert back to local history, do the "Find Usages" again, and yip still no reference. We go to the code where we think it should be called... and surprisingly it is there... go delete the code, do a "mvn clean install" and it fails correctly...&lt;br /&gt;&lt;br /&gt;Off to Google... "netbeans find usages not working" leads me to the following logged bug: &lt;a href="http://netbeans.org/bugzilla/show_bug.cgi?id=186314"&gt;Bug 186314&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As I commented there, I installed the latest 6.9.1 version and the issue still occurs.&lt;br /&gt;&lt;br /&gt;This is such a nasty bug in my opinion that I will probably have to go back to Eclipse until it is sorted. I have just recently changed teams and have roughly 14000 java files that I know nothing about, life without "Find Usages" will be painful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-9222521873505478400?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/9222521873505478400/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/08/netbeans-69-and-691-find-usages-not.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/9222521873505478400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/9222521873505478400'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/08/netbeans-69-and-691-find-usages-not.html' title='NetBeans 6.9 and 6.9.1 find usages not working.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-7120789597340028199</id><published>2010-08-10T22:40:00.000+02:00</published><updated>2010-08-10T22:40:49.198+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='General Info'/><title type='text'>Maven Remote Windows Scheduled Task</title><content type='html'>Just a quick Maven / Windows config I came across the other day, I have recently switched teams and they are using Maven and Hudson to control some of their server tasks. I figure it could come in handy sometime.&lt;br /&gt;&lt;br /&gt;To start and stop a Windows Scheduled task from a Maven pom, actually using the ant run plugin&lt;br /&gt;&lt;br /&gt;Replace the [Server Name] and [Task Name] obviously.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;plugin&gt; &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt; &lt;artifactId&gt;maven-antrun-plugin&lt;/artifactId&gt; &lt;version&gt;1.2&lt;/version&gt; &lt;executions&gt;  &lt;execution&gt;    &lt;id&gt;deploy&lt;/id&gt;    &lt;phase&gt;process-sources&lt;/phase&gt;    &lt;goals&gt;      &lt;goal&gt;run&lt;/goal&gt;    &lt;/goals&gt;    &lt;configuration&gt;     &lt;tasks&gt;      &lt;exec executable="c:/windows/system32/schtasks.exe"&gt;       &lt;arg value="/run"/&gt;       &lt;arg value="/s"/&gt;       &lt;arg value="\\[Server Name]"/&gt;       &lt;arg value="/tn"/&gt;       &lt;arg value="[Task Name]"/&gt;      &lt;/exec&gt;      &lt;exec executable="c:/windows/system32/schtasks.exe"&gt;       &lt;arg value="/end"/&gt;       &lt;arg value="/s"/&gt;       &lt;arg value="\\[Server Name]"/&gt;       &lt;arg value="/tn"/&gt;       &lt;arg value="[Task Name]"/&gt;      &lt;/exec&gt;     &lt;/tasks&gt;    &lt;/configuration&gt;   &lt;/execution&gt;  &lt;/executions&gt; &lt;/plugin&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-7120789597340028199?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/7120789597340028199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/08/maven-remote-windows-scheduled-task.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/7120789597340028199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/7120789597340028199'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/08/maven-remote-windows-scheduled-task.html' title='Maven Remote Windows Scheduled Task'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-1855849204663677827</id><published>2010-08-07T08:41:00.004+02:00</published><updated>2010-08-07T10:30:28.139+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Personal'/><title type='text'>Domain Name Change</title><content type='html'>Since I am now quite addicted to this whole blogging thing, I decided to "move" my blog to new url: &lt;font color=yellow&gt;www.briandupreez.net&lt;/font&gt;... it's just a lot simpler to tell someone my name + .net than java hyphen it hypen zen . blogspot.com... which will still work anyways.&lt;br /&gt;&lt;/br&gt;&lt;br /&gt;www.briandupreez.co.za should also be routing to the .net address, I say should as I played and broke a couple DNS settings trying to get everything pointing to the right place and found a pretty useful site if you ever have to check out what your DNA settings look like to the rest of the world &lt;a href="http://pingability.com/"&gt;Pingability&lt;/a&gt;... There is a link to instantly check your domains relative mappings &lt;a href="http://pingability.com/zoneinfo.jsp"&gt;Quick Check&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-1855849204663677827?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/1855849204663677827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/08/domain-name-change.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1855849204663677827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1855849204663677827'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/08/domain-name-change.html' title='Domain Name Change'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-1059743250988744772</id><published>2010-08-03T06:21:00.000+02:00</published><updated>2010-08-03T06:21:48.789+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web service'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='GlassfishESB'/><category scheme='http://www.blogger.com/atom/ns#' term='Glassfish'/><category scheme='http://www.blogger.com/atom/ns#' term='ESB'/><title type='text'>Glassfish ESB, easier than you think. Part II</title><content type='html'>To continue from &lt;a href="http://java-it-zen.blogspot.com/2010/07/glassfish-esb-easier-than-you-think.html"&gt;Part I&lt;/a&gt;, which simply just went in and out of the BPEL process, I will now add a couple EJBs to show a nice little Glassfish ESB structured activity, namely: Flow&lt;br /&gt;&lt;br /&gt;Since this is now getting a little larger, I have made all the demo source available ... &lt;a href="http://code.google.com/p/itzen/source/browse/#svn/trunk/GlassfishESBExample"&gt;&lt;b&gt;&lt;i&gt;here&lt;/i&gt;&lt;/b&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So using the EJB project Wizard I create 2 EJB projects: DemoEJB1, DemoEJB2&lt;br /&gt;once you have the project, Add a webservice:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/MWK1" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh6.ggpht.com/_4oXSoLPl3uY/TFBF6PuJj1I/AAAAAAAAAHI/PVK0ijVpk-Q/s512/new%20webservice.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For demo purposes I am going to have 2 web services with 2 methods, gatherAppData and gatherHistoryData, these 2 functions can happen concurrently and cause you no pain as long as you change different data in your object model.&lt;br /&gt;Once that is done, from the project menu select the web service, drag it over to the right hand side of the BPEL editor, on the orange circle.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/Hla1" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh6.ggpht.com/_4oXSoLPl3uY/TFcW4PG-FQI/AAAAAAAAAHw/Tml6hm6MTZY/s512/Select%20Webservice.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Then update the Partner Link information that pops up.&lt;br /&gt;&lt;a href="http://goo.gl/photos/pIiF" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh3.ggpht.com/_4oXSoLPl3uY/TFcUkBP7MYI/AAAAAAAAAHc/mVgcbc-dG3I/s512/DemoEJB_PL.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To execute the 2 web service calls concurrently you will need a "flow", grab that from the structured activities.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/Ypes" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh4.ggpht.com/_4oXSoLPl3uY/TFcX3MRgIoI/AAAAAAAAAIA/wDwb0sXjgrk/s512/structured%20activities.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;From the web service palette grab 2 invoke objects and place them in the flow.&lt;br /&gt;&lt;br /&gt;Edit the invoke objects, choosing the different webservices.&lt;br /&gt;&lt;a href="http://goo.gl/photos/FATJ" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh4.ggpht.com/_4oXSoLPl3uY/TFcY6mNOdzI/AAAAAAAAAIU/4dYzuSCemRg/s512/Invoke%20step%201.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Create variables for both, in and out. Try stick to a naming convention of some sorts as when you get to 20ish components it can get very messy.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/6zKS" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh6.ggpht.com/_4oXSoLPl3uY/TFcaAYfhQFI/AAAAAAAAAIo/7Q29khTScvk/s512/Invoke%20step%202.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So now the BPEL will look something like the following.&lt;br /&gt;&lt;a href="http://goo.gl/photos/HHrZ" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh5.ggpht.com/_4oXSoLPl3uY/TFcaxODl9wI/AAAAAAAAAJM/RselCuzCvD4/s512/Invoke%20Step%203.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can add as many concurrent steps to a flow as you like or as many different values you have within your object model.&lt;br /&gt;To get these 2 invokes to function we need to assign the input and output variables and then assign the result of both to the output variable of the BPEL process. For each assign, map the input variable of the BPEL to the input variable of the relevant data for the service that is being called. In the 3rd assign map the relevant part of the each output variable to the output variable of the BPEL.&lt;br /&gt;&lt;br /&gt;just for clarity here is the last assign in the mapper view.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/UoeY" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh4.ggpht.com/_4oXSoLPl3uY/TFcdZrk-egI/AAAAAAAAAJU/ViHdkglfN0o/s512/Last%20Assign.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And that is it... 2 concurrent web service requests within a Glassfish ESB process&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/jpMT" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh3.ggpht.com/_4oXSoLPl3uY/TFcfkIPD2cI/AAAAAAAAAJs/r4Ov6DO9z6g/s512/End%20of%20part%20II.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The final steps are to add the newly created EJBs to the "Service Assembly" in the composite application, you can just drag the EJB project directly onto the middle JBI section, build, deploy and test.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/Gu9b" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh5.ggpht.com/_4oXSoLPl3uY/TFclG7ougAI/AAAAAAAAAKE/eQn51h0-QnQ/s512/Deploy.jpg"&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-1059743250988744772?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/1059743250988744772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/08/glassfish-esb-easier-than-you-think.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1059743250988744772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1059743250988744772'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/08/glassfish-esb-easier-than-you-think.html' title='Glassfish ESB, easier than you think. Part II'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_4oXSoLPl3uY/TFBF6PuJj1I/AAAAAAAAAHI/PVK0ijVpk-Q/s72-c/new%20webservice.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-6299980761680644248</id><published>2010-08-02T11:06:00.000+02:00</published><updated>2010-08-02T11:06:58.824+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Eclipse -clean</title><content type='html'>I am sure most Eclipse users have run into some "funny" (as in, this milk tastes funny, not funny haha) issues from time to time, namely:&lt;br /&gt;&lt;br /&gt;Extremely slow start up times.&lt;br /&gt;Unable to open any editor.&lt;br /&gt;A resource already exists on disk when building.&lt;br /&gt;etc.&lt;br /&gt;etc.&lt;br /&gt;&lt;br /&gt;These will probably be more of an issue for users that install a large amount of plugins or products like MyEclipseIDE.&lt;br /&gt;&lt;br /&gt;I was having some of the issues I mentioned above, went searching for a bit and found and Eclipse option:&lt;br /&gt;-clean&lt;br /&gt;&lt;br /&gt;It looks like this tells Eclipse to erase and rebuild it's internal plugin cache which in turn sorts out some versioning / state issues. You only need to run it once so the option can be removed after the workspace restart.&lt;br /&gt;&lt;br /&gt;So for MyEclipseIDE I added it to myeclipse.ini just before the -vm option.&lt;br /&gt;Closed and opened Eclipse... and both issues were solved. /cheer &lt;br /&gt;&lt;br /&gt;If you are just using standard Eclipse, you can place it in your eclipse.ini&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-6299980761680644248?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/6299980761680644248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/08/eclipse-clean.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6299980761680644248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6299980761680644248'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/08/eclipse-clean.html' title='Eclipse -clean'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-6470308730219223590</id><published>2010-07-25T09:10:00.000+02:00</published><updated>2010-07-26T06:28:38.613+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Web service'/><category scheme='http://www.blogger.com/atom/ns#' term='GlassfishESB'/><category scheme='http://www.blogger.com/atom/ns#' term='Glassfish'/><category scheme='http://www.blogger.com/atom/ns#' term='ESB'/><title type='text'>Glassfish ESB, easier than you think. Part I</title><content type='html'>Over the last 2 years I got to learn, use and enjoy OpenESB, we switched to GlassfishESB when it was released with the support of Sun. Unfortunately I am not using it anymore at work and I missed the 2.2 release in which there seems to have been a couple nice changes, but to get to the point. The concept of a ESB (Enterpise Service Bus) will seem daunting or intimidating to some people, this post is to get rid of that and show how developer friendly GlassfishESB can be. Another huge benefit people do not often mentioned is working on very large distributed applications a tool like GlassfishESB with it's visual representation of your entire deployment makes maintenance and system structural updates a lot simpler.&lt;br /&gt;&lt;br /&gt;Anyways to begin...&lt;br /&gt;Go download GlassfishESB / Netbeans / Glassfish and any other components you need &lt;a href="https://open-esb.dev.java.net/Downloads.html"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Install it, start it up and you are probably half way done, it is that simple.&lt;br /&gt;&lt;br /&gt;Ok so first thing you want to do is create a standard Java project.. and create some classes, for this demo I am just creating a simple "message" with a Header and Body:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.esb.objects;import java.util.Hashtable;public class Body {    private Hashtable&lt;String, String&gt; someRandomAppData = new Hashtable&lt;String, String&gt;();    public Hashtable&lt;String, String&gt; getSomeRandomAppData() {        return someRandomAppData;    }    public void setSomeRandomAppData(Hashtable&lt;String, String&gt; someRandomAppData) {        this.someRandomAppData = someRandomAppData;    }    }package javaitzen.esb.objects;import java.util.ArrayList;import java.util.List;public class Header {    private List&lt;string&gt; history = new ArrayList&lt;string&gt;();    private String currentUser;    private String currentLocation;        public String getCurrentLocation() {        return currentLocation;    }    public void setCurrentLocation(String currentLocation) {        this.currentLocation = currentLocation;    }    public String getCurrentUser() {        return currentUser;    }    public void setCurrentUser(String currentUser) {        this.currentUser = currentUser;    }    public List&lt;string&gt; getHistory() {        return history;    }    public void setHistory(List&lt;string&gt; history) {        this.history = history;    }    }package javaitzen.esb.objects;public class ESBMessage {    private Header header;    private Body body;    public Body getBody() {        return body;    }    public void setBody(Body body) {        this.body = body;    }    public Header getHeader() {        return header;    }    public void setHeader(Header header) {        this.header = header;    }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Now the next bit is my way of "cheating" to actually have anything connect to the ESB process you need to have an webservice, you get that by defining a WSDL and XSD and adding them to the BPEL, but who wants to type out all that boring XML...&lt;br /&gt;&lt;br /&gt;So now create an EJB Project:&lt;br /&gt;&lt;a href="http://goo.gl/photos/s4FT" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh6.ggpht.com/_4oXSoLPl3uY/TEqEES_GPDI/AAAAAAAAACM/jhy1CNRzZdo/s512/create%20ejb%20project.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Click next..&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/PMTZ" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh4.ggpht.com/_4oXSoLPl3uY/TEqFiISdvNI/AAAAAAAAACk/aueR9I-w5N8/s512/create%20ejb%20project%202.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Click next... Finish&lt;br /&gt;&lt;br /&gt;Add the Java project to the libs of the EJB project.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/ayLS" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh6.ggpht.com/_4oXSoLPl3uY/TEqKqGMnC5I/AAAAAAAAAC8/oadyefw3T9Q/s512/add%20object%20model%20project.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Create a new webservice...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/9Ohl" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh4.ggpht.com/_4oXSoLPl3uY/TEqL_re3bcI/AAAAAAAAADU/bNFysxpzVZo/s512/create%20new%20webservice.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And make sure that ... the EJBs' code looks like&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.esb;import javaitzen.esb.objects.ESBMessage;import javax.jws.WebMethod;import javax.jws.WebService;import javax.ejb.Stateless;import javax.jws.WebParam;@WebService()@Stateless()public class DemoESB {    @WebMethod(operationName = "mainESBEntry")    public ESBMessage mainESBEntry(@WebParam ESBMessage esbMessage) {        return esbMessage;    }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Now for the cheat ...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/4jDF" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh3.ggpht.com/_4oXSoLPl3uY/TEqQvCJ8MbI/AAAAAAAAADo/hMZJJeGxa5c/s512/Generate%20and%20copy.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This will generate the WSDL and XSD...&lt;br /&gt;&lt;br /&gt;Now we create the BPEL Project&lt;br /&gt;&lt;a href="http://goo.gl/photos/55WI" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh3.ggpht.com/_4oXSoLPl3uY/TEqchag3PBI/AAAAAAAAAD8/1elzr3tS394/s512/new%20bpel%20module.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Copy the WSDL and XSD from the EJB Project..&lt;br /&gt;Open the bpel... Drag the WSDL onto the little orange circle on the left, the following will popup:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/Iko3" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh3.ggpht.com/_4oXSoLPl3uY/TEqiugqu78I/AAAAAAAAAEQ/ieEqjvzyIs8/s512/main%20PL.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now your BPEL looks like:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/Bx0E" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh5.ggpht.com/_4oXSoLPl3uY/TErc65UL5dI/AAAAAAAAAEw/B2S8p2BTl2A/s512/bpel1.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Add a Receive, Assign and Reply to the BPEL, the edit the Receive:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/bSjL" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh5.ggpht.com/_4oXSoLPl3uY/TErdl4UnCtI/AAAAAAAAAFE/svmwn6rlPdw/s512/bpel2.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Edit the Reply:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/Fri1" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh4.ggpht.com/_4oXSoLPl3uY/TEre_X4AD7I/AAAAAAAAAF0/ydxJG1I6JE8/s512/bpel3.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Click on the Assign and then on "mapper" in the bpel editor window, drag the contents of the In variable to the contents of the Out variable&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/FPvJ" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh3.ggpht.com/_4oXSoLPl3uY/TEreLzSZm5I/AAAAAAAAAFc/vpndUFCq9so/s512/bpel4.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Save, and done...&lt;br /&gt;&lt;br /&gt;Now just add a composite application.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/YGFj" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh4.ggpht.com/_4oXSoLPl3uY/TErg8ePUajI/AAAAAAAAAGM/109XcBb-J5g/s512/Compsite%20App.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Open the Service Assmbly and drag the BPEL project onto the JBI module section:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/G2Sf" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh4.ggpht.com/_4oXSoLPl3uY/TErjWhtfmTI/AAAAAAAAAGk/dmo20RxgRok/s512/Service%20Assembly.jpg"&gt;&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;Add some Endpoints from the Palette, connect the arrows:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/photos/LcEL" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh6.ggpht.com/_4oXSoLPl3uY/TErkCh59HsI/AAAAAAAAAG4/Caq0TEenQQA/s512/end%20points.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Deploy.. and you are done.&lt;br /&gt;&lt;br /&gt;If you like you can add a test to the Composite Application, very simple, On the Test folder, right click add, choose your main WSDL, choose the method you wanna test, it generates test xml based on the XSD. On the properties of the test set the port in ${HttpDefaultPort} in the properties of the test...and test...&lt;br /&gt;&lt;br /&gt;In Part II , I will add some more EJBs, so that this actually becomes a functioning application and some more awesome GlassfishESB functionality.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-6470308730219223590?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/6470308730219223590/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/07/glassfish-esb-easier-than-you-think.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6470308730219223590'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6470308730219223590'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/07/glassfish-esb-easier-than-you-think.html' title='Glassfish ESB, easier than you think. Part I'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_4oXSoLPl3uY/TEqEES_GPDI/AAAAAAAAACM/jhy1CNRzZdo/s72-c/create%20ejb%20project.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-3757547016663860226</id><published>2010-07-22T07:51:00.000+02:00</published><updated>2010-07-22T08:50:40.019+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Hudson'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='General Info'/><title type='text'>So your POM is quite nice.. now what?</title><content type='html'>Last week, I described some of the Maven lessons and configurations we had used in the last while: &lt;a href="http://java-it-zen.blogspot.com/2010/07/some-useful-maven-configurations.html"&gt;Some useful Maven configs&lt;/a&gt;...&lt;br /&gt;&lt;br /&gt;So now that you have all these Maven projects, local repos, well managed versions, unit tests, code coverage and static code analysis what do you do next?... &lt;br /&gt;You run it all the time and you let everyone know how it is going... &lt;br /&gt;Continuous Integration (CI)... &lt;br /&gt;I am not going to go into too much detail about the concept of CI, Martin Fowler and countless others have already done that.&lt;br /&gt;&lt;a href="http://www.martinfowler.com/articles/continuousIntegration.html"&gt;Martin Fowler - Continuous Integration&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I will however ramble out some personal opinions of the advantages and challenges that come with CI and mention some of the tools out there. I say "challenges" because I don't feel there are actually any disadvantages with this approach, but rather it just illuminates some difficulties that always existed in software development.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;The Advantages:&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;CI gives you an early warning of any major broken or conflicting code changes with continuous unit testing of all the changes, it enables better project visibility. Depending on thoroughness of your CI environment there can be immediate feedback to developers on the quality, functionality and state of the application. Bugs, systems issues and the time needed to correct them gets exponentially worse the longer you they go unseen and are left unattended. Another benefit is that there is always a "current" build, that can be used for anything like testing, demos or interim releases, so not only are the unit tests running all the time, functional testing can also happen on more current code.&lt;br /&gt;After the initial setup and with having all the SCM integration, building, deploying and reporting automated it allows people to focus on what they actually should be and not constant "environment" issues.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;The Challenges:&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;If CI is something new to the environment there will be some initial setup time / cost, including maybe some extra hardware as build machines.&lt;br /&gt;I feel there need to be well developed, comprehensive unit test suites these are crucial if there is to be any benefit gotten out of the automated testing. With this need for comprehensive unit test suites there is a requirement for all parties involved clients, management and developers to understand that more upfront development time will be required and there will be long term benefits. What happens all too often as soon a deadline looms... all standards, tests and processes go flying out the window, and as soon as that happens there is generally never time to go back and fix it and those holes in testing and quality will remain in the system.&lt;br /&gt;There is also challenges with large changes can be hindered by the constant builds although this can be be handled in a couple ways, depending mainly on how you handle your &lt;a href="http://en.wikipedia.org/wiki/Revision_control"&gt;Revision control / SCM (source configuration management)&lt;/a&gt;, but that is a subject for another day.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;The Tools:&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;I am only listing the ones that I feel are probably the most common (in the java environment), and obviously all are free and open source. I was tempted to create a very scaled down &amp; up to date version of: &lt;a href="http://confluence.public.thoughtworks.org/display/CC/CI+Feature+Matrix"&gt;CI Feature Matrix&lt;/a&gt;, but when you get down to the details, the 3 tools below all do very similar things, and have very similar features. They all can run, schedule, build, notify, integrate with SCMs (CVS, Subversion, Git, Mercurial, StarTeam, ClearCase), graph and have plugins for pretty much everything you will ever need.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://hudson-ci.org/"&gt;&lt;b&gt;Hudson&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://cruisecontrol.sourceforge.net/"&gt;&lt;b&gt;Cruise Control&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://continuum.apache.org/"&gt;&lt;b&gt;Apache Continuum&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We have used Hudson for the last couple years, and a couple practices that have served us well are:&lt;br /&gt;Ensure that a build can always be reproduced, the build must be a clean build from scratch and by that I mean all the code must code from your SCM tool.&lt;br /&gt;Set up email notifications to all the developers, the architect/s, and the project manager or development manager of the project. That way everyone has an idea of what is going on... and sometimes us developers need a little "motivation". There are also RSS feeds available for all builds, failed builds etc. I personally use those rather than the emails... but that is purely personal preference.&lt;br /&gt;Hudson needs a fair amount of disk space on large projects, to avoid issues midway in a project ensure you have ample space and keep an eye on the version / archiving settings.&lt;br /&gt;There are plugins for all major IDEs that allow you monitor and control Hudson without opening a browser, I personally like having the Hudson build information available within my IDE.&lt;br /&gt;Something I would have liked to have set up, is integration with a issue tracking system like bugzilla or something, but alas my little corporate doesn't work that way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-3757547016663860226?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/3757547016663860226/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/07/so-your-poms-quite-nice-now-what.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3757547016663860226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3757547016663860226'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/07/so-your-poms-quite-nice-now-what.html' title='So your POM is quite nice.. now what?'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-9061168525004117817</id><published>2010-07-19T21:40:00.000+02:00</published><updated>2010-07-19T22:47:20.226+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>MyEclipseIDE Maven4MyEclipse Null Pointer bug</title><content type='html'>I use MyEclipseIDE generally as my main IDE, I recently switched development teams at work, while importing all their existing maven  projects with the Maven4MyEclipse plugin into my new workspace I had quite a few of these little annoying popups:&lt;br /&gt;&lt;a href="http://goo.gl/photos/fECu" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh3.ggpht.com/_4oXSoLPl3uY/TER4FTrtEYI/AAAAAAAAABg/vsxuP9JncAo/s512/MyEclipseIDE%20Maven2%20bug.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I went and checked the Log:&lt;br /&gt;&lt;br /&gt;java.lang.NullPointerException&lt;br /&gt;at com.genuitec.eclipse.maven.project.MyEclipseProjectSupport.findWebRoot (MyEclipseProjectSupport.java:204)&lt;br /&gt;at com.genuitec.eclipse.maven.project.MyEclipseProjectSupport.configureWebProject (MyEclipseProjectSupport.java:71)&lt;br /&gt;at com.genuitec.eclipse.maven.project.MyEclipseProjectSupport.configure (MyEclipseProjectSupport.java:57)&lt;br /&gt;at org.maven.ide.eclipse.project.configurator.AbstractLifecycleMapping.configure (AbstractLifecycleMapping.java:57)&lt;br /&gt;at org.maven.ide.eclipse.internal.project.GenericLifecycleMapping.configure (GenericLifecycleMapping.java:48)&lt;br /&gt;at org.maven.ide.eclipse.internal.project.ProjectConfigurationManager.updateProjectConfiguration (ProjectConfigurationManager.java:332)&lt;br /&gt;at org.maven.ide.eclipse.internal.project.ProjectConfigurationManager.updateProjectConfiguration (ProjectConfigurationManager.java:318)&lt;br /&gt;at org.maven.ide.eclipse.actions.UpdateSourcesAction$1.runInWorkspace (UpdateSourcesAction.java:93)&lt;br /&gt;at org.eclipse.core.internal.resources.InternalWorkspaceJob.run&lt;br /&gt;(InternalWorkspaceJob.java:38)&lt;br /&gt;at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So I figure it is moaning about the WebRoot... let me try:&lt;br /&gt;&lt;br /&gt;Right click on project go to MyEclipse Menu and Add Web Project Capabilities.&lt;br /&gt;&lt;a href="http://goo.gl/photos/z9Td" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="http://lh3.ggpht.com/_4oXSoLPl3uY/TER4qmw8dRI/AAAAAAAAABw/yNrlTmXTtZ4/s512/MyEclipseIDE%20fix.jpg"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Worked like a charm.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-9061168525004117817?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/9061168525004117817/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/07/myeclipseide-maven4myeclipse-null.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/9061168525004117817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/9061168525004117817'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/07/myeclipseide-maven4myeclipse-null.html' title='MyEclipseIDE Maven4MyEclipse Null Pointer bug'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_4oXSoLPl3uY/TER4FTrtEYI/AAAAAAAAABg/vsxuP9JncAo/s72-c/MyEclipseIDE%20Maven2%20bug.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-6207255744395902396</id><published>2010-07-14T08:57:00.000+02:00</published><updated>2010-07-15T20:24:36.908+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Some useful Maven configurations, practices and lessons learnt</title><content type='html'>After using Maven for a while, my colleagues and I have configured a couple useful things and learnt a few lessons. &lt;br /&gt;&lt;br /&gt;&lt;font color='yellow'&gt;Edit: as per comments&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Local Repository Managers&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;On the maven site here: &lt;a href="http://maven.apache.org/repository-management.html"&gt;Repository Management&lt;/a&gt; there is a brief description of the major repo managers out there&lt;br /&gt;and a very good breakdown on why they are a good idea. We had a couple issues with Artifactory, (this was a couple years back) and in the end went with Nexus, which has proven to be very stable and offers all we need.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Parent POMs&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;Define common things, like versions, compiler settings, reporting settings and common build plugins in a parent POM to allow this configuration to be used throughout the applications' components and sub projects. If you have multiple projects with different requirements you can create another layer of Parent. To give an example, we had a legacy project, and the new re-write. For the legacy system we could not enforce checkstyle or code coverage but we did want to enforce it for the new project. So we created a base parent pom that had some general configuration and version numbers in it and then another parent pom for the new system that had the base parent as it's parent and then all the specific code coverage and style checks.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Versioning&lt;/u&gt;&lt;/b&gt;&lt;font color='yellow'&gt;(See update at end of post)&lt;/font&gt;&lt;br /&gt;In a parent POM define variables for all out internal component versions, so that you would have 1 central place to change release versions / snapshots etc. &lt;br /&gt;We didn't include the versions of common 3rd party libraries like Spring, The Apache commons projects, JUnit etc, which in hindsight was a mistake. This is now really quite a pain 3 years and 30ish POMs down the line when trying to upgrade a specific library, and invariably one gets missed and then you have 2 / 3 versions of Spring or Hibernate sneaking into the dependencies.&lt;br /&gt;&lt;br /&gt;Parent POM:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;properties&gt; &lt;org.springframework.version&gt;3.0.2.RELEASE&lt;/org.springframework.version&gt; &lt;javaitzen.spring.cache.ver&gt;1.0.1.SNAPSHOT&lt;javaitzen.spring.cache.ver&gt;&lt;/properties&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Project POM:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;parent&gt; &lt;groupId&gt;javaitzen&lt;/groupId&gt; &lt;artifactId&gt;general-pom&lt;/artifactId&gt; &lt;version&gt;0-SNAPSHOT&lt;/version&gt;&lt;/parent&gt;&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;&lt;groupId&gt;javaitzen.spring.cache&lt;/groupId&gt;&lt;artifactId&gt;SomeExample&lt;/artifactId&gt;&lt;packaging&gt;ear&lt;/packaging&gt;&lt;name&gt;ExampleEAR&lt;/name&gt;&lt;version&gt;${javaitzen.spring.cache.ver}&lt;/version&gt;&lt;dependency&gt; &lt;groupId&gt;org.springframework&lt;/groupId&gt; &lt;artifactId&gt;spring-core&lt;/artifactId&gt; &lt;version&gt;${org.springframework.version}&lt;/version&gt;&lt;/dependency&gt;  &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Compiler Settings&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;Just to ensure that it is the same accross all the projects using the parent.&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;build&gt;   &lt;plugins&gt;     &lt;plugin&gt;       &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;       &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;       &lt;configuration&gt;        &lt;source&gt;1.6&lt;/source&gt;        &lt;target&gt;1.6&lt;/target&gt;       &lt;/configuration&gt;     &lt;/plugin&gt;  &lt;/plugins&gt;&lt;/build&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Common Build Settings&lt;/u&gt;&lt;br /&gt;1.&lt;/b&gt; Unit Testing &lt;br /&gt;Actually running and reporting on the unit tests and results. &lt;br /&gt;1.a. In the report plugin I have included command line arguments to increase the VM size, we found that on our large projects with tons of unit tests it did occasionally ran out of memory.&lt;br /&gt;1.b. In the build plugin, there is a "parallel" config, that i recently saw in &lt;a href="http://weblogs.java.net/blog/johnsmart/archive/2010/07/06/running-junit-tests-parallel-maven"&gt;John Smarts blog&lt;/a&gt;, that allows you to run the test classes concurrently.&lt;br /&gt;&lt;b&gt;2.&lt;/b&gt; Cobertura Code Coverge, This is great way to ensure that there are atleast a certian amount of test cases and that code is being run. &lt;br /&gt;It unfortunately can't check the validility of the test cases so developers will be developers and code "useless" tests just to pass the coverage requirement, but it is still worth putting the plugin in, and "useless" tests can be caught with code reviews.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. Surefire - Running and Reporting&lt;/b&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;reporting&gt; &lt;plugins&gt;  &lt;plugin&gt;   &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;   &lt;artifactId&gt;maven-surefire-report-plugin&lt;/artifactId&gt;   &lt;configuration&gt;    &lt;argline&gt;-Xmx1024m -Xms512m&lt;/argLine&gt;   &lt;/configuration&gt;  &lt;/plugin&gt; &lt;/plugins&gt;&lt;/reporting&gt;&lt;build&gt; &lt;plugins&gt;  &lt;plugin&gt;   &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;   &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;   &lt;version&gt;2.5&lt;/version&gt;   &lt;configuration&gt;    &lt;parallel&gt;classes&lt;/parallel&gt;   &lt;/configuration&gt;  &lt;/plugin&gt; &lt;/plugins&gt;&lt;/build&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. Cobertura Code Coverage&lt;/b&gt;&lt;br /&gt;We found that in our predetermined deadline environment going for more that 50% coverage really extended the development time and effort for components more than we could afford. There were a couple smaller components that off the bat had 80%+, but we couldn't enforce it on all due to the time constraints.We are now slowly increasing that percentage when ever there is new work on a component but that is also quite a slow and painful process.&lt;br /&gt;The "totalLineRate" is the setting that determines the coverage % required. &lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;reporting&gt; &lt;plugins&gt;  &lt;plugin&gt;   &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;   &lt;artifactId&gt;cobertura-maven-plugin&lt;/artifactId&gt;   &lt;version&gt;2.4&lt;/version&gt;  &lt;/plugin&gt;&lt;/plugins&gt;&lt;/reporting&gt;&lt;build&gt; &lt;plugins&gt;  &lt;plugin&gt;   &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;   &lt;artifactId&gt;cobertura-maven-plugin&lt;/artifactId&gt;   &lt;version&gt;2.4&lt;/version&gt;   &lt;configuration&gt;    &lt;check&gt;     &lt;totalLineRate&gt;60&lt;/totalLineRate&gt;    &lt;/check&gt;   &lt;/configuration&gt;   &lt;executions&gt;    &lt;execution&gt;     &lt;id&gt;clean&lt;/id&gt;     &lt;goals&gt;      &lt;goal&gt;clean&lt;/goal&gt;     &lt;/goals&gt;    &lt;/execution&gt;   &lt;/executions&gt;  &lt;/plugin&gt; &lt;/plugins&gt;&lt;/build&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Checkstyle&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;We defined our basic coding standards within &lt;a href="http://checkstyle.sourceforge.net/"&gt;Checkstyle&lt;/a&gt;, and to ensure that they are followed we would fail the build if the code doesn't comply. I have also snuck in the "taglist-maven-plugin" plugin under this topic as it was a pet peeve on one of the developers, and with it in the reporting section it will show up when using 'mvn site'.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;reporting&gt; &lt;plugins&gt;  &lt;plugin&gt;   &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;   &lt;artifactId&gt;maven-checkstyle-plugin&lt;/artifactId&gt;   &lt;version&gt;2.1&lt;/version&gt;    &lt;configuration&gt;     &lt;configLocation&gt;      http://someserver/docs/checkstyle.xml     &lt;/configLocation&gt;    &lt;/configuration&gt;  &lt;/plugin&gt;    &lt;plugin&gt;   &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;   &lt;artifactId&gt;taglist-maven-plugin&lt;/artifactId&gt;   &lt;configuration&gt;    &lt;tags&gt;     &lt;tag&gt;TODO&lt;/tag&gt;     &lt;tag&gt;@todo&lt;/tag&gt;     &lt;tag&gt;FIXME&lt;/tag&gt;     &lt;tag&gt;XXX&lt;/tag&gt;    &lt;/tags&gt;   &lt;/configuration&gt;  &lt;/plugin&gt; &lt;/plugins&gt;&lt;/reporting&gt;&lt;build&gt; &lt;plugin&gt;    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;    &lt;artifactId&gt;maven-checkstyle-plugin&lt;/artifactId&gt;    &lt;version&gt;2.1&lt;/version&gt;    &lt;configuration&gt;     &lt;configLocation&gt;       http://someserver/docs/checkstyle.xml     &lt;/configLocation&gt;     &lt;failsOnError&gt;true&lt;/failsOnError&gt;    &lt;/configuration&gt;    &lt;executions&gt;     &lt;execution&gt;      &lt;id&gt;check&lt;/id&gt;      &lt;goals&gt;        &lt;goal&gt;check&lt;/goal&gt;      &lt;/goals&gt;    &lt;/execution&gt;  &lt;/executions&gt; &lt;/plugin&gt;&lt;/build&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Profiles&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;One of our .EARs needed to be deployed on both Glassfish and Weblogic and there were unfortunate compatibility issues between the 2 so we couldn't actually deploy the same ear.&lt;br /&gt;We configured that specific POM with 2 profiles. The Weblogic on was set to be the default, and when we required a new deployment onto Glassfish we would run maven with -Dglassfish-build=true.&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;profiles&gt; &lt;profile&gt; &lt;id&gt;glassfish-ear&lt;/id&gt; &lt;activation&gt;  &lt;property&gt;   &lt;name&gt;glassfish-build&lt;/name&gt;   &lt;value&gt;true&lt;/value&gt;  &lt;/property&gt; &lt;/activation&gt; &lt;build&gt;  &lt;plugins&gt;   &lt;plugin&gt;    &lt;artifactId&gt;maven-ear-plugin&lt;/artifactId&gt;    &lt;configuration&gt;    &lt;defaultJavaBundleDir&gt;/&lt;/defaultJavaBundleDir&gt;    &lt;modules&gt;     &lt;ejbModule&gt;      &lt;groupId&gt;javaitzen.spring.cache&lt;/groupId&gt;      &lt;artifactId&gt;SomeExample&lt;/artifactId&gt;                                                                                                                &lt;/ejbModule&gt;     &lt;webModule&gt;      &lt;groupId&gt;javaitzen.spring.cache&lt;/groupId&gt;      &lt;artifactId&gt;SomeExample&lt;/artifactId&gt;                                                                                                                 &lt;contextRoot&gt;/SomeExampleWeb&lt;/contextRoot&gt;     &lt;/webModule&gt;    &lt;/modules&gt;          &lt;/configuration&gt;   &lt;/plugin&gt;  &lt;/plugins&gt; &lt;/build&gt;&lt;/profile&gt; &lt;profile&gt;  &lt;id&gt;weblogic-ear&lt;/id&gt;  &lt;activation&gt;   &lt;activeByDefault&gt;true&lt;/activeByDefault&gt;  &lt;/activation&gt;  &lt;build&gt;   &lt;plugins&gt;    &lt;plugin&gt;     &lt;artifactId&gt;maven-ear-plugin&lt;/artifactId&gt;     &lt;configuration&gt;      &lt;defaultJavaBundleDir&gt;/APP-INF/lib&lt;/defaultJavaBundleDir&gt;      &lt;modules&gt;       &lt;ejbModule&gt;        &lt;groupId&gt;javaitzen.spring.cache&lt;/groupId&gt;        &lt;artifactId&gt;SomeExample&lt;/artifactId&gt;                                                                                                                  &lt;/ejbModule&gt;       &lt;webModule&gt;        &lt;groupId&gt;javaitzen.spring.cache&lt;/groupId&gt;        &lt;artifactId&gt;SomeExample&lt;/artifactId&gt;                                                                                                                   &lt;contextRoot&gt;/SomeExampleWeb&lt;/contextRoot&gt;       &lt;/webModule&gt;      &lt;/modules&gt;           &lt;/configuration&gt;    &lt;/plugin&gt;   &lt;/plugins&gt;  &lt;/build&gt; &lt;/profile&gt;&lt;/profiles&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color='yellow'&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Edit 2: Dependency Management and Versioning&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;Again, thanks to the people that commented. I am always happy to learn something new. So a couple people pointed out that I completely missed this. When writing this I based it on personal and team experiences and we somehow missed this section of the maven docs. I state in "Versioning" it is now a bit of a pain in our lives, so to help out others, below is the link to how Maven says you should handle dependencies.&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;a href="http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Management"&gt;Dependency Management&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-6207255744395902396?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/6207255744395902396/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/07/some-useful-maven-configurations.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6207255744395902396'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6207255744395902396'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/07/some-useful-maven-configurations.html' title='Some useful Maven configurations, practices and lessons learnt'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-3357827792451871126</id><published>2010-07-13T10:43:00.000+02:00</published><updated>2010-07-13T10:45:21.833+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web service'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='Glassfish'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>Spring 3: RESTful Web service Support... Take 2 with JPA and on Glassfish 3</title><content type='html'>In my &lt;a href="http://java-it-zen.blogspot.com/2010/07/spring-3-restful-web-service-support.html"&gt;original&lt;/a&gt; example. I just used a horrible static list in a controller as state for the CRUD methods. I couldn't leave it like that so I have now updated that version to use JPA to a MySQL DB.&lt;br /&gt;&lt;br /&gt;This updated source code, config and POM files are available in &lt;a href="http://code.google.com/p/itzen/source/browse/#"&gt;SVN&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I am not going to go through all the code like in my first example, but just go through a couple things I changed and new things picked up while making the change &lt;br /&gt;&lt;br /&gt;&lt;b&gt;1.&lt;/b&gt;&lt;br /&gt;This thing, that actually cost me quite a bit of time...&lt;br /&gt;The exception:&lt;br /&gt;"A JDBC Driver or DataSource class name must be specified in the ConnectionDriverName property"&lt;br /&gt;&lt;br /&gt;Which actually meant in my example &lt;br /&gt;"I couldn't find your persistence.xml" imagine that... obviously very clear.&lt;br /&gt;&lt;br /&gt;When you have a web application you can not just put your JPA persistence.xml in the META-INF folder like you would with a EJB application. Sad thing is I actually (after struggling for quite a while) remembered I had read this while studying for the SCBCD exam like 2 months ago. Doh!&lt;br /&gt;&lt;br /&gt;So you need it in a META-INF in with your source, so you can either put in in a jar or if you lazy just have a META-INF in java/main/src.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2.&lt;/b&gt;&lt;br /&gt;Trying to get Hibernate to run on Glassfish 3 was more effort that I thought it would be, and plain straight JPA was quick and simple.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3.&lt;/b&gt;&lt;br /&gt;I used MySQL many years back, and it was alright. This latest version 5.2 Rocks... Seriously, go download the DB server, the divers and the Workbench.. The workbench is the winner... simple easy admin, almost instant EER / ERD diagrams, nice SQL query interface too, for my own home development I doubt I will look any further.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4.&lt;/b&gt;&lt;br /&gt;For the last project I worked on we used Hibernate, and we used the generation tools to create our mappings and DAOs, which left us will a ton of Abstract and Implementation classes. I was never a fan of all those so went searching while doing this example and came across the Java Generic DAO implementation, which is very nice.&lt;br /&gt;&lt;br /&gt;So you create a base DAO with the Key and Entity defined as generic parameters, just for ease of reading i went with "key" and "entity" instead of the usual K and E.&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.rest.data;import java.io.Serializable;import java.lang.reflect.ParameterizedType;import java.util.List;import javax.persistence.EntityManager;import javax.persistence.PersistenceException;import javax.persistence.Query;import org.springframework.orm.jpa.JpaCallback;import org.springframework.orm.jpa.support.JpaDaoSupport;/** * The Class BaseJpaDAO. *  * @param &lt;key&gt; the generic type * @param &lt;entity&gt; the generic type */public abstract class BaseJpaDAO&lt;key extends Serializable, entity extends Serializable&gt; extends JpaDaoSupport {    protected Class&lt;entity&gt; entityClass;     @SuppressWarnings("unchecked")     public BaseJpaDAO() {         ParameterizedType genericSuperclass =         (ParameterizedType) getClass().getGenericSuperclass();         this.entityClass = (Class&lt;entity&gt;) genericSuperclass.getActualTypeArguments()[1];     }     @SuppressWarnings("unchecked")     public List&lt;entity&gt; findAll() {      Object res = getJpaTemplate().execute(new JpaCallback() {       public Object doInJpa(EntityManager em) throws PersistenceException {        Query q = em.createQuery("SELECT h FROM " +          entityClass.getName() + " h");        return q.getResultList();       }            });            return (List&lt;entity&gt;) res;     }     public entity findById(key id) {       return this.getJpaTemplate().find(entityClass, id);     }    public entity flush(entity entity) {        getJpaTemplate().flush();        return entity;    }    public entity merge(entity entity) {        return getJpaTemplate().merge(entity);    }    public void persist(entity entity) {        getJpaTemplate().persist(entity);    }    public void refresh(entity entity) {            }    public void remove(entity entity) {        getJpaTemplate().remove(entity);    }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;You then just have the following very small implementations just defining the actual Class type.&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.rest.data;import javaitzen.spring.rest.User;import javax.annotation.PostConstruct;import javax.persistence.EntityManagerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Repository;@Repository("userDAO")public class UserDAO extends BaseJpaDAO&lt;Long, User&gt; {    @Autowired    EntityManagerFactory entityManagerFactory;    @PostConstruct    public void init() {     super.setEntityManagerFactory(entityManagerFactory);    }}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Very neat.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5.&lt;/b&gt;&lt;br /&gt;In my original controller I had:&lt;br /&gt;@RequestMapping(value="/users/", method=RequestMethod.POST) on each method.&lt;br /&gt;&lt;br /&gt;Much nicer to have that on Controller level and just the following on the methods:&lt;br /&gt;@RequestMapping(method=RequestMethod.POST) &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;6.&lt;/b&gt;&lt;br /&gt;I mapped my dto purely through JPA annotations:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.rest;import java.io.Serializable;import java.util.Arrays;import java.util.List;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table;import javax.persistence.Transient;import javax.xml.bind.annotation.XmlRootElement;@SuppressWarnings("restriction")@XmlRootElement(name = "user" )@Entity@Table(name = "USER")public class User implements Serializable {    private static final long serialVersionUID = -2474375582120847864L;    @Id      @GeneratedValue(strategy = GenerationType.IDENTITY)    @Column(name="USER_ID", nullable = false)    private Long userId;    @Column(name="FIRST_NAME", nullable = false, length=45)    private String firstName;    @Column(name="LAST_NAME", nullable = false, length=45)    private String lastName;    @Column(name="USERNAME", nullable = false, length=45)    private String userName;    @Transient    private List&lt;string&gt; preferences;      public User() {    }        public User(String firstName, String lastName, String userName, String... preferences) {        super();        this.firstName = firstName;        this.lastName = lastName;        this.userName = userName;        this.preferences = Arrays.asList(preferences);    }       public final String getFirstName() {        return firstName;    }    public final void setFirstName(String firstName) {        this.firstName = firstName;    }    public final String getLastName() {        return lastName;    }    public final void setLastName(String lastName) {        this.lastName = lastName;    }    public final String getUserName() {        return userName;    }    public final void setUserName(String userName) {        this.userName = userName;    }    public final List&lt;string&gt; getPreferences() {        return preferences;    }    public final void setPreferences(final List&lt;string&gt; preferences) {        this.preferences = preferences;    }    public final Long getUserId() {        return userId;    }    public final void setUserId(final Long id) {        this.userId = id;    }    @Override    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());        result = prime * result + userId.hashCode();        result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());        result = prime * result + ((preferences == null) ? 0 : preferences.hashCode());        result = prime * result + ((userName == null) ? 0 : userName.hashCode());        return result;    }    @Override    public boolean equals(Object obj) {        if (this == obj)            return true;        if (obj == null)            return false;        if (getClass() != obj.getClass())            return false;        User other = (User) obj;        if (firstName == null) {            if (other.firstName != null)                return false;        } else if (!firstName.equals(other.firstName))            return false;        if (userId != other.userId)            return false;        if (lastName == null) {            if (other.lastName != null)                return false;        } else if (!lastName.equals(other.lastName))            return false;        if (preferences == null) {            if (other.preferences != null)                return false;        } else if (!preferences.equals(other.preferences))            return false;        if (userName == null) {            if (other.userName != null)                return false;        } else if (!userName.equals(other.userName))            return false;        return true;    }}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-3357827792451871126?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/3357827792451871126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/07/spring-3-restful-web-service-support_13.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3357827792451871126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3357827792451871126'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/07/spring-3-restful-web-service-support_13.html' title='Spring 3: RESTful Web service Support... Take 2 with JPA and on Glassfish 3'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-8408096026360554366</id><published>2010-07-12T18:03:00.000+02:00</published><updated>2010-07-12T18:05:13.677+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Glassfish'/><title type='text'>Gah...This was annoying... Glassfish 3.0.1 on Vista...</title><content type='html'>I have some time off... So I decide to check out Glassfish 3.0.1 (yes that is very geeky), it should be a nice new toy even with and evil red logo on it now. I am quite fond of glassfish, it was a pleasure to work with as a developer. I had spent a good almost 2 years using and fighting for the use of Glassfish 2.1 / OpenESB or Glassfish ESB... and lost the month I decided to get married and go on honeymoon... &lt;br /&gt;That is probably lesson in itself, with some kind of motto:&lt;b&gt;Never go on leave&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;.... anyway ....&lt;br /&gt;&lt;br /&gt;Back to my current annoying discovery:&lt;br /&gt;I try start up Glassfish after the install... (in Netbeans 6.9) and it fails with a silly little error:&lt;br /&gt;&lt;b&gt;"Address family not supported by protocol family: bind: 7676" &lt;/b&gt;&lt;br /&gt;and then proceeds to shutdown..&lt;br /&gt;&lt;br /&gt;So off to google...&lt;br /&gt;Read quite a few useless forum posts... &lt;br /&gt;Eventually find the below... pay it no attention of course... and carry on reading useless posts...&lt;br /&gt;"&lt;br /&gt;&lt;i&gt;Hi, &lt;br /&gt;&lt;br /&gt;Try to change configuration of localhost in file &lt;br /&gt;C:\Windows\System32\drivers\etc\hosts &lt;br /&gt;from &lt;br /&gt;::1 localhost &lt;br /&gt;to &lt;br /&gt;127.0.0.1 localhost &lt;br /&gt;&lt;/i&gt;"&lt;br /&gt;&lt;br /&gt;After another couple minutes, I decide "what the hell", and I go find the host file, make the change...big surprise... Windows doesn't let me.&lt;br /&gt;Download "Unlocker", pretty neat utility if you want to overpower the Windows file locks, but it picks up no lock.&lt;br /&gt;Another trip to google.... Only to find you need to run the edit application as an administrator obviously...&lt;br /&gt;&lt;br /&gt;Make the change, and Tah Dah! Nice new Glassfish 3.0.1 server up and running.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-8408096026360554366?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/8408096026360554366/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/07/gahthis-was-annoying-glassfish-301-on.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/8408096026360554366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/8408096026360554366'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/07/gahthis-was-annoying-glassfish-301-on.html' title='Gah...This was annoying... Glassfish 3.0.1 on Vista...'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-1897375706168916532</id><published>2010-07-08T17:20:00.000+02:00</published><updated>2010-07-08T19:51:13.922+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ehcache'/><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><title type='text'>Ehcache 2.1 Monitoring</title><content type='html'>In my previous post &lt;a href="http://java-it-zen.blogspot.com/2010/06/spring-aspectj-ehcache-method-caching.html"&gt;Spring, AspectJ, Ehcache Method Caching Aspect&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I demo'ed and described how and why to cache the results of methods. Now to enhance that, I did some more investigation into the latest release of ehcache available at &lt;a href="http://www.terracotta.org/"&gt;Terracotta&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;With 2.1 they released a monitoring api, to allow you to monitor cache's real time within your runtime environment, this will allow to fine tune and manage any cache you may have... be that custom caching with something like my MethodCacheAspect or your applications' Hibernate caches. To setup and use the monitoring you will need to do the following (I am setting this up on weblogic 10.3)&lt;br /&gt;&lt;br /&gt;I placed the following 4 jars into my domain/lib, this will be different for every application server, but as long as the following are in the relative classpath you should be ok.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;ehcache-core-2.1.0.jar&lt;/li&gt;&lt;li&gt;ehcache-probe-1.0.0.jar&lt;/li&gt;&lt;li&gt;slf4j-api-1.5.11.jar&lt;/li&gt;&lt;li&gt;slf4j-jdk14-1.5.11.jar&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;So now for the configuration:&lt;br /&gt;&lt;br /&gt;The ehcache.xml, needs to be in your classpath and have the following details: &lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt; &lt;diskStore path="java.io.tmpdir/sce" /&gt; &lt;cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"  properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,multicastGroupPort=4446, timeToLive=0" /&gt; &lt;cacheManagerPeerListenerFactory  class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"  properties="hostName=localhost, port=4001" /&gt; &lt;cacheManagerPeerListenerFactory class="org.terracotta.ehcachedx.monitor.probe.ProbePeerListenerFactory"  properties="serverAddress=localhost, serverPort=9889" /&gt;   &lt;defaultCache maxElementsInMemory="10000" eternal="false"  timeToIdleSeconds="60" timeToLiveSeconds="120" overflowToDisk="true"  diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"  diskPersistent="false" diskExpiryThreadIntervalSeconds="120"  memoryStoreEvictionPolicy="LRU"&gt;  &lt;cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" /&gt; &lt;/defaultCache&gt; &lt;cache name="restCache"  maxElementsInMemory="10000" eternal="true" overflowToDisk="true"&gt; &lt;cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" /&gt; &lt;/cache&gt;&lt;/ehcache&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Take note of the following that is added to the cache you want to monitor.&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;cacheEventListenerFactoryclass="net.sf.ehcache.distribution.RMICacheReplicatorFactory" /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the start up of the application server... in my case weblogic 10.3 you will see the following: &lt;br /&gt;&lt;i&gt;(it is a licensed product from terracotta, and I am only using in a development environment to tune my cache settings)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;INFO: Initializing EHCache CacheManager&lt;br /&gt;04 Jul 2010 6:18:24 PM net.sf.ehcache.distribution.RMICacheManagerPeerListener &lt;init&gt;&lt;br /&gt;WARNING: Explicitly setting the listener hostname to 'localhost' is not recommended. It will only work if all CacheManager peers are on the same machine.&lt;br /&gt;04 Jul 2010 6:18:25 PM org.terracotta.ehcachedx.monitor.probe.ProbeDxService startBackend&lt;br /&gt;INFO: Started probe at http://localhost:51115/monitor/list&lt;br /&gt;04 Jul 2010 6:18:25 PM org.terracotta.ehcachedx.license.LicenseResolver resolveLicense&lt;br /&gt;WARNING: No Ehcache Monitor license key found. This monitoring probe software is not licensed for production usage, and is only licensed for development usage. See LICENSE.txt for details. A temporary key will be generated for development usage. When the temporary key expires, the Ehcache monitoring probe capability will be suspended but your ability to continue to use Ehcache will not be affected. Please contact sales@terracottatech.com to request a license.&lt;br /&gt;04 Jul 2010 6:18:25 PM org.terracotta.ehcachedx.license.LicenseResolver logLicense&lt;br /&gt;INFO: &lt;br /&gt;--------- Ehcache Monitor license key ---------&lt;br /&gt;License type = DevOnly&lt;br /&gt;License number = 0&lt;br /&gt;Licensee = DevOnly User&lt;br /&gt;Product = Ehcache Monitor&lt;br /&gt;Capabilities = monitor&lt;br /&gt;Expiration date = 2010-07-07&lt;br /&gt;-----------------------------------------------&lt;br /&gt;04 Jul 2010 6:18:25 PM org.terracotta.ehcachedx.monitor.probe.ProbeDxService$RegisterWithServer run&lt;br /&gt;INFO: Null license registered&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now that it is up and running, you can browse to:&lt;br /&gt;http://localhost:51115/monitor/list&lt;br /&gt;&lt;br /&gt;There you will get a list of methods that allow you to query you live caches, or even check the status of the CacheManager with, "probeGetCacheManagerStatus( )" very handy if you want to monitor the health of your live application. We have had a couple occasions where we we getting exceptions calling another teams' services and it took a while to discover that the "Cache Manager is not alive" exception. &lt;br /&gt;&lt;br /&gt;The Ehcache API is REST based service. You Should be able to to use a simple RestTemplate like I used in my &lt;a href="http://java-it-zen.blogspot.com/2010/07/spring-3-restful-web-service-support.html"&gt;Spring 3 RESTFul&lt;/a&gt; example to manipulate and query the API, or you can just use a standard web browser:&lt;br /&gt;&lt;br /&gt;http://localhost:51115/monitor/probeGetCacheManagerStatus&lt;br /&gt;&lt;b&gt;Result:&lt;/b&gt;&lt;br /&gt;&lt;i&gt;STATUS_ALIVE&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;http://localhost:51115/monitor/probeGetCacheNames&lt;br /&gt;&lt;b&gt;Result:&lt;/b&gt;&lt;br /&gt;testCache&lt;br /&gt;restCache&lt;br /&gt;&lt;br /&gt;http://localhost:51115/monitor/probeGetCacheElementMemorySize?cache=testCache&lt;br /&gt;&lt;b&gt;Result:&lt;/b&gt;&lt;br /&gt;584&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The full list of functions are:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;AmountOfHistoryStoredOnMonitor( )&lt;br /&gt;getSampledStatisticNames( )&lt;br /&gt;getSamplingHistory( )&lt;br /&gt;getSamplingSeconds( )&lt;br /&gt;getVersion( )&lt;br /&gt;probeEvictExpiredElements( cache )&lt;br /&gt;probeFlushCache( cache )&lt;br /&gt;probeGetAllCachesConfigAllValues( )&lt;br /&gt;probeGetAllCachesSampledStatisticValues( name )&lt;br /&gt;probeGetCacheConfigAllValues( cache )&lt;br /&gt;probeGetCacheConfigNames( )&lt;br /&gt;probeGetCacheConfigValue( cache, name )&lt;br /&gt;probeGetCacheConfigValues( cache, name )&lt;br /&gt;probeGetCacheCount( )&lt;br /&gt;probeGetCacheElementCount( cache )&lt;br /&gt;probeGetCacheElementCountDisk( cache )&lt;br /&gt;probeGetCacheElementCountMemory( cache )&lt;br /&gt;probeGetCacheElementMemorySize( cache )&lt;br /&gt;probeGetCacheElementMetaDataAllValues( cache, key )&lt;br /&gt;probeGetCacheElementMetaDataNames( )&lt;br /&gt;probeGetCacheElementMetaDataValue( cache, key, name )&lt;br /&gt;probeGetCacheElementMetaDataValues( cache, key, name )&lt;br /&gt;probeGetCacheKeys( cache, count, [query] )&lt;br /&gt;probeGetCacheManagerName( )&lt;br /&gt;probeGetCacheManagerStatus( )&lt;br /&gt;probeGetCacheNames( )&lt;br /&gt;probeGetReplicationMode( )&lt;br /&gt;probeGetSampledStatisticAllValues( cache )&lt;br /&gt;probeGetSampledStatisticHistory( cache, name, [fromDateTime], [timeInterval], [offset] )&lt;br /&gt;probeGetSampledStatisticValue( cache, name )&lt;br /&gt;probeGetSampledStatisticValues( cache, name )&lt;br /&gt;probeRemoveAllFromCache( cache )&lt;br /&gt;probeRemoveFromCache( cache, key )&lt;br /&gt;probeRemoveQueryFromCache( cache, query )&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Some of these could be very valuable to fine tune you caching strategy. Knowing things like "probeGetCacheElementCountDisk", "probeGetCacheElementMemorySize" and being able to monitor them may allow you to tailor your Ehcache config for optimal usage and consequently better application performance.&lt;br /&gt;&lt;br /&gt;Also "probeFlushCache" or "probeRemoveFromCache" allow you to clear out the cache in the case of a data change without having to reinitialize / restart your application.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-1897375706168916532?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/1897375706168916532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/07/ehcache-21-monitoring.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1897375706168916532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/1897375706168916532'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/07/ehcache-21-monitoring.html' title='Ehcache 2.1 Monitoring'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-298893366116402940</id><published>2010-07-06T22:11:00.000+02:00</published><updated>2010-07-08T17:58:04.057+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Personal'/><title type='text'>The tale of a Calendar... a Date... and a Object reference bug..</title><content type='html'>To set the scene, there is a software release 4 days away and everyone is in &lt;b&gt;mid-pre-release-panic&lt;/b&gt;... There is one of those nasty bug's only happens sometimes, and was missed by testing until 2 hours before final signoff, and is &lt;b&gt;"absolutely  necessary"&lt;/b&gt; for the release.&lt;br /&gt;&lt;br /&gt;I rush off go through the date calculations done by our system, adding and changing To and From dates into a sequence depending on some items, not overly complicated but just enough to have quite a few Calendar and Date objects flying around.&lt;br /&gt;&lt;br /&gt;So I figure it has to be an object reference being used of one the Date objects, because 2 of the dates set are to the same value. This obviously only happens on the actual deployment and my unit tests pass, and debugs print out the right values.. &lt;br /&gt;&lt;br /&gt;First thing I do is look for shared Date objects (all the Date objects get created via Calendars or set back to the Calendar like below:&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;Calendar cal = Calendar.getInstance();Date date = cal.getTime();cal.setTime(date);&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The shared Date objects are then used on a internal Period class that has From and To dates and some convenience methods that is used all around our system and it was those date values that were incorrect.&lt;br /&gt;&lt;br /&gt;So I think... easy.. I'll just add ".clone()" the Date because it must be their object references.... I put in 2x .clone() compile, deploy ... test... fail... 2 Dates still the same.&lt;br /&gt;&lt;br /&gt;Go back to the code, get a second pair of eyes, a work colleague. Together we slap together  this completely immutable class, that makes the calculations less complicated and ensures that there can't be any object reference sharing between that dates and the calendars or anything, and at the same time create a new Period object to hold these new dates from our new class that we made sure that could not be messed with by reference.&lt;br /&gt;&lt;br /&gt;build, deploy ... test ... works like a charm.. notify the testers, they sign off ... all is good.&lt;br /&gt;&lt;br /&gt;A hour or so later, the same work colleague pops me an IM on MSN Messenger... says that this could happen somewhere else... we get the code... at roughly the same time we both happen to go into Calendar.getTime() source code and to our surprise (and amusement) we discover a little gem... both can't believe that we had not actually seen it before..&lt;br /&gt;&lt;br /&gt;Calendar source code below:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;     /**     * Returns a &lt;code&gt;Date&lt;/code&gt; object representing this     * &lt;code&gt;Calendar&lt;/code&gt;'s time value (millisecond offset from the &lt;a     * href="#Epoch"&gt;Epoch&lt;/a&gt;").     *     * @return a &lt;code&gt;Date&lt;/code&gt; representing the time value.     * @see #setTime(Date)     * @see #getTimeInMillis()     */    public final Date getTime() {        return new Date(getTimeInMillis());    }    /**     * Sets this Calendar's time with the given &lt;code&gt;Date&lt;/code&gt;.     * * Note: Calling &lt;code&gt;setTime()&lt;/code&gt; with     * &lt;code&gt;Date(Long.MAX_VALUE)&lt;/code&gt; or &lt;code&gt;Date(Long.MIN_VALUE)&lt;/code&gt;     * may yield incorrect field values from &lt;code&gt;get()&lt;/code&gt;.     *     * @param date the given Date.     * @see #getTime()     * @see #setTimeInMillis(long)     */    public final void setTime(Date date) {        setTimeInMillis(date.getTime());    }    /**     * Returns this Calendar's time value in milliseconds.      *     * @return the current time as UTC milliseconds from the epoch.     * @see #getTime()     * @see #setTimeInMillis(long)     */    public long getTimeInMillis() {        if (!isTimeSet) {     updateTime(); }        return time;    }    /**     * Sets this Calendar's current time from the given long value.     *     * @param millis the new time in UTC milliseconds from the epoch.     * @see #setTime(Date)     * @see #getTimeInMillis()     */    public void setTimeInMillis(long millis) { // If we don't need to recalculate the calendar field values, // do nothing. if (time == millis &amp;&amp; isTimeSet &amp;&amp; areFieldsSet &amp;&amp; areAllFieldsSet     &amp;&amp; (zone instanceof ZoneInfo) &amp;&amp; !((ZoneInfo)zone).isDirty()) {     return; }        time = millis;        isTimeSet = true;        areFieldsSet = false; computeFields();        areAllFieldsSet = areFieldsSet = true;    }&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The standard java Calendar had ensured a long time ago that you would not have this object reference scenario and that it is safe by using the "TimeInMillis". So we had wasted a good 30 minutes of our lives, when the only issue was our own Period object that was the bad reference.&lt;br /&gt;&lt;br /&gt;So I guess the point of this is.... &lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. &lt;/b&gt; Using the Calendar.getTime() and setTime() is safe and won't let you pollute object references.. and...&lt;br /&gt;&lt;b&gt;2. &lt;/b&gt; I had a similar discovery with Spring a little while back &lt;a href="http://java-it-zen.blogspot.com/2010/06/ahhh-convenience.html"&gt;(...)&lt;/a&gt; So it is fair to say if you have the source code of classes you are using, its probably an excellent idea to have a look at it from time to time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-298893366116402940?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/298893366116402940/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/07/calendar-date-and-object-reference-bug.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/298893366116402940'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/298893366116402940'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/07/calendar-date-and-object-reference-bug.html' title='The tale of a Calendar... a Date... and a Object reference bug..'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-4350702927421229543</id><published>2010-07-05T00:28:00.000+02:00</published><updated>2010-07-13T10:58:50.847+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web service'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='JaxB'/><title type='text'>Spring 3: RESTful Web service Support</title><content type='html'>&lt;font color="yellow"&gt; UPDATE: This has been updated to use JPA and a more real life type object with Id's and the like...&lt;/font&gt; &lt;a href="http://java-it-zen.blogspot.com/2010/07/spring-3-restful-web-service-support_13.html"&gt;Spring 3: RESTful Web service Support Take 2 with JPA&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So in between some really long days at work, the usual before release panic and regression defects. I finally completed a simple RESTFul example, before getting into the details, here are a couple facts about RESTFul services.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;REST stands for Representational State Transfer.&lt;/li&gt;&lt;li&gt;Each unique URL is a representation of some object.&lt;/li&gt;&lt;li&gt;You can get the contents of that object using an HTTP GET.&lt;/li&gt;&lt;li&gt;You may use a POST, PUT, or DELETE to modify the object.&lt;/li&gt;&lt;li&gt;It is not necessary to use XML as a data format, so for small amounts of data it can be significantly lighter on bandwidth.&lt;/li&gt;&lt;li&gt;REST as a protocol does not define any form of message envelope.&lt;/li&gt;&lt;li&gt;REST takes advantage of HTTP caches. (A cache can't to do anything a POST; but they can cache GETs and expire those entries based on PUTs and DELETEs.).&lt;/li&gt;&lt;li&gt;The Sun specification for RESTFul webservices can be found at&lt;a href="http://jcp.org/en/jsr/detail?id=311"&gt;JAX-RS&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Spring does not directly support or implement the JAX-RS spec but instead RESTful functionality is added to feature Spring MVC.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;As with my other examples all the source code, config and POM files are available in &lt;a href="http://code.google.com/p/itzen/source/browse/#"&gt;SVN&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As we are exposing information via HTTP this is going to be a web project. I won't be going into details of compiling and deploying a web application, but will go through all the required parts&lt;br /&gt;Starting with the web.xml:&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;web-app id="WebApp_ID" version="2.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/j2ee" xsi:schemalocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"&gt; &lt;display-name&gt;SpringRestfulExample&lt;/display-name&gt;  &lt;context-param&gt;  &lt;param-name&gt;log4jConfigLocation&lt;/param-name&gt;&lt;param-value&gt;/WEB-INF/classes/log4j.properties&lt;/param-value&gt;&lt;/context-param&gt;  &lt;servlet&gt;  &lt;servlet-name&gt;Spring3RESTFul&lt;/servlet-name&gt;  &lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;  &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;/servlet&gt;  &lt;servlet-mapping&gt;      &lt;servlet-name&gt;Spring3RESTFul&lt;/servlet-name&gt;      &lt;url-pattern&gt;/app/*&lt;/url-pattern&gt; &lt;/servlet-mapping&gt;  &lt;welcome-file-list&gt;  &lt;welcome-file&gt;index.jsp&lt;/welcome-file&gt; &lt;/welcome-file-list&gt;&lt;/web-app&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The DispatcherServlet will receive the request it will then, based on the servlet mapping&lt;br /&gt;go looking for "Spring3RESTFul-servlet.xml" which in turn defines the controller and view (which are dynamically searched for and created):&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;beans xmlns:context="http://www.springframework.org/schema/context" xmlns:oxm="http://www.springframework.org/schema/oxm" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/oxmhttp://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd"&gt;  &lt;context:component-scan base-package="javaitzen.spring.rest.controller" /&gt; &lt;bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /&gt; &lt;bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"&gt;  &lt;property name="messageConverters"&gt;   &lt;list&gt;    &lt;ref bean="marshallingHttpMessageConverter"&gt;   &lt;/ref&gt;&lt;/list&gt;  &lt;/property&gt; &lt;/bean&gt; &lt;bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter" id="marshallingHttpMessageConverter"&gt;  &lt;property name="marshaller" ref="jaxb"&gt;  &lt;property name="unmarshaller" ref="jaxb"&gt; &lt;/property&gt;&lt;/property&gt;&lt;/bean&gt; &lt;oxm:jaxb2-marshaller id="jaxb"&gt;  &lt;oxm:class-to-be-bound name="javaitzen.spring.rest.User" /&gt; &lt;/oxm:jaxb2-marshaller&gt;&lt;/beans&gt;&lt;/script&gt;&lt;br /&gt;The &lt;i&gt;component-scan&lt;/i&gt; in the application context above will be used to automatically pick up our @Controller. If you go to /app/users/Bob, the getUser method is executed and their respective name is passed through as a parameter. The Spring JaxB 2 marshaller will be used to marshall the User object in and out of XML. Any of the OXM marshallers can be used, I just simply prefer JaxB.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;Note:&lt;/b&gt; &lt;font color="red"&gt;You really should not have a horrible static map containing state within a controller (like I do below), I am only doing it now because this is an example, and I want to keep it simple and not digress into a full blown application. If I have time over the next week or so, I'll remove that map of data and just create an embedded DB or something.&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.rest.controller;import java.util.Map;import java.util.TreeMap;import javaitzen.spring.rest.User;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;@Controllerpublic class UsersController {    private static Map&amp;lt; String, User &amp;gt; users = new TreeMap&amp;lt; String, User &amp;gt;();        @RequestMapping(value="/users/{firstName}",method=RequestMethod.GET)     @ResponseBody public User getUser(@PathVariable("firstName")String user) {        System.out.println("retrieve");        User theUser = someExampleData().get(user);        return theUser;            }         @RequestMapping(value="/users/",method=RequestMethod.POST)     @ResponseBody public User createUser(@RequestBody User user) {        System.out.println("create");        users.put(user.getFirstName(), user);        return user;    }         @RequestMapping(value="/users/{firstName}",method=RequestMethod.PUT)     @ResponseBody public User updateUser(@PathVariable("firstName")String name, @RequestBody User user) {        System.out.println("update");        users.put(user.getFirstName(), user);        return user;    }     @RequestMapping(value="/users/{firstName}",method=RequestMethod.DELETE)     @ResponseBody public void deleteUser(@PathVariable("firstName")String name) {         System.out.println("delete");        users.remove(name);            }         /**     * Some example data.     *      * @return the map     */    private Map&amp;lt; String, User &amp;gt; someExampleData() {        users.put("Bob", new User("Bob", "Smith", "bobs", "clean", "simple", "code"));        users.put("John", new User("John", "Doe", "johnd", "large", "complicated", "code"));        users.put("Mary", new User("Mary", "Smith", "marys", "nice", "pretty", "code"));        return users;    }}&lt;/script&gt;&lt;br /&gt;You can view the results in your browser by simply going to the url. I am using weblogic, so mine looks like "http://localhost:7001/Spring3RESTFul-1/app/users/Mary" but depending on your deployment it could differ as long as you add "/app/users/Mary" to your context root you should get the following displayed. &lt;i&gt;(if you are using firefox)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;user&gt; &lt;firstname&gt;Mary&lt;/firstname&gt; &lt;lastname&gt;Smith&lt;/lastname&gt; &lt;preferences&gt;nice&lt;/preferences&gt; &lt;preferences&gt;pretty&lt;/preferences&gt; &lt;preferences&gt;code&lt;/preferences&gt; &lt;username&gt;marys&lt;/username&gt;&lt;/user&gt;&lt;/script&gt;&lt;br /&gt;However, chances are you are not writing this to view some XML in a browser but rather to get or manipulate information from one system or component to another. For this I created a little client, this client uses Springs' &lt;a href="http://blog.springsource.com/2009/03/27/rest-in-spring-3-resttemplate/"&gt;RestTemplate&lt;/a&gt; which is autowired and lets me access the HTTP functions:&lt;br /&gt;&lt;br /&gt;Quote from Spring blog:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;DELETE delete(String, String...)&lt;br /&gt;GET getForObject(String, Class, String...)&lt;br /&gt;HEAD headForHeaders(String, String...)&lt;br /&gt;OPTIONS optionsForAllow(String, String...)&lt;br /&gt;POST postForLocation(String, Object, String...)&lt;br /&gt;PUT put(String, Object, String...)&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;This example only uses getForObject, postForObject, put and delete for the moment, so just the normal CRUD operations.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.rest.client;import javaitzen.spring.rest.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.web.client.RestClientException;import org.springframework.web.client.RestTemplate;@Component("userClient")public class UserServiceClient {    @Autowired    protected RestTemplate restTemplate;    private final static String serviceUrl = "http://127.0.0.1:7001/Spring3RESTFul-1/app/users/";    public User retrieveUserDetails(final String firstName) {        System.out.println("Client: get");        return restTemplate.getForObject(serviceUrl + "{firstName}", User.class, firstName);    }        public User createNewUser(final String firstName, final String lastName, final String userName) {        System.out.println("Client: post");        User newUser = new User(firstName, lastName, userName);        newUser = restTemplate.postForObject(serviceUrl, newUser, User.class);        return newUser;    }        public void updateUserDetails(final String firstName, final String lastName, final String userName) {        System.out.println("Client: put");        User newUser = new User(firstName, lastName, userName);        restTemplate.put(serviceUrl + "{firstName}", newUser, firstName);    }    public boolean deleteUserDetails(final String firstName) {                System.out.println("Client: delete");        try{            restTemplate.delete(serviceUrl + "{firstName}", firstName);        }catch (RestClientException e) {            e.printStackTrace();            return false;        }        return true;    }            }&lt;/script&gt;&lt;br /&gt;Now to use the above client I have a test application context injecting the RestTemplate and a test case preforming the create, retrieve, update and delete.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;beans xmlns:context="http://www.springframework.org/schema/context" xmlns:oxm="http://www.springframework.org/schema/oxm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt; &lt;context:component-scan base-package="javaitzen.spring.rest" /&gt; &lt;bean class="org.springframework.web.client.RestTemplate" id="restTemplate"&gt;  &lt;property name="messageConverters"&gt;   &lt;list&gt;    &lt;bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"&gt;     &lt;constructor-arg&gt;&lt;oxm:jaxb2-marshaller id="jaxb"&gt;        &lt;oxm:class-to-be-bound name="javaitzen.spring.rest.User"&gt;&lt;/oxm:class-to-be-bound&gt;       &lt;/oxm:jaxb2-marshaller&gt;     &lt;/constructor-arg&gt;&lt;/bean&gt;     &lt;/list&gt;    &lt;/property&gt;   &lt;/bean&gt; &lt;/beans&gt;      &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Note:&lt;/b&gt;&lt;i&gt;Because I just wanted to create 1 project for this example I have included the following, just so that you can compile and deploy and then run the test case... but ever adding this to a actual project POM file should be grounds for a good beating.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;&lt;plugin&gt;    &lt;groupid&gt;org.apache.maven.plugins&lt;/groupId&gt;    &lt;artifactid&gt;maven-surefire-plugin&lt;/artifactOd&gt;    &lt;configuration&gt;      &lt;testfailureignore&gt;true&lt;/testFailureIgnore&gt;      &lt;testerrorignore&gt;true&lt;/testErrorIgnore&gt;    &lt;/configuration&gt;&lt;/plugin&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Lastly actual test case. Deploy the war file created by the POM to the web / application server of your choice before running the below:&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: java"&gt;package javaitzen.spring.rest;import static org.junit.Assert.assertEquals;import static org.junit.Assert.assertTrue;import javaitzen.spring.rest.client.UserServiceClient;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@ContextConfiguration(locations={"/javaitzen/spring/rest/applicationContext.xml"})@RunWith(SpringJUnit4ClassRunner.class)public class UserRestTest {    @Autowired    UserServiceClient client;        @Before    public void setup(){    }        @Test    public void testGetRest() throws Exception{        User user = client.retrieveUserDetails("John");        assertEquals(user.getFirstName(), "John");        assertEquals(user.getLastName(), "Doe");    }        @Test    public void testPostRest() throws Exception{        User user = client.createNewUser("Ray", "Pingbo", "NI");        assertEquals(user.getFirstName(), "Ray");        assertEquals(user.getLastName(), "Pingbo");    }    @Test    public void testPutRest() throws Exception{        client.updateUserDetails("Ray", "Pingbo", "NI");    }        @Test    public void testDeleteRest(){        assertTrue(client.deleteUserDetails("Mary"));    }    }&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And that is it... a Simple CRUD RESTFul Webservice example with Spring 3.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-4350702927421229543?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/4350702927421229543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/07/spring-3-restful-web-service-support.html#comment-form' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4350702927421229543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/4350702927421229543'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/07/spring-3-restful-web-service-support.html' title='Spring 3: RESTful Web service Support'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-6087758462421621568</id><published>2010-06-27T10:44:00.000+02:00</published><updated>2010-06-27T11:07:31.671+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Update: Spring 3: OXM Blog entry</title><content type='html'>While doing my RESTful webservice example I came across a marshaller that I had missed in my original &lt;a href="http://java-it-zen.blogspot.com/2010/05/spring-3-oxm-castor-jaxb-jibx-and.html"&gt;Spring 3: OXM&lt;/a&gt; post.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;XStream&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;To the maven pom I added:&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;dependency&gt;&lt;br /&gt; &lt;groupid&gt;com.thoughtworks.xstream&lt;/groupId&gt;&lt;br /&gt; &lt;artifactid&gt;xstream&lt;/artifactId&gt;&lt;br /&gt; &lt;version&gt;1.3.1&lt;/version&gt;&lt;br /&gt;&lt;/dependency&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To the class being marshalled:&lt;br /&gt;&lt;br /&gt;@XStreamAlias( "MyXMLName" )&lt;br /&gt;&lt;br /&gt;And to the application context:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;bean id="xStreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"&gt;&lt;br /&gt; &lt;property name="autodetectAnnotations" value="true"&gt;&lt;/property&gt;&lt;br /&gt;&lt;/bean&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I have also uploaded the example project into &lt;a href="http://code.google.com/p/itzen/source/browse/#"&gt;SVN&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-6087758462421621568?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/6087758462421621568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/06/update-spring-3-oxm-blog-entry.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6087758462421621568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6087758462421621568'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/06/update-spring-3-oxm-blog-entry.html' title='Update: Spring 3: OXM Blog entry'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-2670465662291766359</id><published>2010-06-25T18:42:00.000+02:00</published><updated>2010-06-27T10:13:43.140+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web service'/><category scheme='http://www.blogger.com/atom/ns#' term='General Info'/><title type='text'>No REST for the wicked or the Corporate Developer</title><content type='html'>REST vs. Other Web Services&lt;br /&gt;&lt;br /&gt;I know this topic has probably been covered a million times in the last couple years, but being a developer in a large corporate where "standards" are imposed to limit the craziness that would ensue without them. I have actually only now started to have a look at it. The reason for me looking at it now is the Spring 3 RESTful support, which I plan to play with in the next day or so.&lt;br /&gt;&lt;br /&gt;Not really going to go into SOAP and XML-RPC, as I generally know that and they are the only type of webservices we implemented in my working environment. I know that SOAP and XML-RPC, uses an envelope, XML and is well defined / strongly typed... bla bla bla...&lt;br /&gt;&lt;br /&gt;So from random sources this is what I found about REST:&lt;br /&gt;&lt;br /&gt;REST stands for Representational State Transfer &lt;br /&gt;Each unique URL is a representation of some object. &lt;br /&gt;You can get the contents of that object using an HTTP GET. &lt;br /&gt;You may use a POST, PUT, or DELETE to modify the object.&lt;br /&gt;It is not necessary to use XML as a data format, so for small amounts of data it can be significantly lighter on bandwidth.&lt;br /&gt;REST as a protocol does not define any form of message envelope.&lt;br /&gt;REST takes advantage of HTTP caches. (&lt;i&gt;A cache can't to do anything a POST; but they can cache GETs and expire those entries based on PUTs and DELETEs.&lt;/i&gt;). &lt;br /&gt;&lt;br /&gt;So where to use RESTful ? &lt;br /&gt;Well from what I just read, it is a smaller, quicker, HTTP interface which sounds perfect for replacing all "system internal" service calls happening between components where direct RPC is not ideal and it really isn't worth the time, effort and red tape to set up a WSDL / XSD.&lt;br /&gt;(that was a really long sentence)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Ignore: just for proof of ownership: GUNCP4EUNAGF&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-2670465662291766359?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/2670465662291766359/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/06/no-rest-for-wicked-or-corporate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/2670465662291766359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/2670465662291766359'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/06/no-rest-for-wicked-or-corporate.html' title='No REST for the wicked or the Corporate Developer'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-3585704067818544274</id><published>2010-06-21T22:59:00.000+02:00</published><updated>2010-06-29T18:35:10.811+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><title type='text'>Fluent Interfaces...Great.when.good &amp;&amp; Fn.complicated.ifelse().true.</title><content type='html'>While scanning the internet, looking for something to comment on and maybe learn, My wife, a .Net Developer, mentioned... &lt;br /&gt;&lt;br /&gt;&lt;a href="http://sharptestex.codeplex.com/"&gt;Sharp Test Ex&lt;/a&gt;... I went to check it out and was instantly intrigued...&lt;br /&gt;With syntax shown below who can blame me, nice readable tests:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;const string something = "something";&lt;br /&gt;something.Should().Contain("some");&lt;br /&gt;something.Should().Not.Contain("also");&lt;br /&gt;something.ToUpperInvariant().Should().Not.Contain("some");&lt;br /&gt;&lt;br /&gt;var ints = new[] { 1, 2, 3 };&lt;br /&gt;ints.Should().Have.SameSequenceAs(new[] { 1, 2, 3 });&lt;br /&gt;ints.Should().Not.Have.SameSequenceAs(new[] { 3, 2, 1 });&lt;br /&gt;ints.Should().Not.Be.Null();&lt;br /&gt;ints.Should().Not.Be.Empty();&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I then remembered a couple years back I came across something Martin Fowler chatted about: &lt;a href="http://martinfowler.com/bliki/FluentInterface.html"&gt;Fluent Interface&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I never paid too much attention to it then, but as the years add up and I get more lazy, this appeals to me more. So not to be out done by .Net I went looking for java equivalents. I found 2, FEST and OP4j.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;FEST has a couple sub projects: Reflection, Swing, JavaFX, Mock, Assertions&lt;/i&gt;&lt;br /&gt;To compare with the .Net example above I'll go to FEST Asserts.&lt;br /&gt;&lt;a href="http://fest.easytesting.org/assert/wiki/pmwiki.php"&gt;FEST Asserts&lt;/a&gt;&lt;br /&gt;"&lt;br /&gt;Provides a fluent interface for writing assertions. Its main goal is to improve test code readability and make maintenance of tests easier.&lt;br /&gt;"&lt;br /&gt;&lt;br /&gt;With example Syntax below... nice ... simple ... readable... great, I'll be implementing that in the next project I have a little bit of spare time. It doesn't cater for everything but from the looks of it there will 0 ramp up time and should be usable / understandable right after adding it to the maven pom and downloading the libs.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;int removed = employees.removeFired();&lt;br /&gt;  assertThat(removed).isZero();&lt;br /&gt;&lt;br /&gt;  List&lt; Employee &gt; newEmployees = employees.hired(TODAY);&lt;br /&gt;  assertThat(newEmployees).hasSize(6)&lt;br /&gt;                          .contains(frodo, sam);&lt;br /&gt;&lt;br /&gt;  String[] newHires = employees.newHiresNames();&lt;br /&gt;  assertThat(newHires).containsOnly("Gandalf", "Arwen", "Gimli"); &lt;br /&gt;&lt;br /&gt;  assertThat(yoda).isInstanceOf(Jedi.class)&lt;br /&gt;                  .isEqualTo(foundJedi)&lt;br /&gt;                  .isNotEqualTo(foundSith);&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now OP4J... &lt;br /&gt;&lt;a href="http://www.op4j.org/"&gt;op4j&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;"&lt;br /&gt;op4j is a powerful implementation of the Fluent Interface style of code. It allows you to create chained expressions which apply both predefined or user-defined functions to your objects in a fluid and readable way. This improves the way your code looks and greatly reduces the complexity of executing auxiliary low-level tasks in the highly bureaucratic, statically -and strongly- typed language that Java is.&lt;br /&gt;"&lt;br /&gt;&lt;br /&gt;"several hundred functions with more than one thousand different parameterizations"&lt;br /&gt;&lt;br /&gt;Off the bat seems like a monster. They seem to have put a lot of time and effort into "bending the java spoon". From a quick look it seems they cater for a ton of common code occurences and allow you to condense quite a bit of code into 1 liners.&lt;br /&gt;Although I do see value in this framework, I have some concerns on how much there is to learn, the ramp up time required, and how easy it would be for a junior developer to maintain.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Example syntax below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;// Without op4j&lt;br /&gt;  Set&lt; String &gt; set = new LinkedHashSet&lt; String &gt;(list);      &lt;br /&gt;  // With op4j&lt;br /&gt;  Set&lt; String &gt; set = Op.on(list).toSet().get();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; Set &lt; Calendar &gt; set = Op.on(list).toSet().removeAllNull().forEach()&lt;br /&gt;.exec(FnString.toCalendar("dd/MM/yyyy")).get();&lt;br /&gt;&lt;br /&gt; Function&lt; List &lt; String &gt;,Set &lt; Calendar &gt; &gt; dateProcessFunction = &lt;br /&gt; Fn.onListOf(Types.STRING)&lt;br /&gt;.toSet().map(FnString.toCalendar("dd/MM/yyyy"))&lt;br /&gt;.removeAllNullOrTrue(FnCalendar.after(now)).get();&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In conclusion, it is not entirely fair to compare OP4J with the much smaller "testing" fluent interfaces as they are targeted at different functionality. However, I think the idea of Fluent Interfaces is quite a nice one. On large systems with internal frameworks and structured code environments like large corporates and banks, defining and implementing a proprietary fluent interface type of framework could , if done correctly, be very very useful and simplify large amounts of commonly used code. There is however, a distinct danger that it may also lead to vastly harder to read code that is also harder to maintain and debug instead of the original concept of "The API is primarily designed to be readable and to flow" &lt;br /&gt;&lt;br /&gt;What I do like of both "FEST Asserts" and the .Net "Sharp Test Ex" is that they are limited to testing and geared only towards quicker, more understandable test cases. Anything that makes testing quicker, easier or a little more fun is well worth it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I also stumbled across the following,&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/fluent-builders-generator-eclipse-plugin/"&gt;Fluent Build eclipse builder.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;How not yet had time to investigate it properly, but definitely worth keeping an eye on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-3585704067818544274?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/3585704067818544274/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/06/fluent-interfacesgreatwhengood.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3585704067818544274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3585704067818544274'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/06/fluent-interfacesgreatwhengood.html' title='Fluent Interfaces...Great.when.good &amp;&amp; Fn.complicated.ifelse().true.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-568964812415185760</id><published>2010-06-14T23:25:00.000+02:00</published><updated>2010-06-20T00:51:18.527+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Spring 3: Scheduling... Take 2</title><content type='html'>In the previous blog entry I used Spring annotation scheduling to fire an event, but there is also another way through the application context xml.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Annotation:&lt;/b&gt;&lt;br /&gt;In the application context.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;context:component-scan base-package="javaitzen.spring.liveconfig" &gt;&lt;/context:component-scan&gt;&lt;br /&gt;&lt;task:annotation-driven&gt;&lt;/task:annotation-driven&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;Then within the code annotate the method with &lt;i&gt;@Scheduled(fixedDelay = 10000)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;XML:&lt;/b&gt;&lt;br /&gt;Now if you annotate your class with @Service or @Component (with &lt;i&gt;component-scan&lt;/i&gt;), you can use the &lt;i&gt;scheduled-tasks&lt;/i&gt; tag, and schedule a method on a service and specify a cron expression, which does give you all the control you'll need.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;context:component-scan base-package="javaitzen.spring.liveconfig" &gt;&lt;/context:component-scan&gt;&lt;br /&gt;&lt;br /&gt;&lt;task:scheduled-tasks&gt;&lt;br /&gt;    &lt;task:scheduled ref="TheWorkManager" method="process" cron="0 23 * * 1-5 *"/&gt;&lt;br /&gt;&lt;/task:scheduled-tasks&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Since I personally can never remember the exact format for cron I am adding the next little bit for easy reference.&lt;br /&gt;&lt;br /&gt;*  *  *  *  *  *&lt;br /&gt;|  |  |  |  |  | &lt;br /&gt;|  |  |  |  |  +-- Year              (range: 1900-3000)&lt;br /&gt;|  |  |  |  +---- Day of the Week   (range: 1-7, 1 standing for Monday)&lt;br /&gt;|  |  |  +------ Month of the Year (range: 1-12)&lt;br /&gt;|  |  +-------- Day of the Month  (range: 1-31)&lt;br /&gt;|  +---------- Hour              (range: 0-23)&lt;br /&gt;+------------ Minute            (range: 0-59)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;0 23 * * 1-5 *  At 11:00PM on weekdays Mon-Fri&lt;br /&gt;0 0 1 * * *     At midnight, on the first day of each month&lt;br /&gt;* * * * * ?     Every Second&lt;br /&gt;0 * * * * ?     Every Minute&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-568964812415185760?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/568964812415185760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/06/spring-3-scheduling-take-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/568964812415185760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/568964812415185760'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/06/spring-3-scheduling-take-2.html' title='Spring 3: Scheduling... Take 2'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-770306566456857126</id><published>2010-06-13T13:55:00.000+02:00</published><updated>2010-06-14T21:09:37.004+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Spring 3: Scheduling, Components, PostBeanProcessors and bending the rules.</title><content type='html'>This blog entry should come with one of those warnings "Do not attempt this at home, the following is done by trained professionals".. bla bla bla&lt;br /&gt;&lt;br /&gt;To begin, I, being a developer always push the limits and bend the rules of what we should / or should not do. I set out to "bend" something in Spring for a change. I work in a 24/7/365 live type environment, where there are always people using the system and any downtime causes many reports and cascading pain flowing down the leadership hierarchy in a large corporate environment. Now sometimes in this environment even with tons of effort, signoffs, QA's, UAT's, Training something goes live, or happens in live that needs to be changed / switched off.&lt;br /&gt;&lt;br /&gt;Now using Spring for injecting all that needs to be injected is awesome, but it does require that the application context be recreated / instantiated to pickup configuration changes. The following code changes that...&lt;br /&gt;&lt;br /&gt;As with the method cache aspect, I will make the code available at my google code project:&lt;br /&gt;&lt;a href="http://itzen.googlecode.com/files/SpringLiveConfig.zip"&gt;Source Code&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So we want to configure a field in a Spring managed bean to be available to be changed while the application is running.&lt;br /&gt;&lt;br /&gt;I have specified an annotation &lt;i&gt;@LiveConfig&lt;/i&gt;:&lt;br /&gt;&lt;pre class="brush: java;"&gt;package javaitzen.spring.liveconfig;&lt;br /&gt;&lt;br /&gt;import java.lang.annotation.Documented;&lt;br /&gt;import java.lang.annotation.ElementType;&lt;br /&gt;import java.lang.annotation.Retention;&lt;br /&gt;import java.lang.annotation.RetentionPolicy;&lt;br /&gt;import java.lang.annotation.Target;&lt;br /&gt;&lt;br /&gt;@Retention(RetentionPolicy.RUNTIME) &lt;br /&gt;@Target({ElementType.FIELD })&lt;br /&gt;@Documented&lt;br /&gt;public @interface LiveConfig {&lt;br /&gt;  String configLocation() default "liveconfig.properties";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To pick up all the @LiveConfig annotations, I created a BeanPostProcessor , that will be called when the ApplicationContext instantiates and keep track of all the @LiveConfig available to it.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;package javaitzen.spring.liveconfig;&lt;br /&gt;&lt;br /&gt;import java.lang.reflect.Field;&lt;br /&gt;import org.apache.commons.logging.Log;&lt;br /&gt;import org.apache.commons.logging.LogFactory;&lt;br /&gt;import org.springframework.beans.factory.annotation.Autowired;&lt;br /&gt;import org.springframework.beans.factory.config.BeanPostProcessor;&lt;br /&gt;import org.springframework.stereotype.Component;&lt;br /&gt;&lt;br /&gt;@Component&lt;br /&gt;public class LiveConfigBeanProcessor implements BeanPostProcessor {&lt;br /&gt;    private Log logger = LogFactory.getLog(this.getClass());&lt;br /&gt;&lt;br /&gt;    @Autowired&lt;br /&gt;    private ConfigLoader loader;&lt;br /&gt;    public final Object postProcessBeforeInitialization(final Object bean, final String beanName) {&lt;br /&gt;&lt;br /&gt;        Field[] fields = bean.getClass().getDeclaredFields();&lt;br /&gt;        for (Field field : fields) {&lt;br /&gt;            if (field.isAnnotationPresent(LiveConfig.class)) {&lt;br /&gt;&lt;br /&gt;                try {&lt;br /&gt;                    field.setAccessible(true);&lt;br /&gt;                    LiveConfig ann = field.getAnnotation(LiveConfig.class);&lt;br /&gt;                    LiveConfigData lcd = new LiveConfigData();&lt;br /&gt;                    lcd.setFile(ann.configLocation());&lt;br /&gt;                    lcd.setBean(bean);&lt;br /&gt;                    lcd.setField(field);&lt;br /&gt;                    loader.addConfig(field.getName(), lcd);&lt;br /&gt;                    loader.load();&lt;br /&gt;                } catch (Exception e) {&lt;br /&gt;                    logger.warn(e);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        return bean;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Object postProcessAfterInitialization(final Object bean, final String beanName) {&lt;br /&gt;        return bean;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So now when the ApplicationContext loads, it will add LiveConfigData to the ConfigLoader. This config loader uses the new Spring 3 Scheduling annotations to fire every 30 seconds asynchronously. &lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;package javaitzen.spring.liveconfig;&lt;br /&gt;&lt;br /&gt;import java.io.FileInputStream;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.util.HashMap;&lt;br /&gt;import java.util.Map;&lt;br /&gt;import java.util.Properties;&lt;br /&gt;import java.util.Map.Entry;&lt;br /&gt;&lt;br /&gt;import org.springframework.scheduling.annotation.Async;&lt;br /&gt;import org.springframework.scheduling.annotation.Scheduled;&lt;br /&gt;import org.springframework.stereotype.Component;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * The Class ConfigLoaderImpl.&lt;br /&gt; */&lt;br /&gt;@Component&lt;br /&gt;public class ConfigLoaderImpl implements ConfigLoader {&lt;br /&gt;&lt;br /&gt;    private Map&lt; String, LiveConfigData &gt; liveConfigs = new HashMap&lt; String, LiveConfigData &gt;();&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Instantiates a new config loader impl.&lt;br /&gt;     */&lt;br /&gt;    public ConfigLoaderImpl() {&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Adds the config.&lt;br /&gt;     * &lt;br /&gt;     * @param field&lt;br /&gt;     *            the field&lt;br /&gt;     * @param data&lt;br /&gt;     *            the data&lt;br /&gt;     */&lt;br /&gt;    public void addConfig(final String field, final LiveConfigData data) {&lt;br /&gt;        liveConfigs.put(field, data);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Load.&lt;br /&gt;     * &lt;br /&gt;     * @see javaitzen.spring.liveconfig.ConfigLoader#load()&lt;br /&gt;     */&lt;br /&gt;    @Override&lt;br /&gt;    @Scheduled(fixedDelay = 30000)&lt;br /&gt;    @Async&lt;br /&gt;    public void load() {&lt;br /&gt;&lt;br /&gt;        FileInputStream in = null;&lt;br /&gt;        try {&lt;br /&gt;            for (Entry&lt; String, LiveConfigData &gt; liveConfig : liveConfigs.entrySet()) {&lt;br /&gt;                LiveConfigData lcd = liveConfig.getValue();&lt;br /&gt;                Properties props = new Properties();&lt;br /&gt;                in = new FileInputStream(lcd.getFile());&lt;br /&gt;                props.load(in);&lt;br /&gt;                for (Entry&lt; Object, Object &gt; entry : props.entrySet()) {&lt;br /&gt;                    String key = (String) entry.getKey();&lt;br /&gt;                    String value = (String) entry.getValue();&lt;br /&gt;                    LiveConfigData data = liveConfigs.get(key);&lt;br /&gt;                    data.getField().set(data.getBean(), value);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        } catch (IllegalArgumentException e) {&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;        } catch (IllegalAccessException e) {&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;        } catch (final IOException e) {&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The Application Context, is surprisingly simple. The &lt;i&gt;context:component-scan&lt;/i&gt; picks up the classes annotated with @Component (ConfigLoaderImpl and the BeanPostProcessor). The &lt;i&gt;task:annotation-driven&lt;/i&gt; lets Spring know to look for @Scheduled. The loader is @Autowired into the BeanPostProcessor.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;br /&gt;&lt;beans xmlns="http://www.springframework.org/schema/beans"&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xmlns:context="http://www.springframework.org/schema/context"&lt;br /&gt; xmlns:task="http://www.springframework.org/schema/task"&lt;br /&gt; xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd&lt;br /&gt;  http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd&lt;br /&gt;  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt;&lt;br /&gt;&lt;br /&gt; &lt;context:component-scan base-package="javaitzen.spring.liveconfig" &gt;&lt;/context:component-scan&gt;&lt;br /&gt; &lt;task:annotation-driven&gt;&lt;/task:annotation-driven&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id="loader" class="javaitzen.spring.liveconfig.ConfigLoaderImpl" &gt;&lt;/bean&gt;&lt;br /&gt;&lt;/beans&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For demostration purposes I just created a simple little WorkManager structure to show how to configure the fields and have a running application to test when changing the configuration changes. It also shows how to get config from a file that is not the default "liveconfig.properties"&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;package javaitzen.spring.liveconfig.service;&lt;br /&gt;&lt;br /&gt;import java.util.Date;&lt;br /&gt;&lt;br /&gt;import javaitzen.spring.liveconfig.LiveConfig;&lt;br /&gt;&lt;br /&gt;import org.springframework.beans.factory.annotation.Autowired;&lt;br /&gt;import org.springframework.scheduling.annotation.Scheduled;&lt;br /&gt;import org.springframework.stereotype.Service;&lt;br /&gt;&lt;br /&gt;@Service&lt;br /&gt;public class TheWorkManager implements WorkManager {&lt;br /&gt;&lt;br /&gt;    @LiveConfig&lt;br /&gt;    private String filePickupURL;&lt;br /&gt;&lt;br /&gt;    @LiveConfig&lt;br /&gt;    private String enableDetail;&lt;br /&gt;&lt;br /&gt;    @LiveConfig(configLocation = "duplicate.properties")&lt;br /&gt;    private String allowDuplicates;&lt;br /&gt;&lt;br /&gt;    @Autowired&lt;br /&gt;    private Work worker;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * process.&lt;br /&gt;     * &lt;br /&gt;     * @see javaitzen.spring.liveconfig.service.WorkManager#process()&lt;br /&gt;     */&lt;br /&gt;    @Scheduled(fixedDelay = 10000)&lt;br /&gt;    public void process() {&lt;br /&gt;        System.out.println("processing: " + new Date());&lt;br /&gt;        for (int i = 0; i &lt; 3; i++) {&lt;br /&gt;            worker.doWork("" + i, filePickupURL, enableDetail, allowDuplicates);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&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/2976711854892236281-770306566456857126?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/770306566456857126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/06/spring-3-scheduling-components.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/770306566456857126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/770306566456857126'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/06/spring-3-scheduling-components.html' title='Spring 3: Scheduling, Components, PostBeanProcessors and bending the rules.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-5838836739773894830</id><published>2010-06-09T15:02:00.000+02:00</published><updated>2010-06-09T15:03:35.459+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Neater Item Removal</title><content type='html'>I stumbled apon a bit of code today, this removes items in a list and doesn't get a &lt;br /&gt;java.util.ConcurrentModificationException, but it is pretty ugly.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;List&lt; Item &gt; newItems = new LinkedList&lt; Item &gt;();&lt;br /&gt;&lt;br /&gt;        for (Item item : items) {&lt;br /&gt;            if (item.isAType() ) {&lt;br /&gt;                newItems.add(item);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        items = new LinkedList&lt; Item &gt;();&lt;br /&gt;        items.addAll(newItems);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As Part of reading that "5 Things you didn't know" series from IBM mentioned in a previous blog entry.&lt;br /&gt;&lt;br /&gt;A much neater way is using the remove() method on an Iterator:&lt;br /&gt;&lt;pre class="brush: java;"&gt;for (Iterator&lt; Item &gt; itemsIter = items.iterator(); itemsIter.hasNext();) {&lt;br /&gt;     if (itemsIter.next().isAType()) {&lt;br /&gt;  itemsIter.remove();&lt;br /&gt;     }&lt;br /&gt; }&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/2976711854892236281-5838836739773894830?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/5838836739773894830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/06/neater-item-removal.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5838836739773894830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5838836739773894830'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/06/neater-item-removal.html' title='Neater Item Removal'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-5219128433336435585</id><published>2010-06-07T18:17:00.000+02:00</published><updated>2010-06-26T20:26:38.424+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ehcache'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Spring, AspectJ, Ehcache Method Caching Aspect</title><content type='html'>I know this is not a new concept, and I am pretty sure there a couple implementations of method caching out there, possibly some much more thorough, but I feel quite strongly about it and I think that it is still one of the most beneficial things ever to come out of the AOP design philosophy. It is also something that if implemented correctly can vastly improve the performance for a lot of systems out there.&lt;br /&gt;&lt;br /&gt;A good couple years back, I stumbled across a blog post describing the concept of a method caching interceptor, that would allow you to cache method calls without changing code and thereby make some dramatic performance improvements on existing systems. I jumped on the concept, took some code from the blog, fixed an issue or 2, changed a couple things to my requirements, demo'ed it to the system architect at the time and implemented it for the next release cycle. That bit of code has been running for about 4 years now and had a huge impact on our performance and the pressures our legacy system placed on other internal teams.&lt;br /&gt;&lt;br /&gt;Due to the joys that are large corporate organisations, the use of the latest version of Spring and especially AspectJ are not allowed by the standards and redtape, but that allows me to write a whole new neat version without infringing on too many IP issues :) and publish it here.&lt;br /&gt;&lt;br /&gt;Full source code, maven pom and eclipse files are available for download:&lt;br /&gt;&lt;a href="http://itzen.googlecode.com/files/MethodCacheAspect.zip"&gt;Source Code&lt;/a&gt;&lt;br /&gt;or through SVN:&lt;br /&gt;&lt;a href="http://code.google.com/p/itzen/source/browse/#svn/trunk/MethodCacheAspect"&gt; MethodCacheAspect trunk&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In the project there are 3 main java files of interest:&lt;br /&gt;MethodCacheAspect.java&lt;br /&gt;CacheKeyStrategy.java&lt;br /&gt;DefaultCacheKeyStrategy.java&lt;br /&gt;&lt;br /&gt;The CacheKeyStrategy interface came about when I noticed that even though objects were "equal" there were 2 separate items in ehcache. This was because of 2 issues actually, order of items and just using .toString() to build up a key for ehcache. Not wanting to enforce the order or method of generating a key, I created a the interface and a default implementation. If future users want to handle it any different all they need to do is implement it and specify the implementation in Spring. I have 2 custom implementations in my live project, but for this blog posting I have just created a simple default.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;note:&lt;/b&gt;I removed all JavaDoc just to save space, the downloadable code has docs.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;package javaitzen.spring.interceptors;&lt;br /&gt;&lt;br /&gt;public interface CacheKeyStrategy {&lt;br /&gt;&lt;br /&gt;    String generateKey() throws IllegalStateException;&lt;br /&gt;&lt;br /&gt;    String classForStrategy();&lt;br /&gt;&lt;br /&gt;    void setObject(final Object object);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Below is the simple default key generator, just for convenience, that does a Collections.sort and uses the objects' hashcode method.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;package javaitzen.spring.interceptors;&lt;br /&gt;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;import java.util.Collection;&lt;br /&gt;import java.util.Collections;&lt;br /&gt;import java.util.Comparator;&lt;br /&gt;import java.util.List;&lt;br /&gt;import java.util.Map;&lt;br /&gt;import java.util.Map.Entry;&lt;br /&gt;import java.util.logging.Level;&lt;br /&gt;import java.util.logging.Logger;&lt;br /&gt;&lt;br /&gt;import org.aspectj.lang.ProceedingJoinPoint;&lt;br /&gt;&lt;br /&gt;public class DefaultCacheKeyStrategy implements CacheKeyStrategy {&lt;br /&gt;&lt;br /&gt;    private Logger logger = Logger.getLogger(DefaultCacheKeyStrategy.class.getName());&lt;br /&gt;    private ProceedingJoinPoint pjp;&lt;br /&gt;&lt;br /&gt;    public DefaultCacheKeyStrategy() {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public DefaultCacheKeyStrategy(final ProceedingJoinPoint pjp) {&lt;br /&gt;        this.pjp = pjp;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String generateKey() throws IllegalStateException {&lt;br /&gt;&lt;br /&gt;        String targetName = pjp.getSignature().getDeclaringTypeName();&lt;br /&gt;        String methodName = pjp.getSignature().getName();&lt;br /&gt;        Object[] arguments = pjp.getArgs();&lt;br /&gt;&lt;br /&gt;        return getCacheKey(targetName, methodName, arguments);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private String getCacheKey(final String targetName, final String methodName, final Object[] arguments) {&lt;br /&gt;        StringBuilder sb = new StringBuilder();&lt;br /&gt;        sb.append(targetName).append(".").append(methodName);&lt;br /&gt;&lt;br /&gt;        for (Object arg : arguments) {&lt;br /&gt;            if (arg instanceof Map&lt; ?, ? &gt;) {&lt;br /&gt;                sb.append(expandMap((Map&lt;?, ?&gt;) arg));&lt;br /&gt;            } else if (arg instanceof Collection&lt; ? &gt;) {&lt;br /&gt;                sb.append(buildBuffer((Collection&lt; ? &gt;) arg));&lt;br /&gt;            } else {&lt;br /&gt;                sb.append(".").append(arg.hashCode());&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        logger.log(Level.INFO, "Cache key is: [" + sb.toString() + "]");&lt;br /&gt;        return sb.toString();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private StringBuilder buildBuffer(final Collection&lt; ? &gt; values) {&lt;br /&gt;        StringBuilder bob = new StringBuilder();&lt;br /&gt;        Collections.sort((List&lt; ? &gt;) values, new Comparator&lt; Object &gt;() {&lt;br /&gt;            public int compare(final Object arg0, final Object arg1) {&lt;br /&gt;                String thing1 = arg0.toString();&lt;br /&gt;                String thing2 = arg1.toString();&lt;br /&gt;                return thing1.compareTo(thing2);&lt;br /&gt;            }&lt;br /&gt;        });&lt;br /&gt;        for(Object o : values){&lt;br /&gt;            if (o != null) {&lt;br /&gt;                bob.append(".").append(o.hashCode());&lt;br /&gt;            }            &lt;br /&gt;        }&lt;br /&gt;        return bob;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private StringBuilder expandMap(final Map&lt; ?, ? &gt; args) {&lt;br /&gt;        if (args == null) {&lt;br /&gt;            return new StringBuilder();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        List&lt; Object &gt; values = new ArrayList&lt; Object &gt;();&lt;br /&gt;        for (Entry&lt; ?, ? &gt; entry : args.entrySet()) {&lt;br /&gt;            values.add(entry.hashCode());&lt;br /&gt;        }&lt;br /&gt;        return buildBuffer(values);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   public void setObject(final Object invocation) {&lt;br /&gt;        this.pjp = (ProceedingJoinPoint) invocation;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String classForStrategy() {&lt;br /&gt;        return "*";&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now for the juicy bit, the aspect checks if there are any cache key strategies compares types with information from the ProceedingJoinPoint, it extracts the relevant information and generates a key. It then checks if there is value for that key in the cache and returns that value if relevant, else it executes the method with "pjp.proceed()" and caches the result, so that for the next time the same method is called with the same parameters it can just be returned from the cache. I cant remember the exact numbers but with implementing this between our legacy system and another team we cut our daily calls to that teams web service from something like 65000 to around 6000.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;package javaitzen.spring.interceptors;&lt;br /&gt;&lt;br /&gt;import java.io.Serializable;&lt;br /&gt;import java.util.LinkedList;&lt;br /&gt;import java.util.List;&lt;br /&gt;import java.util.logging.Level;&lt;br /&gt;import java.util.logging.Logger;&lt;br /&gt;&lt;br /&gt;import net.sf.ehcache.Cache;&lt;br /&gt;import net.sf.ehcache.Element;&lt;br /&gt;&lt;br /&gt;import org.aspectj.lang.ProceedingJoinPoint;&lt;br /&gt;import org.aspectj.lang.annotation.Aspect;&lt;br /&gt;&lt;br /&gt;@Aspect&lt;br /&gt;public class MethodCacheAspect {&lt;br /&gt;&lt;br /&gt;    private Logger logger = Logger.getLogger(MethodCacheAspect.class.getName());&lt;br /&gt;    private Cache cache;&lt;br /&gt;    private CacheKeyStrategy defaultKeyStrat;&lt;br /&gt;    private List&lt; CacheKeyStrategy &gt; keyStrategies = new LinkedList&lt; CacheKeyStrategy &gt;();&lt;br /&gt;&lt;br /&gt;    public void setCacheKeyStrategies(final List&lt; CacheKeyStrategy &gt; cacheKeys) {&lt;br /&gt;        this.keyStrategies = cacheKeys;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void addCacheKeyStrategy(final CacheKeyStrategy cacheKey) {&lt;br /&gt;        this.keyStrategies.add(cacheKey);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Object aroundAdvice(final ProceedingJoinPoint pjp) throws Throwable {&lt;br /&gt;&lt;br /&gt;        Object[] arguments = pjp.getArgs();&lt;br /&gt;        Object result;&lt;br /&gt;        StringBuilder cacheKey = new StringBuilder();&lt;br /&gt;        defaultKeyStrat = new DefaultCacheKeyStrategy(pjp);&lt;br /&gt;&lt;br /&gt;         if (!keyStrategies.isEmpty()) {&lt;br /&gt;            logger.log(Level.INFO, "Have a Key Strategy to use...");&lt;br /&gt;            for (CacheKeyStrategy strat : keyStrategies) {&lt;br /&gt;                if ((arguments != null) &amp;&amp; (arguments.length != 0)) {&lt;br /&gt;                    logger.log(Level.INFO, "Have Arguments...");&lt;br /&gt;                    for (Object arg : arguments) {&lt;br /&gt;                        if (Class.forName(strat.classForStrategy()).isInstance(arg)) {&lt;br /&gt;                            strat.setObject(arg);&lt;br /&gt;                            logger.log(Level.INFO, "Using Strategy...");&lt;br /&gt;                            cacheKey.append(strat.generateKey());&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        if (cacheKey.length() == 0) {&lt;br /&gt;            logger.log(Level.INFO, "Using Default...");&lt;br /&gt;            cacheKey.append(defaultKeyStrat.generateKey());&lt;br /&gt;        }&lt;br /&gt;        Element element = cache.get(cacheKey.toString());&lt;br /&gt;&lt;br /&gt;        // not in cache&lt;br /&gt;        if (element == null) {&lt;br /&gt;            result = pjp.proceed();&lt;br /&gt;            if (result != null &amp;&amp; !(result instanceof Serializable)) {&lt;br /&gt;                throw new RuntimeException("[" + result.getClass().getName() + "] is not Serializable");&lt;br /&gt;            }&lt;br /&gt;            logger.log(Level.INFO, "&gt;&gt;&gt; caching result - " + cacheKey);&lt;br /&gt;            element = new Element(cacheKey.toString(), (Serializable) result);&lt;br /&gt;            cache.put(element);&lt;br /&gt;        } else {&lt;br /&gt;            logger.log(Level.INFO, "&gt;&gt;&gt; returning result from cache");&lt;br /&gt;            return element.getValue();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return result;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Cache getCache() {&lt;br /&gt;        return cache;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setCache(final Cache cache) {&lt;br /&gt;        this.cache = cache;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In the application context below you will notice &lt;b&gt;execution(* theBusinessMethod(..))&lt;/b&gt;. That only attaches the aspect for theBusinessMethod, in my test class in the downloadable source.&lt;br /&gt;&lt;br /&gt;Just for quick reference here are a couple more examples from the Spring docs:&lt;br /&gt;The execution of any public method:&lt;br /&gt;&lt;b&gt;execution(public * *(..))&lt;/b&gt;&lt;br /&gt;The execution of any method with a name beginning with "set":&lt;br /&gt;&lt;b&gt;execution(* set*(..))&lt;/b&gt;&lt;br /&gt;The execution of any method defined by the AccountService interface:&lt;br /&gt;&lt;b&gt;execution(* com.xyz.service.AccountService.*(..))&lt;/b&gt;&lt;br /&gt;The execution of any method defined in the service package:&lt;br /&gt;&lt;b&gt;execution(* com.xyz.service.*.*(..))&lt;/b&gt;&lt;br /&gt;The execution of any method defined in the service package or a sub-package:&lt;br /&gt;&lt;b&gt;execution(* com.xyz.service..*.*(..))&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Application Context:&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;br /&gt;&lt;beans xmlns="http://www.springframework.org/schema/beans"&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"&lt;br /&gt; xsi:schemaLocation="http://www.springframework.org/schema/beans&lt;br /&gt;http://www.springframework.org/schema/beans/spring-beans-3.0.xsd&lt;br /&gt;http://www.springframework.org/schema/aop&lt;br /&gt;http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"&gt;&lt;br /&gt;&lt;br /&gt; &lt;bean id="testObject" class="javaitzen.spring.interceptors.MyLittleTestObject"&gt;&lt;/bean&gt;&lt;br /&gt;&lt;br /&gt; &lt;bean id="methodCacheAspect" class="javaitzen.spring.interceptors.MethodCacheAspect"&gt;&lt;br /&gt;  &lt;property name="cache"&gt;&lt;br /&gt;   &lt;ref local="methodCache"&gt;&lt;/ref&gt;&lt;br /&gt;  &lt;/property&gt;&lt;br /&gt; &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt; &lt;aop:config proxy-target-class="true"&gt;&lt;br /&gt;  &lt;aop:aspect ref="methodCacheAspect"&gt;&lt;br /&gt;   &lt;aop:pointcut id="around" expression="execution(* theBusinessMethod(..))"&gt;&lt;/aop:pointcut&gt;&lt;br /&gt;   &lt;aop:around pointcut-ref="around" method="aroundAdvice"&gt;&lt;/aop:around&gt;&lt;br /&gt;  &lt;/aop:aspect&gt;&lt;br /&gt; &lt;/aop:config&gt;&lt;br /&gt;&lt;br /&gt; &lt;!-- Cache Manager --&gt;&lt;br /&gt; &lt;bean id="cacheManager"&lt;br /&gt;  class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"&gt;&lt;br /&gt;  &lt;property name="configLocation"&gt;&lt;br /&gt;   &lt;value&gt;classpath:javaitzen/spring/interceptors/ehcache.xml&lt;br /&gt;   &lt;/value&gt;&lt;br /&gt;  &lt;/property&gt;&lt;br /&gt;  &lt;property name="shared" value="true" &gt;&lt;/property&gt;&lt;br /&gt; &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt; &lt;!-- Cache Provider --&gt;&lt;br /&gt; &lt;bean id="methodCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"&gt;&lt;br /&gt;  &lt;property name="cacheManager"&gt;&lt;br /&gt;   &lt;ref local="cacheManager"&gt;&lt;/ref&gt;&lt;br /&gt;  &lt;/property&gt;&lt;br /&gt;  &lt;property name="cacheName"&gt;&lt;br /&gt;   &lt;value&gt;testCache&lt;/value&gt;&lt;br /&gt;  &lt;/property&gt;&lt;br /&gt; &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/beans&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And finally the ehcache.xml:&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;ehcache&gt;&lt;br /&gt; &lt;diskstore path="java.io.tmpdir"&gt;&lt;/diskStore&gt;&lt;br /&gt; &lt;defaultcache maxElementsInMemory="10000" eternal="false"&lt;br /&gt;  timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"&lt;br /&gt;  diskPersistent="false" diskExpiryThreadIntervalSeconds="120"&gt;&lt;/defaultCache&gt;&lt;br /&gt;&lt;br /&gt; &lt;cache name="testCache" maxElementsInMemory="100" eternal="false"&lt;br /&gt;  overflowToDisk="true" timeToIdleSeconds="300" timeToLiveSeconds="600"&gt;&lt;/cache&gt;&lt;br /&gt;&lt;/ehcache&gt;&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/2976711854892236281-5219128433336435585?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/5219128433336435585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/06/spring-aspectj-ehcache-method-caching.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5219128433336435585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/5219128433336435585'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/06/spring-aspectj-ehcache-method-caching.html' title='Spring, AspectJ, Ehcache Method Caching Aspect'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-3756854435939758490</id><published>2010-06-04T07:38:00.000+02:00</published><updated>2010-06-04T16:41:13.589+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Personal'/><title type='text'>Google, just doing it a little better than everyone else.</title><content type='html'>I log onto my gmail this morning...&lt;br /&gt;&lt;br /&gt;Get this nice red warning on top saying there is unusual activity on my account ... I open it..&lt;br /&gt;&lt;br /&gt;&lt;a target='_blank' title='yay google'&gt;&lt;img src='http://img84.imageshack.us/img84/4591/yaygoogle.png' border='0'/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;panic&gt;&lt;/blockquote&gt;&lt;b&gt;Arrghhh!!!&lt;/b&gt;... &lt;br /&gt;So... signout the other sessions... think of new ultra secure password... change World or Warcraft password... change Google account password... &lt;br /&gt;&lt;blockquote&gt;&lt;/panic&gt;&lt;/blockquote&gt;&lt;br /&gt;Praise Google.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-3756854435939758490?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/3756854435939758490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/06/google-just-doing-it-little-better-than.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3756854435939758490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/3756854435939758490'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/06/google-just-doing-it-little-better-than.html' title='Google, just doing it a little better than everyone else.'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-7877105485273185555</id><published>2010-06-03T09:00:00.000+02:00</published><updated>2010-06-03T09:02:23.975+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>java.sql.Connection JDK 1.5 and 1.6 Compatibility Issue</title><content type='html'>A certain former work colleague of mine found this just before skipping the country to work for some evil IT empire... not to mention any names... but it starts with an "O" and ends with a "racle".&lt;br /&gt;&lt;br /&gt;Today I opened the project again and there is a little Red X in my IDE which gives me a strange tick and psychotic tendencies.&lt;br /&gt;&lt;br /&gt;java.sql.Connection was implemented into a verbose connection to get more information for unit tests.&lt;br /&gt;&lt;br /&gt;Problem is he was running 1.6 jdk ... (our environment is still on 1.5) our hudson build machine is running 1.6, building as 1.5, our maven pom is set to 1.5, and most the developers are using 1.5...&lt;br /&gt;&lt;br /&gt;If you have 1.6 the compiler complains about:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;The type VerboseConnection must implement the inherited abstract method Connection.createArrayOf(String, Object[]) &lt;br /&gt;The type VerboseConnection must implement the inherited abstract method Connection.createBlob() &lt;br /&gt;The type VerboseConnection must implement the inherited abstract method Connection.createClob() &lt;br /&gt;The type VerboseConnection must implement the inherited abstract method Connection.createNClob() &lt;br /&gt;The type VerboseConnection must implement the inherited abstract method Connection.createSQLXML() &lt;br /&gt;The type VerboseConnection must implement the inherited abstract method Connection.createStruct(String, Object[]) &lt;br /&gt;The type VerboseConnection must implement the inherited abstract method Connection.getClientInfo() &lt;br /&gt;The type VerboseConnection must implement the inherited abstract method Connection.getClientInfo(String) &lt;br /&gt;The type VerboseConnection must implement the inherited abstract method Connection.isValid(int) &lt;br /&gt;The type VerboseConnection must implement the inherited abstract method Connection.setClientInfo(Properties) &lt;br /&gt;The type VerboseConnection must implement the inherited abstract method Connection.setClientInfo(String, String) &lt;br /&gt;The type VerboseConnection must implement the inherited abstract method Wrapper.isWrapperFor(Class&lt;?&gt;) &lt;br /&gt;The type VerboseConnection must implement the inherited abstract method Wrapper.unwrap(Class&lt;t&gt;) &lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;So you implement the above methods and there are no little red X's and all is good in the world... Then someone then opens it up in 1.5:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;NClob cannot be resolved to a type &lt;br /&gt;SQLClientInfoException cannot be resolved to a type &lt;br /&gt;SQLClientInfoException cannot be resolved to a type &lt;br /&gt;SQLXML cannot be resolved to a type&lt;br /&gt;The import java.sql.NClob cannot be resolved &lt;br /&gt;The import java.sql.SQLClientInfoException cannot be resolved &lt;br /&gt;The import java.sql.SQLXML cannot be resolved &lt;br /&gt;&lt;/b&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976711854892236281-7877105485273185555?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/7877105485273185555/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/06/javasqlconnection-jdk-15-and-16.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/7877105485273185555'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/7877105485273185555'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/06/javasqlconnection-jdk-15-and-16.html' title='java.sql.Connection JDK 1.5 and 1.6 Compatibility Issue'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-6712711168477174720</id><published>2010-06-02T17:05:00.000+02:00</published><updated>2010-06-09T15:08:16.925+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Ahhh convenience...</title><content type='html'>Ok this may seem a bit mundane, but I have used Spring for a couple years now.. and only today by the chance discovered:&lt;br /&gt;&lt;i&gt;and thanks to MyEclipse 8.5 / Maven integration that automatically downloads Java docs and source code on Ctrl + click.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;and yes it has been there since 2.0 ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"This is a convenience method to load class path resources relative to a&lt;br /&gt;given Class." - Spring Java Docs&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;public ClassPathXmlApplicationContext(String path, Class clazz) throws BeansException {&lt;br /&gt;  this(new String[] {path}, clazz);&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I can't say how many times I have typed out something like:&lt;br /&gt;&lt;pre class="brush: java;"&gt;new ClassPathXmlApplicationContext("com/some/really/long/config/package/config.xml");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;but that now just becomes:&lt;br /&gt;&lt;pre class="brush: java;"&gt;new ClassPathXmlApplicationContext("config.xml", TheClassIamIn.class);&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/2976711854892236281-6712711168477174720?l=www.briandupreez.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.briandupreez.net/feeds/6712711168477174720/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.briandupreez.net/2010/06/ahhh-convenience.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6712711168477174720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2976711854892236281/posts/default/6712711168477174720'/><link rel='alternate' type='text/html' href='http://www.briandupreez.net/2010/06/ahhh-convenience.html' title='Ahhh convenience...'/><author><name>Brian Du Preez</name><uri>https://profiles.google.com/108920578220396628736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-h1jMH98w3EM/AAAAAAAAAAI/AAAAAAAAAUA/EXyVoKQCA4E/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2976711854892236281.post-2729480882577771305</id><published>2010-05-31T21:12:00.000+02:00</published><updated>2010-07-11T09:03:50.987+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='JUnit'/><title type='text'>Spring 3: OXM... Castor, JAXB, JibX and xmlBeans (And XStream)</title><content type='html'>&lt;i&gt;&lt;b&gt;Updated to include XStream&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Another reason to love Spring... OXM...&lt;br /&gt;&lt;br /&gt;Basically there are 5 common Object to XML mapping projects out there... Castor, JaxB, XStream ,JibX and xmlBeans. Since I am lazy an a fan of reuse I won't be going into JibX as this other blogger (Guido Schumtz) did it quite nicely:&lt;br /&gt;&lt;a href="http://guidoschmutz.wordpress.com/2010/01/06/testing-the-new-objectxml-mapping-support-of-spring-3-0-with-jibx-and-maven/"&gt;JibX Maven Spring OXM&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I won't describe xmlBeans either, 'cause as soon as I saw that the objects need to extend XmlObject I lost interest... I don't wanna have to change my class hierarchy just to do mappings, that is so very 90's.&lt;br /&gt;&lt;br /&gt;I did however slap together a quick Castor, JaxB and XStream example:&lt;br /&gt;You need a bean that you want to map in and out of xml in this case (ClassToXMLMap.java)&lt;br /&gt;&lt;pre class="brush: java;"&gt;package javaitzen.spring.oxm;&lt;br /&gt;&lt;br /&gt;import javax.xml.bind.annotation.XmlRootElement;&lt;br /&gt;import com.thoughtworks.xstream.annotations.XStreamAlias;&lt;br /&gt;&lt;br /&gt;@XmlRootElement(name="ClassToXMLMap")&lt;br /&gt;@XStreamAlias( "ClassToXMLMap" )&lt;br /&gt;public class ClassToXMLMap {&lt;br /&gt; private String data;&lt;br /&gt; private String history;&lt;br /&gt; &lt;br /&gt; public String getData() {&lt;br /&gt;  return data;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void setData(String data) {&lt;br /&gt;  this.data = data;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public String getHistory() {&lt;br /&gt;  return history;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void setHistory(String history) {&lt;br /&gt;  this.history = history;&lt;br /&gt; } &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then a class to use the Spring marshallers:&lt;br /&gt;&lt;pre class="brush: java;"&gt;package javaitzen.spring.oxm;&lt;br /&gt;&lt;br /&gt;import java.io.FileInputStream;&lt;br /&gt;import java.io.FileOutputStream;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;&lt;br /&gt;import javax.xml.transform.stream.StreamResult;&lt;br /&gt;import javax.xml.transform.stream.StreamSource;&lt;br /&gt;&lt;br /&gt;import org.springframework.oxm.Marshaller;&lt;br /&gt;import org.springframework.oxm.Unmarshaller;&lt;br /&gt;&lt;br /&gt;public class OXMarshall {&lt;br /&gt;    &lt;br /&gt;    private Marshaller marshaller;&lt;br /&gt;    private Unmarshaller unmarshaller;&lt;br /&gt;&lt;br /&gt;    public void setMarshaller(Marshaller marshaller) {&lt;br /&gt;        this.marshaller = marshaller;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setUnmarshaller(Unmarshaller unmarshaller) {&lt;br /&gt;        this.unmarshaller = unmarshaller;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void saveXML(ClassToXMLMap message, String fileName) throws IOException {&lt;br /&gt;        FileOutputStream fos = null;&lt;br /&gt;        try {&lt;br /&gt;            fos = new FileOutputStream(fileName);&lt;br /&gt;            this.marshaller.marshal(message, new StreamResult(fos));&lt;br /&gt;        } finally {&lt;br /&gt;            if (fos != null) {&lt;br /&gt;                fos.close();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public ClassToXMLMap loadXML(String fileName) throws IOException {&lt;br /&gt;        FileInputStream fis = null;&lt;br /&gt;        try {&lt;br /&gt;            fis = new FileInputStream(fileName);&lt;br /&gt;            return (ClassToXMLMap) this.unmarshaller.unmarshal(new StreamSource(fis));&lt;br /&gt;        } finally {&lt;br /&gt;            if (fis != null) {&lt;br /&gt;                fis.close();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }    &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The JUnit Test:&lt;br /&gt;&lt;pre class="brush: java;"&gt;package javaitzen.spring.oxm;&lt;br /&gt;&lt;br /&gt;import static org.junit.Assert.assertNotNull;&lt;br /&gt;&lt;br /&gt;import org.junit.Before;&lt;br /&gt;import org.junit.Test;&lt;br /&gt;import org.junit.runner.RunWith;&lt;br /&gt;import org.springframework.beans.factory.annotation.Autowired;&lt;br /&gt;import org.springframework.test.context.ContextConfiguration;&lt;br /&gt;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;&lt;br /&gt;&lt;br /&gt;@ContextConfiguration(locations={"/javaitzen/spring/oxm/applicationContext.xml"})&lt;br /&gt;@RunWith(SpringJUnit4ClassRunner.class)&lt;br /&gt;public class OXMTest {&lt;br /&gt;&lt;br /&gt; @Autowired&lt;br /&gt; OXMarshall castor;&lt;br /&gt; &lt;br /&gt; @Autowired&lt;br /&gt; OXMarshall jax;&lt;br /&gt;&lt;br /&gt; @Autowired&lt;br /&gt; OXMarshall xtream;&lt;br /&gt; &lt;br /&gt; ClassToXMLMap message;&lt;br /&gt; &lt;br /&gt; @Before&lt;br /&gt; public void setup(){&lt;br /&gt;     message = new ClassToXMLMap();&lt;br /&gt;     message.setData("I am data");&lt;br /&gt;     message.setHistory("in the past");&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; @Test&lt;br /&gt; public void testCastor() throws Exception{&lt;br /&gt;  String castorFile = "castor.xml";&lt;br /&gt;  castor.saveXML(message, castorFile);&lt;br /&gt;        assertNotNull(castor.loadXML(castorFile));&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; @Test&lt;br /&gt; public void testJaxB() throws Excepti
