I'm trying to adapt my GWT web application from my home-grown MVC to GWT Platform.
I've managed to port the my application views with presenters, and essentially able to access views via PlaceRequest. And with changing the URL (#).
However I am not sure how to deal with Models using this GWT platform, in the common MVP I know there is a go() method in the presenter which fetches data, say from server via RPC.
In the GWT platform presenter here are the methods automatically generated by the Eclipse plugin:
Constructor
revealInParent
onBind
onReset
Where should I put the RPC code that will fetch and update my model. Say in the presenter I have:
ProfilePresenter.java:
public class ProfilePresenter
extends
Presenter<ProfilePresenter.MyView, ProfilePresenter.MyProxy> {
public interface MyView extends View {
HasText getFullname();
HasText getLocation();
HasText getAboutme();
HasText getLastlogin();
}
private User user; // Model which represents the User information etc.
And when the View associated with the Presenter is shown I need to fetch the User model from the server and update the model and then subsequently update the view through the interfaces it expose.
Also, say I have some buttons in the view, which then can be accessed by the presenter through HasClickHandler where should I put the event handlers?
I would put the RPC call in the onReset method.
See the presenter lifecycle
Personally I deal with events using the reversed MVP pattern. But you can also call a handler this way:
getView().getSubmitButton().addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
}
});
with the following signature for getSubmitButton in your view interface:
HasClickHandlers getSubmitButton()
Sydney covered most of your questions.
In general onResetmethod is a good place to make backend calls.
Sometimes when the backend call takes longer and you want to display the view only after the data was loaded you can use manual reveal.
But for the profile page I don't think that is necessary.
I also agree with the reverse MVP pattern. It's way easer to test presenters using the reverse MVP Pattern than using the HasXXXHandlers interfaces.
Related
My application consists of many parts and they are defined in application's e4xmi file. I want to hide and show them dynamically. I am using EpartService to do so in handlers, where I can inject it.
But I also want to control the show/hide of parts with something like life cycle manager, where I can not inject EPartService. Is there any way to achieve and fully control RCP application's life cycle?
There seems the exact same question here and void of solution:
https://www.eclipse.org/forums/index.php/t/595958/
I want to implement 'remember me like feature' where part having sign in screen is shown instead of other parts. Also after log out same sign-in part is to be shown. So I need to control life cycle of RCP app. But I cant inject EPartService before anything in Application's e4xmi is initiated.
If you are creating a class from something which is injected (such as the LifeCycle class) you can create your class with injection using ContextInjectionFactory:
#Inject
IEclipseContext context;
MyClass myClass = ContextInjectionFactory.make(MyClass.class, context);
Or if you just pass an IEclipseContext to the class you can get the part service using:
EPartService partService = context.get(EPartService.class);
Note: There is a separate instance of the part service for each part. Depending on what you are doing you may need to make sure you have the service for the active part.
If you are not locked in to using SWT, you could use the e(fx)clipse e4 renderer for JavaFX instead.
e(fx)clipse has more possibilities to control the lifecycle of the application. For example you can return a Boolean from #PostContextCreate to signal whether you want to continue the startup or not. You will not be able to use EPartService here though, but you can roll your own login dialog using dependency injection as greg-449 has described it in his answer.
public class StartupHook {
#PostContextCreate
public Boolean startUp(IEclipseContext context) {
// show your login dialog
LoginManager loginManager = ContextInjectionFactory.make(LoginManager.class, context);
if(!loginManager.askUserToLogin()) {
return Boolean.FALSE;
}
return Boolean.TRUE;
}
}
(You can also restart the application. Form
more details see http://tomsondev.bestsolution.at/2014/11/03/efxclipse-1-1-new-features-api-to-restart-your-e4-app-on-startup/).
I'm developing an application using GWT 2.6.
Now I have a task to implement a functionality to switch between simple/expert modes (of view) at run-time. It means to show a simplified version of view which may contain another widgets.
But the problem is that all the views in most cases are "static" and defined as singletons (using GIN).
Is it possible to implement this using only GWT and what should I use to make it?.
There are many ways that this can be done. A couple of ideas that spring to mind:
Option 1.
Instead of using GIN to inject the view, inject a view provider (com.google.inject.Provider). This can be used by the code that builds the view (the activity?) to get the view. The implementation of the view provider can then return an implementation of the view for the relevant mode, simple or expert. For example,
#Inject
public ComposeMessageActivity(Provider<ComposeMessageView> viewProvider, ...) { ... }
#Override
public final void start(final AcceptsOneWidget panel, final EventBus eventBus) {
view = viewProvider.get();
Option 2.
Use deferred binding. This is not so dynamic but has the advantage a simple implementation will be a smaller download than an expert implementation. There is a project, gwt-seminar, on github that shows this in practice that has mobile and desktop versions.
I try to understand how the gwt example about activities and places works (https://developers.google.com/web-toolkit/doc/latest/DevGuideMvpActivitiesAndPlaces). I am wondering why they define an interface for the presenter. I know the view interface is helpful to exchange the view easily. But what's the use of the presenter interface?
Its always a best practice to design application with interfaces rather than concrete classes.
Reference - What does "program to interfaces, not implementations" mean?
Reference - WikiPedia example for MVP
Another key factor in MVP architecture to make your design pretty clean is defining an Presenter interface(As we already know the beauty of interface OOP conceptin JAVA).
Presenter interface that allows our View to callback into the presenter when it receives an event. The Presenter interface defines the following:
public interface Presenter<T> {
void onAddButtonClicked();
}
And then you can set the presenter to your view like below
private Presenter<T> presenter;
public void setPresenter(Presenter<T> presenter) {
this.presenter = presenter;
}
Finally when your PresenterConcreteClass implements your presenter interface those implementations will triggers.
Besides the cleanliness of using an interface, there's also no reason you wouldn't test your view. You could use end-to-end tests, but you can also simply use a GWTTestCase where you instantiate the view and use a mock presenter.
You'd then be able to test that “when I click on this button, it should call this method from the presenter with the values X, Y and Z as arguments”, or “when I call this method of the view with those arguments, then such widget should turn red and that other one should hide/collapse/show/whatever”.
I've also used it, once, to similarly build a simple testbed app to manually test the UI with fake data. The app consisted of buttons to simulate the presenter calling the view with fake data, and handled the presenter calls back from the view with Window.alert or similar things. You'd launch the app in your browser and click here and there and validate that the view works as expected.
This can be useful when you later add a field to your form, to make sure you correctly wire it with the presenter. You don't want to setup your GWT-RPC/RequestFactory/whatever services from the real presenter, when a unit-test could be enough.
2 big reasons off the top of my head (there may be others too...)
Testing: Your Presenter then does not have to have a direct reference to the View, which is nice because the View contains GWT Objects (i.e: any Widget) which cannot be used in a standard Unit Test Case: Any GWT Object must have a JS container (i.e: Browser, or GWTTestCase) to be instantiated; A JUnit test case cannot use a Browser; GWTTestCase runs VERY slow, so you should prefer not to have to use it. Without the interface, the Presenter would have to reference the View's methods by a direct reference to the View; that means when testing the Presenter, you must instantiate the View, which must instantiate its Widgets (which at that point require the GWTTestCase for the Widgets). And all you should be aiming to do in the 1st place is to test the logic, which should be completely in the Presenter to avoid GWTTestCase... With the Display interface, you can do just that: Focus on testing the Presenter, without the complication of instantiating the View (which has its own degree of instantation complication) and messing around then necessarily with GWTTestCase
Have multiple Views for the same Presenter: [I think you would only ever do this if you have different platforms (i.e: mobile App vs. browser) which each require their own View (since a mobile App version of the View is rendered differently from a browser View, since they are different platforms with different GUI entities)]. The multiple Views would then all just implement the Display interface in their separate ways. Then the single Presenter can contain the logic that is the same for all Views, be used for all the different Views, and all View implementations are guaranteed to follow the same expectations (which are the codification in the Display interface) of that single Presenter! This is a manifestation of the OOP best practice of designing with interfaces, which #SSR Answers.
I am beginner in gwtp and I want to build an application that displays a list of products, and by clicking I displays the details of the selected product...
My question is how to refresh the page to allow page product Detail to refresh while respecting security measures, obviously I do not want to pass the id of the product in the request.
I thought about storing the id in the session but I do not know if it will impact the application's performance given the high response times of RPC.
Any help or clarification on this would be appreciated.
You might consider using GWT's Cookie Support. Properly implemented, you'd always know exactly what they were doing last and getting them back to there becomes easy. Cookies are obviously client-side, so it's always going to be faster than RPC.
I have some advice but be aware I'm fairly new to GWTP as well....
Security
Communication should take place over SSL/HTTPS. I put it across my entire app using the servlet container (web.xml) so that it integrates seemlessly with non-GWT parts of my app.
I don't see a problem with putting an 'id' in a url. You can always prevent it from showing in the address bar with PlaceManager.revealPlace(PlaceRequest, boolean).
Composed View
I have a view with a list of entities on the left and the edit form on the right. The list is always shown and is placed in a 'slot' explicitly by a parent presenter:
public class Users extends Presenter<Users.View, Users.Proxy> {
#ContentSlot
public static final GwtEvent.Type<RevealContentHandler<?>> LIST_SLOT = new GwtEvent.Type<RevealContentHandler<?>>();
#ContentSlot
public static final GwtEvent.Type<RevealContentHandler<?>> FORM_SLOT = new GwtEvent.Type<RevealContentHandler<?>>();
#Inject
private UserList userList;
#Inject
public Users(EventBus eventBus, View view, Proxy proxy) {
super(eventBus, view, proxy, Configuration.SLOT);
}
#Override
protected void onReveal() {
super.onReveal();
setInSlot(LIST_SLOT, userList);
}
...
My app has an 'empty form' presenter which is shown by default when no list item is selected. This prevents the list and parent presenters from being a 'place' (requiring a token). Only the leaf presenters in the presenter hierarchy should be a 'place'.
I'm trying to pass a parameter that I have loaded on a presenter to another presenter, a car from some client, for example.
What's the best way to do this? Using the gatekeeper? Any example?
PS: I using DI with gin and the GWT-Platform framework.
If the presenter should be loaded when the event is fired you can use a ProxyEvent. Have a look at http://code.google.com/p/gwt-platform/wiki/GettingStarted?tm=6#Attaching_events_to_proxies and http://arcbees.wordpress.com/2010/08/31/using-proxyevent/.
If you want to reduce coupling, you should create a custom event, CarLoadedEvent or something. Use GWTP Plugin for that, it works great.
Then have your presenter that wants to catch that event implement CarLoadedHandler, and in its onBind() method, make it register to the eventBus :
#Override
protected void onBind() {
super.onBind();
registerHandler(getEventBus().addHandler(CarLoadedEvent.TYPE, this));
}
Finally, when a car is loaded, fire an event :
CarLoadedEvent.fire(getEventBus(), myLoadedCar);
See GWTP doc & blog:
for regular Event handling
for Event handling that should wake up another Presenter not yet initialized/showing
boilerplate code generation related to simplifying coding Event handling