How to pass params into vaadin’s ui and control the view to be loaded

So, you want to enable in your vaadin app automated authentification based on request params. The right location for this functionality is your instance of com.vaadin.ui.UI class — here the decision is made which view to show. If the provided for authentification data is incorrect or incomplete, then we will show login view. If the authentification was successful, we show some other view. There are means to pass params between the views, I will mention them later in this article. But they don’t work for authentification.

Sending pass as plain text is a bad practice, you may think of using encrypted password (still can be seen in the browser’s history) or one-time tokens (no need to send the login then). I used login and password params just for demo purpose.

The needed data on requested URL — the first one to ypur app from the current browser’s tab — can be extracted from VaadinRequest in the method init(VaadinRequest vaadinRequest). I used some debug logging:

Map<String ,String[]> paramMap = vaadinRequest.getParameterMap();
for (Map.Entry<String ,String[]> entry: paramMap.entrySet()){
   LOG.debug(">>>> " + entry.getKey() );
   for (String param: entry.getValue()){
        LOG.debug("< <<< " + param);
   }
}

You are supposed to see output like this:

2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-1475658135205
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-browserDetails
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 1
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> theme
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< valo
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-appId
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< main-3343801
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-sh
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 864
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-sw
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 1536
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-cw
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 1423
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-ch
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 771
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-curdate
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 1475658135206
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-tzo
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< -180
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-dstd
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 0
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-rtzo
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< -180
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-dston
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< false
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-vw
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 1423
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-vh
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 0
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-loc
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< http://localhost:8080/main/#!login/log=2222&pass=3333
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-wn
2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< main-3343801-0.0269370820741045

By using «=» and «&» we make links more HTTP-friendly.

Now it’s clear we need the array for key «v-loc»:

private static final String REQUESTED_URL_KEY = "v-loc";
private static final String DELIMITER = "&";
private static final String EQUALITY_SIGN = "=";
private static final String LOGIN_KEYWORD = "login";
private static final String PASSWORD_KEYWORD = "pass";
 
String[] urls = paramMap.get(REQUESTED_URL_KEY);
String url = urls[0];

We want to parse the link, param part is after the last slash — «log=2222&pass=3333»:

String paramString = url.substring(url.lastIndexOf("/") + 1);

Please note that we don’t check the name of the requested view currently.
If there were no param part like in the link http://localhost:8080/main/#!login , after the last slash we get «#!login» and can exit early:

        Map<String , String> argMap = new HashMap<>();
        if (StringUtils.isBlank(paramString) || paramString.contains("#!")) {
            // there were no part with params
            return argMap;
        }

Now populate the arg map:

        String[] msgs = paramString.split(DELIMITER);
 
        for (String msg : msgs) {
            // now splitting each part and adding parts key=value into a HashMap<>
            String[] params = msg.split(EQUALITY_SIGN);
            if (params.length == 2 && StringUtils.isNotBlank(params[0]) && StringUtils.isNotBlank(params[0])){
                argMap.put(params[0], params[1]);
            }
        }

We can use string values argMap.get(LOGIN_KEYWORD) and argMap.get(PASSWORD_KEYWORD) in our auth service:

if (authenticationService.authenticate(login, pass)) {
    Employee employee = employeeService.findByLogin(login);
	// todo compare passwords
    if (employee != null) {
        container.setEmployee(employee);
        authIsSuccessful = true;
    }
}
 
Navigator navigator = new Navigator(this, this);
navigator.addProvider(viewProvider);
if (authIsSuccessful) {
    navigator.navigateTo(OfficeView.VIEW_NAME);
} else {
    navigator.navigateTo(LoginView.VIEW_NAME);
}

That’s it!

And now about sending parameters between views. Our com.vaadin.navigator.View has method enter(ViewChangeListener.ViewChangeEvent viewChangeEvent). Params can be retrieved as follows:

if(viewChangeEvent.getParameters() != null) {
    Map<String , String> paramMap = new HashMap<>(3);
    String[] msgs = viewChangeEvent.getParameters().split(DELIMITER);
    for (String msg : msgs) {
        // now splitting each part and adding parts key=value into a HashMap<>
        String[] params = msg.split(EQUALITY_SIGN);
        if (params.length == 2 && StringUtils.isNotBlank(params[0]) && StringUtils.isNotBlank(params[0])){
            paramMap.put(params[0], params[1]);
        }
    }
 
...
}

You can react upon the values in paramMap now, for eample update the data on the view.

Update. Some details on how vaadin gets param v-loc. I’ve captured traffic with wireshark and in the sequence of requests found this POST:

/app/main/?v-1490967795580 HTTP/1.1
Accept: /
Content-Type: application/x-www-form-urlencoded
Referer: http://localhost:8080/app/main/
Accept-Language: ru-RU
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible;)
Host: localhost:8080
Content-Length: 304
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=BFEF3F7019FE938BAE24327AC754A59E
 
v-browserDetails=1&theme=mytheme&v-appId=appmain-1967030724
&v-sh=768&v-sw=1366&v-cw=1366&v-ch=706&v-curdate=1490967795638
&v-tzo=-180&v-dstd=0&v-rtzo=-180&v-dston=false&v-vw=1366&v-vh=706&
v-loc=http%3A%2F%2Flocalhost%3A8080%2Fabon-client%2Fmain%2F
&v-wn=appmain-1967030724-0.9856022015215805

This request is initiated by vaadin itself. You can see our param in the body of this request.

You can leave a response, or trackback from your own site.

Leave a Reply