由于获取NullPointerException,无法使用gwt requestfactory与子实体(@OneToOne关系)持久化实体

时间:2013-10-20 17:56:47

标签: spring hibernate gwt requestfactory

我在我的网络应用程序中使用GWT RequestFactory + Hibernate + Spring。 我有Principal和Profile实体,它们彼此相关是一对一的。它们共享相同的主键。

在客户端,我编写了这样的代码,导致NullPointerException:

如果我排除“principal.setProfile(profile);”代码行,主体实体将成功存储。我无法弄清楚为什么个人资料实体不能与校长一起存储。

任何建议都将受到高度赞赏。提前谢谢!

public RegistrationPanel() {
        TarantulaFactory factory = GWT.create(TarantulaFactory.class);
        factory.initialize(new SimpleEventBus());

        PrincipalRequestContext principalCtx = factory.createPrincipalRequest();
        ProfileRequestContext profileCtx = factory.createProfileRequest();

        PrincipalProxy principal = principalCtx.create(PrincipalProxy.class);
        principal.setLogin("Billy");
        principal.setPassword("Corgan");

        ProfileProxy profile = profileCtx.create(ProfileProxy.class);
        profile.setNickname("A");
        profile.setName("b");        
        profile.setEmail("ABCD34@gmail.com");
        profile.setBirthDate(new Date());
        profile.setCurrentLocation("Chicago");

        principal.setProfile(profile);
        profile.setPrincipal(principal);


        principalCtx.save(principal).fire();
}

堆栈追踪:

//------------------------------------------------------------------------

21:09:24.992 [ERROR] [application] Uncaught exception escaped
    java.lang.NullPointerException: null
    at            com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext$MyConstraintViolation.<init>(AbstractRequestContext.java:434)
    at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext$StandardPayloadDialect.processPayload(AbstractRequestContext.java:366)
    at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext$5.onTransportSuccess(AbstractRequestContext.java:1151)
    at com.google.web.bindery.requestfactory.gwt.client.DefaultRequestTransport$1.onResponseReceived(DefaultRequestTransport.java:136)
    at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:258)
    at com.google.gwt.http.client.RequestBuilder$1.onReadyStateChange(RequestBuilder.java:412)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:338)
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:219)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:571)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:279)
    at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
    at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
    at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:242)
    at sun.reflect.GeneratedMethodAccessor35.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:293)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:547)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
    at java.lang.Thread.run(Thread.java:722)

//------------------------------------------------------------------------

以下是实体,代理和RequestFactory的源代码。

以下是实体类:

Profile.java

package com.szybieka.tarantula.core.domain;

import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;

import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;

/**
* 
* A Profile representing the user profile entity. Each user has single profile.
* Profile and {@link Principal} entities relate to each other as one-to-one.
* Shared primary key is used to join corresponding tables.
* 
* @author Zmicer Szybieka
* 
*/

@Entity
@Table(name = "profile", uniqueConstraints = { @UniqueConstraint(
columnNames = "id") })
public class Profile {

    @Id
    @NotNull
    @Column(name = "id", unique = true)
    @GeneratedValue(generator = "gen")
    @GenericGenerator(name = "gen", strategy = "foreign",
    parameters = @Parameter(name = "property", value = "principal"))
    private Long id;

    @Length(min = 1, max = 30)
    private String nickname;

    @Length(max = 30)
    private String name;

    @Column(name = "birth_date")
    private Date birthDate; // date of birth, e.g. "20.01.1985"

    @Length(max = 30)
    @Column(name = "current_location")
    private String currentLocation; // current location city, e.g. "NYC"

    @Email
    private String email;

    private Date version;

    @OneToOne(mappedBy = "profile", cascade = CascadeType.ALL)
    private Principal principal; // the user principal corresponding to the
                             // profile

    public Profile() {
    }

    public Long getId() {
       return id;
    }

public void setId(Long id) {
    this.id = id;
}

// omit setters/getters
}

Principal.java

package com.szybieka.tarantula.core.domain;

import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.hibernate.validator.constraints.Length;

/**
 * A Principal representing an identity used to determine access rights to
 * application. Principal relates to {@link Profile} entity as one-to-one.
 * Shared primary key is used to join corresponding tables.
 * 
 * @author Zmicer Szybieka
 * 
*/

@Entity
@Table(name = "principal", uniqueConstraints = { @UniqueConstraint(
    columnNames = "id") })
public class Principal {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Length(max = 20)
    private String login;

    @Length(max = 10)
    private String password;

    private Date version;

    @OneToOne(cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    private Profile profile;

    public Principal() {
    }

    public Long getId() {
       return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    // omit setters/getters
}

我使用RequestFactory连接服务器端。

这是我的RequestFactory:

TarantulaFactory.java

package com.szybieka.tarantula.gwt.client.requestfactory;

import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.RequestFactory;  
import com.google.web.bindery.requestfactory.shared.Service;
import com.szybieka.tarantula.gwt.client.proxy.PrincipalProxy;
import com.szybieka.tarantula.gwt.client.proxy.ProfileProxy;
import com.szybieka.tarantula.gwt.server.locator.PrincipalServiceLocator;
import com.szybieka.tarantula.gwt.server.locator.ProfileServiceLocator;
import com.szybieka.tarantula.gwt.server.service.PrincipalService;
import com.szybieka.tarantula.gwt.server.service.ProfileService;

public interface TarantulaFactory extends RequestFactory {

    PrincipalRequestContext createPrincipalRequest();

    ProfileRequestContext createProfileRequest();

    @Service(value = ProfileService.class,
        locator = ProfileServiceLocator.class)
    public interface ProfileRequestContext extends RequestContext {

        Request<Void> save(ProfileProxy profile);

        Request<ProfileProxy> findProfile(Long id);
    }

    @Service(value = PrincipalService.class,
        locator = PrincipalServiceLocator.class)
    public interface PrincipalRequestContext extends RequestContext {

        Request<PrincipalProxy> findPrincipal(String login, String password);

        Request<PrincipalProxy> findPrincipal(Long id);

        Request<PrincipalProxy> findPrincipalByLogin(String login);

        Request<Void> save(PrincipalProxy principal);

        Request<Void> remove(PrincipalProxy principal);
    }
}

以下是实体类的代理:

ProfileProxy.java

package com.szybieka.tarantula.gwt.client.proxy;

import java.util.Date;

import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
import com.szybieka.tarantula.core.domain.Profile;
import com.szybieka.tarantula.gwt.server.locator.ProfileLocator;

@ProxyFor(value = Profile.class, locator = ProfileLocator.class)
public interface ProfileProxy extends EntityProxy {

    Long getId();

    void setId(Long id);

    // omit other getter/setter methods

}

PrincipalProxy.java

package com.szybieka.tarantula.gwt.client.proxy;

import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
import com.szybieka.tarantula.core.domain.Principal;
import com.szybieka.tarantula.gwt.server.locator.PrincipalLocator;

@ProxyFor(value = Principal.class, locator = PrincipalLocator.class)
public interface PrincipalProxy extends EntityProxy {

    Long getId();

    String getLogin();

    // omit other getter/setter methods
}

1 个答案:

答案 0 :(得分:1)

RequestContext是批处理请求的构建器,您最终触发以发送到服务器进行处理。必须在批处理请求中从同一RequestContext创建和编辑所有代理。

删除您对ProfileRequestContext的使用,并将profileCtx.create(ProfileProxy.class)替换为principalCtx.create(ProfileProxy.class)