Servlet/UI mapping

Hi
My problem is that I map one servlet to /application and the other to /permalink and I also provide the different servlets with a UI via the init-param “ui”. Each UI is annotated with @SpringUI(path = “”). It seems like the UIs aren’t associated with the respective ui. When I start up, I get “No UIProvider has been added and there is no “UI” init parameter”. When I instead annotate the permalink UI with @SpringUI(path = “/permalink”) it works. But then I have to write localhost:8080/permalink/permalink to access that ui, i.e. first the servlet mapping and then the ui path. I want to be able to access the UIs via
localhost:8080/application and localhost:8080/permalink.
How can I achieve that?
I am using vaadin 7.7.6

Regards
Johan

Hi Johan,
if you are using vaadin-spring addon you don’t need to manually specify the servlet; a SpringVaadinServlet should be deployed automatically. (See https://vaadin.com/docs/-/part/framework/advanced/advanced-spring.html#advanced.spring.preparing)

You need only to map your UIs with @SpringUI(path=“/application”) and @SpringUI(path=“/permalink”).

If this does not work, could you post your actual configuration?

Best regards
Marco

Hi
I tried using the standard SpringVaadinServlet but I had a problem with the heartbeats from the permalink UI didn’t reach the servlet so I got the tip to serve the UIs with dedicated servlets and that actually fixed the problem so that is why I use two servlets. I don’t have my code available at the moment bu I will post it first thing in the morning. Specifically, what part of the conf? The servlets alone?

Hi,
if you post the servlet confguration (annotated class or web.xml fragment) it will help to better understand the problem.

Application Servlet:
@WebServlet( urlPatterns = {ApplicationServlet.SERVLET_PATH, “/VAADIN/*”}, asyncSupported = true, initParams = {@WebInitParam(name = “ui”, value = “se.reforce.fasthi.core.interfaces.ui.FasthiApplicationUI”), @WebInitParam(name = “pushmode”, value = “automatic”), @WebInitParam(name = “legacyPropertyToStringMode”, value = “false”)}) @Configurable public class ApplicationServlet extends SpringVaadinServlet {
//Minor overrides
}

Permalink servlet:
@WebServlet( urlPatterns = {PermalinkServlet.SERVLET_PATH}, asyncSupported = true, initParams = {@WebInitParam(name = “ui”, value = “se.reforce.fasthi.core.interfaces.ui.application.permalink.PermalinkUI”), @WebInitParam(name = “pushmode”, value = “automatic”), @WebInitParam(name = “heartbeatInterval”, value = “60”)}) @Configurable public class PermalinkServlet extends SpringVaadinServlet {
//No overrides
}

PermalinkServlet.SERVLET_PATH = /permalink
ApplicationServlet.SERVLET_PATH = /application

Hi Johan,
the problem here is that SpringUIProvider does not allow more than one @SprinUI bean with the same path.

SpringVaadinServlet removes the default UI provider and add its own SpringUIProvider; this provider loads all bean annotated with @SpringUI but it does not allow to have two bean annotated with the same path.
The ui init parameter and @VaadinServletConfiguration.ui are not considered.

As a workaround you can use a custom provider that always return the UI instance you need for your servlet mapping.
Following there is same sample code, just to better explain what I mean

I hope this can help you.

Best regards
Marco

@WebServlet(urlPatterns = {"/application/*", "/VAADIN/*"}, name = "AppServlet", asyncSupported = true)
@VaadinServletConfiguration(ui = AppUI.class, productionMode = false)
@Push
public static class AppServlet extends CustomSpringVaadinServlet {
}

@WebServlet(urlPatterns = "/permalink/*", name = "PermalinkServlet", asyncSupported = true)
@VaadinServletConfiguration(ui = PermalinkUI.class, productionMode = false, heartbeatInterval = 60)
@Push
public static class PermalinkServlet extends CustomSpringVaadinServlet {
}

public abstract class CustomSpringVaadinServlet extends SpringVaadinServlet {

    private final Class<? extends UI> uiClass;

    public CustomSpringVaadinServlet() {
        uiClass = getClass().getAnnotation(VaadinServletConfiguration.class).ui();
    }

    @Override
    protected void servletInitialized() throws ServletException {
        getService().addSessionInitListener(new SessionInitListener() {

            private static final long serialVersionUID = -6307820453486668084L;

            @Override
            public void sessionInit(SessionInitEvent sessionInitEvent)
                throws ServiceException {

                // Code copied from SpringVaadinServlet

                WebApplicationContext webApplicationContext = WebApplicationContextUtils
                    .getWebApplicationContext(getServletContext());

                // remove DefaultUIProvider instances to avoid mapping
                // extraneous UIs if e.g. a servlet is declared as a nested
                // class in a UI class
                VaadinSession session = sessionInitEvent.getSession();
                List<UIProvider> uiProviders = new ArrayList<UIProvider>(
                    session.getUIProviders());
                for (UIProvider provider : uiProviders) {
                    // use canonical names as these may have been loaded with
                    // different classloaders
                    if (DefaultUIProvider.class.getCanonicalName().equals(
                        provider.getClass().getCanonicalName())) {
                        session.removeUIProvider(provider);
                    }
                }

                // add Spring UI provider

                final Class<? extends UI> appUIClass = uiClass;
                UIProvider uiProvider = new SpringUIProvider(session) {

                    // Only map wanted UI class
                    @Override
                    protected void mapPathToUI(String path, Class<? extends UI> uiClass) {
                        if (appUIClass.equals(uiClass)) {
                            super.mapPathToUI(path, uiClass);
                        }
                    }
                };
                session.addUIProvider(uiProvider);
            }
        });
    }

}