Wicket 7 - Select, SelectOptions and pre-set - wicket

Im using Select instead of DropDownChoice to use OPTGROUP.
Select<Role> roleInput = new Select<Role>("role", new PropertyModel<Role>(this,"selectedRole"));
The two list of Role are:
SelectOptions<Role> fedOptions = new SelectOptions<Role>("federazione",federationRoleList,new RoleRenderer());
SelectOptions<Role> eOptions = new SelectOptions<Role>("enti",eRoleList,new RoleRenderer());
Its working well when submitting and also applying a AjaxFormComponentUpdatingBehavior on roleInput, I have my PropertyModel dynamically modified.
Unfortunally I have a problem with pre-set.
I tried to set selectedRole with a specific Role but the Select always start with the first element of the first list.
DropDownChoice works perfectly pre-setting the model but not Select.
I've tried with
roleInput.setModelObject(selectedRole);
but its not working.
I thinks the problem is with this component that has to manage two or more Repeaters instead of a single list.
Any clue?
Thanks
EDIT:
Implementation of RoleRenderer
public class RoleRenderer implements IChoiceRenderer<Role>,Serializable{
private static final long serialVersionUID = 1L;
#Override
public Object getDisplayValue(Role object) {
return object.getName();
}
#Override
public String getIdValue(Role object, int index) {
return object.getId().toString();
}
#Override
public Role getObject(String id, IModel<? extends List<? extends Role>> choices) {
return getObjectFromId(id);
}
public Role getObjectFromId(String id){
return null;
};
}
NOTE: getObjectFromId require access to Manager so will be overrided outside.

Put a breakpoint at org.apache.wicket.extensions.markup.html.form.select.SelectOption#onComponentTag() and see what is returned by select.isSelected(this) for the SelectionOption that matches the default model (object).
It might be that your #equals() implementation is not correct.

Related

Jbehave get Story name inside #BeforeStory

I would like to get the Story name in a method annotated with #BeforeStory.
I need this for debugging purposes, cause i'm running a bunch of stories with runStoriesAsPaths and with multiple threads, and I'm trying to log which thread is running which story.
Is there a way to do this?
first you need to create a new StoryReporter (extend that class). In that class you can add actions to be performed before/after story/scenario/step, and you have the story name.
example:
public class NewStoryReporter implements StoryReporter {
private StoryReporter delegate;
public NewStoryReporter(StoryReporter delegate) {
this.delegate = delegate;
}
#Override
public void beforeStory(Story story, boolean givenStory) {
delegate.beforeStory(story, givenStory);
}
#Override
public void beforeScenario(String scenarioTitle) {
delegate.beforeScenario(scenarioTitle);
}
#Override
public void beforeStep(String step) {
if(step.equals("When after each step")){
return;
}
delegate.beforeStep(step);
}
then you need to extend StoryReporterBuilder, this creates your NewStoryReporter.
example:
public class NewStoryReporterBuilder extends StoryReporterBuilder {
#Override
public StoryReporter build(String storyPath) {
StoryReporter delegate = super.build(storyPath);
return new NewStoryReporter(delegate);
}
}
then in your configuration, create an instance of the NewStoryReporterBuilder, and use it in
Configuration configuration = new YourConfiguration().useStoryReporterBuilder(newStoryReporterBuilder....)
Now in Jbehave it's configured in different way.
So, to achieve that goal you need to:
Create new class which extends org.jbehave.core.reporters.ConsoleOutput. Here you can modify various of methods. In your case - you need to override method:
public void beforeScenario(String title)
Check example attached in the end of this post to see how it can be done.
Create new instance of abstract class org.jbehave.core.reporters.Filter:
public static final Format YOUR_CUSTOM_CONSOLE = new Format("YOUR_CUSTOM_CONSOLE")
{
#Override
public StoryReporter createStoryReporter(FilePrintStreamFactory factory,
StoryReporterBuilder storyReporterBuilder) {
return new TeamCityConsoleOutput(storyReporterBuilder.keywords()).doReportFailureTrace(
storyReporterBuilder.reportFailureTrace()).doCompressFailureTrace(
storyReporterBuilder.compressFailureTrace());
}
};
Then you need to add this format to your story builder which you are using in your configuration, that mean:
new MostUsefulConfiguration()
.useStoryReporterBuilder(
new StoryReporterBuilder()
....//here are another modifications of sorey report builder
.withFormats(YOUR_CUSTOM_CONSOLE , .../* another formats */ HTML, Format.XML, Format.TXT))
....//here are another modifications of configuration
.useStepMonitor(new CrossReference().getStepMonitor());
Here is example of such modification, which can be used to integration with TeamCity:
https://github.com/jbehave/jbehave-core/blob/d15774bf763875662869cdc89ce924b1086af6f8/jbehave-core/src/main/java/org/jbehave/core/reporters/TeamCityConsoleOutput.java

How to bind a list of objects to ListBox in GWT?

I want to bind my services to ListBox but I can't bind it.
//Service class
public class Service {
private String serviceName;
public Service(String serviceName) {
this.serviceName = serviceName;
}
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
}
// SignUpBean class
public class SignUpBean {
private List<Service> services;
public List<Service> getServices() {
return services;
}
public void setServices(List<Service> services) {
this.services = services;
}
}
The following is my Main Editor
public class SignUpEditor extends SimplePanelimplements Editor<SignUpBean> {
public ListBox services;
public void SignUpEditor (){
services.addItem("Service1");
services.addItem("Service2");
setWidget(services);
}
}
I am not getting any error but I think I have to use ListEditor or CompositeEditor. But i don't know about it. Can anyone suggest how to bind Service to ListBox
ListBox suppose to be a LeafValueEditor. Conceptually we don't edit the list in the ListBox. Rather We select a value from the list which will be displayed in the selection. So, ListBox holds only one value and thus ListBox must be leaf value Editor.
Currently there is no GWT support to directly bind the list to ListBox. We have to write an adapter which extends ListEditor ( Refer HasDataEditor class for more detail ). This approach is strange.
Simple approach is to write an adapter which implements LeafValueEditor< List < String > >. In adapter's setValue method we should iterate over the list and call listBox.addItem for each value in the list.
I don't recommend either approaches simply because ListBox's LIST is NON EDITABLE and only VALUE is EDITABLE. I recommend doing addItems manually without using Editors.
UPDATED : HasDataAdapter is an example ListEditor. Refer that implementation. You may get some idea.

How must one use a ListEditor as a child of another Editor?

I am using GWT 2.5.0
My intent was to create an editor hierarchy which binds to a ParentBean object. The ParentBean contains a List<Group>, and the Group bean has a List<ChildBean> and List<Group>. From the Editor tutorials I have found, it seemed simple enough to create an editor which contains a ListEditor as one of its sub-editors. But the parent editor never seems to properly initialize the sub ListEditor.
Here is an explanation of how I attempted to do this.
From the code below, I created a ParentBeanEditor which is composed of one other editor, GroupListEditor.
The GroupListEditor implements IsEditor<ListEditor<Group, GroupEditor>>.
Then, the GroupEditor contains a GroupListEditor subeditor and a ChildBeanEditor.
I initialized the ParentBeanEditor with a ParentBean which contained a list of Group objects, but no GroupEditor was ever constructed for any of the Group objects. I put break points in the EditorSource<GroupEditor>.create(int) method to verify that GroupEditors were being created for each Group in the ParentBean, but the break point was never hit (the ListEditor was not constructing editors).
I expected that the GroupListEditor would be initialized since it was a subeditor of ParentBeanEditor. Neither the list nor the editor chain was set in the GroupListEditor. I tried to set the list of the GroupListEditor subeditor directly in ParentBeanEditor by having it extend ValueAwareEditor<ParentBean>. Doing this, the break point I mentioned above was hit, and the GroupListEditor tried to attach a GroupEditor to the editor chain. But the editor chain was never set, and a NPE is thrown in ListEditorWrapper line 95.
Example
Here is the example where the GroupListEditor is not initializing as expected. The EditorChain is never set, and this results in a NPE being thrown in ListEditorWrapper line 95.
Data Model
public interface ParentBean {
...
List<Group> getGroups();
}
public interface Group {
...
List<ChildBean> getChildBeans();
List<Group> getGroups();
}
public interface ChildBean {
// ChildType is an enum
ChildType getChildType();
}
Editors
The ParentBean Editor
public class ParentBeanEditor extends Composite implements ValueAwareEditor<ParentBean> {
interface ParentBeanEditorUiBinder extends UiBinder<Widget, ParentBeanEditor> {
}
private static ParentBeanEditorUiBinder BINDER = GWT.create(ParentBeanEditorUiBinder.class);
#Path("groups")
#UiField
GroupListEditor groupsEditor;
public ParentBeanEditor() {
initWidget(BINDER.createAndBindUi(this));
}
#Override
public void setDelegate(EditorDelegate<ParentBean> delegate) {}
#Override
public void flush() {}
#Override
public void onPropertyChange(String... paths) {}
#Override
public void setValue(ParentBean value) {
groupsEditor.asEditor().setValue(value.getGroups());
}
}
GroupListEditor
public class GroupListEditor extends Composite implements IsEditor<ListEditor<Group, GroupEditor>>{
interface GroupListEditorUiBinder extends UiBinder<VerticalLayoutContainer, TemplateGroupListEditor> {
}
private static GroupListEditorUiBinder BINDER = GWT.create(GroupListEditorUiBinder.class);
private class GroupEditorSource extends EditorSource<GroupEditor> {
private final GroupListEditor GroupListEditor;
public GroupEditorSource(GroupListEditor GroupListEditor) {
this.GroupListEditor = GroupListEditor;
}
#Override
public GroupEditor create(int index) {
GroupEditor subEditor = new GroupEditor();
GroupListEditor.getGroupsContainer().insert(subEditor, index);
return subEditor;
}
#Override
public void dispose(GroupEditor subEditor){
subEditor.removeFromParent();
}
#Override
public void setIndex(GroupEditor editor, int index){
GroupListEditor.getGroupsContainer().insert(editor, index);
}
}
private final ListEditor<Group, GroupEditor> editor = ListEditor.of(new GroupEditorSource(this));
#UiField
VerticalLayoutContainer groupsContainer;
public GroupListEditor() {
initWidget(BINDER.createAndBindUi(this));
}
public InsertResizeContainer getGroupsContainer() {
return groupsContainer;
}
#Override
public ListEditor<Group, GroupEditor> asEditor() {
return editor;
}
}
GroupEditor
public class GroupEditor extends Composite implements ValueAwareEditor<Group> {
interface GroupEditorUiBinder extends UiBinder<Widget, GroupEditor> {}
private static GroupEditorUiBinder BINDER = GWT.create(GroupEditorUiBinder.class);
#Ignore
#UiField
FieldSet groupField;
#UiField
#Path("childBeans")
ChildBeanListEditor childBeansEditor;
#UiField
#Path("groups")
GroupListEditor groupsEditor;
public GroupEditor() {
initWidget(BINDER.createAndBindUi(this));
}
#Override
public void setDelegate(EditorDelegate<Group> delegate) {}
#Override
public void flush() { }
#Override
public void onPropertyChange(String... paths) {}
#Override
public void setValue(Group value) {
// When the value is set, update the FieldSet header text
groupField.setHeadingText(value.getLabel());
groupsEditor.asEditor().setValue(value.getGroups());
childBeansEditor.asEditor().setValue(value.getChildBeans());
}
}
The ChildBeanListEditor will be using the polymorphic editor methodology mention here. Meaning that a specific leafeditor is attached to the editor chain based off the value of the ChildBean.getType() enum. However, I am not showing that code since I am unable to get the GroupListEditor to properly initialize.
Two concerns about your code:
Why is ParentBeanEditor.setValue feeding data to its child? It appears from this that this was a way to work around the fact that the GroupListEditor was not getting data. This should not be necessary, and may be causing your NPE by wiring up a subeditor before it is time.
Then, assuming this, it seems to follow that the GroupListEditor isn't getting data or a chain. The lack of these suggests that the Editor Framework isn't aware of it. All the basic wiring looks correct, except for one thing: Where is your EditorDriver?
If you are trying to use the editor framework by just invoking parentBeanEditor.setValue and do not have a driver, you are missing most of the key features of this tool. You should be able to ask the driver to do this work for you, and not not to call your own setValue methods throughout the tree.
A quick test - try breaking something in such a way that shouldn't compile. This would include changing the #Path annotation to something like #Path("doesnt.exist"), and trying to run the app. You should get a rebind error, as there is no such path. If you do not get this, you definitely need to be creating and user a driver.
First, try driver itself:
It isn't quite clear from your code what kind of models you are using, so I'll assume that the SimpleBeanEditorDriver will suffice for you - the other main option is the RequestFactoryEditorDriver, but it isn't actually necessary to use the RequestFactoryEditorDriver even if you use RequestFactory.
The Driver is generic on two things: The bean type you intend to edit, and the editor type that will be responsible for it. It uses these generic arguments to traverse both objects and generate code required to bind the data. Yours will likely look like this:
public interface Driver extends
SimpleBeanEditorDriver<ParentBean, ParentBeanEditor> { }
We declare these just like UiBinder interfaces - just enough details to let the code generator look around and wire up essentials. Now that we have the type, we create an instance. This might be created in your view, but may still be owned and controlled by some presenter logic. Note that this is not like uibinder - we cannot keep a static instance, since each one is wired directly to a specific editor instance.
Two steps here - create the driver, and initialize it to a given editor instance (and all sub-editors, which will be automatic):
ParentBeanEditor editor = ...;
Driver driver = GWT.create(Driver.class);
driver.initialize(editor);
Next we bind data by passing it to the driver - it is its responsibility to pass sub-objects to each sub-editor's setValue method, as well as wiring up the editor chain required by the ListEditor.
driver.edit(parentInstance);
Now the user can view or edit the object, as your application requirement works. When editing is complete (say they click the Save button), we can flush all changes from the editors back into the instance (and note that we are still using the same driver instance, still holding that specific editor instance):
ParentBean instance = driver.flush();
Note that we also could have just invoked driver.flush() and reused the earlier reference to parentInstance - its the same thing.
Assuming this has all made sense so far, there is some cleanup that can be done - ParentBeanEditor isn't really using the ValueAwareEditor methods, so they can be removed:
public class ParentBeanEditor extends Composite implements Editor<ParentBean> {
interface ParentBeanEditorUiBinder extends UiBinder<Widget, ParentBeanEditor> {
}
private static ParentBeanEditorUiBinder BINDER = GWT.create(ParentBeanEditorUiBinder.class);
#Path("groups")
#UiField
GroupListEditor groupsEditor;
public ParentBeanEditor() {
initWidget(BINDER.createAndBindUi(this));
}
}
Observe that we still implement Editor<ParentBean> - this allows the driver generics to make sense, and declares that we have fields that might themselves be sub-editors to be wired up. Also: it turns out that the #Path annotation here is unnecessary - any field/method with the same name as the property (getGroups()/setGroups() ==> groups) or the name of the property plus 'Editor' (groupsEditor). If the editor contains a field that is an editor but doesn't map to a property in the bean, you'll get an error. If you actually did this on purpose (say, a text box for searching, not for data entry), you can tag it with #Ignore.

GWT Editor and GXT Grid Not Sending Newly Created Proxy Entities, Only NULL Values

Does anybody have a solution to why I would be saving nulls to a OneToMany List on a server entity through a GXT Grid that contains a ListStoreEditor sub-editor?
I've followed the Sencha Example, GridBindingExample to a tee.
http://www.sencha.com/examples/#ExamplePlace:gridbinding
public class MyEditor implements IsWidget, Editor<FooProxy> {
interface Binder extends UiBinder<Widget, MyEditor> {}
private static Binder uiBinder = GWT.create(Binder.class);
public interface Driver extends SimpleBeanEditorDriver<MyProxy, MyEditor> {}
private Driver driver = GWT.create(Driver.class);
private ListStore<BarProxy> store;
ListStoreEditor<BarProxy> items;
#Ignore
#UiField(provided = true)
Grid<BarProxy> grid;
#Ignore
#UiField
ChildEditor childEditor;
#Override
public Widget asWidget() {
MyProperties props = GWT.create(MyProperties.class);
this.store = new ListStore<BarProxy>(props.key());
List<ColumnConfig<BarProxy, ?>> columns = new ArrayList<ColumnConfig<BarProxy, ?>>();
columns.add(new ColumnConfig<BarProxy, String>(props.itemName(), 300, "MyColumn"));
this.grid = new Grid<BarProxy>(store,new ColumnModel<BarProxy>(columns));
items = new ListStoreEditor<BarProxy>(store);
Widget widget = uiBinder.createAndBindUi(this);
driver.initialize(childEditor);
childEditor.getCreateButton().addSelectHandler(new SelectHandler() {
#Override
public void onSelect(SelectEvent event) {
RequestContext context = factoryProvider.get().barRequest();
BarProxy entity = context.create(BarProxy.class);
entity.setName("Eugene Qtest");
entity.setAge(45);
driver.edit(entity);
store.add(driver.flush());
}
});
return widget;
}
}
public class ChildEditor implements IsWidget, Editor<BarProxy> {
interface Binder extends UiBinder<Widget, ChildEditor> {}
private static Binder uiBinder = GWT.create(Binder.class);
#UiField
TextButton createButton;
#Override
public Widget asWidget() {
return uiBinder.createAndBindUi(this);
}
public TextButton getCreateButton() {
return createButton;
}
}
On an upper level presenter in my code, I am calling:
RequestContext req = editorPresenter.getDriver().flush();
req.fire();
This does save all data elements that the GWT Editor captures. In my database it does create the row for the grid in the above code, but all the values are null, so when the RequestContext fires, the persist brings back an empty row within the grid. So there is no foreign key to associate the entity in the OneToMany relationship back to its parent entity.
Also, I've looked at the JSON request and response to the server and it doesn't look like any of the values are being sent in the entity. It may be obfuscated, but it looks as though the other values are in plain text, so I don't think the proxy entity values are even being passed.
Any help would be great! Thanks
driver.edit(entity);
store.add(driver.flush());
These lines are saying "Draw the new object in the editor-- okay, take whatever value was put in there and add it to the store". I'm not sure this is what you intend.
Later, you reference an editorPresenter, but that doesn't seem to be in your code, and it isn't clear when you do that flush (or even the preliminary edit() call) and fire. You also make an Editor<BarProxy>, but there are no subeditors in that type to allow editing.
In the example you link to, there are two different drivers in the mix. The first takes care of the entire list, by passing it into the ListStore - this wasn't actually needed for the sake of an example, but is there to help explain how you might tie this into a bigger case, like the http://www.sencha.com/examples/#ExamplePlace:listpropertybinding example. The example should really be treated as two different editors, with two different drivers - doubly so when testing. First make sure one works, and returns the right values after driver.flush(), then the other.
As I started with, I think that your invocation of driver.flush() immediately after the edit call is almost certainly not what you want, (since the driver will have had no effect), so starting there would be good. Then, if that is what you want, test that when you receive the call on the server, you are getting the model object with all of its values.
This took me days to figure out, with the help of Colin in the above comments, Thanks!
The reason the grid was populating, but when you flushed the main editor on save, the values disappeared and a blank row was inserted into the grid, was because you have to implement the HasRequestContext interface on the editor to maintain the same RequestContext session. Below is my amended code.
public class MyEditor implements IsWidget, Editor<FooProxy>, HasRequestContext<FooProxy> {
interface Binder extends UiBinder<Widget, MyEditor> {}
private static Binder uiBinder = GWT.create(Binder.class);
private RequestContext ctx;
private ListStore<BarProxy> store;
ListStoreEditor<BarProxy> items;
#Ignore
#UiField(provided = true)
Grid<BarProxy> grid;
#Ignore
#UiField
ChildEditor childEditor;
#Override
public Widget asWidget() {
MyProperties props = GWT.create(MyProperties.class);
this.store = new ListStore<BarProxy>(props.key());
List<ColumnConfig<BarProxy, ?>> columns = new ArrayList<ColumnConfig<BarProxy, ?>>();
columns.add(new ColumnConfig<BarProxy, String>(props.itemName(), 300, "MyColumn"));
this.grid = new Grid<BarProxy>(store,new ColumnModel<BarProxy>(columns));
items = new ListStoreEditor<BarProxy>(store);
Widget widget = uiBinder.createAndBindUi(this);
driver.initialize(childEditor);
childEditor.getCreateButton().addSelectHandler(new SelectHandler() {
#Override
public void onSelect(SelectEvent event) {
RequestContext context = ctx.barRequest();
BarProxy entity = context.create(BarProxy.class);
entity.setName("Eugene Qtest");
entity.setAge(45);
ctx.edit(entity);
store.add(entity);
}
});
return widget;
}
#Override
public void setRequestContext(RequestContext ctx) {
this.ctx = ctx;
}
}

Create Vaadin form using Binding form to data

I'm trying to create form with Vaadin using "Binding form to data" with this class:
public class Job {
private String nom_projet;
private String svn;
private String planning1;
private String planning2;
private String goals;
}
with getters and setters.
When I try this everything works fine:
final Form form = new Form();
Job bean = new Job();
BeanItem<Job> item = new BeanItem<Job>(bean);
form.setItemDataSource(item);
I tried to add a custom field like its described in "Book of Vaadin" so I created this class:
public class MyFieldFactory implements FormFieldFactory {
private static final long serialVersionUID = 1L;
public Field createField(Item item, Object propertyId, Component uiContext) {
Select select = new Select("goals");
select.addItem("compiler:compile");
select.addItem("clean install");
select.addItem("clean");
select.addItem("package");
select.addItem("test");
select.setNewItemsAllowed(true);
return select;
}
}
But when I wanted to add this statement to MyApplication.java:
form.setFieldFactory(new MyFieldFactory());
I got "setFieldFactory" underlined and 3 choices:
() Cast argument 1 to FieldFactory
Change to setFirldFormFactory(...)
Let 'MyFieldFactory' implements 'FieldFactory'
When I click on:
Let 'MyFieldFactory' implements 'FieldFactory'
custom field does not appear in form.
the setFieldFactory method take a FieldFactory as parameter and your MyFieldFactory class implements FormFieldFactory wich is not the same.
In Vaadin javadoc, the setFieldFactory is mark as deprecated and they hint you to use setFormFieldFactory(FormFieldFactory formFieldFactory) instead.
Using this method will solve your problem.
Regards.