And a small follow-up with something like a probable bug in the Guice.

Consider the variant of code from the previous post - removed using the factory from the constructor and added a "hack" postConstruct method annotated with @inject to the Node class so the Guice will call it some time after the node constructor finishes. This hack-postConstruct method creates child nodes, so the overall result is that nodes are created by the factory and their children are created automatically from the caller point of view (the caller does not have to call "createChildrenLater()" after it gets a instance node from the factory).

When run, this variant does not throw any ProvisionExceptions, but it prints the "!!! the factory returned THIS node instead of the new node !!!" message, which means that the instance returned from the call to factory is equal to the "this" object, probably the previous object created by this factory. This is a bug in the Guice - it should have thrown ProvisionException as before if it does not like the way I use the factory. Of course better yet, it should have returned a new instance, as expected.

If the "@inject postConstruct()" method is modified to "@inject postConstruct( Injector injector )" (a parameter of Injector type is added, but the method body does not use it), then the code will work as was expected from the beginning - there will be no ProvisionExceptions and factory will return unique instances on each call.

How the factory manages to return the same instance in the "@inject method()" variant? Why the difference between "@inject method()" and "@inject method( Injector injector )" variants?

=== start of @inject postConstruct() variant ===
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.FactoryModuleBuilder;

public class TestGuiceModule {

   public static void main( String[] args ) {
       Injector injector = Guice.createInjector( new AbstractModule() {
           @Override
           protected void configure() {
               install( new FactoryModuleBuilder()
.implement( new TypeLiteral<Node<Integer>>() {}, IntegerNode.class ) .build( new TypeLiteral<NodeFactory<Integer>>() {} ) );
           }
       } );

NodeFactory<Integer> factory = injector.getInstance( Key.get( new TypeLiteral<NodeFactory<Integer>>() {} ) );

       System.out.println( "create a node first, create children later" );
       Node<Integer> node1 = factory.createNode( 0 );
       System.out.println();

System.out.println( "create a node and create some children in its constructor" );
       Node<Integer> node2 = factory.createNode( 1 );
   }


   public abstract static class Node<E> {

       public E value;

       public Node( E value ) {
           this.value = value;
       }

       @Inject
       private void postConstruct() {
           System.out.println( "TestGuiceModule$Node.postConstruct" );
           createChildrenLater();
       }

       public abstract void createChildrenLater();
   }

   public static interface NodeFactory<E> {

       Node<E> createNode( E value );

   }

   public static class IntegerNode extends Node<Integer> {

       private final NodeFactory<Integer> factory;

       @Inject
public IntegerNode( @Assisted Integer value, NodeFactory<Integer> factory ) {
           super( value );
System.out.println( "TestGuiceModule$IntegerNode.IntegerNode, this identity=" + System.identityHashCode( this ) + ", value=" + value + ", factory identity=" + System.identityHashCode( factory ) );
           this.factory = factory;
       }

       @Override
       public void createChildrenLater() {
           if ( value > 0 ) {
System.out.println( "TestGuiceModule$IntegerNode.createChildrenLater" );
               Node<Integer> child = factory.createNode( value - 1 );
               if ( this == child ) {
System.out.println( "\t!!! the factory returned THIS node instead of the new node !!!" );
               }
           }
       }

   }

}
=== end of @inject postConstruct() variant ===
--
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en.

Reply via email to