I have a dataGrid that iterates a list of object. In each grid I have a commandButton and a tag that tries to put the Id of the object selected in the backing bean, but when action is executed, and also in the setter method of the property, the value is null.
Here is my code:
<p:dataGrid var="element" value="#{CentroController.profiles}" columns="3"
rows="10" paginator="true" paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}" >
<p:panel header="#{CentroController.getDescripcionRoot(element)}" style="text-align:center">
<h:panelGrid columns="2" style="width:100%">
<p:panel>
<p:commandButton value="Borrar perfil" icon="ui-icon-trash" update=":form:tabView:profileButtonPanel" action="#{CentroController.deletePerfil}">
<f:setPropertyActionListener value="#{element.id}" target="#{CentroController.selectedItemId}" />
</p:commandButton>
</p:panel>
</h:panelGrid>
</p:panel>
</p:dataGrid>
In the backing bean:
public void deletePerfil()
{
System.out.println("SELECTED ITEM ID: " + this.selectedItemId);
// selectedItemID is always null
}
When setter is called, the value is also null:
public void setSelectedItemId(BigDecimal selectedItemId) {
System.out.println(selectedItemId); // Value is null
this.selectedItemId = selectedItemId;
}
Thanks.
Edit: the code of the bean (I removed irrelevant methods).
/* imports */
#Named("CentroController")
#SessionScoped
public class CentroController implements Serializable{
private #Inject CentrosDAO dao;
private #Inject CentrosCanalesDAO daoServicios;
private #Inject CatalogoCentrosLaboratorioDAO habitualLabDAO;
private #Inject CatalogoCentrosRadiologiaDAO habitualRadDAO;
private List<Centros> centros;
private Centros selectedCentro;
private List<CentrosCanales> selectedCanales=new ArrayList<CentrosCanales>();
private List<CentrosCanales> listado;
private CentrosCanales selected;
private CatalogoCentros selectedItem;
private BigDecimal selectedItemId;
private TreeNode root;
private DualListModel<Catalogo> listCatalogo;
private DualListModel <Catalogo> listCatalogoLabHabitual;
private DualListModel <Catalogo> listCatalogoRadHabitual;
private CatalogoCentros perfilNuevo=new CatalogoCentros();
private #Inject CentrosCanalesDAO consulta;
private #Inject CatalogoCentrosDAO consulta1;
private #Inject CatalogoDAO consulta2;
private boolean servicioIsSelected; //, perfilIsSelected, pruebaIsSelected;
private List<CatalogoCentros> profiles;
public CentroController() {
}
#PostConstruct
public void init(){
this.centros=dao.obtenListaCentros();
servicioIsSelected = false;
//perfilIsSelected = false;
}
public BigDecimal getSelectedItemId() {
return selectedItemId;
}
public void setSelectedItemId(BigDecimal selectedItemId) {
System.out.println(selectedItemId);
this.selectedItemId = selectedItemId;
}
public void deletePerfil()
{
System.out.println("SELECTED ITEM ID: " + this.selectedItemId);
}
}
UPDATED
The dataGrid is inside a rowExpansion tag within a datatable. I realized that if I put the dataGrid outside instead of nested in the datatable, it works. But I want it in the rowExpansion.
It only works If I put the datagrid outside of the tabView in which is included.
Some questions about CatalogoCentros:
Is the id field a BigDecimal?
Did you override the hashCode and equals?
If "no" to question 2, do something like this:
#Override
public int hashCode() {
return (id != null) ? id.intValue() : 0;
}
#Override
public boolean equals(final Object obj) {
if (obj instanceof CatalogoCentros) {
CatalogoCentros item = (CatalogoCentros) obj;
return item.getId().equals(getId());
}
return false;
}
Set a breakpoint in your equals method and see if that gets tripped when you select something in the dataGrid.
Related
I decided to refactor my application because of hugh memory leaks in the old version. For visualization objects, I decide to not more using fxml, but Styleable interface.
So I created a class Sim Photo like this :
public class SimPhoto extends Control {
private static final String DEFAULT_CLASS_NAME = "sim-photo";
private static final Double DEFAULT_STROKE_WIDTH = 0.0;
#Getter
#Setter
private static String DEFAULT_PHOTO = "";
private StyleableStringProperty imgPath;
private StyleableIntegerProperty arcHeight;
private StyleableIntegerProperty arcWidth;
private DoubleProperty strokeWidth;
private ObjectProperty<Paint> stroke;
private ObjectProperty<Paint> fill;
public SimPhoto() {
initialize();
}
public SimPhoto(#NamedArg("imgPath") String imgPath) {
this();
this.imgPathProperty().set(imgPath);
}
//Example of init properties
public final StyleableIntegerProperty arcHeightProperty() {
if (arcHeight == null) {
arcHeight = new SimpleStyleableIntegerProperty(
StyleableProperties.ARC_WIDTH,
SimPhoto.this,
"arcWidth",
0
);
}
return arcHeight;
}
public final StringProperty imgPathProperty() {
if(imgPath == null) {
imgPath = new SimpleStyleableStringProperty(
StyleableProperties.IMG_PATH,
SimPhoto.this,
"imgPath",
"");
}
return imgPath;
}
(...)
}
In my skin class, I use binding of properties from Control Class
public class SimPhotoSkin extends SkinBase<SimPhoto> {
#Getter
private Rectangle photoFond = new Rectangle();
private Rectangle photoView = new Rectangle();
private boolean invalidate = false;
private InvalidationListener invalidListener = this::invalidated;
private ChangeListener<String> pathListener = this::pathChanged;
public SimPhotoSkin(SimPhoto control) {
super(control);
initVisualization();
initListeners();
}
private void initVisualization() {
getChildren().addAll(photoFond, photoView);
if (getSkinnable().imgPathProperty() != null) {
setNewFond(getSkinnable().getImgPath());
}
}
private void initListeners() {
photoFond.widthProperty().bind(getSkinnable().widthProperty().subtract(5));
photoFond.heightProperty().bind(getSkinnable().heightProperty().subtract(5));
photoView.widthProperty().bind(photoFond.widthProperty().subtract(photoFond.strokeWidthProperty()));
photoView.heightProperty().bind(photoFond.heightProperty().subtract(photoFond.strokeWidthProperty()));
photoView.arcWidthProperty().bind(getSkinnable().arcWidthProperty());
photoView.arcHeightProperty().bind(getSkinnable().arcHeightProperty());
photoFond.arcWidthProperty().bind(getSkinnable().arcWidthProperty());
photoFond.arcHeightProperty().bind(getSkinnable().arcHeightProperty());
photoFond.fillProperty().bind(getSkinnable().fillProperty());
photoFond.strokeProperty().bind(getSkinnable().strokeProperty());
photoFond.strokeWidthProperty().bind(getSkinnable().strokeWidthProperty());
getSkinnable().imgPathProperty().addListener(pathListener);
}
private void pathChanged(ObservableValue<? extends String> observable, String oldValue, String newValue) {
(...)
}
private void setNewFond(String path) {
(...)
}
private void invalidated(Observable observable) {
invalidate = true;
}
}
I know that object cannot been GC while exist a reference to it. So I have a big problem, because event these objects are no more used, thay cannot be GC , and in my application ,when I need creating more than 300 objects at time is a big problem.
I tried to create method clean(), that will be unbind all bidnings and listeners, but it's not realy helpful. Problem still persist.
I'm thinking about any workaround like a Manager, that will store all objects in queue and while calling will return one objects disponibles or create new one.
But this is the last possibility, if I dont find any solution for my problem, and I would like avoid this.
I have this simple form with 2 checkboxes and a submit button. When I submit the form, I get this error
HTTP Status 400 The request sent by the client was syntactically incorrect.
This is my POJO:
public class Menu{
private String day;
private String name;
private int price;
public Menu(){
}
public Menu(String day, String name, int price) {
this.day = day;
this.name = name;
this.price = price;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDay() {
return day;
}
public void setDay(String l) {
this.day = l;
}
#Override
public int hashCode() {
int hash = 3;
hash = 7 * hash + this.day.hashCode();
hash = 7 * hash + this.name.hashCode();
return hash;
}
#Override
public boolean equals(Object object) {
boolean result = false;
System.out.println("ARE YOU EVER CALLLED HOW MANY TIMES");
if (object == null || object.getClass() != getClass()) {
result = false;
} else {
Menu sc = (Menu) object;
if (this.day == sc.getDay() && this.name == sc.getName()
&& this.price == sc.getPrice()) {
result = true;
}
}
return result;
}
This is my Order class:
public class Order {
private List<Menu> menus = new ArrayList<Menu>();
public Order(){}
public Order(ArrayList<Menu> menus){
this.menus = menus;
}
public List<Menu> getMenus() {
return menus;
}
public void setMenus(ArrayList<Menu> menus) {
this.menus = menus;
}
}
And this is my controller:
#Controller
public class RestaurantController {
#RequestMapping(value = "/menu", method = RequestMethod.GET)
public String menuPage(Model model){
Order o = new Order();
ArrayList<Menu> m = new ArrayList<Menu>();
m.add(new Menu("Sunday", "Phir Aloo", 12));
m.add(new Menu("Sunday", "Phir Cholay", 9));
model.addAttribute("today", m);
model.addAttribute("order", o);
return "/menu";
}
#RequestMapping(value = "/confirm", method = RequestMethod.POST)
public String done(#ModelAttribute(value="order") Order order, Model model){
return "/confirm";
}
And this is my menu.jsp: (http://localhost:9080/res/menu)
<form:form modelAttribute="order" method="post" action="/res/confirm">
<c:forEach items="${today}" var="r">
<form:checkbox path="menus" value="${r}" label="${r.name } ${r.price }" />
</c:forEach>
<input type="submit" value="Submit Data">
</form:form>
Now I just expect Class Order's property 'menus' to be filled with selected checkboxes. Instead I get this error "The request sent by the client was syntactically incorrect. I have looked up every possible answer on this website but nothing seems to be solving the problem.
After #R Sawant's suggestion I was able to solve the problem. Here is my Property Editor.
public class MenuTypeEditor extends PropertyEditorSupport {
public void setAsText(String text) {
setValue(new Menu(text.toUpperCase()));
}
}
I kept this class inside the same package which has Menu.java and Order.java
Now inside my controller wrote this:
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Menu.class, new MenuTypeEditor());
}
And voila! Magic happened.
I hope this answer can help someone.
The problem is with the value you are posting when the check box is ticked. Look at the below code
<form:checkbox path="menus" **value="${r}"** label="${r.name } ${r.price }" />
See what have assigned to value attribute in the above line. Its whole object of menu. It will essentially post the toString() representation of the object. Since you have not implemented toString() for Menu class, something like Menu#1ed2e55e gets posted for the check box value. Spring is unable to convert this to something meaningful and hence the problem.
You have to make use of property editor support to deal with these type of situations. Property editor will help you convert string to Object and vice versa. In your case String to Menu object and vice versa. Take a look at examples of property editors. Hope this helps
Edit:- a google search got this result. Take a look at it, may help you to understand.
I have an object Contract and it contains Summary and Observable List of another object ContractDetails inside it.
Now, I am using ContractDetails to populate in tableview from Contract object.
I have a save button, which on clicking needs to save Contract along with ContractDetails. I am able to access ContractDetails since they are in tableview.
How do I access Contract properties in eventlistener of save button.
The related code is given below
public class Contract {
private String tradeDate;
private String contractNote;
.....
.....
private String brokerId;
private ObservableList<ContractDetails> contractdetails = FXCollections.observableArrayList();
public Contract() {
}
public Contract(String tradeDate, String contractNote, ....., String brokerId,ObservableList<ContractDetails> contractdetails) {
this.tradeDate = tradeDate;
this.contractNote = contractNote;
....
....
this.contractdetails=contractdetails;
}
public String getTradeDate() {
return tradeDate;
}
public void setTradeDate(String tradeDate) {
this.tradeDate = tradeDate;
}
public String getContractNote() {
return contractNote;
}
public void setContractNote(String contractNote) {
this.contractNote = contractNote;
}
....
....
public ObservableList<ContractDetails> getContractdetails() {
return contractdetails;
}
public void setContractdetails(ObservableList<ContractDetails> contractdetails) {
this.contractdetails = contractdetails;
}
}
public class ContractDetails {
private String orderNo;
private String contractType;
private String symbol;
private String buysell;
private Integer quantity;
private Double buysellprice;
private Double netcontractValue;
public ContractDetails() {
}
public ContractDetails(String orderNo, String contractType, String symbol, String buysell, Integer quantity, Double buysellprice, Double netcontractValue) {
this.orderNo = orderNo;
this.symbol = symbol;
this.buysell = buysell;
this.quantity = quantity;
this.buysellprice = buysellprice;
this.netcontractValue = netcontractValue;
}
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
....
....
public Double getNetcontractValue() {
return netcontractValue;
}
public void setNetcontractValue(Double netcontractValue) {
this.netcontractValue = netcontractValue;
}
}
In the controller
==================
public class ContractViewController implements Initializable {
#FXML
private TableView<ContractDetails> tblcontractfx;
#FXML
private TableColumn<ContractDetails, String> contractTypefx;
#FXML
private TableColumn<ContractDetails, String> symbolfx;
....
....
#FXML
private Button savefx;
#FXML
private TextField txtclientcodefx;
#FXML
private TextField txttradedtfx;
private void fetchContracts(TableView tableView, Contract contract)
{ txttradedtfx.setText(contract.getTradeDate());
txtclientcodefx.setText(contract.getClientCode());
symbolfx.setCellValueFactory(new PropertyValueFactory<ContractDetails, String>("symbol"));
contractTypefx.setCellValueFactory(new PropertyValueFactory<ContractDetails, String>("contractType"));
tableView.setItems((ObservableList) contract.getContractdetails());
#FXML
private void saveClicked(ActionEvent event) { DBConnection DBcon = new DBConnection();
//Now I am getting the contract details from tableview tblcontractfx
ObservableList<ContractDetails> contractdetails = tblcontractfx.getItems();
//How do I get the summary values from contract. I am able to get those which are in text fields like txttradedtfx and txtclientcodefx.However contractNote which I am not using, I still need to retrieve it to populate into database.
String clientCode=txtclientcodefx.getText();
Thanks
Just store the contract in a local variable.
Contract contract;
private void fetchContracts(TableView tableView, Contract contract)
{
this.contract = contract;
...
}
private void saveClicked(ActionEvent event) {
// here you have full access to the contract variable
String contractNote = contract.getContractNote();
}
As an alternative, if you insist on combining it all in a single table, you could put the Contract into the table via setUserData and retrieve it via getUserData.
By the way, I still don't get your code. Why is there a tableView parameter when you have full access to TableView<ContractDetails> tblcontractfx
For example:
<uc:AdmiralAckbar runat="server" id="myCustomControl">
<Warning SomeAttribute="It's A Trap">
My Data
</Warning>
</uc:AdmiralAckbar>
I'm not sure how to add SomeAttribute. Any ideas?
Code without the attribute is:
private ITemplate warning = null;
[TemplateContainer(typeof(INamingContainer))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Warning
{
get
{
return warning;
}
set
{
warning = value;
}
}
The answer is yes.
For this you should create a type which implements ITemplate interface and add a custom property/properties there (I added property Name in my example); also add a class which inherits from Collection<YourTemplate>.
Here is an example of doing that:
public class TemplateList : Collection<TemplateItem> { }
public class TemplateItem : ITemplate
{
public string Name { get; set; }
public void InstantiateIn(Control container)
{
var div = new HtmlGenericControl("div");
div.InnerText = this.Name;
container.Controls.Add(div);
}
}
and a control itself:
[ParseChildren(true, "Templates"), PersistChildren(false)]
public class TemplateLibrary : Control
{
public TemplateLibrary()
{
Templates = new TemplateList();
}
[PersistenceMode(PersistenceMode.InnerProperty)]
public TemplateList Templates { get; set; }
protected override void RenderChildren(HtmlTextWriter writer)
{
foreach (var item in Templates)
{
item.InstantiateIn(this);
}
base.RenderChildren(writer);
}
}
and finally an example of usage:
<my:TemplateLibrary runat="server">
<my:TemplateItem Name="hello" />
<my:TemplateItem Name="there" />
</my:TemplateLibrary>
BTW, you could also use it as:
<my:TemplateLibrary runat="server">
<Templates>
<my:TemplateItem Name="hello" />
<my:TemplateItem Name="there" />
</Templates>
</my:TemplateLibrary>
the effect will be the same.
I am trying to create 3 drop down menu for a form. First one, is LOB field. Second one is Application field and last one is CTA field. There is one to many relationship between LOB and Application. There is many to many relationship from Application to CTA.
CreateRequest.xhtml
<h:selectOneMenu id="lobField" value="#{manager.lob}" required="true">
<s:selectItems var="lob" value="#{lobs}" label="#{lob.lobDescription}" noSelectionLabel="Select LOB"></s:selectItems>
<s:convertEntity />
<a:support action="#{manager.loadApps}" ajaxSingle="true" event="onchange" reRender="appField,ctaField"/>
</h:selectOneMenu>
<a:outputPanel id="appField">
<h:selectOneMenu value="#{manager.app}" required="true">
<s:selectItems var="app" value="#{manager.applications}" label="#{app.applicationName}" noSelectionLabel="Select Application"></s:selectItems>
<s:convertEntity />
<a:support action="#{manager.loadCtas}" ajaxSingle="true" event="onchange" reRender="ctaField"/>
</h:selectOneMenu>
</a:outputPanel>
<a:outputPanel id="ctaField">
<h:selectOneMenu value="#{manager.cta}" required="true">
<s:selectItems var="cta" value="#{manager.ctas}" label="#{cta.ctaDescription}" noSelectionLabel="Select CTA"></s:selectItems>
<s:convertEntity />
</h:selectOneMenu>
ManagerBean.java
#Stateful
#Name("manager")
public class ManagerBean implements Manager {
#Logger
private Log log;
#In
StatusMessages statusMessages;
private Lob lob;
private Application app;
private Cta cta;
#PersistenceContext(type = PersistenceContextType.EXTENDED)
EntityManager entityManager;
#Out(required = false)
private List<Lob> lobs;
private List<Application> applications;
private List<Cta> ctas;
public void CreateRequest() {
System.out.println("Create Request");
System.out.println(app.getApplicationName());
}
public Lob getLob() {
return lob;
}
public void setLob(Lob lob) {
this.lob = lob;
}
public Application getApp() {
return app;
}
public void setApp(Application app) {
this.app = app;
}
public Cta getCta() {
return cta;
}
public void setCta(Cta cta) {
this.cta = cta;
}
public List<Lob> getLobs() {
return lobs;
}
public void setLobs(List<Lob> lobs) {
this.lobs = lobs;
}
public List<Application> getApplications() {
return applications;
}
public void setApplications(List<Application> applications) {
this.applications = applications;
}
public List<Cta> getCtas() {
return ctas;
}
public void setCtas(List<Cta> ctas) {
this.ctas = ctas;
}
#Destroy
#Remove
public void destroy() {
}
#Factory("lobs")
public void loadLobs() {
lobs = entityManager.createQuery("from Lob").getResultList();
}
public void loadApps() {
System.out.println("load apps called");
applications = lob.getApplicationList();
}
public void loadCtas() {
System.out.println("load ctas called====");
ctas = app.getCtaList();
System.out.println(ctas.size());
}
}
I am able to select a value from LOB, and loadApps is called. Then I am able to select applications, too. But when I select one, I get following error:
19:09:01,921 INFO [lifecycle] WARNING: FacesMessage(s) have been enqueued, but may not have been displayed.
sourceId=managerForm:appField[severity=(ERROR 2), summary=(value is not valid), detail=(value is not valid)]
I am unable to figure out what mistake I am making here.
Are you in a conversation? Without specifying a scope your SFSB will be in the conversation context. Have you started the conversation?