You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by ni...@apache.org on 2015/07/31 04:59:11 UTC

[31/81] [abbrv] [partial] zest-java git commit: First round of changes to move to org.apache.zest namespace.

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/activation/ActivationEventsTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/activation/ActivationEventsTest.java b/core/api/src/test/java/org/apache/zest/api/activation/ActivationEventsTest.java
new file mode 100644
index 0000000..f4861ad
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/activation/ActivationEventsTest.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2011, Rickard Öberg.
+ * Copyright (c) 2012, Niclas Hedhman.
+ * Copyright (c) 2012, Paul Merlin.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.zest.api.activation;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.junit.Test;
+import org.apache.zest.api.activation.ActivationEvent.EventType;
+import org.apache.zest.api.mixin.Mixins;
+import org.apache.zest.api.service.ServiceComposite;
+import org.apache.zest.api.structure.Application;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.bootstrap.AssemblyException;
+import org.apache.zest.bootstrap.ModuleAssembly;
+import org.apache.zest.bootstrap.SingletonAssembler;
+
+import static org.junit.Assert.*;
+import static org.apache.zest.api.activation.ActivationEvent.EventType.*;
+
+public class ActivationEventsTest
+{
+
+    public static interface TestService
+    {
+        void test();
+    }
+
+    public static class TestServiceInstance
+            implements TestService
+    {
+
+        @Override
+        public void test()
+        {
+        }
+
+    }
+
+    @Mixins( TestServiceInstance.class )
+    public static interface TestServiceComposite
+        extends TestService, ServiceComposite
+    {
+    }
+
+    @Test
+    public void testSingleModuleSingleService()
+        throws Exception
+    {
+        final List<ActivationEvent> events = new ArrayList<>();
+
+        new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( TestServiceComposite.class ).instantiateOnStartup();
+            }
+
+            @Override
+            protected void beforeActivation( Application application )
+            {
+                application.registerActivationEventListener( new EventsRecorder( events ) );
+            }
+
+
+        }.application().passivate();
+
+        Iterator<ActivationEvent> it = events.iterator();
+
+        // Activation
+        assertEvent( it.next(), ACTIVATING, "Application" );
+        assertEvent( it.next(), ACTIVATING, "Layer" );
+        assertEvent( it.next(), ACTIVATING, "Module" );
+        assertEvent( it.next(), ACTIVATING, "TestService" );
+        assertEvent( it.next(), ACTIVATED, "TestService" );
+        assertEvent( it.next(), ACTIVATED, "Module" );
+        assertEvent( it.next(), ACTIVATED, "Layer" );
+        assertEvent( it.next(), ACTIVATED, "Application" );
+
+        // Passivation
+        assertEvent( it.next(), PASSIVATING, "Application" );
+        assertEvent( it.next(), PASSIVATING, "Layer" );
+        assertEvent( it.next(), PASSIVATING, "Module" );
+        assertEvent( it.next(), PASSIVATING, "TestService" );
+        assertEvent( it.next(), PASSIVATED, "TestService" );
+        assertEvent( it.next(), PASSIVATED, "Module" );
+        assertEvent( it.next(), PASSIVATED, "Layer" );
+        assertEvent( it.next(), PASSIVATED, "Application" );
+
+        assertFalse( it.hasNext() );
+    }
+
+    @Test
+    public void testSingleModuleSingleImportedService()
+            throws Exception
+    {
+        final List<ActivationEvent> events = new ArrayList<>();
+
+        new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.importedServices( TestService.class ).
+                        setMetaInfo( new TestServiceInstance() ).
+                        importOnStartup();
+            }
+
+            @Override
+            protected void beforeActivation( Application application )
+            {
+                application.registerActivationEventListener( new EventsRecorder( events ) );
+            }
+
+
+        }.application().passivate();
+
+        Iterator<ActivationEvent> it = events.iterator();
+
+        // Activation
+        assertEvent( it.next(), ACTIVATING, "Application" );
+        assertEvent( it.next(), ACTIVATING, "Layer" );
+        assertEvent( it.next(), ACTIVATING, "Module" );
+        assertEvent( it.next(), ACTIVATING, "TestService" );
+        assertEvent( it.next(), ACTIVATED, "TestService" );
+        assertEvent( it.next(), ACTIVATED, "Module" );
+        assertEvent( it.next(), ACTIVATED, "Layer" );
+        assertEvent( it.next(), ACTIVATED, "Application" );
+
+        // Passivation
+        assertEvent( it.next(), PASSIVATING, "Application" );
+        assertEvent( it.next(), PASSIVATING, "Layer" );
+        assertEvent( it.next(), PASSIVATING, "Module" );
+        assertEvent( it.next(), PASSIVATING, "TestService" );
+        assertEvent( it.next(), PASSIVATED, "TestService" );
+        assertEvent( it.next(), PASSIVATED, "Module" );
+        assertEvent( it.next(), PASSIVATED, "Layer" );
+        assertEvent( it.next(), PASSIVATED, "Application" );
+
+        assertFalse( it.hasNext() );
+    }
+
+    @Test
+    public void testSingleModuleSingleLazyService()
+            throws Exception
+    {
+        final List<ActivationEvent> events = new ArrayList<>();
+
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.services( TestServiceComposite.class );
+            }
+
+            @Override
+            protected void beforeActivation( Application application )
+            {
+                application.registerActivationEventListener( new EventsRecorder( events ) );
+            }
+
+        };
+        Application application = assembler.application();
+        application.passivate();
+
+        Iterator<ActivationEvent> it = events.iterator();
+
+        // Activation
+        assertEvent( it.next(), ACTIVATING, "Application" );
+        assertEvent( it.next(), ACTIVATING, "Layer" );
+        assertEvent( it.next(), ACTIVATING, "Module" );
+        // Lazy Service NOT activated
+        assertEvent( it.next(), ACTIVATED, "Module" );
+        assertEvent( it.next(), ACTIVATED, "Layer" );
+        assertEvent( it.next(), ACTIVATED, "Application" );
+
+        // Passivation
+        assertEvent( it.next(), PASSIVATING, "Application" );
+        assertEvent( it.next(), PASSIVATING, "Layer" );
+        assertEvent( it.next(), PASSIVATING, "Module" );
+        // Lazy Service NOT passivated
+        assertEvent( it.next(), PASSIVATED, "Module" );
+        assertEvent( it.next(), PASSIVATED, "Layer" );
+        assertEvent( it.next(), PASSIVATED, "Application" );
+
+        assertFalse( it.hasNext() );
+
+        events.clear();
+        application.activate();
+        Module module = assembler.module();
+        module.findService( TestService.class ).get().test();
+        application.passivate();
+
+        for( ActivationEvent event : events ) {
+            System.out.println( event );
+        }
+
+        it = events.iterator();
+
+        // Activation
+        assertEvent( it.next(), ACTIVATING, "Application" );
+        assertEvent( it.next(), ACTIVATING, "Layer" );
+        assertEvent( it.next(), ACTIVATING, "Module" );
+        assertEvent( it.next(), ACTIVATED, "Module" );
+        assertEvent( it.next(), ACTIVATED, "Layer" );
+        assertEvent( it.next(), ACTIVATED, "Application" );
+
+        // Lazy Service Activation
+        assertEvent( it.next(), ACTIVATING, "TestService" );
+        assertEvent( it.next(), ACTIVATED, "TestService" );
+
+        // Passivation
+        assertEvent( it.next(), PASSIVATING, "Application" );
+        assertEvent( it.next(), PASSIVATING, "Layer" );
+        assertEvent( it.next(), PASSIVATING, "Module" );
+        assertEvent( it.next(), PASSIVATING, "TestService" );
+        assertEvent( it.next(), PASSIVATED, "TestService" );
+        assertEvent( it.next(), PASSIVATED, "Module" );
+        assertEvent( it.next(), PASSIVATED, "Layer" );
+        assertEvent( it.next(), PASSIVATED, "Application" );
+
+        assertFalse( it.hasNext() );
+    }
+
+    private static class EventsRecorder
+            implements ActivationEventListener
+    {
+
+        private final List<ActivationEvent> events;
+
+        private EventsRecorder( List<ActivationEvent> events )
+        {
+            this.events = events;
+        }
+
+        @Override
+        public void onEvent( ActivationEvent event )
+        {
+            events.add( event );
+        }
+
+    }
+
+    // WARN This assertion depends on ApplicationInstance, LayerInstance, ModuleInstance and ServiceReferenceInstance toString() method.
+    private static void assertEvent( ActivationEvent event, EventType expectedType, String expected )
+    {
+        boolean wrongEvent = expectedType != event.type();
+        boolean wrongMessage = ! event.message().contains( expected );
+        if( wrongEvent || wrongMessage )
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.append("Event (").append( event ).append( ") has");
+            if( wrongEvent )
+            {
+                sb.append( " wrong type (expected:'" ).append( expectedType ).
+                        append( "' but was:'" ).append( event.type() ).append( "')" );
+                if( wrongMessage )
+                {
+                    sb.append( ";" );
+                }
+            }
+            if( wrongMessage )
+            {
+                sb.append( " wrong message (expected:'" ).append( expected ).
+                        append( "' but was:'" ).append( event.message() ).append( "')" );
+            }
+            fail( sb.toString() );
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/activation/PassivationExceptionTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/activation/PassivationExceptionTest.java b/core/api/src/test/java/org/apache/zest/api/activation/PassivationExceptionTest.java
new file mode 100644
index 0000000..dcd2848
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/activation/PassivationExceptionTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2013-2014, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zest.api.activation;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Collections;
+import org.junit.Test;
+import org.apache.zest.api.injection.scope.Structure;
+import org.apache.zest.api.mixin.Mixins;
+import org.apache.zest.api.service.ServiceReference;
+import org.apache.zest.api.structure.Application;
+import org.apache.zest.api.structure.Layer;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.bootstrap.Assembler;
+import org.apache.zest.bootstrap.AssemblyException;
+import org.apache.zest.bootstrap.ModuleAssembly;
+import org.apache.zest.bootstrap.builder.ApplicationBuilder;
+
+import static org.hamcrest.core.StringContains.containsString;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class PassivationExceptionTest
+{
+    private static String stack( Exception ex )
+    {
+        StringWriter writer = new StringWriter();
+        ex.printStackTrace( new PrintWriter( writer ) );
+        return writer.toString();
+    }
+
+    @Test
+    public void testEmptyPassivationException()
+    {
+        PassivationException empty = new PassivationException( Collections.<Exception>emptyList() );
+        assertThat( empty.getMessage(), containsString( "has 0 cause" ) );
+    }
+
+    @Test
+    public void testSinglePassivationException()
+    {
+        PassivationException single = new PassivationException( Collections.singletonList( new Exception( "single" ) ) );
+        String stack = stack( single );
+        assertThat( single.getMessage(), containsString( "has 1 cause" ) );
+        assertThat( stack, containsString( "Suppressed: java.lang.Exception: single" ) );
+    }
+
+    @Test
+    public void testMultiplePassivationException()
+    {
+        PassivationException multi = new PassivationException( Arrays.asList( new Exception( "one" ),
+                                                                              new Exception( "two" ),
+                                                                              new Exception( "three" ) ) );
+        String stack = stack( multi );
+        assertThat( multi.getMessage(), containsString( "has 3 cause(s)" ) );
+        assertThat( stack, containsString( "Suppressed: java.lang.Exception: one" ) );
+        assertThat( stack, containsString( "Suppressed: java.lang.Exception: two" ) );
+        assertThat( stack, containsString( "Suppressed: java.lang.Exception: three" ) );
+    }
+
+    @Test
+    public void testPassivationExceptionsAccrossStructure()
+        throws AssemblyException, ActivationException
+    {
+        ApplicationBuilder appBuilder = new ApplicationBuilder( "TestApplication" );
+        appBuilder.withLayer( "Layer 1" ).withModule( "Module A" ).withAssembler( new Assembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( TestService.class ).
+                    identifiedBy( "TestService_Module.A" ).
+                    withActivators( FailBeforePassivationServiceActivator.class ).
+                    instantiateOnStartup();
+            }
+        } );
+        appBuilder.withLayer( "Layer 2" ).withModule( "Module B" ).withAssembler( new Assembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( TestService.class ).
+                    identifiedBy( "TestService_Module.B" ).
+                    withActivators( FailAfterPassivationServiceActivator.class ).
+                    instantiateOnStartup();
+            }
+        } );
+        appBuilder.registerActivationEventListener( new TestActivationEventListener() );
+
+        Application app = appBuilder.newApplication();
+
+        try
+        {
+            Module moduleA = app.findModule( "Layer 1", "Module A" );
+            TestService service = moduleA.findService( TestService.class ).get();
+            assertThat( service.hello(), equalTo( "Hello Zest!" ) );
+        }
+        finally
+        {
+            try
+            {
+                app.passivate();
+                fail( "No PassivationException" );
+            }
+            catch( PassivationException ex )
+            {
+                ex.printStackTrace();
+                String stack = stack( ex );
+                assertThat( ex.getMessage(), containsString( "has 12 cause(s)" ) );
+                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for TestApplication" ) );
+                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for Layer 2" ) );
+                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for Module B" ) );
+                assertThat( stack, containsString( "ACTIVATOR: FAIL AFTER PASSIVATION for TestService_Module.B(active=false,module='Module B')" ) );
+                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for Module B" ) );
+                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for Layer 2" ) );
+                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for Layer 1" ) );
+                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for Module A" ) );
+                assertThat( stack, containsString( "ACTIVATOR: FAIL BEFORE PASSIVATION for TestService_Module.A(active=true,module='Module A')" ) );
+                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for Module A" ) );
+                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for Layer 1" ) );
+                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for TestApplication" ) );
+            }
+        }
+    }
+
+    @Mixins( TestService.Mixin.class )
+    public interface TestService
+    {
+        String hello();
+
+        static class Mixin
+            implements TestService
+        {
+            @Structure
+            private Module module;
+
+            @Override
+            public String hello()
+            {
+                module.name();
+                return "Hello Zest!";
+            }
+        }
+
+    }
+
+    public static class FailBeforePassivationServiceActivator
+        extends ActivatorAdapter<ServiceReference<TestService>>
+    {
+        @Override
+        public void beforePassivation( ServiceReference<TestService> passivated )
+            throws Exception
+        {
+            throw new Exception( "ACTIVATOR: FAIL BEFORE PASSIVATION for " + passivated );
+        }
+    }
+
+    public static class FailAfterPassivationServiceActivator
+        extends ActivatorAdapter<ServiceReference<TestService>>
+    {
+        @Override
+        public void afterPassivation( ServiceReference<TestService> passivated )
+            throws Exception
+        {
+            throw new Exception( "ACTIVATOR: FAIL AFTER PASSIVATION for " + passivated );
+        }
+    }
+
+    public static class TestActivationEventListener
+        implements ActivationEventListener
+    {
+        @Override
+        public void onEvent( ActivationEvent event )
+            throws Exception
+        {
+            if( !( event.source() instanceof Application )
+                && !( event.source() instanceof Layer )
+                && !( event.source() instanceof Module ) )
+            {
+                return;
+            }
+            switch( event.type() )
+            {
+                case PASSIVATING:
+                    throw new Exception( "EVENT: FAIL BEFORE PASSIVATION for " + event.source() );
+                case PASSIVATED:
+                    throw new Exception( "EVENT: FAIL AFTER PASSIVATION for " + event.source() );
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/annotation/MixinsTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/annotation/MixinsTest.java b/core/api/src/test/java/org/apache/zest/api/annotation/MixinsTest.java
new file mode 100644
index 0000000..73755f0
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/annotation/MixinsTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2007 Alin Dreghiciu. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package org.apache.zest.api.annotation;
+
+import java.lang.annotation.Annotation;
+import org.junit.Test;
+import org.apache.zest.api.mixin.Mixins;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests public api exposed by Mixins annotation.
+ * This will ensure that the public api does not get changed by mistake.
+ */
+public class MixinsTest
+{
+
+    @Test
+    public void retention()
+    {
+        Annotation[] annotations = Annotated.class.getDeclaredAnnotations();
+        assertNotNull( "annotations should not be null", annotations );
+        assertEquals( "number of annotations", 1, annotations.length );
+        assertEquals( "annotation type", Mixins.class, annotations[ 0 ].annotationType() );
+    }
+
+    @Mixins( Object.class )
+    private static class Annotated
+    {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/annotation/ModifiedByTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/annotation/ModifiedByTest.java b/core/api/src/test/java/org/apache/zest/api/annotation/ModifiedByTest.java
new file mode 100644
index 0000000..660c762
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/annotation/ModifiedByTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2007 Alin Dreghiciu. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package org.apache.zest.api.annotation;
+
+import java.lang.annotation.Annotation;
+import org.junit.Test;
+import org.apache.zest.api.concern.Concerns;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests public api exposed by Concerns annotation.
+ * This will ensure that the public api does not get changed by mistake.
+ */
+public class ModifiedByTest
+{
+
+    @Test
+    public void retention()
+    {
+        Annotation[] annotations = Annotated.class.getDeclaredAnnotations();
+        assertNotNull( "annotations should not be null", annotations );
+        assertEquals( "number of annotations", 1, annotations.length );
+        assertEquals( "annotation type", Concerns.class, annotations[ 0 ].annotationType() );
+    }
+
+    @Concerns( Object.class )
+    private static class Annotated
+    {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/annotation/scope/ModifiesTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/annotation/scope/ModifiesTest.java b/core/api/src/test/java/org/apache/zest/api/annotation/scope/ModifiesTest.java
new file mode 100644
index 0000000..9eea244
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/annotation/scope/ModifiesTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2007 Alin Dreghiciu. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package org.apache.zest.api.annotation.scope;
+
+import java.lang.annotation.Annotation;
+import org.junit.Test;
+import org.apache.zest.api.concern.internal.ConcernFor;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests public api exposed by Modified annotation.
+ * This will ensure that the public api does not get changed by mistake.
+ */
+public class ModifiesTest
+{
+
+    @Test
+    public void retention()
+        throws NoSuchFieldException
+    {
+        Annotation[] annotations = Annotated.class.getDeclaredField( "modified" ).getDeclaredAnnotations();
+        assertNotNull( "annotations should not be null", annotations );
+        assertEquals( "number of annotations", 1, annotations.length );
+        assertEquals( "annotation type", ConcernFor.class, annotations[ 0 ].annotationType() );
+    }
+
+    private static class Annotated
+    {
+        @ConcernFor
+        String modified;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/common/AppliesToTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/common/AppliesToTest.java b/core/api/src/test/java/org/apache/zest/api/common/AppliesToTest.java
new file mode 100644
index 0000000..7a491fe
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/common/AppliesToTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2007 Alin Dreghiciu. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package org.apache.zest.api.common;
+
+import java.lang.annotation.Annotation;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests public api exposed by AppliesTo annotation.
+ * This will ensure that the public api does not get changed by mistake.
+ */
+public class AppliesToTest
+{
+
+    @Test
+    public void retention()
+    {
+        Annotation[] annotations = Annotated.class.getDeclaredAnnotations();
+        assertNotNull( "annotations should not be null", annotations );
+        assertEquals( "number of annotations", 1, annotations.length );
+        assertEquals( "annotation type", AppliesTo.class, annotations[ 0 ].annotationType() );
+    }
+
+    @AppliesTo( Object.class )
+    private static class Annotated
+    {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/common/QualifiedNameTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/common/QualifiedNameTest.java b/core/api/src/test/java/org/apache/zest/api/common/QualifiedNameTest.java
new file mode 100644
index 0000000..5fa0e8b
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/common/QualifiedNameTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.zest.api.common;
+
+import org.junit.Test;
+import org.apache.zest.api.util.NullArgumentException;
+
+import static org.junit.Assert.assertEquals;
+
+public class QualifiedNameTest
+{
+    @Test
+    public void testQualifiedNameWithDollar()
+    {
+        assertEquals( "Name containing dollar is modified", "Test-Test",
+                      new QualifiedName( TypeName.nameOf( "Test$Test" ), "satisfiedBy" ).type() );
+    }
+
+    @Test
+    public void testQualifiedNameFromQNWithDollar()
+    {
+        assertEquals( "Name containing dollar is cleaned up", "Test-Test",
+                      QualifiedName.fromFQN( "Test$Test:satisfiedBy" ).type() );
+    }
+
+    @Test( expected = NullArgumentException.class )
+    public void nonNullArguments1()
+    {
+        new QualifiedName( TypeName.nameOf( "Test" ), null );
+    }
+
+    @Test( expected = NullArgumentException.class )
+    public void nonNullArguments2()
+    {
+        new QualifiedName( null, "satisfiedBy" );
+    }
+
+    @Test( expected = NullArgumentException.class )
+    public void nonNullArguments3()
+    {
+        new QualifiedName( null, null );
+    }
+
+    @Test( expected = NullArgumentException.class )
+    public void nonNullArguments4()
+    {
+        QualifiedName.fromFQN( null );
+    }
+
+    @Test( expected = NullArgumentException.class )
+    public void nonNullArguments5()
+    {
+        QualifiedName.fromAccessor( null );
+    }
+
+    @Test( expected = NullArgumentException.class )
+    public void nonNullArguments6()
+    {
+        QualifiedName.fromClass( null, "satisfiedBy" );
+    }
+
+    @Test( expected = NullArgumentException.class )
+    public void nonNullArguments7()
+    {
+        QualifiedName.fromClass( null, null );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/composite/PropertyMapperTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/composite/PropertyMapperTest.java b/core/api/src/test/java/org/apache/zest/api/composite/PropertyMapperTest.java
new file mode 100644
index 0000000..f30f887
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/composite/PropertyMapperTest.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2009 Niclas Hedhman.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zest.api.composite;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class PropertyMapperTest
+{
+    private final static Method MAP_TO_TYPE;
+
+    static
+    {
+        try
+        {
+            MAP_TO_TYPE = PropertyMapper.class.getDeclaredMethod( "mapToType", Composite.class, Type.class, Object.class );
+            MAP_TO_TYPE.setAccessible( true );
+        }
+        catch( NoSuchMethodException e )
+        {
+            InternalError error = new InternalError();
+            error.initCause( e );
+            throw error;
+        }
+    }
+
+    @Test
+    public void testMappingOfInteger()
+        throws Exception
+    {
+        assertEquals( 5, mapToType( null, Integer.class, "5" ) );
+        assertEquals( -5, mapToType( null, Integer.class, "-5" ) );
+        assertEquals( Integer.class, mapToType( null, Integer.class, "5" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfLong()
+        throws Exception
+    {
+        assertEquals( 5L, mapToType( null, Long.class, "5" ) );
+        assertEquals( 5876328476238746238L, mapToType( null, Long.class, "5876328476238746238" ) );
+        assertEquals( Long.class, mapToType( null, Long.class, "5" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfBoolean()
+        throws Exception
+    {
+        assertEquals( false, mapToType( null, Boolean.class, "false" ) );
+        assertEquals( true, mapToType( null, Boolean.class, "true" ) );
+        assertEquals( Boolean.class, mapToType( null, Boolean.class, "false" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfFloat()
+        throws Exception
+    {
+        assertEquals( 5.1234f, mapToType( null, Float.class, "5.1234" ) );
+        assertEquals( 5876328476.6238f, mapToType( null, Float.class, "5876328476.6238" ) );
+        assertEquals( Float.class, mapToType( null, Float.class, "5" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfDouble()
+        throws Exception
+    {
+        assertEquals( 5.1234, mapToType( null, Double.class, "5.1234" ) );
+        assertEquals( 5876328476.623823, mapToType( null, Double.class, "5876328476.623823" ) );
+        assertEquals( Double.class, mapToType( null, Double.class, "5" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfBigDecimal()
+        throws Exception
+    {
+        assertEquals( new BigDecimal( 3 ), mapToType( null, BigDecimal.class, "3" ) );
+        assertEquals( new BigDecimal( "12345.67891011" ), mapToType( null, BigDecimal.class, "12345.67891011" ) );
+        assertEquals( BigDecimal.class, mapToType( null, BigDecimal.class, "5" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfBigInteger()
+        throws Exception
+    {
+        assertEquals( new BigInteger( "20", 16 ), mapToType( null, BigInteger.class, "32" ) );
+        assertEquals( new BigInteger( "1234567891011" ), mapToType( null, BigInteger.class, "1234567891011" ) );
+        assertEquals( BigInteger.class, mapToType( null, BigInteger.class, "5" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfEnum()
+        throws Exception
+    {
+        assertEquals( TestEnum.FIRST, mapToType( null, TestEnum.class, "FIRST" ) );
+        assertEquals( TestEnum.SECOND, mapToType( null, TestEnum.class, "SECOND" ) );
+        assertEquals( TestEnum.class, mapToType( null, TestEnum.class, "SECOND" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfIntegerArray()
+        throws Exception
+    {
+        Object[] value = (Object[]) mapToType( null, Integer[].class, "5,4 , 3   ,2,1" );
+        assertEquals( 5, value.length );
+        assertEquals( 5, value[ 0 ] );
+        assertEquals( 4, value[ 1 ] );
+        assertEquals( 3, value[ 2 ] );
+        assertEquals( 2, value[ 3 ] );
+        assertEquals( 1, value[ 4 ] );
+    }
+
+    @Test
+    public void testMappingOfStringArray()
+        throws Exception
+    {
+        {
+            Object[] value = (Object[]) mapToType( null, String[].class, "5,4 , 3   ,2,1" );
+            assertEquals( 5, value.length );
+            assertEquals( "5", value[ 0 ] );
+            assertEquals( "4 ", value[ 1 ] );
+            assertEquals( " 3   ", value[ 2 ] );
+            assertEquals( "2", value[ 3 ] );
+            assertEquals( "1", value[ 4 ] );
+        }
+        {
+            Object[] value = (Object[]) mapToType( null, String[].class, "5,4 ,\" 3,   \",  \" 2\" ,1" );
+            assertEquals( "5", value[ 0 ] );
+            assertEquals( "4 ", value[ 1 ] );
+            assertEquals( " 3,   ", value[ 2 ] );
+            assertEquals( " 2", value[ 3 ] );
+            assertEquals( "1", value[ 4 ] );
+            assertEquals( 5, value.length );
+        }
+    }
+
+    @Test
+    public void testMappingOfBooleanArray()
+        throws Exception
+    {
+        Object[] value = (Object[]) mapToType( null, Boolean[].class, " true,false,  false, true ,true,false" );
+        assertEquals( true, value[ 0 ] );
+        assertEquals( false, value[ 1 ] );
+        assertEquals( false, value[ 2 ] );
+        assertEquals( true, value[ 3 ] );
+        assertEquals( true, value[ 4 ] );
+        assertEquals( false, value[ 5 ] );
+        assertEquals( 6, value.length );
+    }
+
+    @Test
+    public void testMappingOfList()
+        throws Exception
+    {
+        Type type = Testing.class.getDeclaredMethod( "list" ).getGenericReturnType();
+        List<String> value = (List<String>) mapToType( null, type, "5,4 ,\" 3,   \",  \" 2\" ,1" );
+        assertEquals( "5", value.get( 0 ) );
+        assertEquals( "4 ", value.get( 1 ) );
+        assertEquals( " 3,   ", value.get( 2 ) );
+        assertEquals( " 2", value.get( 3 ) );
+        assertEquals( "1", value.get( 4 ) );
+        assertEquals( 5, value.size() );
+    }
+
+    @Test
+    public void testMappingOfSet()
+        throws Exception
+    {
+        Type type = Testing.class.getDeclaredMethod( "set" ).getGenericReturnType();
+        Set<String> value = (Set<String>) mapToType( null, type, "5,4 ,\" 3,   \",  \" 2\" ,1" );
+        assertTrue( value.contains( "5" ) );
+        assertTrue( value.contains( "4 " ) );
+        assertTrue( value.contains( " 3,   " ) );
+        assertTrue( value.contains( " 2" ) );
+        assertTrue( value.contains( "1" ) );
+        assertEquals( 5, value.size() );
+    }
+
+    @Test
+    public void testMappingOfMap()
+        throws Exception
+    {
+        Type type = Testing.class.getDeclaredMethod( "map" ).getGenericReturnType();
+        Map<String, String> value = (Map<String, String>) mapToType( null, type, "first:5,second:4 , third:\" 3,   \", fourth:  \" 2\" ,fifth : 1" );
+        assertEquals( "5", value.get( "first" ) );
+        assertEquals( "4 ", value.get( "second" ) );
+        assertEquals( " 3,   ", value.get( " third" ) );
+        assertEquals( " 2", value.get( " fourth" ) );
+        assertEquals( " 1", value.get( "fifth " ) );
+        assertEquals( 5, value.size() );
+    }
+
+    private Object mapToType( Composite composite, Type propertyType, Object value )
+        throws IllegalAccessException, InvocationTargetException
+    {
+        return MAP_TO_TYPE.invoke( null, composite, propertyType, value );
+    }
+
+    interface Testing
+    {
+        List<String> list();
+
+        Set<String> set();
+
+        Map<String, String> map();
+    }
+
+    enum TestEnum
+    {
+        FIRST,
+        SECOND
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/concern/DocumentationSupport.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/concern/DocumentationSupport.java b/core/api/src/test/java/org/apache/zest/api/concern/DocumentationSupport.java
new file mode 100644
index 0000000..b9aefc1
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/concern/DocumentationSupport.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.zest.api.concern;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.zest.api.common.AppliesTo;
+import org.apache.zest.api.common.AppliesToFilter;
+import org.apache.zest.api.injection.InjectionScope;
+
+public class DocumentationSupport
+{
+// START SNIPPET: class
+    @AppliesTo( java.sql.Connection.class )
+    public class CacheConcern extends GenericConcern
+        implements InvocationHandler
+    {
+// END SNIPPET: class
+        @Override
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            return null;
+        }
+    }
+
+// START SNIPPET: filter
+    @AppliesTo( BusinessAppliesToFilter.class )
+    public class BusinessConcern extends GenericConcern
+        implements InvocationHandler
+    {
+// END SNIPPET: filter
+        @Override
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            return null;
+        }
+    }
+
+// START SNIPPET: filter
+    public class BusinessAppliesToFilter
+        implements AppliesToFilter
+    {
+
+        @Override
+        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass
+        )
+        {
+            return true; // Some criteria for when a method is wrapped with the concern.
+        }
+    }
+// END SNIPPET: filter
+
+
+// START SNIPPET: annotation
+    @AppliesTo( Audited.class )
+    public class AuditConcern extends GenericConcern
+        implements InvocationHandler
+    {
+// START SNIPPET: annotation
+        @Override
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            return null;
+        }
+    }
+
+// START SNIPPET: annotation
+    @Retention( RetentionPolicy.RUNTIME )
+    @Target( { ElementType.METHOD } )
+    @Documented
+    @InjectionScope
+    public @interface Audited
+    {
+    }
+// END SNIPPET: annotation
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/configuration/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/configuration/ConfigurationTest.java b/core/api/src/test/java/org/apache/zest/api/configuration/ConfigurationTest.java
new file mode 100644
index 0000000..8d67f6c
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/configuration/ConfigurationTest.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.zest.api.configuration;
+
+import org.junit.Test;
+import org.apache.zest.api.injection.scope.This;
+import org.apache.zest.api.mixin.Mixins;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.api.service.ServiceComposite;
+import org.apache.zest.api.value.ValueComposite;
+import org.apache.zest.bootstrap.AssemblyException;
+import org.apache.zest.bootstrap.ModuleAssembly;
+import org.apache.zest.test.AbstractQi4jTest;
+import org.apache.zest.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class ConfigurationTest extends AbstractQi4jTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MyService.class ).instantiateOnStartup();
+        module.entities( MyConfig.class );
+        module.values( PersonDetails.class, Address.class, City.class, Country.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void testConfiguration()
+        throws Exception
+    {
+        MyService service = module.findService( MyService.class ).get();
+        PersonDetails details = service.details();
+        assertThat(details.name().get(), equalTo( "Niclas" ) );
+        assertThat(details.address().get().street1().get(), equalTo( "Henan Lu 555" ) );
+        assertThat(details.address().get().street2().get(), equalTo( "Block 15" ) );
+        assertThat(details.address().get().city().get().cityName().get(), equalTo( "Shanghai" ) );
+        assertThat(details.address().get().city().get().country().get().countryName().get(), equalTo( "China" ) );
+    }
+
+    @Mixins(MyServiceMixin.class)
+    public interface MyService extends ServiceComposite
+    {
+        PersonDetails details();
+    }
+
+    public abstract class MyServiceMixin
+        implements MyService
+    {
+        @This
+        Configuration<MyConfig> myconf;
+
+        @Override
+        public PersonDetails details()
+        {
+            return myconf.get().me().get();
+        }
+    }
+
+    public interface MyConfig extends ConfigurationComposite
+    {
+        Property<PersonDetails> me();
+    }
+
+    public interface PersonDetails extends ValueComposite
+    {
+        Property<String> name();
+        Property<Address> address();
+
+    }
+
+    public interface Address extends ValueComposite
+    {
+        Property<String> street1();
+        Property<String> street2();
+        Property<City> city();
+    }
+
+    public interface City extends ValueComposite
+    {
+        Property<String> cityName();
+        Property<Country> country();
+    }
+
+    public interface Country extends ValueComposite
+    {
+        Property<String> countryName();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/configuration/DeclareConfigurationDefaultsTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/configuration/DeclareConfigurationDefaultsTest.java b/core/api/src/test/java/org/apache/zest/api/configuration/DeclareConfigurationDefaultsTest.java
new file mode 100644
index 0000000..dbc8b18
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/configuration/DeclareConfigurationDefaultsTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012 Paul Merlin.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zest.api.configuration;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.zest.api.injection.scope.This;
+import org.apache.zest.api.mixin.Mixins;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.api.service.ServiceComposite;
+import org.apache.zest.bootstrap.AssemblyException;
+import org.apache.zest.bootstrap.ModuleAssembly;
+import org.apache.zest.test.AbstractQi4jTest;
+import org.apache.zest.test.EntityTestAssembler;
+
+public class DeclareConfigurationDefaultsTest
+        extends AbstractQi4jTest
+{
+
+    @Mixins( FooServiceMixin.class )
+    public static interface FooServiceComposite
+            extends ServiceComposite
+    {
+
+        String configuredFoo();
+
+    }
+
+    public static abstract class FooServiceMixin
+            implements FooServiceComposite
+    {
+
+        @This
+        private Configuration<FooConfigurationComposite> config;
+
+        public String configuredFoo()
+        {
+            return config.get().foo().get();
+        }
+
+    }
+
+    public static interface FooConfigurationComposite
+            extends ConfigurationComposite
+    {
+
+        Property<String> foo();
+
+    }
+
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        module.services( FooServiceComposite.class ).identifiedBy( "bazar" );
+        module.entities( FooConfigurationComposite.class );
+        new EntityTestAssembler().assemble( module );
+        FooConfigurationComposite config = module.forMixin( FooConfigurationComposite.class ).declareDefaults();
+        config.foo().set( "bar" );
+    }
+
+    @Test
+    public void testConfigurationDefaults()
+    {
+        FooServiceComposite fooService = module.findService( FooServiceComposite.class ).get();
+        Assert.assertEquals( "bar", fooService.configuredFoo() );
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/configuration/MailService.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/configuration/MailService.java b/core/api/src/test/java/org/apache/zest/api/configuration/MailService.java
new file mode 100644
index 0000000..ff0311e
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/configuration/MailService.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2012, Paul Merlin.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ *
+ *     You may obtain a copy of the License at 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zest.api.configuration;
+
+import org.apache.zest.api.injection.scope.This;
+import org.apache.zest.api.mixin.Mixins;
+import org.apache.zest.library.constraints.annotation.Email;
+import org.apache.zest.library.constraints.annotation.MinLength;
+
+// Documentation Support
+@Mixins( MailService.MailServiceMixin.class )
+public interface MailService
+{
+    void sendMail( @Email String to, @MinLength( 8 ) String subject, String body );
+    
+    // START SNIPPET: write
+    void changeExternalMailService( String hostName, int port );
+    // END SNIPPET: write
+    
+    public class MailServiceMixin
+        implements MailService
+    {
+        // START SNIPPET: read        
+        @This
+        private Configuration<MailServiceConfiguration> config;
+
+        @Override
+        public void sendMail( @Email String to, @MinLength( 8 ) String subject, String body )
+        {
+            config.refresh();
+            MailServiceConfiguration conf = config.get();
+            String hostName = conf.hostName().get();
+            int port = conf.port().get();
+            // END SNIPPET: read
+
+            // START SNIPPET: read        
+        }
+        // END SNIPPET: read        
+
+        // START SNIPPET: write        
+        @Override
+        public void changeExternalMailService( String hostName, int port )
+        {
+            MailServiceConfiguration conf = config.get();
+            conf.hostName().set( hostName );
+            conf.port().set( port );
+            config.save();
+        }
+        // START SNIPPET: write        
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/configuration/MailServiceConfiguration.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/configuration/MailServiceConfiguration.java b/core/api/src/test/java/org/apache/zest/api/configuration/MailServiceConfiguration.java
new file mode 100644
index 0000000..4129bd4
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/configuration/MailServiceConfiguration.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ *
+ *     You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zest.api.configuration;
+
+import org.apache.zest.api.property.Property;
+
+// Documentation Support class
+// START SNIPPET: configuration
+public interface MailServiceConfiguration extends ConfigurationComposite
+{
+    Property<String> hostName();
+
+    Property<Integer> port();
+}
+// END SNIPPET: configuration

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/dataset/iterable/IterableDataSetTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/dataset/iterable/IterableDataSetTest.java b/core/api/src/test/java/org/apache/zest/api/dataset/iterable/IterableDataSetTest.java
new file mode 100644
index 0000000..352edb6
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/dataset/iterable/IterableDataSetTest.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.zest.api.dataset.iterable;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.apache.zest.api.dataset.DataSet;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.bootstrap.AssemblyException;
+import org.apache.zest.bootstrap.ModuleAssembly;
+import org.apache.zest.functional.Iterables;
+import org.apache.zest.test.AbstractQi4jTest;
+
+/**
+ * TODO
+ */
+@Ignore( "Not implemented yet" )
+public class IterableDataSetTest
+    extends AbstractQi4jTest
+{
+    DataSet<TestValue> dataSet;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( TestValue.class );
+    }
+
+    @Before
+    public void setUp()
+    {
+        dataSet = new IterableDataSet<TestValue>( Iterables.iterable( newTestValue( "Rickard" ), newTestValue( "Niclas" ), newTestValue( "Paul" ) ) );
+    }
+
+    private TestValue newTestValue( String name )
+    {
+        return module.newValueFromSerializedState( TestValue.class, "{name:'" + name + "'}" );
+    }
+
+    interface TestValue
+    {
+        Property<String> name();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/docsupport/ApplicationDocs.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/docsupport/ApplicationDocs.java b/core/api/src/test/java/org/apache/zest/api/docsupport/ApplicationDocs.java
new file mode 100644
index 0000000..7685a35
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/docsupport/ApplicationDocs.java
@@ -0,0 +1,274 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.zest.api.docsupport;
+
+import org.apache.zest.api.structure.Application;
+import org.apache.zest.api.structure.ApplicationDescriptor;
+import org.apache.zest.bootstrap.ApplicationAssembler;
+import org.apache.zest.bootstrap.ApplicationAssembly;
+import org.apache.zest.bootstrap.ApplicationAssemblyFactory;
+import org.apache.zest.bootstrap.Assembler;
+import org.apache.zest.bootstrap.AssemblyException;
+import org.apache.zest.bootstrap.Energy4Java;
+import org.apache.zest.bootstrap.LayerAssembly;
+import org.apache.zest.bootstrap.ModuleAssembly;
+import org.apache.zest.bootstrap.SingletonAssembler;
+
+public class ApplicationDocs
+{
+    public static void someMethod( String[] args )
+        throws Exception
+    {
+        {
+// START SNIPPET: application1
+            SingletonAssembler qi4j = new SingletonAssembler()
+            {
+                public void assemble( ModuleAssembly assembly )
+                    throws AssemblyException
+                {
+                    assembly.values( MyStuffValueComposite.class );
+                }
+            };
+// END SNIPPET: application1
+        }
+        {
+            Assembler customerListEditAssembler = new DummyAssembler();
+            Assembler customerEditAssembler = new DummyAssembler();
+            Assembler customerSearchAssembler = new DummyAssembler();
+            Assembler accountsListEditAssembler = new DummyAssembler();
+            Assembler accountsEditAssembler = new DummyAssembler();
+            Assembler accountsSearchAssembler = new DummyAssembler();
+            Assembler customerDomainAssembler = new DummyAssembler();
+            Assembler accountsDomainAssembler = new DummyAssembler();
+// START SNIPPET: application2
+            final Assembler[][][] assemblers =
+                {
+                    { // web layer
+                      { // Customer Module
+                        customerListEditAssembler,
+                        customerEditAssembler,
+                        customerSearchAssembler
+                      },
+                      { // Accounts Module
+                        accountsListEditAssembler,
+                        accountsEditAssembler,
+                        accountsSearchAssembler
+                      }
+                    },
+                    { // domain layer
+                      { // Customer Module
+                        customerDomainAssembler,
+                      },
+                      { // Accounts Module
+                        accountsDomainAssembler,
+                      }
+                    }
+                };
+            Energy4Java qi4j = new Energy4Java();
+            Application app = qi4j.newApplication( new ApplicationAssembler()
+            {
+
+                @Override
+                public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+                    throws AssemblyException
+                {
+                    return applicationFactory.newApplicationAssembly( assemblers );
+                }
+            } );
+            app.activate();
+// END SNIPPET: application2
+        }
+    }
+
+    public interface MyStuffValueComposite
+    {
+    }
+
+    private static class DummyAssembler implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+
+        }
+    }
+
+    // START SNIPPET: application3
+    private static Energy4Java qi4j;
+
+    public static void main( String[] args )
+        throws Exception
+    {
+        qi4j = new Energy4Java();
+        ApplicationDescriptor model = qi4j.newApplicationModel( new ApplicationAssembler()
+        {
+            @Override
+            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+                throws AssemblyException
+            {
+                return createAssembly( applicationFactory );
+            }
+        } );
+        Application application = model.newInstance( qi4j.spi() );
+    }
+
+    private static ApplicationAssembly createAssembly( ApplicationAssemblyFactory factory )
+        throws AssemblyException
+    {
+        String applicationName = "Example Application";
+        ApplicationAssembly app = factory.newApplicationAssembly();
+        app.setName( applicationName );
+        LayerAssembly webLayer = createWebLayer( app );
+        LayerAssembly domainLayer = createDomainLayer( app );
+        LayerAssembly infraLayer = createInfrastructureLayer( app );
+        webLayer.uses( domainLayer );
+        webLayer.uses( infraLayer );  // Accesses the WebService
+        domainLayer.uses( infraLayer ); // For persistence
+        return app;
+    }
+
+    private static LayerAssembly createWebLayer(
+        ApplicationAssembly application
+    )
+    {
+        LayerAssembly layer = application.layer( "Web Layer" );
+        createCustomerWebModule( layer );
+        return layer;
+    }
+
+    private static LayerAssembly createDomainLayer(
+        ApplicationAssembly application
+    )
+    {
+        LayerAssembly layer = application.layer( "Domain Layer" );
+        createCustomerDomainModule( layer );
+        // :
+        // :
+        return layer;
+    }
+
+    private static LayerAssembly createInfrastructureLayer(
+        ApplicationAssembly application
+    )
+        throws AssemblyException
+    {
+        LayerAssembly layer = application.layer( "Infrastructure Layer" );
+        createWebServiceModule( layer );
+        createPersistenceModule( layer );
+        return layer;
+    }
+
+    private static void createCustomerWebModule( LayerAssembly layer )
+    {
+        ModuleAssembly assembly = layer.module( "Customer Web Module" );
+        assembly.transients( CustomerViewComposite.class );
+        assembly.transients( CustomerEditComposite.class );
+        assembly.transients( CustomerListViewComposite.class );
+        assembly.transients( CustomerSearchComposite.class );
+    }
+
+    private static void createCustomerDomainModule( LayerAssembly layer )
+    {
+        ModuleAssembly assembly = layer.module( "Customer Domain Module" );
+        assembly.entities( CustomerEntity.class );
+        assembly.entities( CountryEntity.class );
+        assembly.transients( AddressComposite.class );
+    }
+
+    private static void createWebServiceModule( LayerAssembly layer )
+        throws AssemblyException
+    {
+        ModuleAssembly assembly = layer.module( "Web Service Module" );
+        // Someone has created an assembler for a Jetty Web Service.
+        JettyAssembler jetty = new JettyAssembler( 8080 );
+        jetty.assemble( assembly );
+    }
+
+    private static void createPersistenceModule( LayerAssembly layer )
+        throws AssemblyException
+    {
+        ModuleAssembly assembly = layer.module( "Persistence Module" );
+        // Someone has created an assembler for the Neo EntityStore
+        NeoAssembler neo = new NeoAssembler( "./neostore" );
+        neo.assemble( assembly );
+    }
+// START SNIPPET: application3
+
+    public static class CustomerViewComposite
+    {
+
+    }
+    public static class CustomerEditComposite
+    {
+
+    }
+    public static class CustomerListViewComposite
+    {
+
+    }
+    public static class CustomerSearchComposite
+    {
+
+    }
+
+
+    public static class CustomerEntity
+    {
+
+    }
+    public static class CountryEntity
+    {
+
+    }
+    public static class AddressComposite
+    {
+
+    }
+
+    public static class JettyAssembler
+        implements Assembler
+    {
+
+        public JettyAssembler( int port )
+        {
+        }
+
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+        }
+    }
+    public static class NeoAssembler
+        implements Assembler
+    {
+
+        public NeoAssembler( String s )
+        {
+        }
+
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/docsupport/CompositionDocs.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/docsupport/CompositionDocs.java b/core/api/src/test/java/org/apache/zest/api/docsupport/CompositionDocs.java
new file mode 100644
index 0000000..8009677
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/docsupport/CompositionDocs.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.zest.api.docsupport;
+
+import org.apache.zest.api.mixin.Mixins;
+import org.apache.zest.bootstrap.ModuleAssembly;
+
+public class CompositionDocs
+{
+// START SNIPPET: comp1
+    @Mixins( { BalanceCheckMixin.class } )
+    public interface BankAccount
+    {
+        Money checkBalance();
+// END SNIPPET: comp1
+// START SNIPPET: comp1
+    }
+// END SNIPPET: comp1
+
+// START SNIPPET: comp2
+    public void assemble( ModuleAssembly module )
+    {
+        module.entities( BankAccount.class );
+    }
+// END SNIPPET: comp2
+
+    public static class BalanceCheckMixin
+        implements BankAccount
+    {
+        @Override
+        public Money checkBalance()
+        {
+            return null;
+        }
+    }
+
+    public static class Money
+    {
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/docsupport/package.html
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/docsupport/package.html b/core/api/src/test/java/org/apache/zest/api/docsupport/package.html
new file mode 100644
index 0000000..f6fa115
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/docsupport/package.html
@@ -0,0 +1,21 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<html>
+<body>
+This package exists to contain snippets for documentation.
+</body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/injection/scope/StateFieldTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/injection/scope/StateFieldTest.java b/core/api/src/test/java/org/apache/zest/api/injection/scope/StateFieldTest.java
new file mode 100644
index 0000000..07f98b0
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/injection/scope/StateFieldTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.zest.api.injection.scope;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.zest.api.association.Association;
+import org.apache.zest.api.association.ManyAssociation;
+import org.apache.zest.api.common.Optional;
+import org.apache.zest.api.common.UseDefaults;
+import org.apache.zest.api.entity.EntityComposite;
+import org.apache.zest.api.mixin.Mixins;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.api.unitofwork.UnitOfWork;
+import org.apache.zest.bootstrap.AssemblyException;
+import org.apache.zest.bootstrap.ModuleAssembly;
+import org.apache.zest.test.AbstractQi4jTest;
+import org.apache.zest.test.EntityTestAssembler;
+
+/**
+ * Define a field to be a Property
+ */
+public class StateFieldTest
+    extends AbstractQi4jTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( PersonEntity.class );
+    }
+
+    @Test
+    public void givenEntityWithFieldPropertiesWhenUpdatedThenReturnCorrect()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = module.newUnitOfWork();
+        try
+        {
+            PersonEntity charles = unitOfWork.newEntity( PersonEntity.class );
+            charles.changeName( "Charles" );
+            Assert.assertEquals( charles.getName(), "Charles" );
+
+            PersonEntity daniel = unitOfWork.newEntity( PersonEntity.class );
+            daniel.changeName( "Daniel" );
+            Assert.assertEquals( daniel.getName(), "Daniel" );
+
+            PersonEntity lisa = unitOfWork.newEntity( PersonEntity.class );
+            lisa.changeName( "Lisa" );
+            Assert.assertEquals( lisa.getName(), "Lisa" );
+
+            charles.befriend( daniel );
+            charles.befriend( lisa );
+            charles.marry( lisa );
+
+            unitOfWork.complete();
+
+            unitOfWork = module.newUnitOfWork();
+
+            charles = unitOfWork.get( charles );
+            daniel = unitOfWork.get( daniel );
+            Assert.assertTrue( charles.isFriend( daniel ) );
+
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Mixins( PersonEntity.Mixin.class )
+    public interface PersonEntity
+        extends EntityComposite
+    {
+        void changeName( String newName );
+
+        void marry( PersonEntity entity );
+
+        void befriend( PersonEntity entity );
+
+        boolean isFriend( PersonEntity entity );
+
+        String getName();
+
+        abstract class Mixin
+            implements PersonEntity
+        {
+            @State
+            @UseDefaults
+            public Property<String> name;
+
+            @State
+            @Optional
+            public Association<PersonEntity> spouse;
+
+            @State
+            public ManyAssociation<PersonEntity> friends;
+
+            @Override
+            public void changeName( String newName )
+            {
+                name.set( newName );
+            }
+
+            @Override
+            public void marry( PersonEntity entity )
+            {
+                spouse.set( entity );
+            }
+
+            @Override
+            public void befriend( PersonEntity entity )
+            {
+                friends.add( entity );
+            }
+
+            @Override
+            public String getName()
+            {
+                return name.get();
+            }
+
+            @Override
+            public boolean isFriend( PersonEntity entity )
+            {
+                return friends.contains( entity );
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/injection/scope/ThisTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/injection/scope/ThisTest.java b/core/api/src/test/java/org/apache/zest/api/injection/scope/ThisTest.java
new file mode 100644
index 0000000..b2e753b
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/injection/scope/ThisTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2007 Alin Dreghiciu. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package org.apache.zest.api.injection.scope;
+
+import java.lang.annotation.Annotation;
+import org.junit.Test;
+import org.apache.zest.api.common.Optional;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests public api exposed by This annotation.
+ * This will ensure that the public api does not get changed by mistake.
+ */
+public class ThisTest
+{
+
+    @Test
+    public void retention()
+        throws NoSuchFieldException
+    {
+        Annotation[] annotations = Annotated.class.getDeclaredField( "uses" ).getDeclaredAnnotations();
+        assertNotNull( "annotations should not be null", annotations );
+        assertEquals( "number of annotations", 1, annotations.length );
+        assertEquals( "annotation type", This.class, annotations[ 0 ].annotationType() );
+    }
+
+    private static class Annotated
+    {
+        @This
+        String uses;
+        @Optional
+        @This
+        String usesOptional;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/metrics/DocumentationSupport.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/metrics/DocumentationSupport.java b/core/api/src/test/java/org/apache/zest/api/metrics/DocumentationSupport.java
new file mode 100644
index 0000000..9bba670
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/metrics/DocumentationSupport.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ *
+ *     You may obtain a copy of the License at 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zest.api.metrics;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import org.apache.zest.api.injection.scope.Service;
+
+public class DocumentationSupport
+{
+    // START SNIPPET: common
+    @Service
+    private MetricsProvider provider;
+    // END SNIPPET: common
+
+    public void forDocumentationOnly()
+    {
+        // START SNIPPET: gauge
+        final BlockingQueue queue = new LinkedBlockingQueue( 20 );
+        // END SNIPPET: gauge
+        // START SNIPPET: gauge
+        MetricsGaugeFactory gaugeFactory = provider.createFactory( MetricsGaugeFactory.class );
+        MetricsGauge<Integer> gauge = gaugeFactory.registerGauge( getClass(), "Sample Gauge", new MetricsGauge<Integer>()
+        {
+            @Override
+            public Integer value()
+            {
+                return queue.size();
+            }
+        } );
+        // END SNIPPET: gauge
+
+        // START SNIPPET: counter
+        MetricsCounterFactory counterFactory = provider.createFactory( MetricsCounterFactory.class );
+        MetricsCounter counter = counterFactory.createCounter( getClass(), "Sample Counter" );
+        // END SNIPPET: counter
+
+        // START SNIPPET: histogram
+        MetricsHistogramFactory histoFactory = provider.createFactory( MetricsHistogramFactory.class );
+        MetricsHistogram histogram = histoFactory.createHistogram( getClass(), "Sample Histogram" );
+        // END SNIPPET: histogram
+
+        // START SNIPPET: meter
+        MetricsMeterFactory meterFactory = provider.createFactory( MetricsMeterFactory.class );
+        MetricsMeter meter = meterFactory.createMeter( getClass(), "Sample Meter", "requests", TimeUnit.MINUTES );
+        // END SNIPPET: meter
+
+        // START SNIPPET: timer
+        MetricsTimerFactory timerFactory = provider.createFactory( MetricsTimerFactory.class );
+        MetricsTimer timer = timerFactory.createTimer( getClass(), "Sample Timer", TimeUnit.SECONDS, TimeUnit.HOURS );
+        // END SNIPPET: timer
+
+        // START SNIPPET: healthcheck
+        MetricsHealthCheckFactory healthFactory = provider.createFactory( MetricsHealthCheckFactory.class );
+        MetricsHealthCheck healthCheck = healthFactory.registerHealthCheck(
+            getClass(),
+            "Sample Healthcheck",
+            new MetricsHealthCheck()
+            {
+                @Override
+                public Result check()
+                    throws Exception
+                {
+                    ServiceStatus status = pingMyService();
+                    return new Result( status.isOk(), status.getErrorMessage(), status.getException() );
+                }
+            } );
+        // END SNIPPET: healthcheck
+
+    }
+
+    private ServiceStatus pingMyService()
+    {
+        return new ServiceStatus();
+    }
+
+    private static class ServiceStatus
+    {
+        String errorMessage;
+        Exception exception;
+
+        public String getErrorMessage()
+        {
+            return errorMessage;
+        }
+
+        public Exception getException()
+        {
+            return exception;
+        }
+
+        public boolean isOk()
+        {
+            return errorMessage.equals( "OK" );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/mixin/BankAccount.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/mixin/BankAccount.java b/core/api/src/test/java/org/apache/zest/api/mixin/BankAccount.java
new file mode 100644
index 0000000..65de035
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/mixin/BankAccount.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.zest.api.mixin;
+
+
+// START SNIPPET: mixinType
+public interface BankAccount
+{
+    Money checkBalance();
+}
+// END SNIPPET: mixinType
+
+class Money {}
+

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/mixin/Car.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/mixin/Car.java b/core/api/src/test/java/org/apache/zest/api/mixin/Car.java
new file mode 100644
index 0000000..7bbc83a
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/mixin/Car.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.zest.api.mixin;
+
+// START SNIPPET: mixins
+@Mixins( { StartMixin.class, VehicleMixin.class } )
+public interface Car extends Startable, Vehicle
+{}
+// END SNIPPET: mixins
+

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/mixin/Something.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/mixin/Something.java b/core/api/src/test/java/org/apache/zest/api/mixin/Something.java
new file mode 100644
index 0000000..8597cc2
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/mixin/Something.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.zest.api.mixin;
+
+// START SNIPPET: something
+@Mixins( SomethingMixin.class )
+public interface Something
+{}
+// END SNIPPET: something
+
+

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/test/java/org/apache/zest/api/mixin/SomethingMixin.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/mixin/SomethingMixin.java b/core/api/src/test/java/org/apache/zest/api/mixin/SomethingMixin.java
new file mode 100644
index 0000000..d623625
--- /dev/null
+++ b/core/api/src/test/java/org/apache/zest/api/mixin/SomethingMixin.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.zest.api.mixin;
+
+// START SNIPPET: something
+public class SomethingMixin
+        implements Something
+{
+    // State is allowed.
+
+    public void doSomething()
+    {
+        // do stuff...
+    }
+}
+// END SNIPPET: something