ErrorStateRenderer extends AbstractNavigationStateRenderer { @Override public int handle(NavigationEvent event) { assert event instanceof ErrorNavigationEvent : "Error handling needs ErrorNavigationEvent"; ExceptionsTrace trace = ComponentUtil.getData(event.getUI(), ExceptionsTrace.class); boolean isFirstCall = trace == null; Exception exception = ((ErrorNavigationEvent) event).getErrorParameter() .getCaughtException(); if (isFirstCall) { trace = new ExceptionsTrace(exception); ComponentUtil.setData(event.getUI(), ExceptionsTrace.class, trace); } else if (trace.hasException(exception)) { LoggerFactory.getLogger(ErrorStateRenderer.class) .error("The same exception {} " + "has been thrown several times during navigation. " + "Can't use any {} view for this error.", exception.getClass().getName(), HasErrorParameter.class.getSimpleName(), trace); throw trace; } trace.addException(exception); try { return super.handle(event); } finally { if (isFirstCall) { ComponentUtil.setData(event.getUI(), ExceptionsTrace.class, null); } } } ErrorStateRenderer(NavigationState navigationState); @Override int handle(NavigationEvent event); @Override List<Class<? extends RouterLayout>> getRouterLayoutTypes(
            Class<? extends Component> targetType, Router router);  }
@Test(expected = ExceptionsTrace.class) public void handle_openNPEErrorTarget_infiniteReroute_noStackOverflow_throws() { UI ui = configureMocks(); NavigationState state = new NavigationStateBuilder(ui.getInternals().getRouter()) .withTarget(InfiniteLoopErrorTarget.class).build(); ErrorStateRenderer renderer = new ErrorStateRenderer(state); RouteConfiguration.forRegistry(ui.getInternals().getRouter().getRegistry()) .setAnnotatedRoute(InfiniteLoopNPEView.class); ErrorParameter<Exception> parameter = new ErrorParameter<>( Exception.class, new NullPointerException()); ErrorNavigationEvent event = new ErrorNavigationEvent(ui.getInternals().getRouter(), new Location("error"), ui, NavigationTrigger.CLIENT_SIDE, parameter); renderer.handle(event); }
@Test(expected = ExceptionsTrace.class) public void handle_openNPEView_infiniteReroute_noStackOverflow_throws() { UI ui = configureMocks(); NavigationState state = new NavigationStateBuilder(ui.getInternals().getRouter()) .withTarget(InfiniteLoopNPEView.class).build(); NavigationStateRenderer renderer = new NavigationStateRenderer(state); RouteConfiguration.forRegistry(ui.getInternals().getRouter().getRegistry()) .setAnnotatedRoute(InfiniteLoopNPEView.class); ((ApplicationRouteRegistry) ui.getInternals().getRouter().getRegistry()) .setErrorNavigationTargets( Collections.singleton(InfiniteLoopErrorTarget.class)); NavigationEvent event = new NavigationEvent(ui.getInternals().getRouter(), new Location("npe"), ui, NavigationTrigger.CLIENT_SIDE); renderer.handle(event); JsonObject routerLinkState = Json.createObject(); routerLinkState.put("href", "router_link"); routerLinkState.put("scrollPositionX", 0d); routerLinkState.put("scrollPositionY", 0d); event = new NavigationEvent(ui.getInternals().getRouter(), new Location("npe"), ui, NavigationTrigger.ROUTER_LINK, routerLinkState, false); renderer.handle(event); }
@Test public void handle_errorViewLayoutForwardsToAView_viewIsNavigated() { UI ui = configureMocks(); NavigationState state = new NavigationStateBuilder(ui.getInternals().getRouter()) .withTarget(HappyPathErrorTarget.class).build(); ErrorStateRenderer renderer = new ErrorStateRenderer(state); RouteConfiguration.forRegistry(ui.getInternals().getRouter().getRegistry()) .setAnnotatedRoute(HappyPathViewView.class); ErrorParameter<Exception> parameter = new ErrorParameter<>( Exception.class, new NullPointerException()); ErrorNavigationEvent event = new ErrorNavigationEvent(ui.getInternals().getRouter(), new Location("error"), ui, NavigationTrigger.CLIENT_SIDE, parameter); Assert.assertEquals(200, renderer.handle(event)); List<HasElement> chain = ui.getInternals() .getActiveRouterTargetsChain(); Assert.assertEquals(1, chain.size()); Assert.assertEquals(HappyPathViewView.class, chain.get(0).getClass()); }