tags:

views:

98

answers:

6

I have a method that contains the following code:

public void myMethod(){
    final MyDto expectedtDto = new MyDto();

    MyRepository reposWithMock = new MyRepository(){
        protected MyDao createDao(){

            return new MyDao() {
                public MyDto someMethod(){
                   return expectedtDto;
                }
            };

        }
    };

  reposWithMock.doSomethingWithDao();
}

MyRepository.createDao() is called from the constructor of MyRepository. MyDao.someMethod() is called from MyRepository.doSomethingWithDao().

However, the MyDao().someMethod() returns null instead of the expectedDto

Any idea why this is?

For clarification, some real working code:

package nl.tests;

public class TestAnon {
  static class MyDao {
    private int value;

    public MyDao(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
  }

  static class Repository {
    private MyDao dao;

    public Repository() {
        dao = createDao();
    }

    protected MyDao createDao(){
        return new MyDao( 4 );
    }

    public MyDao getDao(){
        return dao;
    }
  }

  public static void main(String[] args) {
    final MyDao testDao = new MyDao(8);

    Repository repos = new Repository() {
        protected MyDao createDao() {
            if ( testDao == null ) {
                System.out.println( "Error ");
                return new MyDao(0);
            }
            return testDao;
        }
    };

    System.out.println( "Dao :" + repos.getDao().getValue() );
  }
}

This results in :

Error 
Dao :0

Some additional information: I currently (have to) work with java 1.4. My development environment is Rational Application Developer 7.

Addendum, to the given (and accepted answer). For the below code I've made the createDao() method public :

public static void main(final String[] args) {        
    final MyDao testDao = new MyDao(8);    


    Repository repos = new Repository() {
        public MyDao createDao() {

            if ( testDao == null ) {
                System.out.println( "Error ");
                return new MyDao(0);
            }
            return testDao;
        }
    };

    System.out.println( "Dao :" + repos.getDao().getValue() );
    System.out.println( "Dao :" + repos.createDao().getValue() );
}

Returns:

Error
Dao :0
Dao :8
A: 

Make sure you actually override the method you think you do. Your IDE or @Override should help.

Aaron Digulla
I know it is overridden. Tracing (Eclipse) show me the method is called.However expectedDto is considered null at that moment.
In that case, the line `final MyDto expectedtDto = new MyDto();` hasn't been called (`final` variables can only be assigned once). This means the code you posted doesn't reflect what is really happening.
Aaron Digulla
Another option is that there is a public/protected field `expectedtDto` in `MyDao` or `MyRepository `
Aaron Digulla
I have now added code that really reflects what's happening. There is no field expectedDto in MyDao or MyRepository. And final MyDto expectedtDto = new MyDto(); has been called.
The code above works, so the bug must be somewhere else.
Aaron Digulla
On my system with Java 5, I get "Dao :8" as expected.
Aaron Digulla
A: 

Is MyDto a child of MyDao?
Your return a MyDto when the method indicates you return a MyDao.
Maybe that is a piece of the problem.

A second solution could be:
Put the expectedtDto in the inner-class instead of the method.

Martijn

Martijn Courteaux
Apologies, that was a typo. MyDto is not a child of MyDAo.I actually applied that solution, however I'd prefer it if the code works as I'd expect it to.
+2  A: 

According to what you provided a quick test outputs MyDto@190d11 or similar. So I bet you left out some important code which is responsible for some variable name hiding.

Test.java

public class Test {
  public static void main(String args[]) {
    new Test().myMethod();
  }
  public void myMethod() {
    final MyDto expectedtDto = new MyDto();

    MyRepository reposWithMock = new MyRepository() {
      @Override
      protected MyDao createDao() {
        return new MyDao() {
          @Override
          public MyDto someMethod(){
            return expectedtDto;
          }
        };
      }
    };
    reposWithMock.doSomethingWithDao();
  }
}

MyDto.java

public class MyDto {}

MyRepository.java

public abstract class MyRepository {
  protected abstract MyDao createDao();
  public void doSomethingWithDao() {
    System.out.println(createDao().someMethod());
  }
}

MyDao.java

public abstract class MyDao {
  public abstract MyDto someMethod();
}
jitter
A: 

Your code works for me. The only way I could see that expectedDto could be null within the anonymous inner class is if you're referencing it on another thread without proper synchronization.

Matt Ryall
A: 

The test-case you described works fine for me.

You should provide minimal but complete standalone test-case that illustrates the problem to get help.

denis.zhdanov
I have now added such code.
Your code produces 'Dao :8' for me (java6 was used during testing)
denis.zhdanov
+4  A: 

It fails in Java 1.4 because the field containing the local variable is not yet initialized when the super constructor for Repository is executed.

It works in Java 1.5 and later, because then the field is initialized before the super constructor is called.

In general it is bad style to call methods which may be overridden in subclasses in a constructor, because it leads to this kind of problems.

starblue
I think you're up to something but I can't follow your explanation. What "local variable" are you talking about?
Aaron Digulla
Ah, I see. Thank you.
@Aaron Digulla The local variable is testDao in main(), which is accessed in the anonymous class. The compiler implements this by adding a parameter for the variable to the constructor and storing its value in a field of the anonymous class, which is then accessed.
starblue