I have strange stacktrace when click to submit button (this code is rendered but don't work form processing). Example class:
public class SamplePage extends WebPage {
private List<String> list = Arrays.asList(new String[] { "item1", "item2", "item3" });
private List<String> selectedItem = Arrays.asList(new String[] { "item1" });
public SamplePage(final PageParameters parameters) {
super(parameters);
Form<?> form = new Form<Void>("form");
form.add(new Button("submin") {
#Override
public void onSubmit() {
System.out.println("Selected");
for (String tag : selectedItem)
System.out.println(tag);
}
});
ListMultipleChoice<String> selector = new ListMultipleChoice<>("itemSelector",
new PropertyModel<List<String>>(this, "selectedItem"), list);
add(form);
form.add(selector);
}
public List<String> getSelectedItem() {
return selectedItem;
}
public void setSelectedItem(List<String> selectedItem) {
this.selectedItem = selectedItem;
}
}
Caused by: java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at java.util.AbstractList$Itr.remove(AbstractList.java:374)
at java.util.AbstractList.removeRange(AbstractList.java:571)
at java.util.AbstractList.clear(AbstractList.java:234)
at org.apache.wicket.markup.html.form.FormComponent.updateCollectionModel(FormComponent.java:1531)
at org.apache.wicket.markup.html.form.ListMultipleChoice.updateModel(ListMultipleChoice.java:369)
at org.apache.wicket.markup.html.form.Form$FormModelUpdateVisitor.component(Form.java:221)
at org.apache.wicket.markup.html.form.Form$FormModelUpdateVisitor.component(Form.java:192)
at org.apache.wicket.util.visit.Visits.visitPostOrderHelper(Visits.java:273)
at org.apache.wicket.util.visit.Visits.visitPostOrderHelper(Visits.java:261)
at org.apache.wicket.util.visit.Visits.visitPostOrder(Visits.java:244)
at org.apache.wicket.markup.html.form.FormComponent.visitComponentsPostOrder(FormComponent.java:388)
at org.apache.wicket.markup.html.form.Form.internalUpdateFormComponentModels(Form.java:1701)
at org.apache.wicket.markup.html.form.Form.updateFormComponentModels(Form.java:1666)
at org.apache.wicket.markup.html.form.Form.process(Form.java:827)
at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:762)
at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:692)
... 31 more
How I understand problem is in definition model, but I don't understand why (I tried a lot of ways and didn't check problem). When I created DropDownChoice in same way, all worked correctly, but in this case I used
new PropertyModel<String>(this, "field")
in contrast to
new PropertyModel<List<String>>(this, "selectedItem")
I think it's very silly mistake and ask your help.
Arrays.asList() returns a fixed size list, you (i.e. Wicket) cannot remove elements form it.
Use another list instead:
private List<String> selectedItem = new ArrayList<String>();
public SamplePage(final PageParameters parameters) {
....
selectedItem.add("item1");
Without actually trying it out, but I guess that the List implementation you get from Arrays.asList() does not support removal of entries in the list.
Try something along the lines:
private List<String> selectedItem =
new LinkedList(Arrays.asList(new String[] { "item1")});
E.g. use an Implementation that allows removal. Wicket needs to modify the entries in the list to reflet the selected items.
Hope that helps. Bert
Related
I have an ArrayList which is filled by Objects.
My object class called Article which has two fields ;
public class Article {
private int codeArt;
private String desArt;
public Article(int aInt, String string) {
this.desArt = string;
this.codeArt = aInt;
}
public int getCodeArt() {return codeArt; }
public void setCodeArt(int codeArt) {this.codeArt = codeArt;}
public String getDesArt() {return desArt;}
public void setDesArt(String desArt) { this.desArt = desArt;}
}
I want to filter my List using the desArt field, and for test I used the String "test".
I used the Guava from google which allows me to filter an ArrayList.
this is the code I tried :
private List<gestionstock.Article> listArticles = new ArrayList<>();
//Here the I've filled my ArrayList
private List<gestionstock.Article> filteredList filteredList = Lists.newArrayList(Collections2.filter(listArticles, Predicates.containsPattern("test")));
but this code isn't working.
In Java 8, using filter
List<Article> articleList = new ArrayList<Article>();
List<Article> filteredArticleList= articleList.stream().filter(article -> article.getDesArt().contains("test")).collect(Collectors.toList());
This is normal: Predicates.containsPattern() operates on CharSequences, which your gestionStock.Article object does not implement.
You need to write your own predicate:
public final class ArticleFilter
implements Predicate<gestionstock.Article>
{
private final Pattern pattern;
public ArticleFilter(final String regex)
{
pattern = Pattern.compile(regex);
}
#Override
public boolean apply(final gestionstock.Article input)
{
return pattern.matcher(input.getDesArt()).find();
}
}
Then use:
private List<gestionstock.Article> filteredList
= Lists.newArrayList(Collections2.filter(listArticles,
new ArticleFilter("test")));
However, this is quite some code for something which can be done in much less code using non functional programming, as demonstrated by #mgnyp...
You can use a for loop or for each loop to loop thru the list.
Do you want to create another list based on some condition?
This should work I think.
List<Article> secondList = new ArrayList<Article>();
for( Article a : listArticles) {
// or equalsIgnoreCase or whatever your conditon is
if (a.getDesArt().equals("some String")) {
// do something
secondList.add(a);
}
}
Guava is a library that allows you to use some functional programming in Java.
One of the winning things in functional programming is collection transformation like
Collection -> op -> op -> op -> transformedCollection.
Look here:
Collection<Article> filtered = from(listArticles).filter(myPredicate1).filter(myPredicate2).filter(myPredicate3).toImmutableList();
It's beautiful, isn't it?
The second one winning thing is lambda functions. Look here:
Collection<Article> filtered = from(listArticles)
.filter((Predicate) (candidate) -> { return candidate.getCodeArt() > SOME_VALUE })
.toImmutableList();
Actually, Java has not pure lambda functions yet. We will be able to do it in Java 8. But for now we can write this in IDE Inellij Idea, and IDE transforms such lambda into Predicate, created on-the-fly:
Collection<Article> filtered = from(listArticles)
.filter(new Predicate<Article>() {
#Override
public boolean apply(Article candidate) {
return candidate.getCodeArt() > SOME_VALUE;
}
})
.toImmutableList();
If your filter condition requires regexp, the code become more complicated, and you will need to move condition to separate method or move whole Predicate to a separate class.
If all this functional programming seems too complicated, just create new collection and fill it manually (without Guava):
List<Article> filtered = new ArrayList<Article>();
for(Article article : listArticles)
{
if(article.getCodeArt() > SOME_VALUE)
filtered.add(article);
}
With Guava, I would say that the easiest way by far would be by using Collections2.filter, such as:
Collections2.filter(YOUR_COLLECTION, new Predicate<YOUR_OBJECT>() {
#Override
public boolean apply(YOUR_OBJECT candidate) {
return SOME_ATTRIBUTE.equals(candidate.getAttribute());
}
});
Try this:
private List<gestionstock.Article> listArticles = new ArrayList<>();
private List<gestionstock.Article> filteredList filteredList = Lists.newArrayList(Collections2.filter(listArticles, new Predicate<gestionstock.Article>(){
public boolean apply(gestationstock.Article article){
return article.getDesArt().contains("test")
}
}));
The idea being is since you're using a custom object, you should implement your own predicate. If you're using it anywhere else, define it in a file, otherwise, this implementation works nicely.
I have a simple panel (the panel itself is part of bigger form) with CheckGroup. The checkboxes in the check group are generated in the list view component. I need to dynamicaly change this panel and upon every change I need to retrieve the selected items. The code of the panel basically looks like this:
CheckGroup<MyObject> group = new CheckGroup<MyObject>(ID, selectedObjects);
ListView<MyObject> objectList = new ListView<MyObject>(ID, values) {
#Override
protected void populateItem(ListItem<MyObject> item) {
Check<MyObject> check = new Check<MyObject>(TIME_CHECK, item.getModel());
Label l = new Label(TIME_LABEL, item.getModel());
item.add(check);
item.add(l);
}
}
group.add(objectList);
group.add(new AjaxFormChoiceComponentUpdatingBehavior() {
#Override
protected void onUpdate(AjaxRequestTarget target) {
System.out.println("Selected objects: "+selectedObjects.size());
}
});
add(group);
Now, the problem is, whenever I click on the check box, the two identical objects are added to the selectedObjects list. And if I remove the AjaxFormChoiceComponentUpdatingBehavior, no objects are added to the list (which make sense, because I'm not submiting the form at this point).
I'm not exactly sure how to solve this problem and the best solution I came up with was getting the list and the going through it, removing duplicities.
Also, sorry for the title, but I have no idea how to name this problem.
Here's a little example to clarify the problem:
Lets say the check group is displaying these objects:
object 1
object 2
object 3
object 4
object 5
Then when I select object 1 the model of check group (=selectedObjects) will look like this:
object 1
object 1
This was a bug on wicket. I used version 7.1 then changed on version 7.10 and the problem solved!
Try
target.add(form);`
or
target.add(group);
or something similar, depending on your code.
You can try the following construction, recreate the checkgroup so that it is up to date. Maybe a bit overkill, but it should do the trick.
private CheckGroup<MyObject> group;
private IModel<MyObject> selectedObjects;
public MyCurrentPanel() {
selectedObjects = new CompoundPropertyModel<MyObject>(new MyObject());
group = createCheckGroup();
group.setOutputMarkupId(true);
add(group);
}
public CheckGroup<MyObject> createCheckGroup() {
CheckGroup<MyObject> newGroup = new CheckGroup<MyObject>(ID, MyCurrentPanel.this.selectedObjects);
ListView<MyObject> objectList = new ListView<MyObject>(ID, values) {
#Override
protected void populateItem(ListItem<MyObject> item) {
Check<MyObject> check = new Check<MyObject>(TIME_CHECK, item.getModel());
Label l = new Label(TIME_LABEL, item.getModel());
item.add(check);
item.add(l);
}
}
newGroup.add(objectList);
newGroup.add(new AjaxFormChoiceComponentUpdatingBehavior() {
#Override
protected void onUpdate(AjaxRequestTarget target) {
System.out.println("Selected objects: "+selectedObjects.size());
CheckGroup<MyObject> updateGroup = createCheckGroup();
updateGroup.setOutpurMarkupId(true);
MyCurrentPanel.this.group.replaceWith(updateGroup);
MyCurrentPanel.this.group = updateGroup;
target.add(MyCurrentPanel.this.group);
}
});
}
In my program, I have a jList and I can add, delete, modify items in this Jlist.
My problem is, if I click on my add button before selecting an item in my jList, the items inside the jList disapear. (only in apeareance because they are actually still in the jList)
If, before that, I select an item in my list, then everything is working fine. So my guess would be that the "valueChanged()" method from my listener is doing something that I don't do myself.
Here is my list initialisation, which I call at the start of the program:
public final void initList() {
jListPaiement.setModel(new MyListModel(ls.getDb().getListePaiements()));
final DecimalFormat df = new DecimalFormat("###.##");
jListPaiement.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent lse) {
MoyenPaiement mp = (MoyenPaiement) ((MyListModel) jListPaiement.getModel()).getElementAt(jListPaiement.getSelectedIndex());
jTextFieldFF.setText(df.format(mp.getFraisf()));
jTextFieldFV.setText(df.format(mp.getFraisv() * 100));
jTextFieldNomP.setText(mp.getNom());
jTextFieldFF.setVisible(true);
jTextFieldFV.setVisible(true);
jTextFieldNomP.setVisible(true);
jLabel1.setVisible(true);
jLabel6.setVisible(true);
jLabel7.setVisible(true);
jLabel8.setVisible(true);
jLabel11.setVisible(true);
jButtonSaveP.setVisible(true);
}
});
Here is the code from the add button:
private void jButtonAddPActionPerformed(java.awt.event.ActionEvent evt) {
MoyenPaiement mp = new MoyenPaiement("Nouveau", 0, 0);
((MyListModel) jListPaiement.getModel()).addElement(mp);
jListPaiement.setSelectedValue(mp, true);
jListPaiement.repaint();
}
MyListModel code:
public class MyListModel extends AbstractListModel {
ArrayList list;
public MyListModel(ArrayList list) {
this.list = list;
}
#Override
public int getSize() {
return list.size();
}
#Override
public Object getElementAt(int i) {
return list.get(i);
}
public void addElement(Object o){
list.add(o);
}
public void deleteElement(Object o){
list.remove(o);
}
public void setElement(int i,Object o){
list.set(i, o);
}
public ArrayList getList() {
return list;
}
public void setList(ArrayList list) {
this.list = list;
}
}
Any help will be greatly appreciated.
Thanks
Edit: After further research, the problem is when I add item to my model.
It comes exactly on the line:
((MyListModel) jListPaiement.getModel()).addElement(mp);
Even if I add a simple string such as:
((MyListModel) jListPaiement.getModel()).addElement("String");
The problem still occurs.
Look in detail what happens on this line and if you initialize jListPaiement correctly with the right data.
jListPaiement.setModel(new MyListModel(ls.getDb().getListePaiements()));
Seems like on this line setSelectedValue() can't find the element mp
jListPaiement.setSelectedValue(mp, true);
I finally found a solution.
Rather than using my own List Model, I used DefaultListModel and everything works fine. It's been long time since i worked on this project and I don't remember why i chose to make my own list model class.
Even tough it works now, I still don't understand what was missing in my own class (MyListModel) that made it not working..
I have an ArrayList which is filled by Objects.
My object class called Article which has two fields ;
public class Article {
private int codeArt;
private String desArt;
public Article(int aInt, String string) {
this.desArt = string;
this.codeArt = aInt;
}
public int getCodeArt() {return codeArt; }
public void setCodeArt(int codeArt) {this.codeArt = codeArt;}
public String getDesArt() {return desArt;}
public void setDesArt(String desArt) { this.desArt = desArt;}
}
I want to filter my List using the desArt field, and for test I used the String "test".
I used the Guava from google which allows me to filter an ArrayList.
this is the code I tried :
private List<gestionstock.Article> listArticles = new ArrayList<>();
//Here the I've filled my ArrayList
private List<gestionstock.Article> filteredList filteredList = Lists.newArrayList(Collections2.filter(listArticles, Predicates.containsPattern("test")));
but this code isn't working.
In Java 8, using filter
List<Article> articleList = new ArrayList<Article>();
List<Article> filteredArticleList= articleList.stream().filter(article -> article.getDesArt().contains("test")).collect(Collectors.toList());
This is normal: Predicates.containsPattern() operates on CharSequences, which your gestionStock.Article object does not implement.
You need to write your own predicate:
public final class ArticleFilter
implements Predicate<gestionstock.Article>
{
private final Pattern pattern;
public ArticleFilter(final String regex)
{
pattern = Pattern.compile(regex);
}
#Override
public boolean apply(final gestionstock.Article input)
{
return pattern.matcher(input.getDesArt()).find();
}
}
Then use:
private List<gestionstock.Article> filteredList
= Lists.newArrayList(Collections2.filter(listArticles,
new ArticleFilter("test")));
However, this is quite some code for something which can be done in much less code using non functional programming, as demonstrated by #mgnyp...
You can use a for loop or for each loop to loop thru the list.
Do you want to create another list based on some condition?
This should work I think.
List<Article> secondList = new ArrayList<Article>();
for( Article a : listArticles) {
// or equalsIgnoreCase or whatever your conditon is
if (a.getDesArt().equals("some String")) {
// do something
secondList.add(a);
}
}
Guava is a library that allows you to use some functional programming in Java.
One of the winning things in functional programming is collection transformation like
Collection -> op -> op -> op -> transformedCollection.
Look here:
Collection<Article> filtered = from(listArticles).filter(myPredicate1).filter(myPredicate2).filter(myPredicate3).toImmutableList();
It's beautiful, isn't it?
The second one winning thing is lambda functions. Look here:
Collection<Article> filtered = from(listArticles)
.filter((Predicate) (candidate) -> { return candidate.getCodeArt() > SOME_VALUE })
.toImmutableList();
Actually, Java has not pure lambda functions yet. We will be able to do it in Java 8. But for now we can write this in IDE Inellij Idea, and IDE transforms such lambda into Predicate, created on-the-fly:
Collection<Article> filtered = from(listArticles)
.filter(new Predicate<Article>() {
#Override
public boolean apply(Article candidate) {
return candidate.getCodeArt() > SOME_VALUE;
}
})
.toImmutableList();
If your filter condition requires regexp, the code become more complicated, and you will need to move condition to separate method or move whole Predicate to a separate class.
If all this functional programming seems too complicated, just create new collection and fill it manually (without Guava):
List<Article> filtered = new ArrayList<Article>();
for(Article article : listArticles)
{
if(article.getCodeArt() > SOME_VALUE)
filtered.add(article);
}
With Guava, I would say that the easiest way by far would be by using Collections2.filter, such as:
Collections2.filter(YOUR_COLLECTION, new Predicate<YOUR_OBJECT>() {
#Override
public boolean apply(YOUR_OBJECT candidate) {
return SOME_ATTRIBUTE.equals(candidate.getAttribute());
}
});
Try this:
private List<gestionstock.Article> listArticles = new ArrayList<>();
private List<gestionstock.Article> filteredList filteredList = Lists.newArrayList(Collections2.filter(listArticles, new Predicate<gestionstock.Article>(){
public boolean apply(gestationstock.Article article){
return article.getDesArt().contains("test")
}
}));
The idea being is since you're using a custom object, you should implement your own predicate. If you're using it anywhere else, define it in a file, otherwise, this implementation works nicely.
I'm getting very strange problem in JSF page when I try to display Java List<String> with countries in JSF page. This is the code:
private List<String> listCountries;
// Get the list with Countries
public List<String> getlistCountries() {
// Generate List of Countries
initlistCountries();
return listCountries;
}
public void initlistCountries(){
listCountries.add("Afghanistan");
listCountries.add("Albania");
listCountries.add("Algeria");
listCountries.add("Andorra");
listCountries.add("Angola");
......
}
Is this code correct? I can't use #PostConstruct because I have use it already.
I get his error when I load the JSF page:
java.lang.NullPointerException
at com.DX_57.AC_57.AddAccount.initlistCountries(AddAccount.java:344)
at com.DX_57.AC_57.AddAccount.getlistCountries(AddAccount.java:339)
You haven't initialized listCountries so make it
public void initlistCountries(){
listCountries = new ArrayList<String>();
listCountries.add("Afghanistan");
listCountries.add("Albania");
listCountries.add("Algeria");
listCountries.add("Andorra");
listCountries.add("Angola");
......
}
Initialize the arraylist.
private List<String> listCountries=new ArrayList<String>();
It doesn't look like you ever initialized listCountries.
public void initlistCountries()
{
listCountries = new ArrayList< String >(); // Add this line.
listCountries.add("Afghanistan");
listCountries.add("Albania");
listCountries.add("Algeria");
listCountries.add("Andorra");
listCountries.add("Angola");
......
}