You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ga...@apache.org on 2009/07/30 23:12:29 UTC

svn commit: r799440 - in /geronimo/sandbox/blueprint/blueprint-core/src: main/java/org/apache/geronimo/blueprint/container/ main/java/org/apache/geronimo/blueprint/di/ test/java/org/apache/geronimo/blueprint/ test/java/org/apache/geronimo/blueprint/poj...

Author: gawor
Date: Thu Jul 30 21:12:29 2009
New Revision: 799440

URL: http://svn.apache.org/viewvc?rev=799440&view=rev
Log:
break cyclic dependencies and other updates

Added:
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/DependencyGraph.java   (with props)
Modified:
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/AbstractServiceReferenceRecipe.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BeanRecipe.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintContainerImpl.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintRepository.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ServiceRecipe.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/AbstractRecipe.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/Recipe.java
    geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/WiringTest.java
    geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/pojos/PojoCircular.java
    geronimo/sandbox/blueprint/blueprint-core/src/test/resources/test-circular.xml

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/AbstractServiceReferenceRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/AbstractServiceReferenceRecipe.java?rev=799440&r1=799439&r2=799440&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/AbstractServiceReferenceRecipe.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/AbstractServiceReferenceRecipe.java Thu Jul 30 21:12:29 2009
@@ -169,14 +169,21 @@
         return satisfied.get();
     }
 
+    @Override
+    public List<Recipe> getConstructorDependencies() {
+        List<Recipe> recipes = new ArrayList<Recipe>();
+        if (explicitDependencies != null) {
+            recipes.addAll(explicitDependencies);
+        }
+        return recipes;
+    }
+    
     public List<Recipe> getDependencies() {
         List<Recipe> recipes = new ArrayList<Recipe>();
         if (listenersRecipe != null) {
             recipes.add(listenersRecipe);
         }
-        if (explicitDependencies != null) {
-            recipes.addAll(explicitDependencies);
-        }
+        recipes.addAll(getConstructorDependencies());
         return recipes;
     }
 

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BeanRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BeanRecipe.java?rev=799440&r1=799439&r2=799440&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BeanRecipe.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BeanRecipe.java Thu Jul 30 21:12:29 2009
@@ -128,13 +128,11 @@
         this.explicitDependencies = explicitDependencies;
     }
 
-    public List<Recipe> getDependencies() {
+    @Override
+    public List<Recipe> getConstructorDependencies() {
         List<Recipe> recipes = new ArrayList<Recipe>();
-        for (Object o : properties.values()) {
-            if (o instanceof Recipe) {
-                Recipe recipe = (Recipe) o;
-                recipes.add(recipe);
-            }
+        if (explicitDependencies != null) {
+            recipes.addAll(explicitDependencies);
         }
         if (arguments != null) {
             for (Object argument : arguments) {
@@ -143,9 +141,18 @@
                 }
             }
         }
-        if (explicitDependencies != null) {
-            recipes.addAll(explicitDependencies);
+        return recipes;
+    }
+    
+    public List<Recipe> getDependencies() {
+        List<Recipe> recipes = new ArrayList<Recipe>();
+        for (Object o : properties.values()) {
+            if (o instanceof Recipe) {
+                Recipe recipe = (Recipe) o;
+                recipes.add(recipe);
+            }
         }
+        recipes.addAll(getConstructorDependencies());
         return recipes; 
     }
 

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintContainerImpl.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintContainerImpl.java?rev=799440&r1=799439&r2=799440&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintContainerImpl.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintContainerImpl.java Thu Jul 30 21:12:29 2009
@@ -437,7 +437,8 @@
         }
 
         Map<String, Object> objects = repository.createAll(typeConverters);
-        for (Object obj : objects.values()) {
+        for (String name : typeConverters) {
+            Object obj = objects.get(name);
             if (obj instanceof Converter) {
                 converter.registerConverter((Converter) obj);
             } else {

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintRepository.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintRepository.java?rev=799440&r1=799439&r2=799440&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintRepository.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintRepository.java Thu Jul 30 21:12:29 2009
@@ -21,6 +21,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -116,13 +117,27 @@
         recipes.put(name, recipe);
     }
 
+    private Object convert(String name, Object instance) throws ComponentDefinitionException {
+        try {
+            // Make sure to go through the conversion step in case we have a Convertible object
+            return convert(instance, new ReifiedType(Object.class));
+        } catch (Exception e) {
+            throw new ComponentDefinitionException("Unable to convert instance " + name, e);
+        }
+    }
+    
     public Object create(String name) throws ComponentDefinitionException {
         return create(name, true);
     }
     
     public Object create(String name, boolean allowReentry) throws ComponentDefinitionException {
-        Map<String, Object> instances = createAll(Arrays.asList(name), allowReentry);
-        return instances.get(name);
+        ExecutionContext oldContext = ExecutionContext.Holder.setContext(this);
+        try {
+            Object instance = createInstance(name, allowReentry);                       
+            return convert(name, instance);
+        } finally {
+            ExecutionContext.Holder.setContext(oldContext);
+        }
     }
 
     public Map<String, Object> createAll(Collection<String> names) throws ComponentDefinitionException {
@@ -132,16 +147,10 @@
     public Map<String, Object> createAll(Collection<String> names, boolean allowReentry) throws ComponentDefinitionException {
         ExecutionContext oldContext = ExecutionContext.Holder.setContext(this);
         try {
-            Map<String, Object> instances = new LinkedHashMap<String, Object>();
+            Map<String, Object> instances = createInstances(names, allowReentry);                       
             for (String name : names) {
-                Object obj = createInstance(name, allowReentry);
-                try {
-                    // Make sure to go through the conversion step in case we have a Convertible object
-                    obj = convert(obj, new ReifiedType(Object.class));
-                } catch (Exception e) {
-                    throw new ComponentDefinitionException("Unable to convert instance " + name, e);
-                }
-                instances.put(name, obj);
+                Object obj = instances.get(name);
+                instances.put(name, convert(name, obj));
             }
             return instances;
         } finally {
@@ -187,36 +196,46 @@
     }
 
     private Object createInstance(String name, boolean allowReentry) {
+        Object instance = getInstance(name);
+        if (instance == null) {
+            Map <String, Object> instances = createInstances(Arrays.asList(name), allowReentry);
+            instance = instances.get(name); 
+            if (instance == null) {
+                throw new NoSuchComponentException(name);
+            }
+        }
+        return instance;
+    }
+
+    private Map<String, Object> createInstances(Collection<String> names, boolean allowReentry) {
         // We need to synchronize recipe creation on the repository
         // so that we don't end up with multiple threads creating the
         // same instance at the same time.
-        Object instance = getInstance(name);
-        if (instance == null) {
-            synchronized (instanceLock) {
-                try {
-                    if (!allowReentry) {
-                        createReentered++;               
-                    }
-                    instance = getInstance(name);
-                    if (instance == null) {
-                        Recipe recipe = getRecipe(name);
-                        if (recipe != null) {
-                            instance = recipe.create();
-                        }
-                    }
-                } finally {
-                    if (!allowReentry) {
-                        createReentered--;
+        synchronized (instanceLock) {
+            try {
+                if (!allowReentry) {
+                    createReentered++;
+                }
+                DependencyGraph graph = new DependencyGraph(this);
+                HashMap<String, Object> objects = new LinkedHashMap<String, Object>();
+                for (Map.Entry<String, Recipe> entry : graph.getSortedRecipes(names).entrySet()) {
+                    String name = entry.getKey();
+                    Object object = instances.get(name);
+                    if (object == null) {
+                        Recipe recipe = entry.getValue();
+                        object = recipe.create();
                     }
+                    objects.put(name, object);
+                }
+                return objects;
+            } finally {
+                if (!allowReentry) {
+                    createReentered--;
                 }
             }
         }
-        if (instance == null) {
-            throw new NoSuchComponentException(name);
-        }
-        return instance;
     }
-
+    
     public boolean isCreateReentered() {
         return createReentered >= 2;
     }

Added: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/DependencyGraph.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/DependencyGraph.java?rev=799440&view=auto
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/DependencyGraph.java (added)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/DependencyGraph.java Thu Jul 30 21:12:29 2009
@@ -0,0 +1,188 @@
+/**
+ *
+ * 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.geronimo.blueprint.container;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.geronimo.blueprint.di.CircularDependencyException;
+import org.apache.geronimo.blueprint.di.Recipe;
+import org.apache.geronimo.blueprint.di.RefRecipe;
+import org.osgi.service.blueprint.container.NoSuchComponentException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DependencyGraph {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(DependencyGraph.class);
+
+    private BlueprintRepository repository;
+    
+    public DependencyGraph(BlueprintRepository repository) {
+        this.repository = repository;        
+    }
+    
+    public LinkedHashMap<String, Recipe> getSortedRecipes(Collection<String> names) {
+        // construct the graph
+        Map<String, Node> nodes = new LinkedHashMap<String, Node>();
+        for (String name : names) {
+            Object object = repository.getObject(name);
+            if (object == null) {
+                throw new NoSuchComponentException(name);
+            }
+            if (object instanceof Recipe) {
+                Recipe recipe = (Recipe) object;
+                if (!recipe.getName().equals(name)) {
+                    throw new RuntimeException("Recipe '" + name + "' returned from the repository has name '" + name + "'");
+                }
+                createNode(name, recipe,  nodes);
+            }
+        }
+
+        // find all initial leaf nodes (and islands)
+        List<Node> sortedNodes = new ArrayList<Node>(nodes.size());
+        LinkedList<Node> leafNodes = new LinkedList<Node>();
+        for (Node n : nodes.values()) {
+            if (n.referenceCount == 0) {
+                // if the node is totally isolated (no in or out refs),
+                // move it directly to the finished list, so they are first
+                if (n.references.size() == 0) {
+                    sortedNodes.add(n);
+                } else {
+                    leafNodes.add(n);
+                }
+            }
+        }
+
+        // pluck the leaves until there are no leaves remaining
+        while (!leafNodes.isEmpty()) {
+            Node node = leafNodes.removeFirst();
+            sortedNodes.add(node);
+            for (Node ref : node.references) {
+                ref.referenceCount--;
+                if (ref.referenceCount == 0) {
+                    leafNodes.add(ref);
+                }
+            }
+        }
+
+        // There are no more leaves so if there are there still
+        // unprocessed nodes in the graph, we have one or more curcuits
+        if (sortedNodes.size() != nodes.size()) {
+            findCircuit(nodes.values().iterator().next(), new ArrayList<Recipe>(nodes.size()));
+            // find circuit should never fail, if it does there is a programming error
+            throw new RuntimeException("Internal Error: expected a CircularDependencyException");
+        }
+        
+        // return the recipes
+        LinkedHashMap<String, Recipe> sortedRecipes = new LinkedHashMap<String, Recipe>();
+        for (Node node : sortedNodes) {
+            sortedRecipes.put(node.name, node.recipe);
+        }
+        
+        return sortedRecipes;
+    }
+
+    private void findCircuit(Node node, ArrayList<Recipe> stack) {
+        if (stack.contains(node.recipe)) {
+            ArrayList<Recipe> circularity = new ArrayList<Recipe>(stack.subList(stack.indexOf(node.recipe), stack.size()));
+
+            // remove anonymous nodes from circularity list
+            for (Iterator<Recipe> iterator = circularity.iterator(); iterator.hasNext();) {
+                Recipe recipe = iterator.next();
+                if (recipe != node.recipe && recipe.getName() == null) {
+                    iterator.remove();
+                }
+            }
+
+            // add ending node to list so a full circuit is shown
+            circularity.add(node.recipe);
+            
+            throw new CircularDependencyException(circularity);
+        }
+
+        stack.add(node.recipe);
+        for (Node reference : node.references) {
+            findCircuit(reference, stack);
+        }
+    }
+
+    private Node createNode(String name, Recipe recipe, Map<String, Node> nodes) {
+        // if node already exists, verify that the exact same recipe instnace is used for both
+        if (nodes.containsKey(name)) {
+            Node node = nodes.get(name);
+            if (node.recipe != recipe) {
+                throw new RuntimeException("The name '" + name +"' is assigned to multiple recipies");
+            }
+            return node;
+        }
+
+        // create the node
+        Node node = new Node();
+        node.name = name;
+        node.recipe = recipe;
+        nodes.put(name, node);
+
+        // link in the references
+        LinkedList<Recipe> constructorRecipes = new LinkedList<Recipe>(recipe.getConstructorDependencies());
+        while (!constructorRecipes.isEmpty()) {
+            Recipe nestedRecipe = constructorRecipes.removeFirst();            
+            if (nestedRecipe instanceof RefRecipe) {
+                nestedRecipe =  nestedRecipe.getDependencies().get(0);
+                String nestedName = nestedRecipe.getName();
+                Node nestedNode = createNode(nestedName, nestedRecipe, nodes);
+                node.referenceCount++;
+                nestedNode.references.add(node);                
+            } else {
+                constructorRecipes.addAll(nestedRecipe.getDependencies());
+            }
+        }
+        
+        return node;
+    }
+
+    private class Node {
+        String name;
+        Recipe recipe;
+        final List<Node> references = new ArrayList<Node>();
+        int referenceCount;
+        
+        public String toString() {
+            StringBuffer buf = new StringBuffer();
+            buf.append("Node[").append(name);
+            if (references.size() > 0) {
+                buf.append(" <- ");
+                Iterator<Node> iter = references.iterator();
+                while(iter.hasNext()) {
+                    buf.append(iter.next().name);
+                    if (iter.hasNext()) {
+                        buf.append(", ");
+                    }
+                }
+            }
+            buf.append("]");
+            return buf.toString();
+        }
+
+    }
+}

Propchange: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/DependencyGraph.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/DependencyGraph.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/DependencyGraph.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ServiceRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ServiceRecipe.java?rev=799440&r1=799439&r2=799440&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ServiceRecipe.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ServiceRecipe.java Thu Jul 30 21:12:29 2009
@@ -102,6 +102,15 @@
         return listenersRecipe;
     }
 
+    @Override
+    public List<Recipe> getConstructorDependencies() {
+        List<Recipe> recipes = new ArrayList<Recipe>();
+        if (explicitDependencies != null) {
+            recipes.addAll(explicitDependencies);
+        }
+        return recipes;
+    }
+    
     public List<Recipe> getDependencies() {
         List<Recipe> recipes = new ArrayList<Recipe>();
         if (serviceRecipe != null) {
@@ -112,10 +121,8 @@
         }
         if (propertiesRecipe != null) {
             recipes.add(propertiesRecipe);
-        }
-        if (explicitDependencies != null) {
-            recipes.addAll(explicitDependencies);
-        }
+        }        
+        recipes.addAll(getConstructorDependencies());        
         return recipes;
     }
 

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/AbstractRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/AbstractRecipe.java?rev=799440&r1=799439&r2=799440&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/AbstractRecipe.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/AbstractRecipe.java Thu Jul 30 21:12:29 2009
@@ -19,6 +19,8 @@
 
 import java.lang.reflect.Type;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 import org.apache.geronimo.blueprint.container.GenericType;
 import org.osgi.service.blueprint.container.ReifiedType;
@@ -28,6 +30,7 @@
 
     protected final String name;
     protected boolean prototype = true;
+    private boolean creating = false;
 
     protected AbstractRecipe(String name) {
         if (name == null) throw new NullPointerException("name is null");
@@ -51,18 +54,19 @@
         ExecutionContext context = ExecutionContext.Holder.getContext();
 
         synchronized (context.getInstanceLock()) {
+            if (creating && context.isCreateReentered()) {
+                ArrayList<Recipe> circularity = new ArrayList<Recipe>();
+                circularity.add(this);
+                throw new CircularDependencyException("Dynamic cycle detected in recipe", circularity);
+            }
             // if this recipe has already been executed in this container, return the currently registered value
             Object obj = context.getPartialObject(name);
             if (obj != null) {
-                if (context.isCreateReentered()) {
-                    ArrayList<Recipe> circularity = new ArrayList<Recipe>();
-                    circularity.add(this);
-                    throw new CircularDependencyException("Dynamic cycle detected in recipe", circularity);
-                }
                 return obj;
             }
 
             // execute the recipe
+            creating = true;
             context.push(this);
             try {
                 obj = internalCreate();
@@ -73,6 +77,7 @@
                 }
                 return obj;
             } finally {
+                creating = false;
                 Recipe popped = context.pop();
                 if (popped != this) {
                     //noinspection ThrowFromFinallyBlock
@@ -120,6 +125,10 @@
     public void destroy(Object instance) {
     }
 
+    public List<Recipe> getConstructorDependencies() {
+        return Collections.emptyList();
+    }
+    
     public String toString() {
         return getClass().getSimpleName() + "[" +
                 "name='" + name + '\'' +

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/Recipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/Recipe.java?rev=799440&r1=799439&r2=799440&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/Recipe.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/di/Recipe.java Thu Jul 30 21:12:29 2009
@@ -33,9 +33,19 @@
      * @return the unique name for this recipe.
      */
     String getName();
+    
+    /**
+     * Get the list of constructor dependencies, i.e. explicit and
+     * argument dependencies. These dependencies must be satisfied
+     * before the an object can be created.
+     * 
+     * @return a list of constructor dependencies
+     */
+    List<Recipe> getConstructorDependencies();
 
     /**
-     * Get the list of nested recipes, i.e. its dependencies.
+     * Get the list of nested recipes, i.e. all dependencies including 
+     * constructor dependencies.
      *
      * @return a list of dependencies
      */

Modified: geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/WiringTest.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/WiringTest.java?rev=799440&r1=799439&r2=799440&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/WiringTest.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/WiringTest.java Thu Jul 30 21:12:29 2009
@@ -338,20 +338,11 @@
     }
     
     public void testCircular() throws Exception {
-        ComponentDefinitionRegistryImpl registry = parse("/test-circular.xml");
-        Repository repository = new TestBlueprintContainer(registry).getRepository();
+        BlueprintRepository repository = createBlueprintContainer().getRepository();
 
         // this should pass (we allow circular dependencies for components without init method)
         Object obj1 = repository.create("a");
-        
-//        // this should fail (we do not allow circular dependencies for components with init method)
-//        try {
-//            graph.create("c");
-//            fail("Test should have thrown an exception caused by the circular reference");
-//        } catch (Exception e) {
-//            // ok
-//        }
-        
+                
         // test service and listener circular dependencies
         Object obj2 = repository.create("service");
         assertNotNull(obj2);
@@ -365,8 +356,7 @@
     }
      
     public void testCircularPrototype() throws Exception {
-        ComponentDefinitionRegistryImpl registry = parse("/test-circular.xml");
-        BlueprintRepository repository = new TestBlueprintContainer(registry).getRepository();
+        BlueprintRepository repository = createBlueprintContainer().getRepository();
         
         PojoCircular driver1 = (PojoCircular) repository.create("circularPrototypeDriver");
         
@@ -385,8 +375,7 @@
     }
     
     public void testRecursive() throws Exception {
-        ComponentDefinitionRegistryImpl registry = parse("/test-circular.xml");
-        BlueprintRepository repository = new TestBlueprintContainer(registry).getRepository();
+        BlueprintRepository repository = createBlueprintContainer().getRepository();
         
         try {
             repository.create("recursiveConstructor", false);
@@ -424,4 +413,23 @@
             }
         }
     }
+    
+    public void testCircularBreaking() throws Exception {
+        BlueprintRepository repository;
+        
+        repository = createBlueprintContainer().getRepository();        
+        assertNotNull(repository.create("c1"));
+        
+        repository = createBlueprintContainer().getRepository();        
+        assertNotNull(repository.create("c2"));
+        
+        repository = createBlueprintContainer().getRepository();        
+        assertNotNull(repository.create("c3"));
+    }
+    
+    private TestBlueprintContainer createBlueprintContainer() throws Exception {
+        ComponentDefinitionRegistryImpl registry = parse("/test-circular.xml");
+        return new TestBlueprintContainer(registry);
+    }
+    
 }

Modified: geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/pojos/PojoCircular.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/pojos/PojoCircular.java?rev=799440&r1=799439&r2=799440&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/pojos/PojoCircular.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/pojos/PojoCircular.java Thu Jul 30 21:12:29 2009
@@ -22,6 +22,13 @@
 
     private PojoCircular circular;
 
+    public PojoCircular() {        
+    }
+    
+    public PojoCircular(PojoCircular circular) {
+        this.circular = circular;
+    }
+    
     public PojoCircular getCircular() {
         return circular;
     }

Modified: geronimo/sandbox/blueprint/blueprint-core/src/test/resources/test-circular.xml
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/test/resources/test-circular.xml?rev=799440&r1=799439&r2=799440&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/test/resources/test-circular.xml (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/test/resources/test-circular.xml Thu Jul 30 21:12:29 2009
@@ -55,7 +55,7 @@
            unregistration-method="unregister"/>
     </service>
     
-    
+    <!-- for prototype cycle tests -->
     
     <bean id="circularPrototype" class="org.apache.geronimo.blueprint.pojos.PojoCircular" scope = "prototype">
         <property name="circular" ref="circularPrototype"/>
@@ -64,9 +64,9 @@
     <bean id="circularPrototypeDriver" class="org.apache.geronimo.blueprint.pojos.PojoCircular" scope = "prototype">
         <property name="circular" ref="circularPrototypeDriver"/>
     </bean>
-    
-    
-    
+            
+     <!-- for dynamic cycle tests (blueprintContainer.getComponentInstance()) -->
+     
     <bean id="recursiveConstructor" class="org.apache.geronimo.blueprint.pojos.PojoRecursive">
         <argument ref="blueprintContainer"/>
         <argument value="recursiveConstructor"/>
@@ -84,4 +84,18 @@
         <argument value="recursiveInitMethod"/>
     </bean>
 
+    <!-- for breaking dependency cycle tests  -->
+
+    <bean id="c1" class="org.apache.geronimo.blueprint.pojos.PojoCircular">
+        <argument ref="c2"/>
+    </bean>
+    
+    <bean id="c2" class="org.apache.geronimo.blueprint.pojos.PojoCircular">
+        <argument ref="c3"/>
+    </bean>
+    
+    <bean id="c3" class="org.apache.geronimo.blueprint.pojos.PojoCircular">
+        <property name="circular" ref="c1"/>
+    </bean>
+    
 </blueprint>
\ No newline at end of file