I'm trying to pass the changed value of the variable to a bean method:
<h:panelGroup rendered="#{! empty gradesBean.getAllGrades()}">
<h:dataTable value="#{gradesBean.getAllGrades()}" var="g">
<h:column>
<f:facet name="header">#{msg['outputSubject']}</f:facet>
<h:inputText value="#{g.subject}" onchange="#{g.subject}" />
</h:column>
<h:column>
<f:facet name="header">#{msg['outputGrade']}</f:facet>
<h:inputText value="#{g.mark}" onchange="#{g.mark}"/>
</h:column>
<h:column>
<h:form>
<h:commandButton value="#{msg['actionSave']}" action="#{gradesBean.edit(g)}" />
</h:form>
</h:column>
</h:dataTable>
(.........)
</h:panelGroup>
I want the changes of the user he does in the inputText on g.subject and g.mark to be passed to gradesBean.edit(g). When I try to do that somehow the same values of the original values of the both variables are passed. There are getter and setter methods in the respective object
#Named
#ViewScoped
public class GradesBean extends AbstractBean implements Serializable {
private static final long serialVersionUID = 320401008216711886L;
private static final String NO_GRADES_PRESENT = "keine Noten eingetragen";
private static final Logger loggerLogger.getLogger(GradesBean.class);
#Inject
private transient GradeDAO gradeDAO;
#Inject
private UserDAO userDAO;
private Grade grade;
private List<Grade> allGrades;
#PostConstruct
public void init() {
if (!isLoggedIn()) {
return;
}
grade = new Grade();
allGrades = getSession().getUser().getGrades();
}
public Grade getGrade() {
return grade;
}
public List<Grade> getAllGrades() {
return allGrades;
}
public String getGradeAverage() {
final List<BigDecimal> theDecimals = new ArrayList<>(allGrades.size());
for (final Grade g : allGrades) {
theDecimals.add(g.getMark());
}
final Configuration config = Configuration.getDefault();
final int scale = config.getScale();
final RoundingMode roundingMode = config.getRoundingMode();
try {
final BigDecimal average = de.unibremen.st.gradelog.businesslogic.Math
.average(theDecimals, scale, roundingMode);
return average.stripTrailingZeros().toPlainString();
} catch (final ArithmeticException e) {
logger.debug(
"Calculation of grade average has been called without any grades.", e);
return NO_GRADES_PRESENT;
}
}
public String getGradeMedian() {
final List<BigDecimal> theDecimals = new ArrayList<>(allGrades.size());
for (final Grade g : allGrades) {
theDecimals.add(g.getMark());
}
try {
final BigDecimal median = de.unibremen.st.gradelog.businesslogic.Math
.median(theDecimals);
return median.stripTrailingZeros().toPlainString();
} catch (final ArithmeticException e) {
logger.debug(
"Calculation of grades median has been called without any grades.", e);
return NO_GRADES_PRESENT;
}
}
public String save() {
if (!isLoggedIn()) {
return null;
}
final User user = getSession().getUser();
grade.setUser(user);
user.addGrade(grade);
gradeDAO.save(grade);
try {
userDAO.update(user);
} catch (final DuplicateUniqueFieldException e) {
throw new UnexpectedUniqueViolationException(e);
}
init();
return null;
}
public String edit() {
if (!isLoggedIn()) {
return null;
}
assertNotNull(grade);
final User user = getSession().getUser();
gradeDAO.update(grade);
try {
userDAO.update(user);
} catch (final DuplicateUniqueFieldException e) {
throw new UnexpectedUniqueViolationException(e);
}
init();
return null;
}
public String remove(final Grade theGrade) {
if (!isLoggedIn()) {
return null;
}
assertNotNull(theGrade);
final User user = getSession().getUser();
user.removeGrade(theGrade);
gradeDAO.remove(theGrade);
try {
userDAO.update(user);
} catch (final DuplicateUniqueFieldException e) {
throw new UnexpectedUniqueViolationException(e);
}
init();
return null;
}
}`
g.mark and g.subject will already call the corresponding setters on your backing bean class (I assume that public setters getMark() and getSubject() exist).
Since action="#{gradesBean.edit(g)}" is resolved at the server (when the page is first displayed), it will have the original values , not the changed values. Anyway , to see the changed values you can use ajax (f:ajax tag and the corresponding listener attribute should be set). But you don't have to do this. Simply change your handler to
action="#{gradesBean.edit()}" //no argument
and get the latest values from your bean class instance.
I could be more specific if you want.
Related
I´m trying to use the Primefaces component: p:selectOneListbox
I would like to use the grouping function.
Currently I´m getting only a String instead the POJO. I´m already using a converter, but I don´t know what is currently wrong. If I´m returning only the List then it´s working fine and I´ve get the values as expected...
Here is my JSF code:
<p:selectOneListbox id="diagramElementList" value="#{myBean.selectedDiagramElementFromList}"
converter="diagramElementConverter" style="width: 100%"
var="diagramElement" filter="true" filterMatchMode="contains">
<f:selectItems
value="#{availableAutomationComponentControllerView.generateListAvailableElements()}"
var="diagramElement" itemLabel="#{diagramElement.name}"
itemValue="#{diagramElement}" />
<p:column style="width: 10px;">
<h:outputText value="#{diagramElement.icon}" />
</p:column>
Here my backend bean:
public List<SelectItem> generateListAvailableElements() {
try {
List<SelectItem> list = new ArrayList<SelectItem>();
SelectItemGroup g1 = new SelectItemGroup("Workflow");
List<DiagramElement> workflowList = automationElementService.generateListAvailableElements(
loginBean.getCurrentEmployee(), localeBean.getLanguage(),
AutomationElementCategory.WORKFLOW.toString());
g1.setSelectItems(createItemList(workflowList));
list.add(g1);
return list;
} catch (Exception e) {
LOGGER.error(ExceptionUtils.getFullStackTrace(e));
ErrorMessage.showErrorMessage();
}
return null;
}
private SelectItem[] createItemList(List<DiagramElement> list) {
List<SelectItem> newlist = new ArrayList<SelectItem>();
for (DiagramElement e : list) {
newlist.add(new SelectItem(e, e.getName()));
}
SelectItem[] arr = new SelectItem[newlist.size()];
arr = newlist.toArray(arr);
return arr;
}
And here my converter:
#FacesConverter("diagramElementConverter")
public class DiagramElementConverter implements Converter {
#Inject
private AutomationElementService automationElementService;
#Inject
private LoginBean loginBean;
#Inject
private LocaleBean localeBean;
public String getAsString(FacesContext context, UIComponent component, Object object) {
String field = (object instanceof DiagramElement) ? ((DiagramElement) object).getId() : null;
return (field != null) ? String.valueOf(field) : null;
}
public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
try {
if (submittedValue == null) {
return null;
}
if (submittedValue.trim().equals("")) {
return null;
} else {
for (DiagramElement diagramElement : automationElementService.generateListAvailableElements(
loginBean.getCurrentEmployee(), localeBean.getLanguage(), null)) {
if (diagramElement.getId().equals(submittedValue)) {
return diagramElement;
}
}
}
} catch (Exception e) {
}
return null;
}
}
I tried to make same list as in the below link:
http://www.primefaces.org/showcase/ui/input/listbox.xhtml
Unfortunately I get validation error:
Select Box: Validation Error: Value is not valid
I don't know where I've made mistake. I read a lot about this issue (in most cases it was solved by BalusC) however still can't find the issue.
If you can help I really appreciate.
StoreHouse.java
#Entity
public class StoreHouse implements Serializable {
#Id
#GeneratedValue
private Integer id;
#OneToOne
private Supply supply;
#Column(nullable = false)
private Integer amount;
//geters setters namedqueryies
Supply.java
#Entity
public class Supply implements Serializable {
#Id
#GeneratedValue
private Integer id;
#Column(unique = true, nullable = false, length = 32)
private String name;
#Column(length = 1024)
private String description;
#Column
private Double price;
#Enumerated(EnumType.STRING)
#NotNull
private SupplyType supplyType;
//geters setters namedqueryies
StoreHouseController.java
#ManagedBean
public class StoreHouseController implements Serializable {
#Inject
private StoreHouseBean storeHouseBean; // DAO for storeHouse
#ManagedProperty("#{supplyController}")
private SupplyController supplyController; //Manged bean for Supply
private StoreHouse storeHouse = new StoreHouse();
private List<Supply> allSupplies;
#PostConstruct
public void init() {
allSupplies = supplyController.findAll();
}
public void check() {
System.out.println("storeHousetheme" + storeHouse.toString()); // Function just to check if the supply was set
}
SupplyConverter.java
#FacesConverter("supplyConverter")
public class SupplyConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value != null && value.trim().length() > 0) {
try {
SupplyController supplyController = (SupplyController) context.getExternalContext().getApplicationMap().get("supplyController");
Supply supply = supplyController.findById(Integer.parseInt(value));
System.out.println("CONVERTER:" + supply.toString());
return supply;
} catch (NumberFormatException e) {
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion error", "ERROR."));
}
} else {
return null;
}
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object object) {
if (object != null) {
return String.valueOf(((Supply) object).getId());
} else {
return null;
}
}
}
view.xhtml
<h:form>
<p:messages autoUpdate="true" />
<h:panelGrid columns="2">
<h:outputLabel value="Nazwa" />
<p:selectOneListbox id="supplies" value="#{storeHouseController.storeHouse.supply}" converter="supplyConverter" var="s" filter="true" label="Select Box">
<f:selectItems value="#{storeHouseController.allSupplies}" var="supply" itemLabel="#{supply.name}" itemValue="#{supply}"/>
<p:column>
<h:outputText value="#{s.name}" />
</p:column>
</p:selectOneListbox>
<p:commandButton action="#{storeHouseController.check}" type="submit" value="submit" />
</h:panelGrid>
If you need any other file/class please just add comment.
Your SelectItem-value is your object, so the toString()-method is called and you get something like "Supply#44de6bae".
Then, your controller tries to parse it to int and fails. Try...
<f:selectItems value="#{...}" var="..." itemLabel="..." itemValue="#{supply.id}"/>
If the error occures while loading the page, this might help as well as at least some components don't like "none-basic-type-or-enum" values. I hope this helped, Greez.
After few more days of searching and googling I've found the solution. I'm a bit angry that this is not posted anywhere on primefaces because I've lost many hours to fix the issue.
It came out that I did not overwrite equals method of Supply class which is required.
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Supply other = (Supply) obj;
if (!Objects.equals(this.id, other.id)) {
return false;
}
if (!Objects.equals(this.name, other.name)) {
return false;
}
if (this.supplyType != other.supplyType) {
return false;
}
return true;
}
I believe that this topic will help someone in the future...
I am currently implementing a orderable list using PrimeFaces' component, embedded inside a . I was able to get the list to appear properly with my items. However, when I saved the list and submitted it back to the server, the rearranged items did not get reflected in the backing bean for some reason. Since the Primefaces showcase was able to see the changes, what am I doing wrong?
XHTML Snippet:
<h:form id="confirmDialogForm">
<p:confirmDialog id="arrangeProjDialog" widgetVar="arrangeDlg" width="600"
header="Meeting Order"
appendToBody="true" message="Drag and drop to rearrange meeting order">
<p:orderList id="arrangeProjDialogList"
value="#{adminMeetingListBean.orderProjList}"
converter="#{adminMeetingListBean.rowConverter}"
var="po"
controlsLocation="left"
styleClass="wideList"
itemLabel="#{po.projectTitle}"
itemValue="#{po}"
>
<f:facet name="caption">Proposals</f:facet>
</p:orderList>
<p:commandButton value="Save" ajax="true" process="arrangeProjDialogList #this"
actionListener="#{adminMeetingListBean.updateProposalMeetingOrder}" onclick="arrangeDlg.hide();">
</p:commandButton>
<p:button value="Cancel" onclick="arrangeDlg.hide(); return false;" />
</p:confirmDialog>
</h:form>
Backing Bean:
public void updateProposalMeetingOrder() {
if (selectedMeeting != null) {
orderProjTitles.get(0);
meetingService.updateMeetingProjSequence(orderProjList, selectedMeeting.getMeetingId());
}
}
The List is a list of POJO "ProposalOrderRow" objects. This has the definition:
public class ProposalOrderRow implements Serializable {
private static final long serialVersionUID = -5012155654584965160L;
private int dispSeq;
private int appId;
private int assignmentId;
private String refNo;
private String projectTitle;
public int getDispSeq() {
return dispSeq;
}
public void setDispSeq(int dispSeq) {
this.dispSeq = dispSeq;
}
public int getAppId() {
return appId;
}
public void setAppId(int appId) {
this.appId = appId;
}
public String getRefNo() {
return refNo;
}
public void setRefNo(String refNo) {
this.refNo = refNo;
}
public String getProjectTitle() {
return projectTitle;
}
public void setProjectTitle(String projectTitle) {
this.projectTitle = projectTitle;
}
public int getAssignmentId() {
return assignmentId;
}
public void setAssignmentId(int assignmentId) {
this.assignmentId = assignmentId;
}
}
Converter:
#FacesConverter("proposalOrderRowConverter")
public class ProposalOrderRowConverter implements Converter {
private List<ProposalOrderRow> orderRows;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String newValue) {
if (newValue.isEmpty()) {
return null;
}
for (ProposalOrderRow item : orderRows) {
String refNo = item.getRefNo();
if (refNo.equals(newValue)) {
return item;
}
}
return null;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) {
return "";
}
ProposalOrderRow row = (ProposalOrderRow) value;
String output = row.getRefNo();
return output;
}
public List<ProposalOrderRow> getOrderRows() {
return orderRows;
}
public void setOrderRows(List<ProposalOrderRow> orderRows) {
this.orderRows = orderRows;
}
}
This problem is caused by appendToBody="true" in the confirm dialog. Setting it to false solved the problem.
See link here: link
hey I am using the following code to create the number of text fields as the user wants
<h:form>
<p>Number Of News <h:inputText value="#{news.noOfFields}" /></p>
<ui:repeat value="#{news.values}" var="item">
<hr/>
News #{item.no}
<h:inputText value="#{item.news}" /><br/>
</ui:repeat>
<hr/>
<h:commandButton styleClass="btn btn-blue" action="#{news.submit}" value="Save" />
</h:form>
The managed bean news has a class News as
#ManagedBean
#SessionScoped
public class News
{
private String noOfFields;
private List<NewsVO> values;
public News()
{
this.values = new ArrayList<NewsVO>();
}
public String submit() {
for(NewsVO newsVO : this.values)
{
System.out.println(newsVO.getNews());
System.out.println(newsVO.getNo());
}
return null;
// save values in database
}
public String getNoOfFields() {
return noOfFields;
}
public List<NewsVO> getValues() {
return values;
}
public void setValues(List<NewsVO> values) {
this.values = values;
}
public void setNoOfFields(String noOfFields) {
this.values = new ArrayList<NewsVO>();
try {
for(int i=0;i<Integer.valueOf(noOfFields);i++)
{
NewsVO newsVO = new NewsVO();
newsVO.setNo(i+1);
this.values.add(newsVO);
}
this.noOfFields = noOfFields;
}
catch(NumberFormatException ex) {
/*values = new String[1];*/
noOfFields = "1";
}
}
}
The NewsVO is just a javaBean class as follows
public class NewsVO
{
public int no;
public String news;
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getNews() {
return news;
}
public void setNews(String news) {
this.news = news;
}
}
The problem is the values inside the input Text doesn't get reflected on pressing the save button. It gives me null, even though, I have written something inside all the textfields.
<h:inputText value="#{item.news}" />
Everytime you push the submit button, all setters in the bean are called (including setNoOfFields()). In this setter you are resetting your list, that's why you loose your values. Since you only need to modify your list if there is a size change, here is a simple way doing it :
#ManagedBean
#SessionScoped
public class News
{
private int noOfFields;
private List<NewsVO> values;
public News()
{
this.values = new ArrayList<NewsVO>();
}
public String submit()
{
for(NewsVO newsVO : this.values)
{
System.out.println(newsVO.getNews());
System.out.println(newsVO.getNo());
}
return null;
// save values in database
}
public int getNoOfFields()
{
return noOfFields;
}
public List<NewsVO> getValues()
{
return values;
}
public void setValues(List<NewsVO> values)
{
this.values = values;
}
public void setNoOfFields(int noOfFields)
{
if(noOfFields < this.noOfFields)
{
for(int i = this.noOfFields - 1;i >= noOfFields;i--)
{
getValues().remove(i);
}
}
else if(noOfFields > this.noOfFields)
{
for(int i = this.noOfFields;i < noOfFields;i++)
{
NewsVO newsVO = new NewsVO();
newsVO.setNo(i+1);
getValues().add(newsVO);
}
}
}
}
Note : I've also changed your noOfFields getter/setter for simple int, JSF will do the conversion for you.
I'm a JSF Newbie and having problem with displaying data using datatable. These is my scenario:
I want to display the contract(s) assigned to the Customer
JSF page's Datatable : customerdetail.jsp
<h:dataTable id="dt_contract_list" value="#{customerBean.customer.contracts}" var="item">
<h:column>
<f:facet name="header">
<h:outputText value="Contract Identifier"/>
</f:facet>
<h:outputText style="" value="#{item.contractIdentifier}"></h:outputText>
</h:column>
</h:dataTable>
Entity Bean : Customer.java
#Entity
#NamedQueries({
#NamedQuery(name="getCustomerByName", query="SELECT customer FROM Customer customer WHERE customer.name = :name"),
#NamedQuery(name="getAllCustomer", query="SELECT customer FROM Customer customer")
})
public class Customer {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
#OneToMany(targetEntity = Contract.class,
mappedBy = "customer",
cascade = CascadeType.ALL,
fetch=FetchType.EAGER)
private List<Contract> contracts = new ArrayList<Contract>();
public Customer() {
super();
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public List<Contract> getContracts() {
return this.contracts;
}
#Override
public boolean equals(Object object) {
if (this.getClass().isInstance(object)) {
return this.getName().equals(((Customer) object).getName());
} else {
return false;
}
}
}
BackingBean : CustomerBean.java
public class CustomerBean implements Serializable {
#EJB
private CustomerControllerLocal customerController;
private Customer customer;
public CustomerBean() {
customer = new Customer();
}
public String createCustomer() {
// create customer
}
public String updateCustomer() {
// update customer
}
public String deleteCustomer() {
// delete custoer
}
public String getCustomerByName() {
try {
customerController.getCustomerByName(customer.getName());
} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "customer_got";
}
public String assignContractsToCustomer() {
// assign contract to customer
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
There's no errors and the whole business logic layer, data layer were tested and work fine but the result is null (and it shouldn't!) and no sign of any exception. Can anyone help me figure it out what's wrong with this? T___T
Your facelet code looks ok.
In your entity class there is one thing that looks suspicious. It is this line:
private List<Contract> contracts = new ArrayList<Contract>();
In the entity classe for my own projects (classes generated by netbeans) the relationship lists are never initialized. I am no expert in JPA but you could try it without the initialization part.