I have an app which works fine at the moment and uses geolocation. I have a method which calls com.google.gwt.geolocation.client.Geolocation.
I extended the existing entry point and overriden this method to use the native Geolocation library so I don't have any permission popups.
How can I avoid having two modules which takes twice as long to compile?
In GWT normally you have an entry-point per application, or perl .html page, but you can have other scenarios: you could have a module file (.gwt.xml) with multiple entry-points, or a page loading multiple modules (.cache.js), or even you could load the same module (.cache.js) in different pages.
So, in your case, you could maintain one entrypoint and one module file and include the same compiled module in both pages. In this case you have to write some code in your entry point to know what to do in each page:
public void onModuleLoad() {
if (Window.Location.getPath().matches(".*page_1.html.*")) {
// do something
} else {
// do another thing
}
}
Think that in this case you will have all the compiled stuff in both pages, but you could take advantage of gwt code-splitting and make each page load just the stuff it needs:
public void onModuleLoad() {
if (Window.Location.getPath().matches(".*page_1.html.*")) {
GWT.runAsync(new RunAsyncCallback() {
public void onSuccess() {
// do something
}
public void onFailure(Throwable reason) {
}
});
} else {
GWT.runAsync(new RunAsyncCallback() {
public void onSuccess() {
// do another thing
}
public void onFailure(Throwable reason) {
}
});
}
}
The advantages of this approach is that you compile just once for all your site, and you share the same code in all your pages taking advantage of the cache. There are disadvantages as well like your final code is higher, dev-mode could be slower, etc.
Related
I am new to GWT and GWTP. I know what is GWT Code Split and GWTP Proxy Code Split. I've already red:
http://www.gwtproject.org/doc/latest/DevGuideCodeSplitting.html
http://dev.arcbees.com/gwtp/core/presenters/creating-places.html
I assumed that I understand it. So I've like to used.:
I have application with Administration panel, where only part of users can access. So there is no need to download Administration panel related code for all. So in Administration Presenter I've added #ProxyCodeSplit like follow:
public class AdminAreaPresenter extends Presenter<AdminAreaPresenter.MyView, AdminAreaPresenter.MyProxy> {
#ProxyCodeSplit
#NameToken(Routing.Url.admin)
#UseGatekeeper(IsAdminGatekeeper.class)
public interface MyProxy extends TabContentProxyPlace<AdminAreaPresenter> {}
#TabInfo(container = AppPresenter.class)
static TabData getTabLabel(IsAdminGatekeeper adminGatekeeper) {
return new MenuEntryGatekeeper(Routing.Label.admin, 1, adminGatekeeper);
}
public interface MyView extends View {}
AppPresenter appPresenter;
#Inject
AdminAreaPresenter(EventBus eventBus, MyView view, MyProxy proxy, AppPresenter appPresenter) {
super(eventBus, view, proxy, AppPresenter.SLOT_TAB_CONTENT);
this.appPresenter = appPresenter;
}
}
In other Presenters I have #ProxyStandard instead of #ProxyCodeSplit.
I've run app and log in. then I've opened Network tab in chrome's developer console:
And after opening Administation Panel in application:
As You can see, there is no new resources added to application.
My main app presenter AppPresenter implements interfaces AsyncCallStartHandler, AsyncCallFailHandler, AsyncCallSucceedHandler from: com.gwtplatform.mvp.client.proxy. and I override those methods:
#ProxyEvent
#Override
public void onAsyncCallStart(AsyncCallStartEvent event) {
Window.alert("Async start");
getView().setTopMessage("Loading...");
}
#ProxyEvent
#Override
public void onAsyncCallFail(AsyncCallFailEvent event) {
Window.alert("Async fail");
getView().setTopMessage("Oops, something went wrong...");
}
#ProxyEvent
#Override
public void onAsyncCallSucceed(AsyncCallSucceedEvent event) {
Window.alert("Async success");
getView().setTopMessage(null);
}
And when I enter AdmininArea I am getting to allerts: "Async start", "Async success". So I think that everythink work, but unfortunatelly I don't see any changes in resources. Please help. Am I doing something wrong or what?
Code splitting is disabled in SuperDevMode because it is not compatible with the incremental compiler and would also slow down compilation (see this issue).
To test code splitting, compile your GWT application (mvn clean install gwt:compile) and test it in production mode (take war file from target directory and put it in f.e.: Tomcat server catalog: webapps).
This should not be causing me so much pain but it is. It is a very weird problem. In a GWT application, I have two .java files, login.java and application.java.
In login.java, I'm creating a user login page where if the username and password is verified the user is logged into the application and application.java takes from here.
Now in application. java's onModuleLoad() this is how i'm starting with a login page.
public void onModuleLoad() {
Login login = new Login();
login.textBoxUsername.setFocus(true);
RootLayoutPanel.get().add(login);}
This works great, except for the tiny problem of not being able to set focus on the username TextBox when the page loads. I have tried evrything I can think of. But the focus just doesn't get set on the TextBox. If anyone can suggest a solution, please do. Your help is greatly appreciated.
Solution: (In case it helps anyone facing the same issue)
final Login login = new Login();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute () {
login.textBoxUsername.setFocus(true);
}
});
RootLayoutPanel.get().add(login);
Try using Scheduler.scheduleDeferred():
public void onModuleLoad() {
Login login = new Login();
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand () {
public void execute () {
login.textBoxUsername.setFocus(true);
}
});
RootLayoutPanel.get().add(login);
}
Update: answer updated to use Scheduler.get().scheduleDeferred() instead of DeferredCommand, which is deprecated.
Why using DefferedCommand, I think it's better to use someWidget.getElement().focus() which is a native Javascript. I'm using it everywhere, I've not seen any problem.
If your Widget extends Composite, you can:
#Override
protected void onAttach() {
super.onAttach();
textBoxUsername.setFocus(true);
}
It would be so easy for GWT to store a 'wantsFocus' in the internal state, and call focus after the widget is attached. We are still waiting after many years for that feature however...
Still, even after the attach handler is called, setFocus does not always work.
So in the meantime, our GwtUtil library has used the following code. It is a combination of several other solutions, and has been wrapped in a utility function:
static public void setFocus(final FocusWidget focusWidget) {
if (focusWidget.isAttached()) {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
#Override
public void execute() {
focusWidget.setFocus(true);
}
});
} else {
focusWidget.addAttachHandler(new AttachEvent.Handler() {
#Override
public void onAttachOrDetach(AttachEvent event) {
if (event.isAttached()) {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
#Override
public void execute() {
focusWidget.setFocus(true);
}
});
}
}
});
}
}
And call it like this:
setFocus(myTextBox);
It makes sense to use a utility function; If and when GWT finally makes setFocus work, you won't have to change your source code in multiple places.
In my larg GWT app i tried to split initial download and it happened but I confused in Leftover and exclusive fragments.
Because for example when I use of GWT.runAsync --> onSuccess --> "Window.alert("blob blob");" in onModuleLoad it caused to download a fragment with 1MB size! I think it is other initial fragment, isn't ?
In general my question is how to change leftover or initial fragments to exclusive fragments?
RGDS
Navid
In general with the GWT.runAsync method you can create exclusive fragments or leftovers.
In order to move a piece of code from the initial download to an exclusive fragment, not only you have to use the runAsync method but you also have to make sure that the code in the runAsync method is not referenced in sync parts of your application.
Provided this condition is satisfied, your code can end up in an exclusive fragment (if the code is not used by other runAsync methods) or a leftover (if it is referenced in mulptiple runAsync method).
//Class A is referenced only here!
GWT.runAsync(new RunAsyncCallback() {
#Override
public void onSuccess() {
a = new A();
}
#Override
public void onFailure(Throwable reason) {
...
}
});
....
//Class B is referenced in different points but always inside async calls!
GWT.runAsync(new RunAsyncCallback() {
#Override
public void onSuccess() {
b = new B();
}
#Override
public void onFailure(Throwable reason) {
...
}
});
....
GWT.runAsync(new RunAsyncCallback() {
#Override
public void onSuccess() {
b = new B();
}
#Override
public void onFailure(Throwable reason) {
....
}
});
The code relative to class A will be in an exclusive fragment, class B will be in a leftover.
In general, i suggest you use Compile Reports to understand what's going on in code splitting.
Also: calling runAsync in onModuleLoad doesn't make much sense.
1MB? Are you sure? maybe post an example and I can try to understand what's going on
Code-splitting doesn't work in development mode
I've been trying to setup gwt-phonegap in my project,
but keep getting timeout, saying that phonegap was not loaded (the handler of timeout is called)
i'm compiling the project with GWT, copying the entire war directory over to the phonegap www directory, remove the old index.html and rename my project's main html to index.html
the page than loads, showing the background image, but moments later get the timeout
what am i doing wrong?
code:
public class GWTphonegapExample1 implements EntryPoint {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() {
#Override
public void onUncaughtException(Throwable e) {
Window.alert("uncaught: " + e.getLocalizedMessage());
}
});
final PhoneGap phoneGap = new PhoneGap();
phoneGap.addHandler(new PhoneGapAvailableHandler() {
#Override
public void onPhoneGapAvailable(PhoneGapAvailableEvent event) {
RootPanel.get().add(new FlowPanel());
}
});
phoneGap.addHandler(new PhoneGapTimeoutHandler() {
#Override
public void onPhoneGapTimeout(PhoneGapTimeoutEvent event) {
Window.alert("can not load phonegap");
}
});
phoneGap.initializePhoneGap();
}
}
i hate to solve my own questions,
but after hours of searching, i came to realize that i did need to include the phonegap.js in the gwt html...
so that solved it
adding this:
< script type="text/javascript" charset="utf-8" src="phonegap.js">
to the html is the solution
I am learning GWT and i have read at multiple places that using MVP architecture is best suitable to develop a GWT Application
I have also read that its easy to do testing using the MVP ARCH.Can somebody explain me why its easy to do testing using the MVP architecture.
Also i am working on a project using MVP and i find it very tedious to make the view connect to the data base.I mean i have to update my presenter,service,serviceAsync,servicImpl,Facades in order to make connection to database.
So can somebody provide me the essence of MVP for GWT?i would appreciate a couple of examples.
Separation between the presenter (which contains logic) and view (a dumb wrapper around UI controls) allows you to:
write unit tests for the presenters that can run without needing the corresponding environment (desktop, browser, GWT widgets)
reuse front-end logic without being tied to a particular set of widgets/UI framework
The latter use case is rare, so let's focus on the MVP model's suitability for automated, programmatic testing. With a team of developers this often takes the form of a continuous build/test cycle using Hudson (or similar) on a headless server, where it's not practical to open a web browser, create controls, etc. every time a test is run.
Typical usage of MVP+GWT is that views implement an interface provided by the presenter, and often this interface is defined in terms of other generic interfaces. Here's a very simple presenter that increments a numeric label when a button is clicked - note that instead of exposing the TextBox and Button directly, the view returns generic HasText and HasClickHandlers instances:
public class ButtonClickPresenter {
public interface View {
HasText currentValue();
HasClickHandlers incrementButton();
}
private final View myView;
private int currentValue = 0;
public ButtonClickPresenter(View myView) {
this.myView = myView;
this.myView.currentValue().setText("0");
this.bind(); // for the sake of demonstration
}
public void bind() {
this.myView.incrementButton.addClickHandler(
#Override
new ClickHandler() {
void onClick(ClickEvent event) {
currentValue ++;
myView.currentValue().setText(
Integer.toString(currentValue));
}
});
}
}
The "real" view returns UI widgets (created via UiBinder in this example):
public class ButtonClickView implements ButtonClickPresenter.View {
// ... skipped UiBinder initialisation ...
#UiField Label currentValueLabel;
#UiField Button incrementButton;
#Override
public HasText currentValue() {
return currentValueLabel;
}
#Override
public HasClickHandlers incrementButton() {
return incrementButton;
}
// ... etc ...
}
whereas unit tests create a dummy implementation (or use Mockito, EasyMock, etc.) and thus don't require any UI components:
public class ButtonClickPresenterTest {
ButtonClickPresenter presenter;
ClickHandler currentHandler;
String currentText;
#Before
public void setUp() {
presenter = new ButtonClickPresenter(
// dummy view - just stores label text in a String and
// keeps track of the Presenter's click handler
new ButtonClickPresenter.View() {
#Override
public HasText currentValue() {
return new HasText() {
#Override public String getText() { return currentText; }
#Override public void setText(String text) { currentText = text; }
};
}
#Override
public HasClickHandlers incrementButton() {
return new HasClickHandlers() {
#Override
public HandlerRegistration addClickHandler(ClickHandler handler) {
currentHandler = handler;
}
};
}
});
}
#Test
public void testIncrement() {
// initial value
assertEquals("0", currentText);
// clicking the button should increment the number
currentHandler.onClick(null);
assertEquals("1", currentText);
}
}
As for your next paragraph: your views shouldn't be connecting to the database at all! The presenter should request data via Service/ServiceAsync (or an abstraction such as gwt-dispatch or gwt-platform), then call methods on the view to populate the UI.
By the way, those last two links (along with gwt-presenter) are a good start if you're looking for GWT MVP code samples - combined with Google GIN they provide frameworks for tying all this stuff together.
Having said all that, I agree - the combination of GWT+MVP+Java can be hard work and extremely verbose (I'm glad I don't have to work with it much these days). The alternative, though, is even less attractive: an untestable, unmaintainable ball of spaghetti...
You might like to have a look at the sample gwt-platform application blogged about here-> http://uptick.com.au/content/serendipity-working-gwt-platform-and-smartgwt.
Cheers
Mark