So I really need some helpful hints with an issue I am having with my GWTP application, perhaps one of you have ran into this problem before. So I am using GWTP 1.1 with:
- com.gwtplatform.mvp.Mvp (Not w/ entry point)
- com.gwtplatform.dispatch.Dispatch with
- com.google.gwt.uibinder.UiBinder
The issue I am having is that when ever I have a client sided error (can be almost anywhere in my client side, not sure where the boundary is) I receive a very cryptic message to do with GIN rather than a message that will help me resolve the issue. Seems like something to do with GWTP Proxying, here is the typical message that I get: http://pastebin.com/YgxPbkru the real issue isn't what the error message is presenting to me. The OpenIcidentPresenter extends IncidentPresenter which is a Presenter I have made to manage lifecycles of an Incident (in this case) this extends another presenter that I have made called a RequestPresenter, this is a Presenter that allows the user to Request PresenterWidget classes into it (into any given slot for that presenters lifecycle), this extends another presenter called RichPresenter, which just has things that almost all my Presenters require like page load indication and certain page locking etc, etc. Here are these classes:
OpenIncidentPresenter
public class OpenIncidentPresenter extends IncidentPresenter<OpenIncidentPresenter.MyView,
OpenIncidentPresenter.MyProxy> implements ViewUiHandlers, HasRequestedWidgets, NewIncidentHandler,
ChangeSectionHandler, ConfigureHandler {
public interface MyView extends View, HasUiHandlers<ViewUiHandlers> {
... Snip ...
}
@ProxyCodeSplit
@NameToken(NameTokens.open)
//@UseGatekeeper(LoginGatekeeper.class)
public interface MyProxy extends ProxyPlace<OpenIncidentPresenter> {
}
private static Logger logger = Logger.getLogger(OpenIncidentPresenter.class.getName());
Process process;
SectionTuple currentSection = new SectionTuple();
Map<Integer, SectionTuple> sections = new HashMap<Integer, SectionTuple>();
List<AccordionSection> sectionWigets = new ArrayList<AccordionSection>();
List<Activity> cachedActivities = new ArrayList<Activity>();
List<Authority> cachedAuthorities = new ArrayList<Authority>();
List<Severity> cachedSeverities = new ArrayList<Severity>();
List<Location> cachedLocations = new ArrayList<Location>();
List<Site> cachedSites = new ArrayList<Site>();
List<Area> cachedAreas = new ArrayList<Area>();
Severity currentSeverity;
boolean configured = false;
boolean changedConsequences = false;
final ImageResources imageResources;
RegisteredRequestWidget<ActionBarPresenterWidget> actionBarReg;
RegisteredRequestWidget<ProgressBarPresenterWidget> progressBarReg;
@Inject
public OpenIncidentPresenter(final EventBus eventBus, final MyView view,
final MyProxy proxy, final DispatchAsync dispatch,
final PlaceManager placeManager, ImageResources imageResources) {
super(eventBus, view, proxy, dispatch, placeManager);
this.imageResources = imageResources;
getView().setUiHandlers(this);
logger.log(Level.INFO, "Constructed OpenIncidentPresenter");
}
@Override
protected void revealInParent() {
RevealContentEvent.fire(this, ApplicationPresenter.SLOT_MIDDLE, this);
}
... Snip ...
}
IncidentPresenter
public abstract class IncidentPresenter<T extends View,
H extends Proxy<?>> extends RequestPresenter<T, H> implements HasIncident {
Logger logger = Logger.getLogger(IncidentPresenter.class.getName());
public static final String INCIDENT_COOKIE = "incidentId";
public interface LoadCallback {
void onFinished();
}
protected Incident incident;
protected DispatchAsync dispatch;
private boolean loaded = false;
public IncidentPresenter(EventBus eventBus, T view, H proxy,
DispatchAsync dispatch, PlaceManager placeManager) {
super(eventBus, view, proxy, placeManager, true);
this.dispatch = dispatch;
}
public abstract void onFailureToLoadIncident(Integer incidentId);
public abstract void onLoadedIncident(Incident incident);
@Override
public void loadIncident(final Integer id) {
loadIncident(id, null);
}
@Override
public void loadIncident(final Integer id, final LoadCallback callback) {
.. Snip ..
}
/**
* Process the incident dependencies
*/
protected void loadDependencies(final Incident incident, final LoadCallback callback) {
.. Snip ..
}
@Override
public Incident getIncident() {
return incident;
}
@Override
public void setIncident(Incident incident) {
this.incident = incident;
if(hasIncident()) {
String incidentCookie = Cookies.getCookie("incidentId");
if(incidentCookie == null || !incidentCookie.equals(String.valueOf(
incident.getId()))) {
// Set the cookie to the new incident id
Cookies.setCookie("incidentId", String.valueOf(incident.getId()));
logger.log(Level.INFO, "Set incident " + String.valueOf(incident.getId())
+ " to the cookie session");
}
} else {
Cookies.removeCookie("incidentId");
logger.log(Level.INFO, "Set incident to null incident object, cleared " +
"the cookie session");
}
}
@Override
public boolean isIncidentLoaded() {
return hasIncident() && loaded;
}
@Override
public boolean hasIncident() {
return IncidentUtils.isValid(incident);
}
@Override
public void resetIncident() {
setIncident(null);
loaded = false;
}
@Override
public DispatchAsync getDispatch() {
return dispatch;
}
public String getIncidentCookie() {
return Cookies.getCookie(INCIDENT_COOKIE);
}
}
RequestPresenter
public abstract class RequestPresenter<T extends View, H extends Proxy<?>>
extends RichPresenter<T, H> implements HasRequestedWidgets {
RequestWidgetManager requestManager = new RequestWidgetManager(this);
public RequestPresenter(EventBus eventBus, T view, H proxy,
PlaceManager placeManager) {
this(eventBus, view, proxy, placeManager, false);
}
public RequestPresenter(EventBus eventBus, T view, H proxy,
PlaceManager placeManager, boolean leaveConfirmation) {
super(eventBus, view, proxy, placeManager, leaveConfirmation);
}
@Override
public void prepareFromRequest(PlaceRequest request) {
prepareFromRequest(request, null);
}
/**
* Alternative to {@link RequestPresenter#prepareFromRequest(PlaceRequest)} that
* will allow you to register the {@link FinalCallback} in case you have dependency
* on the request widgets.
* @param request
* @param callback
*/
public void prepareFromRequest(PlaceRequest request, FinalCallback callback) {
super.prepareFromRequest(request);
executeAfterRequesting(callback);
requestWidgets();
}
@Override
protected void onBind() {
super.onBind();
registerRequestWidgets();
}
@Override
protected void onUnbind() {
super.onUnbind();
unregisterRequestWidgets();
}
@Override
protected void onHide() {
super.onHide();
dismissWidgets();
}
@Override
protected void onReveal() {
super.onReveal();
requestWidgets();
}
private void requestWidgets() {
requestManager.requestAll();
onRequestWidgets();
}
private void dismissWidgets() {
requestManager.dismissAll();
onDismissWidgets();
}
public void unregisterRequestWidgets() {
requestManager.unregisterAllWidgets();
}
@Override
public abstract void registerRequestWidgets();
public void onRequestWidgets() {
// Do nothing by default
}
public void onDismissWidgets() {
// Do nothing by default
}
protected RequestWidgetManager getRequestManager() {
return requestManager;
}
/**
* This will execute the callback method when the final request is made on loading.<br>
* This must be set before super.onReveal or super.prepareFromRequest are called.
* Or use {@link RequestPresenter#prepareFromRequest(PlaceRequest, FinalCallback)} to
* set the final callback.
* @param callback
*/
public void executeAfterRequesting(FinalCallback callback) {
requestManager.setFinalCallback(callback);
}
public <P extends PresenterWidget<?>> RequestedWidget<P> getRequestedWidget(
RegisteredRequestWidget<P> registry) {
return requestManager.get(registry);
}
public <P extends PresenterWidget<?>> RegisteredRequestWidget<P> registerRequestWidget(
HasHandlers handler, Class<P> clazz, Object slot, boolean clearSlot) {
return registerRequestWidget(handler, clazz, slot, clearSlot, null);
}
public <P extends PresenterWidget<?>> RegisteredRequestWidget<P> registerRequestWidget(
HasHandlers handler, Class<P> clazz, Object slot, boolean clearSlot,
RequestWidgetEvent.Callback<P> callback) {
return requestManager.registerWidget(handler, clazz, slot, clearSlot, callback);
}
}
RichPresenter
public abstract class RichPresenter<T extends View,
H extends Proxy<?>> extends Presenter<T, H> {
protected final PlaceManager placeManager;
private boolean leaveConfirmation;
private String defaultLeaveMessage = "Any unsaved work will be lost when " +
"leaving this page, are you sure you would like to leave?";
public RichPresenter(EventBus eventBus, T view, H proxy,
PlaceManager placeManager) {
this(eventBus, view, proxy, placeManager, false);
}
public RichPresenter(EventBus eventBus, T view, H proxy,
PlaceManager placeManager, boolean leaveConfirmation) {
super(eventBus, view, proxy);
this.placeManager = placeManager;
this.leaveConfirmation = leaveConfirmation;
}
/**
* Setup component control handlers for the UI
*/
protected void setupHandlers(final T view) {
// Do nothing by default
}
@Override
public void prepareFromRequest(PlaceRequest request) {
super.prepareFromRequest(request);
// Start Load Indicator
LoadingIndicatorEvent.fire(this, true);
// Attempt to set leave confirmation
setLeaveConfirmation(leaveConfirmation);
}
@Override
protected void onBind() {
super.onBind();
setupHandlers(getView());
}
@Override
protected void onUnbind() {
super.onUnbind();
// Remove all the event handlers
for(HandlerRegistration reg : handlerRegistrations) {
reg.removeHandler();
}
handlerRegistrations.clear();
}
@Override
protected void onReveal() {
super.onReveal();
// Stop Load Indicator
LoadingIndicatorEvent.fire(this, true);
// Attempt to set leave confirmation
setLeaveConfirmation(leaveConfirmation);
}
@Override
protected void onReset() {
super.onReset();
// Stop Load Indicator
LoadingIndicatorEvent.fire(this, false);
}
/**
* Set the page leave confirmation.
* @param leaveConfirmation
*/
public void setLeaveConfirmation(boolean leaveConfirmation) {
this.leaveConfirmation = leaveConfirmation;
if(leaveConfirmation && !BrowserUtils.isIEBrowser()) {
placeManager.setOnLeaveConfirmation(defaultLeaveMessage);
} else {
placeManager.setOnLeaveConfirmation(null);
}
}
public boolean isConfirmOnLeave() {
return leaveConfirmation;
}
public String getDefaultLeaveMessage() {
return defaultLeaveMessage;
}
public void setDefaultLeaveMessage(String message) {
this.defaultLeaveMessage = message;
}
}
I feel like this could be a contributing factor here. I have a large chain of presenters that I could be implementing wrong.
This is making it crazy hard for me to identify issues in my client side code. I have to go through my changes, reverting them until I no longer get this message. Which is just ridiculous. If you can see that I am doing something wrong or need more information let me know please! Would be so greatly appreciated.
Cheers! Ben