I'm starting to code a little cookbook. Therefor i've created a page to add some menusteps, a menustep should describe how to cook the menu step by step.
I have a datatable containing a list of MenuSteps. The user can click a commandLink to add/delete a new step. The Bean adds or removes a MenuStep of the list and rerender the datatable with ajax. That works great, except I lost all the data given to the two inputText fields for the steps. They are all blank after I add or delete a row of my datatable.
I hope someone can help me.
Below you can see my code. Let me know if you need more input!
Best regards,
Benjamin
Here is my XHTML (it's a part of a template):
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:util="http://java.sun.com/jsf/composite/components/util"
xmlns:f="http://java.sun.com/jsf/core">
<h:form id="form">
<h:dataTable id="menuStepTable" styleClass="longTable" value="#{MenuCreation.menuSteps}" var="step">
<h:column>
<h:panelGrid columns="2" styleClass="longTable" columnClasses="profileColumn1,profileColumn2">
<h:outputLabel for="inputStepName" value="Name:"/>
<h:inputText id="inputStepName" value="#{step.stepName}"/>
<h:outputLabel for="inputTask" value="Beschreibung:"/>
<h:inputText id="inputTask" value="#{step.task}"/>
<h:commandLink styleClass="safe" value="Schritt entfernen" action="#{MenuCreation.removeMenuStepRow(step)}">
<f:ajax execute="#this" render="#form"/>
</h:commandLink>
</h:panelGrid>
<hr />
</h:column>
</h:dataTable>
<h:commandLink styleClass="safe" value="Schritt hinzufügen" action="#{MenuCreation.addMenuStepRow}">
<f:ajax execute="#this" render="#form"/>
</h:commandLink>
</h:form>
</ui:composition>
Here is my ManagedBean:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.charite.ne.server.admin.menue;
import de.charite.ne.server.persistence.menu.MenuStep;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
/**
*
* #author benjamin
*/
#ManagedBean(name = "MenuCreation")
#SessionScoped
public class MenuCreationBean implements Serializable{
private List<MenuStep> menuSteps = new ArrayList<MenuStep>();
#PostConstruct
public void init() {
MenuStep menuStep = new MenuStep();
menuStep.setStepName("Neuer Schritt...");
menuStep.setTask("Beschreibung des Schrittes...");
menuSteps.add(menuStep);
}
public void addMenuStepRow() {
MenuStep menuStep = new MenuStep();
menuSteps.add(menuStep);
}
public void removeMenuStepRow(MenuStep menuStep) {
menuSteps.remove(menuStep);
}
public List<MenuStep> getMenuSteps() {
return menuSteps;
}
public void setMenuSteps(List<MenuStep> menuSteps) {
this.menuSteps = menuSteps;
}
}
Here is my Entity:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.charite.ne.server.persistence.menu;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
* #author benjamin
*/
#Entity
#Table(name = "menustep")
public class MenuStep implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private int sequenceNumber;
private String stepName;
private String task;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getSequenceNumber() {
return sequenceNumber;
}
public void setSequenceNumber(int sequenceNumber) {
this.sequenceNumber = sequenceNumber;
}
public String getStepName() {
return stepName;
}
public void setStepName(String stepName) {
this.stepName = stepName;
}
public String getTask() {
return task;
}
public void setTask(String task) {
this.task = task;
}
}
I solved it.
<h:commandButton styleClass="safe" value="Zutat hinzufügen" action="#{MenuCreation.addInTakeRow}">
<f:ajax disabled="true" execute="#this" render="#form"/>
</h:commandButton>
disabled=true for each of those ajax commands.
Related
I have the problem in a JSF / xhtml page, that my primefaces datatable won't sort and filter correctly. I populate the datatable from my database, which works fine. However, as soon as I start to type something into the filter, or click on the header of a column to sort, all the entries disappear. I don't really know where my error here is.
This is the code of the datatable in JSF:
<p:dataTable var="c" value="#{proposalController.contractList}">
<p:column headerText="ID" sortBy="#{c.id}" filterBy="#{c.id}" filterMatchMode="contains">
<h:outputText value="#{c.id}" />
</p:column>
<p:column headerText="Customer Name" sortBy="#{c.custName}" filterBy="#{c.custName}" filterMatchMode="contains">
<h:outputText value="#{c.custName}" />
</p:column>
<p:column headerText="Asset" sortBy="#{c.asset}" filterBy="#{c.asset}" filterMatchMode="contains">
<h:outputText value="#{c.asset}" />
</p:column>
</p:dataTable>
And this is the java code behind it:
package controller;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import model.Contract;
import model.ContractManager;
#ManagedBean (name="proposalController")
#SessionScoped
public class proposalController {
#EJB
private ContractManager contract;
private int id;
private String custName;
private String custStreet;
private String custZIP;
private String custCity;
private int creditScore;
private String custPers;
private String mail;
private String phone;
private Date start;
private Date endd;
private String asset;
private String insurance;
private double rate;
private String status;
private List<Contract> contractList;
public List<Contract> getContractList() {
this.contractList = contract.getContractList();
return this.contractList;
}
It would be great if someone could help me!
In your getContractList() method, you return a list from some service, which is probably a new list everytime the method is called. You should instead get this list just once from your service on initialization (some #PostConstruct-annotated method for instance), save it in your session-bean and return the list from your session-bean instead.
Something like this:
#ManagedBean (name="proposalController")
#SessionScoped
public class proposalController {
#EJB
private ContractManager contract;
private List<Contract> contractList;
#PostConstruct
public void init() {
contractList = contract.getContractList();
}
public List<Contract> getContractList() {
return this.contractList;
}
}
I have the following problem. I have a list that consists of dynamically generated checkboxes. When I click once on one of those checkboxes, the value of the backing bean is ok for this call. When clicking on another checkbox, this one is fine, but the others fall back to false, even the checkmark is shown in the front-end. The same problem, when I click on a final submit button. All values in the backing bean become the state false.
Here is the JSF:
<?xml version="1.0"?>
<f:view
xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head />
<h:body>
<h:form>
<h:messages/>
<h:dataTable value="#{registration.registrationlist}" var="entry">
<h:column>
<f:facet name="header">Name</f:facet>
#{entry.me.name}
</h:column>
<h:column>
<f:facet name="header">Status</f:facet>
<h:selectBooleanCheckbox value="#{entry.checked}">
</h:selectBooleanCheckbox>
</h:column>
</h:dataTable>
<h:commandButton value="Submit">
<f:ajax listener="#{registration.listener}" />
</h:commandButton>
</h:form>
</h:body>
</f:view>
This is my backing bean:
package de.rwd.mm.beans;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.AjaxBehaviorEvent;
#ManagedBean
#ViewScoped
public class Registration {
private List<RegistrationEntry> registrationlist;
public Registration() {
// Populating the registrationlist from database and initialize it with false
List<MarketingEvent> me_list;
me_list = MarketingEventLocalServiceUtil.getAllMarketingevents();
registrationlist = new ArrayList<RegistrationEntry>();
for (MarketingEvent me : me_list) {
RegistrationEntry re = new RegistrationEntry(me, false);
registrationlist.add(re);
}
}
public List<RegistrationEntry> getRegistrationlist() {
return registrationlist;
}
public void setRegistrationlist(List<RegistrationEntry> registrationlist) {
this.registrationlist = registrationlist;
}
public void listener(AjaxBehaviorEvent event) {
System.out.println("listener");
System.out.println("called by " + event.getComponent().getClass().getName());
for (RegistrationEntry entry : registrationlist) {
String me = entry.getMe().getName();
boolean value = entry.isChecked();
System.out.println(me + " " + value);
}
}
}
My RegistrationEntry class that holds the database values and the boolean for the checkbox.
package de.rwd.mm.beans;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import de.rwd.mm.services.model.MarketingEvent;
#ManagedBean
#ViewScoped
public class RegistrationEntry {
private MarketingEvent me;
private boolean checked;
public RegistrationEntry() {
}
public RegistrationEntry(MarketingEvent me, boolean checked) {
this.me = me;
this.checked = checked;
}
public MarketingEvent getMe() {
return me;
}
public void setMe(MarketingEvent me) {
this.me = me;
}
public boolean isChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
}
}
Is #ViewScoped the right scope? Or is there anything completly wrong?
The non-ajax version works, but this is no option for me. This "portlet" is placed in several pages with much content and a page refresh looks extremly ugly. This JSF runs as portlet in Liferay 6.2.
Thanks for any help and suggestions.
PS: My Liferay 6.2.0-ce-ga1 runs in Tomcat 7.0.42
Use the <f:ajax execute="#form"> setting just like this example code (it uses Lombok #Data annotation to avoid typing getter/setter methods):
The sample facet:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<h:dataTable value="#{myBean.records}" var="record">
<h:column>
<f:facet name="header">Name</f:facet>
#{record.name}
</h:column>
<h:column>
<f:facet name="header">Selected</f:facet>
<h:selectBooleanCheckbox value="#{record.checked}"/>
</h:column>
</h:dataTable>
<h:commandButton value="Submit">
<f:ajax listener="#{myBean.onSubmit}" execute="#form"/>
</h:commandButton>
</h:form>
</h:body>
</html>
The managed bean:
package x;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.event.AjaxBehaviorEvent;
import javax.inject.Named;
import javax.faces.view.ViewScoped;
import lombok.Data;
#Data
#Named( value = "myBean" )
#ViewScoped
public class MyBean implements Serializable
{
private List<MyRecord> records;
//#EJB
//private RecordDAO recordDAO;
#PostConstruct
public void init()
{
System.out.println( "MyBean.ini() called");
records = new ArrayList<>();
records.add( new MyRecord( "Name 1", false ) );
records.add( new MyRecord( "Name 2", false ) );
records.add( new MyRecord( "Name 3", false ) );
records.add( new MyRecord( "Name 4", false ) );
records.add( new MyRecord( "Name 5", false ) );
}
public void onSubmit( AjaxBehaviorEvent abe_ )
{
System.out.println( "MyBeam.onSubmit() called! Values : " + getRecordValues() );
// You should take care about persisting data here
//recordDAO.persistRecords( records );
}
protected String getRecordValues()
{
String s = "";
for ( MyRecord mr : records)
s += "( name=" + mr.getName() + ", checked= " + mr.isChecked() + " ); ";
return s;
}
public MyBean()
{
}
}
The test DB record:
package x;
import java.io.Serializable;
import lombok.Data;
#Data
public class MyRecord implements Serializable
{
private String name;
private boolean checked;
public MyRecord( String name_, boolean checked_ )
{
name = name_;
checked = checked_;
}
}
I'm getting an issues when trying to delete a list of entities which have a foreign key. A delete method in CrudRepository work fine with table doesn't have foreign key but when I tried to delete a list of entities have foreign key, it reported success but nothing was delete in database. The deleteInBatch() work fine in both.
What is differences between the method delete(Iterable<? extends T> itrbl) in CrudRepository and deleteInBatch(Iterable<T> itrbl) in JpaRepository?
I have gone through this.
Any help would be appreciated
My model SmsNotifyTemplate.java:
package com.viettel.pcrf.webconfig.model;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* #author Anh Nguyen
*/
#Entity
#Table(name = "SMS_NOTIFY_TEMPLATE", catalog = "", schema = "VPCRF")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "SmsNotifyTemplate.findAll", query = "SELECT s FROM SmsNotifyTemplate s"),
#NamedQuery(name = "SmsNotifyTemplate.findBySmsNotifyTemplateId", query = "SELECT s FROM SmsNotifyTemplate s WHERE s.smsNotifyTemplateId = :smsNotifyTemplateId"),
#NamedQuery(name = "SmsNotifyTemplate.findByMessageTemplate", query = "SELECT s FROM SmsNotifyTemplate s WHERE s.messageTemplate = :messageTemplate"),
#NamedQuery(name = "SmsNotifyTemplate.findByComments", query = "SELECT s FROM SmsNotifyTemplate s WHERE s.comments = :comments"),
#NamedQuery(name = "SmsNotifyTemplate.findBySmsTemplateCode", query = "SELECT s FROM SmsNotifyTemplate s WHERE s.smsTemplateCode = :smsTemplateCode")})
public class SmsNotifyTemplate implements Serializable {
public static enum COLUMNS {
COMMENTS, LANGID, MESSAGETEMPLATE, SMSNOTIFYTEMPLATEID, SMSTEMPLATECODE
};
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "SMS_NOTIFY_TEMPLATE_ID", nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO, generator = "sms_notify_template_seq_gen")
#SequenceGenerator(name = "sms_notify_template_seq_gen", sequenceName = "SMS_NOTIFY_TEMPLATE_SEQ")
private Short smsNotifyTemplateId;
#Column(name = "MESSAGE_TEMPLATE", length = 480)
private String messageTemplate;
#Column(name = "COMMENTS", length = 200)
private String comments;
#Column(name = "SMS_TEMPLATE_CODE")
private Integer smsTemplateCode;
#JoinColumn(name = "LANG_ID", referencedColumnName = "LANG_ID", nullable = false)
#ManyToOne(optional = false)
private Lang langId;
public SmsNotifyTemplate() {
}
public SmsNotifyTemplate(Short smsNotifyTemplateId) {
this.smsNotifyTemplateId = smsNotifyTemplateId;
}
public Short getSmsNotifyTemplateId() {
return smsNotifyTemplateId;
}
public void setSmsNotifyTemplateId(Short smsNotifyTemplateId) {
this.smsNotifyTemplateId = smsNotifyTemplateId;
}
public String getMessageTemplate() {
return messageTemplate;
}
public void setMessageTemplate(String messageTemplate) {
this.messageTemplate = messageTemplate;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public Integer getSmsTemplateCode() {
return smsTemplateCode;
}
public void setSmsTemplateCode(Integer smsTemplateCode) {
this.smsTemplateCode = smsTemplateCode;
}
public Lang getLangId() {
return langId;
}
public void setLangId(Lang langId) {
this.langId = langId;
}
#Override
public int hashCode() {
int hash = 0;
hash += (smsNotifyTemplateId != null ? smsNotifyTemplateId.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof SmsNotifyTemplate)) {
return false;
}
SmsNotifyTemplate other = (SmsNotifyTemplate) object;
return !((this.smsNotifyTemplateId == null && other.smsNotifyTemplateId != null) || (this.smsNotifyTemplateId != null && !this.smsNotifyTemplateId.equals(other.smsNotifyTemplateId)));
}
#Override
public String toString() {
return "com.viettel.pcrf.model.SmsNotifyTemplate[ smsNotifyTemplateId=" + smsNotifyTemplateId + " ]";
}
}
I have a mapper to map the model with a normal class:
SmsTemplateMapper.java:
package com.viettel.pcrf.webconfig.mapper;
import com.viettel.fw.common.util.mapper.BaseMapper;
import com.viettel.pcrf.webconfig.dto.SmsTemplateDTO;
import com.viettel.pcrf.webconfig.model.SmsNotifyTemplate;
public class SmsTemplateMapper extends BaseMapper<SmsNotifyTemplate, SmsTemplateDTO> {
#Override
public SmsTemplateDTO toDtoBean(SmsNotifyTemplate model) {
SmsTemplateDTO obj = null;
if (model != null) {
obj = new SmsTemplateDTO();
obj.setComments(model.getComments());
obj.setMessageTemplate(model.getMessageTemplate());
obj.setSmsNotifyTemplateId(model.getSmsNotifyTemplateId());
obj.setSmsTemplateCode(model.getSmsTemplateCode());
obj.setLangId(model.getLangId());
}
return obj;
}
#Override
public SmsNotifyTemplate toPersistenceBean(SmsTemplateDTO dtoBean) {
SmsNotifyTemplate obj = null;
if (dtoBean != null) {
obj = new SmsNotifyTemplate();
obj.setComments(dtoBean.getComments());
obj.setMessageTemplate(dtoBean.getMessageTemplate());
obj.setSmsNotifyTemplateId(dtoBean.getSmsNotifyTemplateId());
obj.setSmsTemplateCode(dtoBean.getSmsTemplateCode());
obj.setLangId(dtoBean.getLangId());
System.out.println(obj.getLangId().getNationality());
}
return obj;
}
}
SmsTemplateDTO.java:
package com.viettel.pcrf.webconfig.dto;
import com.viettel.fw.dto.BaseDTO;
import com.viettel.pcrf.webconfig.model.Lang;
import java.io.Serializable;
public class SmsTemplateDTO extends BaseDTO implements Serializable {
public String getKeySet() {
return keySet;
}
private String comments;
private String messageTemplate;
private Short smsNotifyTemplateId;
private Integer smsTemplateCode;
private Lang langId;
public String getComments() {
return this.comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public String getMessageTemplate() {
return this.messageTemplate;
}
public void setMessageTemplate(String messageTemplate) {
this.messageTemplate = messageTemplate;
}
public Short getSmsNotifyTemplateId() {
return this.smsNotifyTemplateId;
}
public void setSmsNotifyTemplateId(Short smsNotifyTemplateId) {
this.smsNotifyTemplateId = smsNotifyTemplateId;
}
public Integer getSmsTemplateCode() {
return this.smsTemplateCode;
}
public void setSmsTemplateCode(Integer smsTemplateCode) {
this.smsTemplateCode = smsTemplateCode;
}
public Lang getLangId() {
return langId;
}
public void setLangId(Lang langId) {
this.langId = langId;
}
}
SmsTemplateRepo.java:
package com.viettel.pcrf.webconfig.repo;
import com.viettel.fw.persistence.BaseRepository;
import java.util.List;
import com.viettel.pcrf.webconfig.model.SmsNotifyTemplate;
public interface SmsTemplateRepo extends BaseRepository<SmsNotifyTemplate>, SmsTemplateRepoCustom {
public List<SmsNotifyTemplate> findByComments(String comments);
public List<SmsNotifyTemplate> findByMessageTemplate(String messageTemplate);
public List<SmsNotifyTemplate> findBySmsNotifyTemplateId(Short smsNotifyTemplateId);
public List<SmsNotifyTemplate> findBySmsTemplateCode(Integer smsTemplateCode);
}
BaseRepository extends JpaRepository.
A delete method will be in deleteSmsNotifyTemplates method in this class:
SmsTemplateServiceImpl.java:
package com.viettel.pcrf.webconfig.service;
import com.viettel.fw.common.util.extjs.FilterRequest;
import com.viettel.fw.dto.BaseMessage;
import com.viettel.pcrf.webconfig.repo.SmsTemplateRepo;
import com.viettel.pcrf.webconfig.mapper.SmsTemplateMapper;
import com.viettel.pcrf.webconfig.dto.SmsTemplateDTO;
import com.viettel.pcrf.webconfig.model.SmsNotifyTemplate;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/**
*
* #author Anh Nguyen
*/
#Service
public class SmsTemplateServiceImpl extends BaseServiceImpl implements SmsTemplateService {
private final SmsTemplateMapper mapper = new SmsTemplateMapper();
#Autowired
private SmsTemplateRepo repository;
public Logger logger = Logger.getLogger(SmsTemplateService.class);
#Override
public BaseMessage deleteSmsNotifyTemplates(List<SmsTemplateDTO> smsNotifyTemplateDTOs) throws Exception {
BaseMessage baseMessage = new BaseMessage();
repository.delete(mapper.toPersistenceBean(smsNotifyTemplateDTOs));
baseMessage.setSuccess(true);
baseMessage.setOutputObject(smsNotifyTemplateDTOs);
return baseMessage;
}
}
The Controller:
SmsTemplateCtrl.java:
package com.viettel.pcrf.webconfig.controller;
import com.viettel.fw.Exception.LogicException;
import com.viettel.fw.common.util.extjs.FilterRequest;
import com.viettel.fw.web.controller.BaseController;
import com.viettel.pcrf.webconfig.dto.LangDTO;
import com.viettel.pcrf.webconfig.dto.SmsTemplateDTO;
import com.viettel.pcrf.webconfig.model.Lang;
import com.viettel.pcrf.webconfig.service.LangService;
import com.viettel.pcrf.webconfig.service.SmsTemplateService;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/**
*
* #author Anh Nguyen
*/
#Component("smsNotifyTemplateController")
#Scope("view")
public class SmsTemplateCtrl extends BaseController implements Serializable {
private List<SmsTemplateDTO> listSmsNotifyTemplate;
private SmsTemplateDTO smsNotifyTemplate;
private List<SmsTemplateDTO> selectedSmsNotifyTemplates;
private List<LangDTO> listLang;
#Autowired
private SmsTemplateService smsNotifyTemplateService;
#Autowired
private LangService langService;
public List<SmsTemplateDTO> getListSmsNotifyTemplate() {
return listSmsNotifyTemplate;
}
public void setListSmsNotifyTemplate(List<SmsTemplateDTO> listSmsNotifyTemplate) {
this.listSmsNotifyTemplate = listSmsNotifyTemplate;
}
public SmsTemplateDTO getSmsNotifyTemplate() {
return smsNotifyTemplate;
}
public void setSmsNotifyTemplate(SmsTemplateDTO smsNotifyTemplate) {
this.smsNotifyTemplate = smsNotifyTemplate;
}
public List<SmsTemplateDTO> getSelectedSmsNotifyTemplates() {
return selectedSmsNotifyTemplates;
}
public void setSelectedSmsNotifyTemplates(List<SmsTemplateDTO> selectedSmsNotifyTemplates) {
this.selectedSmsNotifyTemplates = selectedSmsNotifyTemplates;
}
public List<LangDTO> getListLang() {
return listLang;
}
public void setListLang(List<LangDTO> listLang) {
this.listLang = listLang;
}
/**
* Khoi Tao Cac doi tuong de load len view
*/
#PostConstruct
public void init() {
listSmsNotifyTemplate = smsNotifyTemplateService.findAllSort();
listLang = langService.findAllSort();
formStatus = getFormStatus();
}
/**
* Chuan bi cho thao tac delete
*/
public void delete() {
try {
if (selectedSmsNotifyTemplates == null || selectedSmsNotifyTemplates.isEmpty()) {
reportError("msgInfo", "Choose one row!");
} else {
smsNotifyTemplateService.deleteSmsNotifyTemplates(selectedSmsNotifyTemplates);
reportSuccess("msgInfo", "common.msg.success.delete");
reset();
updateController();
}
} catch (LogicException logicE) {
reportError("msgInfo", logicE);
} catch (Exception exception) {
reportError("msgInfo", exception.getMessage());
}
}
/**
* Kiem tra SmsNotifyTemplateId ton tai trong bang SMS_NOTIFY_TEMPLATE
*
* #param smsNotifyTemplates
* #return
*/
public boolean SmsNotifyTemplateIdExistedInSmsNotifyTemplate(List<SmsTemplateDTO> smsNotifyTemplates) {
List<FilterRequest> listReq = new ArrayList<>();
for (SmsTemplateDTO s : smsNotifyTemplates) {
listReq.add(new FilterRequest("LANGID", s.getLangId()));
}
List<SmsTemplateDTO> list = smsNotifyTemplateService.findAll(listReq);
return !list.isEmpty();
}
/**
* Kiem tra SmsNotifyTemplateCode ton tai trong bang LANG
*
* #param smsTemplateCode
* #param smsNotifyTemplateId
* #return
*/
public boolean SmsTemplateCodeExisted(Integer smsTemplateCode, Short smsNotifyTemplateId) {
List<FilterRequest> listReq = new ArrayList<>();
listReq.add(new FilterRequest("SMSTEMPLATECODE", smsTemplateCode));
List<SmsTemplateDTO> list = smsNotifyTemplateService.findAll(listReq);
if (list.isEmpty()) {
return false;
}
if (list.size() > 1) {
return true;
} else {
return !list.get(0).getSmsNotifyTemplateId().equals(smsNotifyTemplateId);
}
}
}
And the xhtml page. I'm using primefaces framework.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="../../templates/layoutTemplate.xhtml" >
<ui:define name="title">SMS Notify Template Configuration</ui:define>
<ui:define name="featureName">SMS Notify Template Configuration</ui:define>
<ui:define name="content">
<h:form id="frmSmsNotifyTemplate">
<p:dataTable var="tabSmsNotifyTemplate"
id="smsNotifyTemplateList"
value="#{smsNotifyTemplateController.listSmsNotifyTemplate}"
selection="#{smsNotifyTemplateController.selectedSmsNotifyTemplates}"
rowsPerPageTemplate="5,10,15,20,50"
paginatorPosition="bottom"
paginator="true"
rows="10"
paginatorAlwaysVisible="false"
sortMode="single"
sortBy="#{tabSmsNotifyTemplate.smsNotifyTemplateId}"
rowKey="#{tabSmsNotifyTemplate.smsNotifyTemplateId}" >
<p:column selectionMode="multiple" style="width:16px;text-align:center" />
<p:ajax event="toggleSelect" update="#([id$=btnEdit]) #([id$=btnDelete])" />
<p:ajax event="rowSelect" update="#([id$=btnEdit]) #([id$=btnDelete])" />
<p:ajax event="rowSelectCheckbox" update="#([id$=btnEdit]) #([id$=btnDelete])" />
<p:ajax event="rowUnselectCheckbox" update="#([id$=btnEdit]) #([id$=btnDelete])" />
<p:column headerText="ID" style="width: 100px;">
<h:outputText value="#{tabSmsNotifyTemplate.smsNotifyTemplateId}" />
</p:column>
<p:column headerText="Message Template" style="width: 100px;" sortBy="#{tabSmsNotifyTemplate.messageTemplate}">
<h:outputText value="#{tabSmsNotifyTemplate.messageTemplate}" />
</p:column>
<p:column headerText="SMS Template Code" sortBy="#{tabSmsNotifyTemplate.smsTemplateCode}">
<h:outputText value="#{tabSmsNotifyTemplate.smsTemplateCode}" />
</p:column>
<p:column headerText="Language" sortBy="#{tabSmsNotifyTemplate.langId.nationality}">
<h:outputText value="#{tabSmsNotifyTemplate.langId.nationality}" />
</p:column>
<p:column headerText="Comments" sortBy="#{tabSmsNotifyTemplate.comments}">
<h:outputText value="#{tabSmsNotifyTemplate.comments}" />
</p:column>
<f:facet name="footer">
<div align="left">
<span class="vt-button">
<p:commandLink
action="#{smsNotifyTemplateController.prepareInsert()}"
process="smsNotifyTemplateList"
update="#form"
resetValues="true"
style="margin-right:30px;border: none">
<p:graphicImage style="width:10px;height:10px;"
value="/resources/themes/images/icon-add.png"/>
<span class="vt-button-text">
<h:outputText value="#{lang['common.button.add']}"/>
</span>
<f:setPropertyActionListener
target="#{smsNotifyTemplateController.formStatus}"
value="#{vpcrfConst.BTN_ADD}"/>
</p:commandLink>
<p:commandLink
id="btnEdit"
action="#{smsNotifyTemplateController.prepareEdit()}"
process="smsNotifyTemplateList"
update="#form"
disabled="#{smsNotifyTemplateController.selectedSmsNotifyTemplates.size()>1 or smsNotifyTemplateController.selectedSmsNotifyTemplates==null or smsNotifyTemplateController.selectedSmsNotifyTemplates.size()==0}"
resetValues="true"
style="margin-right:30px;border: none">
<p:graphicImage style="width:10px;height:10px;"
value="/resources/themes/images/icon-edit.png"/>
<span class="vt-button-text">
<h:outputText value="#{lang['common.button.edit']}"/>
</span>
<f:setPropertyActionListener
target="#{smsNotifyTemplateController.formStatus}"
value="#{vpcrfConst.BTN_EDIT}"/>
</p:commandLink>
<p:commandLink
id="btnDelete"
action="#{smsNotifyTemplateController.delete()}"
immediate="true"
update="#form"
disabled="#{smsNotifyTemplateController.selectedSmsNotifyTemplates.size()==0 or smsNotifyTemplateController.selectedSmsNotifyTemplates==null}"
resetValues="true"
style="margin-right:30px;border: none">
<p:graphicImage style="width:10px;height:10px;"
value="/resources/themes/images/icon-delete.png"/>
<span class="vt-button-text">
<h:outputText value="#{lang['common.button.delete']}"/>
</span>
<p:confirm header="Delete" message="Are you sure? (Ok/Cancel)" icon="ui-icon-alert" />
</p:commandLink>
</span>
</div>
</f:facet>
</p:dataTable>
<p:growl id="testMsg" showSummary="false" showDetail="true" autoUpdate="true" sticky="true" />
<p:focus context="editPanel"/>
<p:fieldset legend="SMS Notify Template Detail" rendered="#{smsNotifyTemplateController.smsNotifyTemplate!=null}">
<h:panelGrid id="editPanel"
columnClasses="vocs-120, vocs-300"
columns="2" rendered="#{smsNotifyTemplateController.smsNotifyTemplate!=null}">
<p:outputLabel for="smsID" value="ID" />
<p:inputText id="smsID"
value="#{smsNotifyTemplateController.smsNotifyTemplate.smsNotifyTemplateId}"
required="true"
maxlength="15"
disabled="true"
style="min-width: 300px;"/>
<p:outputLabel for="messTemplate" value="Message Template" />
<p:inputText id="messTemplate"
value="#{smsNotifyTemplateController.smsNotifyTemplate.messageTemplate}"
required="true"
maxlength="60"
style="min-width: 300px;"/>
<p:outputLabel for="langId" value="SMS Notify Template" />
<p:selectOneMenu id="langId"
required="true"
value="#{smsNotifyTemplateController.smsNotifyTemplate.langId.langId}"
style="width: 306px;">
<f:selectItem itemLabel="Select Language"
itemDisabled="true"
noSelectionOption="true"/>
<f:selectItems value="#{smsNotifyTemplateController.listLang}"
var="l"
itemLabelEscaped="true"
itemValue="#{l.langId}"
itemLabel="#{l.nationality}" />
</p:selectOneMenu>
<p:outputLabel for="templateCode" value="Template Code" />
<p:inputTextarea id="templateCode"
value="#{smsNotifyTemplateController.smsNotifyTemplate.smsTemplateCode}"
required="true"
maxlength="10"
style="min-width: 300px;"/>
<p:outputLabel for="comments" value="Comments" />
<p:inputTextarea id="comments"
value="#{smsNotifyTemplateController.smsNotifyTemplate.comments}"
required="false"
maxlength="10"
style="min-width: 300px;"/>
<div />
<h:panelGroup>
<p:commandButton
value="OK"
process="editPanel"
rendered="#{smsNotifyTemplateController.formStatus==vpcrfConst.BTN_ADD}"
action="#{smsNotifyTemplateController.insert()}"
update="smsNotifyTemplateList,editPanel,#form" />
<p:commandButton rendered="#{smsNotifyTemplateController.formStatus==vpcrfConst.BTN_ADD}"
value="#{lang['common.button.reset']}"
immediate="true">
<p:ajax update="smsID,messTemplate,langId,templateCode,comments" resetValues="true" />
</p:commandButton>
<p:commandButton
value="OK"
rendered="#{smsNotifyTemplateController.formStatus==vpcrfConst.BTN_EDIT}"
action="#{smsNotifyTemplateController.update()}"
update="smsNotifyTemplateList,editPanel,#form" />
<p:commandButton rendered="#{smsNotifyTemplateController.formStatus==vpcrfConst.BTN_EDIT}"
value="#{lang['common.button.reset']}"
immediate="true"
action="#{smsNotifyTemplateController.clearInput()}"
update="smsID,messTemplate,langId,templateCode,comments"
resetValues="true"/>
<p:commandButton
value="#{lang['common.button.cancel']}"
action="#{smsNotifyTemplateController.reset()}"
immediate="true"
update="#form"/>
</h:panelGroup>
</h:panelGrid>
</p:fieldset>
</h:form>
</ui:define>
</ui:composition>
</html>
The documentation explains the difference. deleteInBatch() does the following:
Deletes the given entities in a batch which means it will create a single Query. Assume that we will clear the EntityManager after the call.
whereas delete() does the following:
Deletes the given entities.
So, the fist one will execute a delete JPQL query like
delete from SomeEntity e where e.id in :ids
whereas the second one will loop through the entities and call
entityManager.remove(entity)
Both should work, whether your entity has a foreign key or not. The second one will apply cascades whereas the first one won't. It's impossible to tell why you're having this issue without knowing anything about your code.
Have used setInterval to call ajax method which will render the value on page or probably keep updating the page. But in debug the control does not comes to ajax method in bean. please advise the issue in below code
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:body>
<script>
setInterval(function() {
document.getElementById("changeme").click();
}, 3000);
</script>
<h3>JSF 2.0 + Ajax Hello World Example</h3>
<h:form>
<h:inputText id="name" value="#{helloBean.name}"></h:inputText>
<h:commandButton value="Welcome Me">
<f:ajax execute="name" render="output" />
</h:commandButton>
<h2><h:outputText id="output" value="#{helloBean.sayWelcome}" /></h2>
<h2><h:outputText id="countsee" value="#{helloBean.name}" /></h2>
<h:commandButton id="changeme" style="display:none">
<f:ajax execute="#this" listener="#{helloBean.updates}" render="countsee" ></f:ajax>
</h:commandButton>
</h:form>
</h:body>
</html>
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.AjaxBehaviorEvent;
import java.io.Serializable;
#ManagedBean
#SessionScoped
public class HelloBean implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private static int count;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSayWelcome(){
//check if null?
if("".equals(name) || name ==null){
return "";
}else{
return "Ajax message : Welcome " + name;
}
}
public void getUpdates(ActionBehaviorEvent event){
System.out.println("Printing"+count);
this.name=name+"agdam";
}
}
Try giving the below:
public void updates(ActionBehaviorEvent event)
The method name and name given in the listener should be same.
I have 2 SelectOneMenu as follows in the index.xhtml. The menu1 essentially chooses a language(sp or en) and menu2 displays the possible serial numbers(0 to 3). I have the init constructor(post constructor) which initialises the default values on the two Menus. However for some strange reason, if I select a serial number other than the default serial number for the language other than the default language, somehow the language gets reset to init default :(
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>My page</title>
</h:head>
<h:body>
<div>
<h4>Change Existing Description</h4>
</div>
<h:form id="myForm">
<h:panelGrid columns="4">
<h:outputLabel value="Language:" />
<h:selectOneMenu value="#{myBean.language}">
<f:selectItems value="#{myBean.languages}" />
<f:ajax listener="#{myBean.doUpdate}" render ="myForm" />
</h:selectOneMenu>
<h:outputLabel value="SerialID:" />
<h:selectOneMenu value="#{myBean.serialID}">
<f:selectItems value="#{myBean.serialIDs}" />
<f:ajax listener="#{myBean.doUpdate}" render ="myForm" />
</h:selectOneMenu>
</h:panelGrid>
</h:form>
</h:body>
</html>
Here is my Bean code. Where is the problem?? please advise!
package bean;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.Stateful;
import javax.enterprise.context.RequestScoped;
import javax.faces.bean.ManagedBean;
#ManagedBean(name = "myBean")
//#Stateless
#Stateful
#RequestScoped
public class MyBean {
public static final int PERMISSIONS = 2;
private List<String> languages;
private String language;
private int serialID;
private List<Integer> serialIDs;
/**
* init() method for initializing the bean. Is called after constuction.
*/
#PostConstruct
private void init() {
//public MyBean () {
languages = getAllLanguages();
language = "en"; //defaultLanguage
serialID = 3;
serialIDs = getSerialIDsFromOverview();
}
public List<String> getLanguages() {
System.out.println("getLanguages, language " +language);
return languages;
}
public int getPERMISSIONS() {
return PERMISSIONS;
}
public String getLanguage() {
System.out.println("getLanguage " +language);
return language;
}
public void setLanguage(String language) {
System.out.println("setLanguage " +language);
this.language = language;
}
public int getSerialID() {
System.out.println("getSerialID " +serialID);
return serialID;
}
public void setSerialID(int serialID) {
System.out.println("setSerialID " +serialID);
this.serialID = serialID;
}
public List<Integer> getSerialIDs() {
System.out.println("getSerialIDs language = "+language );
return serialIDs;
}
public List<String> getAllLanguages() {
List<String> results = new ArrayList<String>();
results.add("sp");
results.add("en");
if(results != null){
System.out.println("getting all languages");
}
return results;
}
public void doUpdate() {
System.out.println("doUpdate language " +language);
System.out.println("doUpdate serialID " +serialID);
}
/**
* Returns a list of all serialIDs present in the overview.
* #return
*/
private List<Integer> getSerialIDsFromOverview() {
List<Integer> results = new ArrayList<Integer>();
results.add(0);
results.add(1);
results.add(2);
results.add(3);
return results;
}
}
UPDATES:
After taking suggestions from cubbuk, I sat down and corrected my code with #ViewScoped annotation and making the bean implement Serializable. THIS WORKS. However, the next thing I had to do was include an #EJB annotation to call a stateless bean which calls the Entity manager to fetch the serialIDs from a database instead of "hardcoding" it. That is when I encounter the problem: Not serializable exception "java.io.NotSerializableException: bean.__EJB31_Generated__. How do I solve this? When I made myBean back to RequestScope and remove Serializable, I could run the code without problems however there the toggling of the menu to init values :(
By the way I check this post: #EJB in #ViewScoped managed bean causes java.io.NotSerializableException and set my STATE SAVING METHOD to server but that gives me "empy response from server" pop up message :(
Please help!
Since you are using #RequestScoped bean as your backing bean after each request your init method is getting called and your values are getting reset. To avoid that you need to use #ViewScoped bean as your backing bean. I updated your bean accordingly note that your backing bean now implements Serializable interface. This is needed as this bean will be stored in your servlet and it needs to be flushed to disk if the content can not be hold in the memory. For learning the details of #ViewScoped beans please check the following post:
http://balusc.blogspot.com/2010/06/benefits-and-pitfalls-of-viewscoped.html
Apart from these, for naming conventions I renamed your getAllLanguages and getSerialIDsFromOverview methods to initAllLanguages and initSerialIds as methods starting with get and set can be confusing because they are mostly used for getters and setters.
Lastly when you use f:ajax command by default the UIInput the ajax command is bind to is rendered and executed. Since you don't refresh the h:selectOneMenu menus according to the values of each other you don't need to render the whole form. The following will be enough for this case:
<h:form id="myForm">
<h:panelGrid columns="4">
<h:outputLabel value="Language:" />
<h:selectOneMenu value="#{myBean.language}">
<f:selectItems value="#{myBean.languages}" />
<f:ajax listener="#{myBean.doUpdate}"/>
</h:selectOneMenu>
<h:outputLabel value="SerialID:" />
<h:selectOneMenu value="#{myBean.serialID}">
<f:selectItems value="#{myBean.serialIDs}" />
<f:ajax listener="#{myBean.doUpdate}"/>
</h:selectOneMenu>
</h:panelGrid>
</h:form>
#ManagedBean
#ViewScoped
public class MyBean implements Serializable
{
public static final int PERMISSIONS = 2;
private List<String> languages;
private String language;
private int serialID;
private List<Integer> serialIDs;
/**
* init() method for initializing the bean. Is called after constuction.
*/
#PostConstruct
protected void init()
{
//public MyBean () {
System.out.println("lang: " + language);
System.out.println("serialId: " + serialID);
System.out.println("init is called");
initAllLanguages();
initSerialIds();
language = "en"; //defaultLanguage
serialID = 3;
}
public List<String> getLanguages()
{
return languages;
}
public int getPERMISSIONS()
{
return PERMISSIONS;
}
public String getLanguage()
{
return language;
}
public void setLanguage(String language)
{
this.language = language;
}
public int getSerialID()
{
return serialID;
}
public void setSerialID(int serialID)
{
this.serialID = serialID;
}
public List<Integer> getSerialIDs()
{
return serialIDs;
}
private void initAllLanguages()
{
languages = new ArrayList<String>();
languages.add("sp");
languages.add("en");
}
public void doUpdate()
{
System.out.println("doUpdate language " + language);
System.out.println("doUpdate serialID " + serialID);
}
/**
* Returns a list of all serialIDs present in the overview.
*
* #return
*/
private void initSerialIds()
{
serialIDs = new ArrayList<Integer>();
serialIDs.add(0);
serialIDs.add(1);
serialIDs.add(2);
serialIDs.add(3);
}
}
Cheers