SessionRouteRegistry extends AbstractRouteRegistry { @Override public Optional<Class<? extends Component>> getNavigationTarget( String url) { Objects.requireNonNull(url, "pathString must not be null."); final Optional<Class<? extends Component>> target = getConfiguration() .getTarget(url); if (target.isPresent()) { return target; } return getParentRegistry().getNavigationTarget(url); } SessionRouteRegistry(VaadinSession session); static RouteRegistry getSessionRegistry(VaadinSession session); @Override List<RouteData> getRegisteredRoutes(); @Override Registration addRoutesChangeListener(
            RoutesChangedListener listener); @Override NavigationRouteTarget getNavigationRouteTarget(String url); @Override RouteTarget getRouteTarget(Class<? extends Component> target,
            RouteParameters parameters); @Override Optional<Class<? extends Component>> getNavigationTarget(
            String url); @Override Optional<Class<? extends Component>> getNavigationTarget(
            String url, List<String> segments); @Override Optional<String> getTargetUrl(
            Class<? extends Component> navigationTarget); @Override Optional<String> getTargetUrl(
            Class<? extends Component> navigationTarget,
            RouteParameters parameters); @Override Optional<String> getTemplate(
            Class<? extends Component> navigationTarget); @Override @Deprecated List<Class<? extends RouterLayout>> getRouteLayouts(String path,
            Class<? extends Component> navigationTarget);  }
@Test public void sessionRegistryOverridesParentRegistryWithOwnClass_globalRouteReturnedAfterClassRemoval() { registry.setRoute("MyRoute", MyRoute.class, Collections.emptyList()); SessionRouteRegistry sessionRegistry = getRegistry(session); sessionRegistry.setRoute("MyRoute", Secondary.class, Collections.emptyList()); Assert.assertEquals( "Route 'MyRoute' should return Secondary as registered to SessionRegistry.", Secondary.class, sessionRegistry.getNavigationTarget("MyRoute").get()); sessionRegistry.removeRoute(Secondary.class); Assert.assertEquals( "Route 'MyRoute' should return MyRoute as registered to GlobalRegistry.", MyRoute.class, sessionRegistry.getNavigationTarget("MyRoute").get()); }
@Test public void registerRouteWithAliases_routeAliasesRegisteredAsExpected() { SessionRouteRegistry sessionRegistry = getRegistry(session); sessionRegistry.setRoute("MyRoute", MyRouteWithAliases.class, Collections.emptyList()); sessionRegistry.setRoute("info", MyRouteWithAliases.class, Collections.emptyList()); sessionRegistry.setRoute("version", MyRouteWithAliases.class, Collections.emptyList()); Assert.assertTrue("Main route was not registered for given Class.", sessionRegistry.getNavigationTarget("MyRoute").isPresent()); Assert.assertTrue( "RouteAlias 'info' was not registered for given Class.", sessionRegistry.getNavigationTarget("info").isPresent()); Assert.assertTrue( "RouteAlias 'version' was not registered for given Class.", sessionRegistry.getNavigationTarget("version").isPresent()); }
@Test public void setSameRouteValueFromDifferentThreads_ConcurrencyTest() throws InterruptedException, ExecutionException { final int THREADS = 5; ExecutorService executorService = Executors.newFixedThreadPool(THREADS); List<Callable<Result>> callables = IntStream.range(0, THREADS) .mapToObj(i -> { Callable<Result> callable = () -> { try { SessionRouteRegistry sessionRegistry = getRegistry( session); sessionRegistry.setRoute("MyRoute", MyRoute.class, Collections.emptyList()); } catch (Exception e) { return new Result(e.getMessage()); } return new Result(null); }; return callable; }).collect(Collectors.toList()); List<Future<Result>> futures = executorService.invokeAll(callables); List<String> exceptions = new ArrayList<>(); executorService.shutdown(); for (Future<Result> resultFuture : futures) { Result result = resultFuture.get(); if (result.value != null) { exceptions.add(result.value); } } Assert.assertEquals( "Expected 4 route already exists exceptions due to route target validation", THREADS - 1, exceptions.size()); String expected = String.format( "Navigation targets must have unique routes, found navigation targets '%s' and '%s' with the same route.", MyRoute.class.getName(), MyRoute.class.getName()); for (String exception : exceptions) { Assert.assertEquals(expected, exception); } Optional<Class<? extends Component>> myRoute = getRegistry(session) .getNavigationTarget("MyRoute"); Assert.assertTrue( "MyRoute was missing from the session scope registry.", myRoute.isPresent()); }
@Test public void useRouteResolutionFromDifferentThreads_ConcurrencyTest() throws InterruptedException, ExecutionException { final int THREADS = 5; ExecutorService executorService = Executors.newFixedThreadPool(THREADS); List<Callable<Result>> callables = IntStream.range(0, THREADS) .mapToObj(i -> { Callable<Result> callable = () -> { try { SessionRouteRegistry sessionRegistry = getRegistry( session); sessionRegistry.setRoute("MyRoute", MyRoute.class, Collections.emptyList()); } catch (Exception e) { return new Result(e.getMessage()); } return new Result(null); }; return callable; }).collect(Collectors.toList()); List<Future<Result>> futures = executorService.invokeAll(callables); List<String> exceptions = new ArrayList<>(); executorService.shutdown(); for (Future<Result> resultFuture : futures) { Result result = resultFuture.get(); if (result.value != null) { exceptions.add(result.value); } } Assert.assertEquals( "Expected 4 route already exists exceptions due to route target validation", THREADS - 1, exceptions.size()); String expected = String.format( "Navigation targets must have unique routes, found navigation targets '%s' and '%s' with the same route.", MyRoute.class.getName(), MyRoute.class.getName()); for (String exception : exceptions) { Assert.assertEquals(expected, exception); } Optional<Class<? extends Component>> myRoute = getRegistry(session) .getNavigationTarget("MyRoute"); Assert.assertTrue( "MyRoute was missing from the session scope registry.", myRoute.isPresent()); }
@Test public void updateRoutesFromMultipleThreads_allRoutesAreRegistered() throws InterruptedException, ExecutionException { List<Callable<Result>> callables = new ArrayList<>(); callables.add(() -> { try { getRegistry(session).setRoute("home", MyRoute.class, Collections.emptyList()); } catch (Exception e) { return new Result(e.getMessage()); } return new Result(null); }); callables.add(() -> { try { getRegistry(session).setRoute("info", MyRoute.class, Collections.emptyList()); } catch (Exception e) { return new Result(e.getMessage()); } return new Result(null); }); callables.add(() -> { try { getRegistry(session).setRoute("palace", MyRoute.class, Collections.emptyList()); } catch (Exception e) { return new Result(e.getMessage()); } return new Result(null); }); ExecutorService executorService = Executors.newFixedThreadPool(5); List<Future<Result>> futures = executorService.invokeAll(callables); executorService.shutdown(); List<String> exceptions = new ArrayList<>(); for (Future<Result> resultFuture : futures) { Result result = resultFuture.get(); if (result.value != null) { exceptions.add(result.value); } } Assert.assertEquals( "No exceptions should have been thrown for threaded updates.", 0, exceptions.size()); Assert.assertTrue("Route 'home' was not registered into the scope.", getRegistry(session).getNavigationTarget("home").isPresent()); Assert.assertTrue("Route 'info' was not registered into the scope.", getRegistry(session).getNavigationTarget("info").isPresent()); Assert.assertTrue("Route 'palace' was not registered into the scope.", getRegistry(session).getNavigationTarget("palace").isPresent()); }
@Test public void updateAndRemoveFromMultipleThreads_endResultAsExpected() throws InterruptedException, ExecutionException { getRegistry(session).setRoute("home", MyRoute.class, Collections.emptyList()); getRegistry(session).setRoute("info", MyRoute.class, Collections.emptyList()); List<Callable<Result>> callables = new ArrayList<>(); callables.add(() -> { try { getRegistry(session).removeRoute("info"); } catch (Exception e) { return new Result(e.getMessage()); } return new Result(null); }); callables.add(() -> { try { getRegistry(session).setRoute("modular", MyRoute.class, Collections.emptyList()); } catch (Exception e) { return new Result(e.getMessage()); } return new Result(null); }); callables.add(() -> { try { getRegistry(session).setRoute("palace", MyRoute.class, Collections.emptyList()); getRegistry(session).removeRoute("home"); } catch (Exception e) { return new Result(e.getMessage()); } return new Result(null); }); ExecutorService executorService = Executors.newFixedThreadPool(5); List<Future<Result>> futures = executorService.invokeAll(callables); executorService.shutdown(); List<String> exceptions = new ArrayList<>(); for (Future<Result> resultFuture : futures) { Result result = resultFuture.get(); if (result.value != null) { exceptions.add(result.value); } } Assert.assertEquals( "No exceptions should have been thrown for threaded updates.", 0, exceptions.size()); Assert.assertFalse( "Route 'home' was still registered even though it should have been removed.", getRegistry(session).getNavigationTarget("home").isPresent()); Assert.assertFalse( "Route 'info' was still registered even though it should have been removed.", getRegistry(session).getNavigationTarget("info").isPresent()); Assert.assertTrue("Route 'modular' was not registered into the scope.", getRegistry(session).getNavigationTarget("modular") .isPresent()); Assert.assertTrue("Route 'palace' was not registered into the scope.", getRegistry(session).getNavigationTarget("palace").isPresent()); }
@Test public void serialize_deserialize_parentRegistryIsANewOne() throws Throwable { session = new MockVaadinSession(vaadinService); TestSessionRouteRegistry registry = new TestSessionRouteRegistry( session); TestSessionRouteRegistry deserialized = serializeAndDeserialize( registry); VaadinService service = new TestService(); RouteRegistry newAppRegistry = service.getRouteRegistry(); Mockito.when(newAppRegistry.getNavigationTarget("foo", Collections.emptyList())) .thenReturn(Optional.of(HtmlContainer.class)); WrappedSession wrappedSession = Mockito.mock(WrappedSession.class); deserialized.session.refreshTransients(wrappedSession, service); Assert.assertEquals(Optional.empty(), registry.getNavigationTarget("foo", Collections.emptyList())); Assert.assertEquals(Optional.of(HtmlContainer.class), deserialized .getNavigationTarget("foo", Collections.emptyList())); }