我在我的网络应用程序中使用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
}
答案 0 :(得分:1)
RequestContext
是批处理请求的构建器,您最终触发以发送到服务器进行处理。必须在批处理请求中从同一RequestContext
创建和编辑所有代理。
删除您对ProfileRequestContext
的使用,并将profileCtx.create(ProfileProxy.class)
替换为principalCtx.create(ProfileProxy.class)
。