Error al crear una instancia de Servicio a través de enlace diferido

He estado tratando de crear una aplicación web GWT / Google App Engine usando elmarco mvp4g.

Sigo recibiendo un error sobreNo crear una instancia de mi Servicio a través de un enlace diferido.

Mi archivo Acebankroll.gwt.xml se ve así:

<?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>

Mi módulo de entrada se ve así:

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

Publico el seguimiento de error completo como respuesta.

Preguntas frecuentes y ensayos

He leído que la siguiente lista de errores comunes puede causar este error:

Las interfaces de ServiceAsync tienen métodos con valores de retorno. Esto esincorrecto, todos los métodos deben devolver nulo.

Las interfaces de servicio no extienden la interfaz RemoteService.

Los métodos en las interfaces ServiceAsync pierden el argumento final de AsyncCallback.

Los métodos en las dos interfaces, ExampleService y ExampleServiceAsync, no coinciden exactamente (aparte del valor de retorno y el argumento AsyncCallback)

Revisé todas las condiciones anteriores y no encontré el problema.

¿Cómo inserta sus servicios en los presentadores?

Aquí hay un fragmento que ilustra cómo inyecto el servicio en mis clases de presentador.

protected MainServiceAsync service = null;
@InjectService
public void setService( MainServiceAsync service ) {
    this.service = service;
}
¿Tienes las bibliotecas necesarias?

Sí, tengo commons-configuration-1.6.jar, commons-lang-2.4.jar y mvp4g-1.1.0.jar en mi directorio lib.

¿Tu proyecto se compila?

Sí, se compila. Uso Eclipse con el complemento GWT / Google App Engine. A continuación publico mi .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>
¿Son sus frijoles serializables?

Sí, son serializables. Implementan la siguiente interfaz:

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

Todos tienen un constructor de argumentos vacío. Algunos de ellos tienen dos constructores. Uno sin argumentos y otro con argumentos.

Algunos de ellos implementan esta interfaz

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

¿Puede el Comparable causar problemas?

¿Cómo se ve su código de servicio?

Publico mi código de servicio:

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);
}
Frijol Básico
import java.io.Serializable;    
public interface BasicBean extends Serializable  {
    public String getId();      
    public void copy(BasicBean ob); 
}
Usuario Bean
@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;      
    }
}

A continuación publico un extracto de web.xml
Nota. Tengo otros 7 servicios. Estoy usando la funcionalidad del módulo de MVP4G. Tengo otros servlets definidos para cada módulo en 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);
    }
}
SOLUCIÓN

Aparentemente, las anotaciones de Google App Engine en mis clases de Bean estaban causando el problema. Eliminar la anotación del código del lado del cliente resolvió el problema. Lo que sí sé si tengo las clases con la notación JDO en el lado del servidor. Es decir, los beans son objetos de transferencia de datos simples que se clonan en objetos con anotaciones JDO en el lado del servidor.

Estoy literalmente apilado. No se que intentar. ¡Cualquier ayuda es muy apreciada!

Respuestas a la pregunta(2)

Su respuesta a la pregunta