Buscar este blog

Theme images by MichaelJay. Powered by Blogger.

Datos personales

Author Info

Labels

Video Of Day

Flickr

Showing posts with label SPRINGFRAMEWORK. Show all posts
Showing posts with label SPRINGFRAMEWORK. Show all posts

Tuesday, July 3, 2018

Vaadin 10 + Spring Demo application: World Cup Rusia 2018 stats

To test out some new interesting web technologies, we decided to go ahead and build a small demo application that will point out ideas that could potentially help a developer when trying to decide which ones to use in a new project. We decided to create a small application with responsiveness in mind, that would show real time and aggregated data about the current Football World Cup event that is taking place in Russia.

Technologies

The chosen technologies where:
  • Vaadin 10: The brand new version of the popular framework, that is powered by the new standards being pushed by the most popular browsers.
  • SpringFramework: The almost de-facto standard dependency injection framework, that stands as the backbone of almost every java project that are currently being built.
  • REST API: Our project uses the API available here. That API exposes data as a REST API with information being delivered in JSON format.

Features

This is a short list of currently supported features:
  • The application is responsive, it will correctly display information regardless the device being used. This feature is achieved by using Vaadin & Polymer technologies.
  • Depending on the device that you're browsing the site (especially mobile phones), you can add the application to the home screen, so it will look like a native application. The only catch is that it will not function in offline mode (yet, maybe sooner).
  • You can follow the matches in realtime. Using WebSockets, the application maintains an opened communication pipe between the browser and the server, so the updates can be informed to the client as soon as they are received from the API

Construction

You need to have a good starting point to start any new project. For us it was the Vaadin Base Project with String starter. By choosing this option, we could benefit of the fact that it already has a tested and working Spring configuration, so it was an easy decision. 

Responsiveness

We achieved this goal, by starting also a parallel development: a new Addon for the Vaadin platform that helps you to build new applications using a simple skeleton that takes care of building the usual visual elements present in a responsive application: hamburger menu, paper-cards and more.
Besides that, we also used some CSS techniques as media queries to make the final touches.

PWA

To allow the application to be added to the home screen of your device, and then showing it as a native application, we generated a PWA manifest, with some properties that you can easily mimic, by using a tool like the App Manifest Generator.

Realtime updates

This feature is really easy to implement, given Vaadin's @Push tecnology, based on websockets. Just adding a simple annotation to your main layout will give life to your bubbling screen.
You can learn more about this technology in Vaadin's official documentation.

Roadmap

These are the things we would like to implement in the near future:
  • Support for offline message that tells you that you need connectivity to use the app
  • Support for notifications
  • Localization
You can reach the demo online, by accessing: http://worldcup.flowingcode.com/ ... Try adding it to the home screen of your mobile device!
If you want to give us feedback, feel free to create issues in the GithHub page.
Finally some interesting links regarding these technologies:

Monday, April 9, 2018

ComboBox lazy loading with REST API in Vaadin 8

In this post we'll explore how to access a REST service in order to display items in a ComboBox in Vaadin 8.
First, we'll implement a REST service with Spring Boot, as described here
The web service will be exposed at http://127.0.0.1:8081/api/countries. It will receive no parameters and return an array containing the name of all the countries known by the JVM (the Geography knowledge of the JVM is amazing!).

@RestController
public class CountriesController {

    @RequestMapping("/api/countries")
    public String[] getCountries() {
        return countries().toArray(String[]::new);
    }    

    private static Stream<String> getCountries() {
        return Stream.of(Locale.getISOCountries())
            .map(countryCode -> new Locale("", countryCode))
            .map(locale->locale.getDisplayCountry(Locale.ENGLISH))
            .sorted();
    }
}
Next, we'll implement a REST client that consumes our REST API
public class CountriesClient {        

    private static String ALL_COUNTRIES_URI = "http://127.0.0.1:8081/api/countries";

    public Stream<String> getAllCountries() {
        RestTemplate restTemplate = new RestTemplate();
        String[] countries = restTemplate.getForObject(ALL_COUNTRIES_URI, String[].class);
        return Stream.of(countries);
    }
}
We'll need to add the dependencies for spring-web and jackson-databind in the project's POM (for a detailed explanation of consuming REST services with Spring, you can check this tutorial https://spring.io/guides/gs/consuming-rest/)
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.4</version>
    </dependency>
Now, we'll write a small application that loads the countries form the REST client, and displays them in a combobox:
    @Theme(ValoTheme.THEME_NAME)
    public class MyUI extends UI {

        private CountriesClient client = new CountriesClient();

        @Override
        protected void init(VaadinRequest vaadinRequest) {
            VerticalLayout layout = new VerticalLayout();
            ComboBox<String> cbCountry = new ComboBox<>();
            cbCountry.setWidth(300, Unit.PIXELS);
            initializeItems(cbCountry);

            layout.addComponents(cbCountry);
            setContent(layout);
        }

        private void initializeItems(ComboBox<String> cbCountry) {
            cbCountry.setItems(client.getAllCountries());
        }

        @WebServlet(urlPatterns = "/simple", asyncSupported = true)
        @VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
        public static class MyUIServlet extends VaadinServlet {
        }

    }
While this approach works, there is a drawback: all the items are loaded when the UI initializes, and setItems instantiates a ListDataProvider, which stores all the items in memory until the combobox itself is disposed. (This is not so critical in this case, since there are only 250 countries, but imagine a combobox loaded with thousands of items...)
Fortunately, we can do it better by specifying an smarter DataProvider that will take the responsibility of fetching items on demand. For this we'll use the method setDataProvider of ComboBox, that instead of a stream/collection/array of items, receives as parameter a DataProvider<T, String>.
DataProvider<T,F> is an interface where the type parameter T refers to the data type (in this case, the ComboBox<T> item type), and the second parameter is the filter type (which for ComboBox is always String, since the ComboBox is filtered by the text the user writes inside). The Vaadin framework supplies an implementation of DataProvider, named CallbackDataProvider, which has the following constructor:
public CallbackDataProvider(
        FetchCallback<T, F> fetchCallback,
        CountCallback<T, F> countCallback)
The fetch callback returns a stream with the items matching a Query, and the count callback returns the number of items matching a Query (a Query is another object in the Vaadin framework, that contains information about index, limits, sorting and filtering):
    @FunctionalInterface
    public interface FetchCallback<T, F> extends Serializable {
        public Stream<T> fetch(Query<T, F> query);
    }

    @FunctionalInterface
    public interface CountCallback<T, F> extends Serializable {
        public int count(Query<T, F> query);
    }

    public class Query<T, F> implements Serializable {
        private final int offset;
        private final int limit;
        private final List<QuerySortOrder> sortOrders;
        private final Comparator<T> inMemorySorting;
        private final F filter;
        //...
    }
In order to take advantage from the CallbackDataProvider, we'll need to introduce a couple of changes to our REST service (CountriesController).
First, we'll need a method that returns a subset of <count> items, matching a given <filter> and starting at a given <offset>.
    @RequestMapping("/api/countries/list")
    public String[] getCountries(
            @RequestParam(value="filter") String filter,
            @RequestParam(value="offset") int offset, 
            @RequestParam(value="limit")  int count) {
        return countries().filter(country->filter(country,filter))
            .skip(offset).limit(count).toArray(String[]::new);
    }       

    private boolean filter(String country, String filter) {
        return filter.isEmpty() || country.toLowerCase().contains(filter.toLowerCase());
    }
Then, we'll need a method that returns the count of items matching a given <filter>
    @RequestMapping("/api/countries/count")
    public int getCountries(
            @RequestParam(value="filter") String filter) {
        return (int) countries().filter(country->filter(country,filter)).count();
    }
Now, we proceed to adapt the REST client (CountriesClient) to these changes, by adding the following methods:
    private static String GET_COUNTRIES_URI = "http://127.0.0.1:8081/api/countries/list?offset={1}&limit={2}&filter={3}";

    private static String COUNT_URI = "http://127.0.0.1:8081/api/countries/count?filter={1}";

    public Stream<String> getCountries(int offset, int limit, String filter) {
        RestTemplate restTemplate = new RestTemplate();
        String[] countries = restTemplate.getForObject(GET_COUNTRIES_URI, String[].class, offset, limit, filter);
        return Stream.of(countries);
    }

    public int getCount(String filter) {
        RestTemplate restTemplate = new RestTemplate();
        Integer count = restTemplate.getForObject(COUNT_URI, Integer.class, filter);
        return count;
    }
Finally, we integrate the modified service in the UI code:
private void initializeItems(ComboBox<String> cbCountry) {
    cbCountry.setDataProvider(new CallbackDataProvider<>(
        query-> 
            client.getCountries(query.getOffset(),query.getLimit(), getFilter(query)),
        query->
            (int) client.getCount(getFilter(query))
        ));
    }

    private String getFilter(Query<?,String> query) {
        return ((String)query.getFilter().orElse(null));
    }
As a final note, there are other components that also use DataProvider, such as Grid and TwinColSelect.
You can download and run the complete code of this example from github.

Monday, October 30, 2017

Implementing Spring Security on a Vaadin application

Today I'm going to write a little bit about my experience of trying to secure a simple Vaadin application using one of the most popular security frameworks: the security extensions of SpringFramework.
This post will cover the part of configuring a default setting to make it work, of course after this, there are a lot of things to do in your project to finish implementing this, such as storing and retrieving your user details from the underlying datastore of your choice, choosing the password-hashing algorithm, and so on. But at least you will have an overview of what needs to be done to accomplish this.

Starting point

The first requisite you're going to need to build this application is Maven. Using this command-line tool you can create a blank application using the following command:

mvn archetype:generate

After executing that command, maven will list a lot of predefined archetypes, you can filter that list using a keyword. If you enter "vaadin", the list will be shortened, I choose "com.vaadin:vaadin-archetype-application". After entering all of the required information (we are using 8.1.5 version of Vaadin), maven will create a small application that you can compile, package and ran using a built-in Jetty configuration just by launching this command:

mvn jetty:run

After this, you're ready to go with the rest of steps.

Adding Spring Framework

The first thing you'll need to do is to add the spring framework dependency to your project. For achieving this, you'll need to modify your project's pom.xml file, and add this inside the <dependencies> section:

<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.3.RELEASE</version>
</dependency>

<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>


This will add all of the required dependencies that you're going to need to implement this. We are considering using 4.2.3.RELEASE, that is the last stable version of that part of the framework at the time this article was written. And also, we are using Vaadin-Spring addon version 2.0.1 (latest stable version).

Adding some classes

With Spring Framework, and Servlet 3.0 specification, you can get rid of all of the old xml configurations and just create some classes to configure the framework. We are going to need the creation of:

  • User model class: This class will model the user that is currently logged in. It has to implement the interface org.springframework.security.core.userdetails.UserDetails, that will you implement some methods, of which these ones are worth mentioning:
    • getUsername & getPassword: This methods should return the stored username and password of your logged in user.
    • getAuthorities: This method should return the granted authorities that will be useful for choosing which functionalities of your application this user can see/execute
    • isAccountNonExpired, isAccountNonLocked, isCredentialsNonExpired and isEnabled: This methods are useful if you want to apply different security policies to control the availability of your user / credentials
  • User Service: Is the class responsible for loading the previous model from the underlying database. In this little example, this class is just creating and returning a new simple User.
  • SecurityConfig: This is the class that controls the security configuration of your application. There are a lot of interesting things in this class to mention:
    • Through the method authenticationProvider(), we are configuring the previous service as the mechanism to retrieve the user from the database.
    • The method configure() is the most important one, and allows a lot of configurations to be set. We are using the minimal ones to allow some unprotected url patterns (like the login form page) and restrict everything else to allow only the access to logged in users.
    • We are also setting some standard configurations regarding the session utilizing the method sessionControlAuthenticationStrategy().
    • Another interesting thing is to create a Session Registry, that is a class that will allow spring to store the security sessions detail in memory.
    • Finally there is a method encoder() that will allow you to hash the password, so no plain password are going to be stored on the database. Just because this is a simple example, we are using a NoOpPasswordEncoder.
  • SecurityWebApplicationInitializer: This class will be responsible of assigning the class SecurityConfig as the base class of spring configuration.
  • LoginUI: Because we are going to secure some urls, and others are going to be left unsecured, we need to create a new UI, that will render the login form. In this class we are using one interesting Vaadin component: the LoginForm, this will render a login form in vaadin using some interesting features like being able to tell the browser to remember the user credentials.
Finally we have to modify the MainUI, a little bit to allow using a SpringVaadinServlet instead the default one. And also we are adding a logout button, that will be doing the logout process, invoking some class of spring security.
After adding this classes you're ready to go and test the application. If you try to access to the default url, you're going to be redirected to the LoginUI and your credentials are going to be asked. Just enter "admin" as username and "admin" as password and you are going to be granted the access to the application.
After that if you click in the logout button, you are going to be logged out of the application and then be redirected to the login page.
That's it. All of the sources are uploaded into a small github project so if you want, you can take a look there. If you have any issues please comment!
Hope this could be useful to someone.


Interested for our works and services?
Get more of our update !