polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject [1/3] zest-qi4j git commit: Giving some love to the InvocationCache library, which was simply in a very bad shape.
Date Thu, 09 Jul 2015 08:48:01 GMT
Repository: zest-qi4j
Updated Branches:
  refs/heads/develop 8f87df34c -> 4076eae35


Giving some love to the InvocationCache library, which was simply in a very bad shape.


Project: http://git-wip-us.apache.org/repos/asf/zest-qi4j/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-qi4j/commit/c24b54ec
Tree: http://git-wip-us.apache.org/repos/asf/zest-qi4j/tree/c24b54ec
Diff: http://git-wip-us.apache.org/repos/asf/zest-qi4j/diff/c24b54ec

Branch: refs/heads/develop
Commit: c24b54ecca37845c0665bb1575bdd3d09b97c3e2
Parents: 8f87df3
Author: Niclas Hedhman <hedmann@betfair.com>
Authored: Thu Jul 9 11:16:54 2015 +0300
Committer: Niclas Hedhman <hedmann@betfair.com>
Committed: Thu Jul 9 11:16:54 2015 +0300

----------------------------------------------------------------------
 .../src/docs/invocation-cache.txt               | 69 +++++++++++++++++++-
 .../CacheInvocationResultSideEffect.java        | 62 ------------------
 .../InvalidateCacheOnSettersSideEffect.java     | 53 ---------------
 .../invocationcache/InvocationCache.java        |  3 +
 .../InvocationCacheAbstractComposite.java       | 32 ---------
 .../invocationcache/InvocationCacheMixin.java   | 60 -----------------
 .../ReturnCachedValueConcern.java               | 26 ++++----
 .../ReturnCachedValueOnExceptionConcern.java    | 33 +++++-----
 .../SimpleInvocationCacheMixin.java             | 69 ++++++++++++++++++++
 .../invocationcache/DocumentationSupport.java   | 51 +++++++++++++++
 10 files changed, 215 insertions(+), 243 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/c24b54ec/libraries/invocation-cache/src/docs/invocation-cache.txt
----------------------------------------------------------------------
diff --git a/libraries/invocation-cache/src/docs/invocation-cache.txt b/libraries/invocation-cache/src/docs/invocation-cache.txt
index da5e60f..40600b7 100644
--- a/libraries/invocation-cache/src/docs/invocation-cache.txt
+++ b/libraries/invocation-cache/src/docs/invocation-cache.txt
@@ -25,9 +25,72 @@
 source=libraries/invocation-cache/dev-status.xml
 --------------
 
-The Invocation Cache Library provides constructs to easily cache composite methods invocations.
-It has nothing to do with the <<core-spi-cache>>.
+The Invocation Cache Library provides constructs to easily cache the return value of
+method invocations on composites.
 
-NOTE: This Library has no documentation yet. Learn how to contribute in <<community-docs>>.
+NOTE: It has nothing to do with the <<core-spi-cache>>.
 
 include::../../build/docs/buildinfo/artifact.txt[]
+
+
+By applying one of the <<def-concern,Concerns>> it is possible to cache the return
values of method
+calls. The concern will in turn delegate to the +InvocationCache+ that is expected to be
a
+<<def-private-mixin>> in the same composite.
+
+== +@Cached+ ==
+This annotation is used to mark the methods that should be considered for caching. Only if
a
+caching concern has been defined and that an +InvocationCache+ implementation mixin has been
provided
+will the caching actually take place.
+
+== +ReturnCachedValueConcern+ ==
+This generic mixin implementation will first look in the cache and see if the value is there,
if so the value
+is unconditionally returned to the caller.
+
+This concern skip its function if there is no +InvocationCache+ mixin declared on the composite
or if the method
+has a +void+ return type.
+
+== +ReturnCachedValueOnExceptionConcern+ ==
+This generic mixin implementation will first call the method, and if it fails with an Exception,
it will try to
+return a value from the cache. If no value is present in the cache (i.e. null is returned
from the cache) then
+the exception will be rethrown.
+
+This concern skip its function if there is no +InvocationCache+ mixin declared on the composite
or if the method
+has a +void+ return type.
+
+== Example ==
+
+Let's say that we have some service that is very expensive to call.
+
+[snippet,java]
+----
+source=libraries/invocationcache/src/test/java/org/qi4j/library/invocationcache/DocumentationSupport.java
+tag=composite
+----
+
+And we know that the argument combinations into this method are relatively few, we can simply
declare the
++SimpleInvocationCache+ mixin implementation to store the permutations and return them if
already been
+provided.
+
+[snippet,java]
+----
+source=libraries/invocationcache/src/test/java/org/qi4j/library/invocationcache/DocumentationSupport.java
+tag=assembly
+----
+
+It is important to realize that the +SimpleInvocationCache+ implementation never drops the
cached values,
+and it is not possible to instruct it to do so. So, in most cases it is required to implement
the +InvocationCache+
+interface yourself, and choose a caching strategy that works for you.
+
+== Custom +InvocationCache+ implementation ==
+The interface to implement is very straight forward. It is important to realize that the
implementation is a
+<<def-private-mixin>> of the composite where the caching is applied, and not
a separate service. So, if
+the implementation is expecting to be part of an entity, it is possible to have
+
+[source,java]
+----
+@This
+private Identity myIdentity;
+----
+
+to get hold of the current entity's +Identity+. This approach makes the caching a lot simpler
than if a separate
+service would have been used instead, but still possible to delegate to such.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/c24b54ec/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/CacheInvocationResultSideEffect.java
----------------------------------------------------------------------
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/CacheInvocationResultSideEffect.java
b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/CacheInvocationResultSideEffect.java
deleted file mode 100644
index fb3e73b..0000000
--- a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/CacheInvocationResultSideEffect.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg.
- *
- * 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.qi4j.library.invocationcache;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.injection.scope.Invocation;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.sideeffect.GenericSideEffect;
-
-/**
- * Cache result of @Cached method calls.
- */
-@AppliesTo( Cached.class )
-public class CacheInvocationResultSideEffect
-    extends GenericSideEffect
-{
-    @This
-    private InvocationCache cache;
-    @Invocation
-    private Method method;
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        // Get value
-        // if an exception is thrown, don't do anything
-        Object res = result.invoke( proxy, method, args );
-        if( res == null )
-        {
-            res = Void.TYPE;
-        }
-        String cacheName = method.getName();
-        if( args != null )
-        {
-            cacheName += Arrays.asList( args );
-        }
-        Object oldResult = cache.cachedValue( cacheName );
-        if( oldResult == null || !oldResult.equals( result ) )
-        {
-            cache.setCachedValue( cacheName, result );
-        }
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/c24b54ec/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvalidateCacheOnSettersSideEffect.java
----------------------------------------------------------------------
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvalidateCacheOnSettersSideEffect.java
b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvalidateCacheOnSettersSideEffect.java
deleted file mode 100644
index f819a76..0000000
--- a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvalidateCacheOnSettersSideEffect.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg.
- *
- * 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.qi4j.library.invocationcache;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.sideeffect.GenericSideEffect;
-
-/**
- * Invalidate cache on setters.
- */
-@AppliesTo( InvalidateCacheOnSettersSideEffect.AppliesTo.class )
-public class InvalidateCacheOnSettersSideEffect
-    extends GenericSideEffect
-{
-    public static class AppliesTo
-        implements AppliesToFilter
-    {
-        @Override
-        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType,
Class<?> modifierClass )
-        {
-            return !( method.getDeclaringClass().equals( InvocationCache.class )
-                      || method.getDeclaringClass().equals( InvocationCacheMixin.class )
);
-
-        }
-    }
-
-    @This
-    private InvocationCache cache;
-
-    @Override
-    protected void invoke( Method method, Object[] args )
-    {
-        cache.clearCachedValues();
-    }
-}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/c24b54ec/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCache.java
----------------------------------------------------------------------
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCache.java
b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCache.java
index 7d83355..4ab8e9c 100644
--- a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCache.java
+++ b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCache.java
@@ -17,9 +17,12 @@
  */
 package org.qi4j.library.invocationcache;
 
+import org.qi4j.api.mixin.Mixins;
+
 /**
  * Invocation Cache.
  */
+@Mixins( SimpleInvocationCacheMixin.class )
 public interface InvocationCache
 {
     Object setCachedValue( String name, Object aResult );

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/c24b54ec/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCacheAbstractComposite.java
----------------------------------------------------------------------
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCacheAbstractComposite.java
b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCacheAbstractComposite.java
deleted file mode 100644
index 183c490..0000000
--- a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCacheAbstractComposite.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg.
- *
- * 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.qi4j.library.invocationcache;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.sideeffect.SideEffects;
-
-/**
- * JAVADOC
- */
-@Mixins( InvocationCacheMixin.class )
-@Concerns( ReturnCachedValueOnExceptionConcern.class )
-@SideEffects( { CacheInvocationResultSideEffect.class, InvalidateCacheOnSettersSideEffect.class
} )
-public interface InvocationCacheAbstractComposite
-{
-}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/c24b54ec/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCacheMixin.java
----------------------------------------------------------------------
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCacheMixin.java
b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCacheMixin.java
deleted file mode 100644
index b45a4a3..0000000
--- a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCacheMixin.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg.
- *
- * 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.qi4j.library.invocationcache;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Default implementation of InvocationCache.
- */
-public class InvocationCacheMixin
-    implements InvocationCache
-{
-    private final Map<String, Object> cachedValues = new ConcurrentHashMap<>();
-
-    @Override
-    public Object setCachedValue( String name, Object aResult )
-    {
-        return cachedValues.put( name, aResult );
-    }
-
-    @Override
-    public Object cachedValue( String name )
-    {
-        return cachedValues.get( name );
-    }
-
-    @Override
-    public Object removeCachedValue( String name )
-    {
-        return cachedValues.remove( name );
-    }
-
-    @Override
-    public void clearCachedValues()
-    {
-        cachedValues.clear();
-    }
-
-    @Override
-    public int currentCacheSize()
-    {
-        return cachedValues.size();
-    }
-}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/c24b54ec/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueConcern.java
----------------------------------------------------------------------
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueConcern.java
b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueConcern.java
index 8c0d2d2..9ad0d3f 100644
--- a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueConcern.java
+++ b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueConcern.java
@@ -21,6 +21,7 @@ import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.util.Arrays;
 import org.qi4j.api.common.AppliesTo;
+import org.qi4j.api.common.Optional;
 import org.qi4j.api.concern.ConcernOf;
 import org.qi4j.api.injection.scope.Invocation;
 import org.qi4j.api.injection.scope.This;
@@ -33,34 +34,29 @@ public class ReturnCachedValueConcern
     extends ConcernOf<InvocationHandler>
     implements InvocationHandler
 {
-    @This
+    @This @Optional
     private InvocationCache cache;
-    @Invocation
-    private Method method;
 
     @Override
     public Object invoke( Object proxy, Method method, Object[] args )
         throws Throwable
     {
-        // Try cache
-        String cacheName = method.getName();
-        if( args != null )
+        boolean voidReturnType = method.getReturnType().equals( Void.TYPE );
+        if( cache != null || voidReturnType )
         {
-            cacheName += Arrays.asList( args );
-        }
-        Object result = cache.cachedValue( cacheName );
-        if( result != null )
-        {
-            if( result == Void.TYPE )
+            // Try cache
+            String cacheName = method.getName();
+            if( args != null )
             {
-                return null;
+                cacheName += Arrays.asList( args );
             }
-            else
+            Object result = cache.cachedValue( cacheName );
+            if( result != null )
             {
                 return result;
             }
         }
-        // No cached value found - call method
+        // No cached value found or no InvocationCache defined - call method
         return next.invoke( proxy, method, args );
     }
 }

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/c24b54ec/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueOnExceptionConcern.java
----------------------------------------------------------------------
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueOnExceptionConcern.java
b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueOnExceptionConcern.java
index 400baf5..1287b39 100644
--- a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueOnExceptionConcern.java
+++ b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueOnExceptionConcern.java
@@ -42,32 +42,29 @@ public class ReturnCachedValueOnExceptionConcern
     public Object invoke( Object proxy, Method method, Object[] args )
         throws Throwable
     {
-        try
+        boolean voidReturnType = method.getReturnType().equals( Void.TYPE );
+        if( cache != null || voidReturnType ) // Skip if void return type or no InvocationCache
has been defined.
         {
-            // Invoke method
-            return next.invoke( proxy, method, args );
-        }
-        catch( Exception e )
-        {
-            // Try cache
             String cacheName = method.getName();
             if( args != null )
             {
                 cacheName += Arrays.asList( args );
             }
-            Object result = cache.cachedValue( cacheName );
-            if( result != null )
+            try
+            {
+                // Invoke method
+                Object result = next.invoke( proxy, method, args );
+                // update cache
+                cache.setCachedValue( cacheName, result );
+                return result;
+            }
+            catch( Exception e )
             {
-                if( result == Void.TYPE )
-                {
-                    return null;
-                }
-                else
-                {
-                    return result;
-                }
+                // Try cache
+                return cache.cachedValue( cacheName );
             }
-            throw e;
         }
+        // if no InvocationCache is present.
+        return next.invoke( proxy, method, args );
     }
 }

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/c24b54ec/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/SimpleInvocationCacheMixin.java
----------------------------------------------------------------------
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/SimpleInvocationCacheMixin.java
b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/SimpleInvocationCacheMixin.java
new file mode 100644
index 0000000..5897412
--- /dev/null
+++ b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/SimpleInvocationCacheMixin.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2007 Rickard Öberg.
+ *
+ * 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.qi4j.library.invocationcache;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Simple implementation of InvocationCache.
+ * <p>
+ * This {@link InvocationCache} should typically not be used at all, and only serves as an
+ * example. The @{code cachedValues} member is never emptied, so it constitutes a memory
leak
+ * if the method arguments keep changing.
+ * </p>
+ * <p>
+ * <b>IMPORTANT: Only use this is you know that only a small set of arguments are used
into your
+ * method(s).</b>
+ * </p>
+ */
+public class SimpleInvocationCacheMixin
+    implements InvocationCache
+{
+    private final Map<String, Object> cachedValues = new ConcurrentHashMap<>();
+
+    @Override
+    public Object setCachedValue( String name, Object aResult )
+    {
+        return cachedValues.put( name, aResult );
+    }
+
+    @Override
+    public Object cachedValue( String name )
+    {
+        return cachedValues.get( name );
+    }
+
+    @Override
+    public Object removeCachedValue( String name )
+    {
+        return cachedValues.remove( name );
+    }
+
+    @Override
+    public void clearCachedValues()
+    {
+        cachedValues.clear();
+    }
+
+    @Override
+    public int currentCacheSize()
+    {
+        return cachedValues.size();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/c24b54ec/libraries/invocation-cache/src/test/java/org/qi4j/library/invocationcache/DocumentationSupport.java
----------------------------------------------------------------------
diff --git a/libraries/invocation-cache/src/test/java/org/qi4j/library/invocationcache/DocumentationSupport.java
b/libraries/invocation-cache/src/test/java/org/qi4j/library/invocationcache/DocumentationSupport.java
new file mode 100644
index 0000000..782ce76
--- /dev/null
+++ b/libraries/invocation-cache/src/test/java/org/qi4j/library/invocationcache/DocumentationSupport.java
@@ -0,0 +1,51 @@
+/*
+ * 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.qi4j.library.invocationcache;
+
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.bootstrap.ModuleAssembly;
+import org.qi4j.bootstrap.layered.ModuleAssembler;
+
+public class DocumentationSupport
+{
+// START SNIPPET: composite
+    public interface ExpensiveOperation
+    {
+        @Cached
+        double compute( double... arguments );
+    }
+// END SNIPPET: composite
+
+// START SNIPPET: assembly
+    public class ExpensiveModuleAssembler
+        implements ModuleAssembler{
+
+        @Override
+        public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.services( ExpensiveOperation.class )
+                .withMixins( SimpleInvocationCacheMixin.class )
+                .withConcerns( ReturnCachedValueConcern.class );
+            return module;
+        }
+    }
+// END SNIPPET: assembly
+}


Mime
View raw message