我有一个jsf表单,其中用户键入一个int和一个字符串值,在单击Save按钮后存储在数据库中。
<h:form id="TbtestCreateForm">
<p:inputText value="#{tbtestController.selected.name}" />
<p:commandButton actionListener="#{tbtestController.saveNew}" value="#{myBundle.Save}" />
</h:form>
我正在使用带有façade模式的EJB,它使用AbstractController类中定义的CRUD操作,该类使用“绑定”实体类的AbstractFacade。
我需要的是硬编码/手动设置表单中的字符串值,并将其与用户通知的int值一起存储在数据库中,在同一操作中(同一个对象)
我尝试过如下操作,但没有成功:
@Named
public class MyBean implements Serializable {
@Inject
TbtestController tbtestController;
private String myName;
//GETTERS AND SETTERS
@PostConstruct
public void init() {
myName = "some foo name";
Tbtest myTbtest = new Tbtest();
myTbtest.setName(myName);
tbtestController.setSelected(myTbtest);
tbtestController.saveNew(null); // to simulate what the savNew method do
}
我已经创建了一个可以克隆的小型netbeans项目:https://github.com/f6750699/webAppTest.git
下面是AbstractController类中定义的2个方法:
saveNew 方法:
public void saveNew(ActionEvent event) {
String msg = ResourceBundle.getBundle("/MyBundle").getString(itemClass.getSimpleName() + "Created");
persist(PersistAction.CREATE, msg);
if (!isValidationFailed()) {
items = null; // Invalidate list of items to trigger re-query.
}
}
持久方法:
private void persist(PersistAction persistAction, String successMessage) {
if (selected != null) {
this.setEmbeddableKeys();
try {
if (persistAction != PersistAction.DELETE) {
this.ejbFacade.edit(selected);
} else {
this.ejbFacade.remove(selected);
}
JsfUtil.addSuccessMessage(successMessage);
} catch (EJBException ex) {
Throwable cause = JsfUtil.getRootCause(ex.getCause());
if (cause != null) {
if (cause instanceof ConstraintViolationException) {
ConstraintViolationException excp = (ConstraintViolationException) cause;
for (ConstraintViolation s : excp.getConstraintViolations()) {
JsfUtil.addErrorMessage(s.getMessage());
}
} else {
String msg = cause.getLocalizedMessage();
if (msg.length() > 0) {
JsfUtil.addErrorMessage(msg);
} else {
JsfUtil.addErrorMessage(ex, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
}
}
}
} catch (Exception ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
JsfUtil.addErrorMessage(ex, ResourceBundle.getBundle("/MyBundle").getString("PersistenceErrorOccured"));
}
}
}
我真的很感激它的一些帮助,因为我已经坚持了一段时间了。
提前致谢。
保罗莫里斯解决方案
我专注于一节课,正如保罗建议的那样:
@Named
@ViewScoped
public class TbtestController extends AbstractController<Tbtest> {
@EJB
private TbtestFacade ejbFacade;
public TbtestController() {
super(Tbtest.class); //-> there is already an invocation here, see below
}
@PostConstruct
@Override
public void init() {
super.setFacade(ejbFacade);
//Paul Morris solution below
myName = "some foo name";
this.setMyName(myName);
this.saveNew(null); // to simulate what the savNew method do
}
private String myName;
public void setMyName(String name) {
myName = name;
}
@Override
public void saveNew(ActionEvent event) {
this.getSelected().setName(myName);
//super.(event); // -> invocation of a superclass constructor must be the first line in the subclass constructor, but there is already one invocation, see above. Then, I've tried to invoke the super method:
super.saveNew(event); // but this didn't resolved, as it launches a NullPointerException, see below.
}
}
例外:
org.jboss.weld.exceptions.WeldException: WELD-000049: Unable to invoke public void beans.TbtestController.init() on beans.TbtestController@37668b21
[...]
Caused by: java.lang.NullPointerException
at beans.TbtestController.saveNew(TbtestController.java:40)
at beans.TbtestController.init(TbtestController.java:29)
... 87 more
答案 0 :(得分:1)
你说这一切都错了。将AbstractController类保留为生成。相反,修改派生类TbtestController并为硬编码字符串添加属性。然后覆盖saveNew方法,如下所示:
private String myName;
public void setMyName(String name) {
myName = name;
}
@Override
public void saveNew(ActionEvent event) {
this.getSelected().setName(myName);
super.saveNew(event);
}
然后你的bean方法应该像这样编码:
@PostConstruct
public void init() {
myName = "some foo name";
tbtestController.setMyName(myName);
}
虽然我不确定你为什么要拥有MyBean类。对代码中的字符串进行硬编码,然后只需在问题顶部使用表单中的Controller saveNew方法。
更新
试试这个......
@Named
@ViewScoped
public class TbtestController extends AbstractController<Tbtest> {
@EJB
private TbtestFacade ejbFacade;
public TbtestController() {
super(Tbtest.class); //-> there is already an invocation here, see below
}
@PostConstruct
@Override
public void init() {
super.setFacade(ejbFacade);
//Paul Morris solution below
myName = "";
}
private String myName;
public void setMyName(String name) {
myName = name;
}
public String getMyName(String name) {
if (myName.isEmpty()) {
myName = "Default Value";
}
return myName;
}
@Override
public void saveNew(ActionEvent event) {
this.getSelected().setName(this.getMyName(myName));
super.saveNew(event);
}
}
答案 1 :(得分:0)
请注意:在JSF中,MVC控制器不是用户编写的代码。它们是FacesServlet和标签实现。
当人们命名JSF支持bean&#34; XXXController&#34;时,我的迂腐条纹变得模糊不清。支持bean是MODEL。动作方法和监听器是额外的MVC功能,而不是Controller方法。所有的控制器都是从View复制数据,正如我所说,JSF自动完成,无需使用用户代码。