Navigation with URI Templates and path parameters (Vaadin 8 and Spring Boot

Hello,

I have been annoyed with the default navigator implementation for a while now. I do have a domain model I am exposing via a RESTful API and I would like to browse and interact with the UI with simmilar URI patters as you see in the RESTful API.

So in order to create a controller in Spring you would annotate a method with something like:

@RequestMapping(value = "/v1/apples/{appleId}/cores/{coreId}", method = RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE) I wanted to replicate this kind of navigation with vaadin views. Thus, I implemented a custom SpringViewProvider that allows for this. Vaadin 8 Spring Boot Demo here:
https://github.com/heutelbeck/VaadinUriTemplateNavigation

In short, You can declare View names with URI Templates now:

[code]
@SpringView(name = CoreView.TEMPLATE)
public class CoreView extends VerticalLayout implements View {

private static final long serialVersionUID = 1L;

public static final String TEMPLATE = "apples/{appleId}/cores/{coreId}";
public static final UriTemplate URI_TEMPLATE = new UriTemplate(TEMPLATE);

Label appleId = new Label();
Label coreId = new Label();

public static String getViewName(String appleId, String coreId) {
    Map<String, String> vars = new HashMap<String, String>();
    vars.put("appleId", appleId);
    vars.put("coreId", coreId);
    return URI_TEMPLATE.expand(vars).toString();
}

@PostConstruct
void init() {
    addComponent(new Label("This views shows an individual core in a specific apple  Fragment: '"
            + UI.getCurrent().getPage().getUriFragment() + "'"));
    addComponent(appleId);
    appleId.setCaption("Apple ID:");
    addComponent(coreId);
    coreId.setCaption("Core ID:");
}

@Override
public void enter(ViewChangeEvent event) {
    Map<String, String> map = URI_TEMPLATE.match(event.getViewName());
    for (Entry<String, String> entry : map.entrySet()) {
        log.info("key = '{}' value='{}'", entry.getKey(), entry.getValue());
    }
    appleId.setValue(map.get("appleId"));
    coreId.setValue(map.get("coreId"));
}

}
[/code]I have not found anything like this so far. Any feedback and improvements ofr this approach are welcome. Maybe this can be developed into an addon later on. It is certainly possible to automate some things even more, and the view resolution is less efficient this way.

I hope this is helpful for others having simmilar use-cases.

Best regards,
Dominic

Edit: Removed some examples because they are now documented in the README.md

This looks like something that would be very nice to have as an add-on for better discoverability. It also looks to me like this is not even Spring specific apart from the base class of the view provider, so perhaps a non-Spring version could also be made.

Hello, Henri.

It is a bit tricky to do this. You can do a non-spring version, but I still end up with spring dependencies, or I would have to copy & paste all the UriFragment handling source code into the addon. I am not a fan of doing so.

Also, implementing this as a custom navigation feels just a little bit awkward, as in both cases the spring as in the vanilla Vaadin case, the navigation classes are referenced by implementation and not via an interface, so that you have to subclass the original Navigator classes and override a lot of methods, and in parts copy methods, as certain internals of the classes are not accessible for inheritance. This is an area, where a future version of Vaadin could benefit from introducing a Navigator interface to allow plugging in custom Navigators more easily.

That said, I did sit down today to look, if I could actually do it and create a vanilla Vaadin addon for this, and ended up with the following solution:


https://github.com/heutelbeck/vaadin-uritemplates

This certainly needs some more extensive testing and a bit documentation for release. But would you be interested in looking if it makes sense in this way. I would be happy to make this feature publicly available as an addon.

Best,
Dominic

‚Äč