Falha ao criar uma instância do Serviço via ligação adiada

Estou tentando criar um aplicativo da web GWT / Google App Engine usando oestrutura mvp4g.

Eu continuo recebendo um erro sobreFalha ao criar uma instância do meu Serviço por meio de ligação adiada.

Meu arquivo Acebankroll.gwt.xml se parece com:

<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='acebankroll'>
    <inherits name='com.google.gwt.user.User'/>
    <inherits name="com.google.gwt.i18n.I18N"/>
    <inherits name='com.google.gwt.user.theme.standard.Standard'/>  
    <inherits name='com.mvp4g.Mvp4gModule'/>
    <entry-point class='com.softamo.acebankroll.client.AceBankroll'/>
     <source path='client'/>  
</module>

Meu módulo de entrada é semelhante a:

public class AceBankroll implements EntryPoint {
    public void onModuleLoad() {
        Mvp4gModule module = (Mvp4gModule)GWT.create( Mvp4gModule.class );
        module.createAndStartModule();
        RootPanel.get().add((Widget)module.getStartView());
    }
}
Rastreamento de erro

Eu posto o rastreamento completo do erro como resposta.

Perguntas frequentes e avaliações

Eu li que a próxima lista de erros comuns pode causar esse erro:

As interfaces ServiceAsync têm métodos com valores de retorno. Isto éerrado, todos os métodos precisam retornar nulos.

As interfaces de serviço não estendem a interface RemoteService.

Os métodos nas interfaces ServiceAsync perdem o argumento final de AsyncCallback.

Os métodos nos dois interfaces, ExampleService e ExampleServiceAsync, não correspondem exatamente (exceto o valor de retorno e o argumento AsyncCallback)

Verifiquei todas as condições acima e não encontrei o problema.

Como você insere seus serviços nos apresentadores?

Aqui está um trecho que ilustra como injeto o serviço nas minhas aulas de apresentador.

protected MainServiceAsync service = null;
@InjectService
public void setService( MainServiceAsync service ) {
    this.service = service;
}
Você tem as bibliotecas necessárias?

Sim, eu tenho commons-configuration-1.6.jar, commons-lang-2.4.jar e mvp4g-1.1.0.jar no meu diretório lib.

Seu projeto é compilado?

Sim, ele compila. Eu uso o Eclipse com o plug-in GWT / Google App Engine. Em seguida, eu publico meu .classpath

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
    <classpathentry kind="src" path="src"/>
    <classpathentry kind="src" output="test-classes" path="test"/>
    <classpathentry kind="con" path="com.google.appengine.eclipse.core.GAE_CONTAINER"/>
    <classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
    <classpathentry kind="lib" path="lib/commons-configuration-1.6.jar"/>
    <classpathentry kind="lib" path="lib/commons-lang-2.4.jar"/>
    <classpathentry kind="lib" path="lib/mvp4g-1.1.0.jar"/>
    <classpathentry kind="lib" path="test/lib/emma.jar"/>
    <classpathentry kind="lib" path="test/lib/junit-4.5.jar"/>
    <classpathentry kind="lib" path="C:/Users/sdelamo/Programms/eclipse/plugins/com.google.appengine.eclipse.sdkbundle.1.3.1_1.3.1.v201002101412/appengine-java-sdk-1.3.1/lib/testing/appengine-testing.jar"/>
    <classpathentry kind="lib" path="C:/Users/sdelamo/Programms/eclipse/plugins/com.google.appengine.eclipse.sdkbundle.1.3.1_1.3.1.v201002101412/appengine-java-sdk-1.3.1/lib/impl/appengine-api.jar"/>
    <classpathentry kind="lib" path="C:/Users/sdelamo/Programms/eclipse/plugins/com.google.appengine.eclipse.sdkbundle.1.3.1_1.3.1.v201002101412/appengine-java-sdk-1.3.1/lib/impl/appengine-api-labs.jar"/>
    <classpathentry kind="lib" path="C:/Users/sdelamo/Programms/eclipse/plugins/com.google.appengine.eclipse.sdkbundle.1.3.1_1.3.1.v201002101412/appengine-java-sdk-1.3.1/lib/impl/appengine-api-stubs.jar"/>
    <classpathentry kind="lib" path="C:/Users/sdelamo/Programms/eclipse/plugins/com.google.appengine.eclipse.sdkbundle.1.3.1_1.3.1.v201002101412/appengine-java-sdk-1.3.1/lib/impl/appengine-local-runtime.jar"/>
    <classpathentry kind="output" path="war/WEB-INF/classes"/>
</classpath>
O seu Bean é serializável?

Sim, eles são serializáveis. Eles implementam a próxima interface:

public interface BasicBean extends Serializable  {
    public String getId();      
    public void copy(BasicBean ob); 
}

Todos eles têm um construtor de argumentos vazio. Alguns deles têm dois construtores. Um sem argumentos e outro com argumentos.

Alguns deles implementam essa interface

public interface NameObject extends BasicBean, BaseOwnedObject, Comparable<NameObject>   { 
    public String getName();
    public void setName(String name);       
    public abstract int compareTo(NameObject ob);
}

O Comparable pode causar problemas?

Como é o seu código de serviço?

Eu posto meu código de serviço:

MainService
@RemoteServiceRelativePath( "main" )
public interface MainService extends RemoteService {
    public List<UserBean> getUsers();    
    public void deleteUser(UserBean user);    
    public void createUser(UserBean user);    
    public void updateUser( UserBean user );        
    public String authenticate(String username, String password);       
    public boolean isSessionIdStillLegal(String sessionId);     
    public void signOut();      
    public boolean userAlreadyExists(String email);     
    public UserBean getByEmail(String email);       
    public void confirmUser(String email);          
    public UserBean getUserById(String id);
}
MainServiceAsync
public interface MainServiceAsync {
    public void getUsers(AsyncCallback<List<UserBean>> callback);    
    public void deleteUser(UserBean user, AsyncCallback<Void> callback);    
    public void createUser(UserBean user, AsyncCallback<Void> callback);    
    public void updateUser( UserBean user, AsyncCallback<Void> callback);       
    public void authenticate(String username, String password, AsyncCallback<String> callback);     
    public void isSessionIdStillLegal(String sessionId, AsyncCallback<Boolean> callback);       
    public void signOut(AsyncCallback<Void> callback);      
    public void userAlreadyExists(String email, AsyncCallback<Boolean> callback);       
    public void getByEmail(String email, AsyncCallback<UserBean> callback );            
    public void confirmUser(String email, AsyncCallback<Void> callback );           
    public void getUserById(String id, AsyncCallback<UserBean> callback);
}
Feijão básico
import java.io.Serializable;    
public interface BasicBean extends Serializable  {
    public String getId();      
    public void copy(BasicBean ob); 
}
Bean de usuário
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class UserBean implements BasicBean {
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    protected Long ident;       
    @Persistent
    private String name = null;     
    @Persistent
    private String email = null;        
    @Persistent
    private boolean confirmed = false;      
    @Persistent
    private String password = null;

    public UserBean() { }

    public String getId() {
        if( ident == null ) return null;
        return ident.toString();
    }
    public void setId(String id) {
        this.ident = Long.parseLong(id);
    }           
    public String getEmail( ) { return email; }
    public void setEmail(String email) { this. email = email; }     
    public String getName() { return name; }
    public void setName(String name) { this. name = name; }     
    public String getPassword() { return password; }    
    public void setPassword(String password) {  this.password = password;}      
    public boolean isConfirmed() { return confirmed;}
    public void setConfirmed(boolean confirmed) {this.confirmed = confirmed;}       
    public void copy(BasicBean ob) {
         UserBean user = (UserBean) ob;
        this.name = user.name;
        this.email = user.email;
        this.password = user.password;      
    }
}

Em seguida, publico uma extração de web.xml
Nota. Eu tenho 7 outros serviços. Estou usando a funcionalidade do módulo MVP4G. Eu tenho outros servlets definidos para cada módulo no web.xml

<servlet>
    <servlet-name>mainServlet</servlet-name>
    <servlet-class>com.softamo.acebankroll.server.MainServiceImpl</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>mainServlet</servlet-name>
    <url-pattern>/acebankroll/main</url-pattern>
</servlet-mapping>
ServidorBaseServiceImpl
public abstract class BaseServiceImpl extends RemoteServiceServlet {
    protected Map users = new HashMap();
    protected static final MemcacheService memcache = MemcacheServiceFactory.getMemcacheService();
    protected static final Logger log = Logger.getLogger(BaseServiceImpl.class.getName());    
    protected String getSessionId() {
        return getThreadLocalRequest().getSession().getId();
    }    
    protected String getCurrentUserId() {
        String id = getSessionId();
        UserBean user = (UserBean) users.get(id);
        if(user!=null) 
            return user.getId();
        return null;
    }    
    protected void saveBaseObject(BasicBean ob) {
        PersistenceManager pm = JdoUtil.getPm();
        String sessionId = getSessionId();      
        UserBean user = (UserBean) users.get(sessionId);
        if(user!=null) {
            String user_id = user.getId();
            ((BaseOwnedObject)ob).setUserId(user_id);
            pm.makePersistent(ob);
        }           
    }    
    protected void deleteBaseObject(Class classname, String id) {
        PersistenceManager pm = JdoUtil.getPm();                
        pm.deletePersistent( pm.getObjectById(classname, Long.parseLong(id) ));     
    }    
    protected List getAll(Class class_name) {
        PersistenceManager pm = JdoUtil.getPm();
        pm.setDetachAllOnCommit(true);

        Query q = pm.newQuery(class_name);          
        if(q==null) 
            return new ArrayList<BasicBean>();
        q.setFilter("userId == userIdParam");
        q.declareParameters("String userIdParam");          
        String userId = getCurrentUserId();
        return (List) q.execute(userId);
    }    
    public boolean isSessionIdStillLegal(String sessionId) {
        return (users.containsKey(sessionId))? true : false;
    }    
    public void signOut() {
        String id = getSessionId();
        synchronized(this) {
            users.remove(id);
        }
    }    
    public BasicBean getObjectById(Class classname, String id) {
        BasicBean result = null;
        PersistenceManager pm = JdoUtil.getPm();
        pm.setDetachAllOnCommit(true);
        result = pm.getObjectById(classname, Long.parseLong(id) );
        return result;
    }
}
MainServiceImpl
public class MainServiceImpl extends BaseServiceImpl implements MainService {       
    public MainServiceImpl() {}     
    public String authenticate(String username, String password) {
        PersistenceManager pm = JdoUtil.getPm();

        UserBean user = getByEmail(username);
        if(user==null || !user.isConfirmed())
            return null;
        String hashFromDB = user.getPassword();
        boolean valid = BCrypt.checkpw(password, hashFromDB);
        if(valid) { 
            String id = getSessionId();
            synchronized( this ) {
                users.put(id, user) ;
            }
            return id;  
        }
        return null;
    }    
    public void deleteUser(UserBean user) {
        deleteBaseObject(UserBean.class, user.getId());
    }
    public List<UserBean> getUsers() {
        PersistenceManager pm = JdoUtil.getPm();
        pm.setDetachAllOnCommit(true);
        Query q = pm.newQuery(UserBean.class);          
        if(q==null) 
            return new ArrayList<UserBean>();           
        return (List) q.execute();      
    }    
    public boolean userAlreadyExists(String email) {
        return (getByEmail(email)!=null) ? true : false; ,       
    }    
    public void updateUser(UserBean object) {
        saveBaseObject(object);
    }    
    public void confirmUser(String email) {
        PersistenceManager pm = JdoUtil.getPm();        
        UserBean user = getByEmail(email);
        if(user!=null) {
            user.setConfirmed(true);
            pm.makePersistent(user);
        }   
    }    
    public void createUser(UserBean user) {
        PersistenceManager pm = JdoUtil.getPm();
        String sessionId = getSessionId();
        // Only store it if it does not exists
        if( (getByEmail(user.getEmail()))==null) {
            String hash = BCrypt.hashpw(user.getPassword(), BCrypt.gensalt());
            user.setPassword(hash);
            pm.makePersistent(user);
            synchronized( this ) {
                users.put(sessionId, user);              
            }           
        }       
    }    
    public UserBean getByEmail(String email) {
        return new MyAccountServiceImpl().getByEmail(email);
    }    
    public UserBean getUserById(String id) {
        return new MyAccountServiceImpl().getUserById(id);
    }
}
SOLUÇÃO

Aparentemente, as anotações do Google App Engine nas minhas classes Bean estavam causando o problema. A remoção da anotação do código do lado do cliente resolveu o problema. O que sei se tenho as classes com a notação JDO no lado do servidor. Isso significa que os beans são objetos simples de transferência de dados que são clonados no objeto com anotações JDO no lado do servidor.

Eu estou literalmente empilhado. Eu não sei o que tentar. Qualquer ajuda é realmente apreciada!