I have a GWTP PresenterWidget and View pair that contains a simple search form.
Currently I am adding the SubmitHandler to the form by calling the getSearchForm() method of my View, which is bad practice as it references the actual class instead of an interface:
public class HeaderPresenter extends PresenterWidget<HeaderPresenter.MyView>
{
public interface MyView extends View
{
void submitForm();
Form getSearchForm();
}
// ...omitted for brevity
#Inject
public HeaderPresenter(EventBus eventBus, DispatchAsync dispatchAsync, MyView view, PlaceManager placeManager)
{
// ...omitted for brevity
}
#Override
protected void onBind()
{
super.onBind();
getView().getSearchForm().addSubmitHandler(new SubmitHandler()
{
#Override
public void onSubmit(SubmitEvent event)
{
// stops the form submission
event.cancel();
// now we can do our stuff
String query = getView().getSearchQuery();
if(query != "") // don't search for a blank string
{
PlaceRequest request = new PlaceRequest.Builder().nameToken(NameTokens.search).with("q", query).build();
placeManager.revealPlace(request);
}
}
});
}
Is there a way to add the SubmitHandler in the HeaderPresenter, or will I have to put that code in the View?
I'd like to keep as much logic in the Presenter as possible.
I found a discussion on this here, and ended up using option 4 as suggested by Thomas Broyer:
https://groups.google.com/forum/#!topic/google-web-toolkit/Fbo-SEDjRa4
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
I have a bean named SignUpBean and it's editor is SignUpBeanEditor and following is its Driver interface.
public interface SignUpDriver extends SimpleBeanEditorDriver<SignUpBean, SignUpEditor>{
}
Following is entry point class
public class Signup implements EntryPoint {
private SignUpDriver signUpDriver;
private SignUpEditor signUpEditor;
private SignUpBean signUpBean;
private VerticalPanel verticalPanel;
private Label signUpLbl;
private Button submitButton;
private Button cancelButton;
private RequestBuilder requestBuilder;
final SignUpConverter signUpConverter=GWT.create(SignUpConverter.class);
public void onModuleLoad() {
signUpLbl = new Label("Sign Up");
signUpDriver = GWT.create(SignUpDriver.class);
signUpBean = new SignUpBean();
signUpEditor = new SignUpEditor();
submitButton = new Button("Submit");
cancelButton = new Button("Cancel");
signUpDriver.initialize(signUpEditor);
signUpDriver.edit(signUpBean);
System.out.println(signUpBean.getUserName());
submitButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
SignUpBean signUpBeanEdited=signUpDriver.flush();
}
}
}
}
I am getting only null value from signUpBeanEdited after giving value in UI. If i am initializing SignUpBean with constructor then also data is not binding to UI. My problem is I cant bind data in GWT UI using editor framework.
The fields( sub editors ) declared in SignUpEditor should be of at least DEFAULT scope. I guess you declared them as private. If so, the Editor Impl classes generated cannot access the fields to bind the data.
Changing scope to at least DEFAULT might solve your problem.
I found a lot of example how to create back button in wicket but it was in wicket 1.4 and lower where they use getPageMap . This feature isnt in wicket 1.5. I know there are some js feature as window.history.back() or history.go(-1) but I want implement some clear solution. Any idea ?
My idea was to store webPage in my own webSesion as Stack. Is this good ?
public class TournamentSession extends WebSession {
protected final Logger logger = LoggerFactory.getLogger(getClass());
private static final long serialVersionUID = 1L;
private Stack<BasePage> previosPage = new Stack<BasePage>();
public TournamentSession(Request request) {
super(request);
}
public void addPreviosPage(BasePage basePage) {
logger.info(basePage.getClass().toString());
previosPage.push(basePage);
}
public BasePage getPreviousPage() {
BasePage basePage = previosPage.pop();
logger.info(basePage.getClass().toString());
return basePage;
}
}
and when page are render store actual page to this stack
Use session.getPageManager().getPage(id)
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;
}
}