Contents


Develop full-stack Java apps with Vaadin in the cloud

Build an interactive order-desk app in minutes with Bluemix and the Vaadin Rich Web Starter boilerplate

Comments

This article was written using the Bluemix classic interface. Given the rapid evolution of technology, some steps and illustrations may have changed.

As a Java developer, you don't need to learn HTML5, CSS, or JavaScript to start creating interactive web applications. With the Vaadin framework and its huge library of ready-to-deploy add-ons and components, you can create 100 percent full-stack Java applications by using familiar IDE and server-side technologies. My developerWorks article "Full-stack Java web dev with Vaadin" explains how Vaadin works under the hood and helps you get started with creating web apps with Vaadin.

Vaadin apps work well with Bluemix, which offers the Vaadin Rich Web Starter boilerplate. Vaadin apps that are deployed on Bluemix enjoy industry-standard Liberty Profile application server runtime support, and IBM DB2 for relational data storage. And all Vaadin apps on Bluemix can take advantage of a rich and growing variety of server-side services.

In this tutorial, I'll take you step-by-step through building a complete Vaadin web app for a simple order desk. You'll construct the app with components by using Vaadin Contexts and Dependency Injection (CDI) and by using the Java Persistence API (JPA) to access a back-end database. You'll code in the familiar Eclipse IDE and deploy the resulting app to Bluemix.

You'll learn how to:

  • Kickstart your Vaadin app creation by using the Vaadin Rich Web Starter boilerplate on Bluemix
  • Extend a Vaadin CDI application to add access control
  • Use two third-party add-on UI components from the Vaadin Add-ons directory in your web application
  • Add a login page to the app, and authenticate against the customer database.
  • Add an order search view to the app

All Vaadin apps on Bluemix can take advantage of a rich and growing variety of server-side services.

What you'll need

Required:

If you want to modify or work on the code:

  • Java Development Kit (JDK) 1.7 or higher (1.7.0_60-b19 is used in the development of this code)
  • Eclipse IDE for Java EE Developers (Luna or higher)
  • Vaadin Plugin for Eclipse (from Eclipse Marketplace)
  • WebSphere Application Server Liberty Profile Web Profile v8.5.5.5 or higher (from Eclipse marketplace, or the IBM WebSphere Liberty Repository)
  • Apache Derby database (derby.jar from the distribution) 10.11.1.1. or higher

Run the appGet the code

Step 1. Explore the UI of the app

Click the Run the app button (preceding this step) and try the order-desk application:

  1. If you click any menu item on the left (except for About), you are taken to the login page. The About page is used for loading data into the Customer database, which is necessary for login to work. Click the Fill test data into DB button.
  2. On the login page, log in with user name brian@robinson.com and password abc123: Screenshot of the Login view
    Screenshot of the Login view
  3. Check out the animated charts in the Analyze view:Screenshot of the Analyze view
    Screenshot of the Analyze view
  4. Browse through the customers in the Customer List view, and see customer locations in the Map view: Screenshot of the Map view
  5. Use the Search view to search for an order: Screenshot of the Search view
    Screenshot of the Search view
  6. Shrink the browser page width to see how the app adjusts responsively.
  7. Select the Login-Logout view again to log out, and notice that you can no longer navigate to any of the other views.

Step 2. Clone and deploy the Vaadin Bluemix boilerplate

This tutorial starts with the code in the Vaadin boilerplate for Bluemix and adds to it. Alternatively, you can click the Get the code button (before Step 1. Explore the UI of the app in this tutorial) to go to the Bluemix DevOps Services project that contains the final code. Then, you can compare the final code in that project with the boilerplate version as you follow along in this tutorial.

  1. Log in to your Bluemix account (or sign up for a free trial).
  2. Click Cloud Foundry Apps > CREATE APP.
  3. Click Web, and then click Browse Boilerplates.
  4. Click Vaadin Rich Web Starter: Screenshot of the Vaadin Reich Web Starter icon
  5. Give your app a unique name, and click CREATE. An IBM WebSphere Liberty Profile server and a free beta instance of the SQL Database service (currently backed by IBM DB2) are provisioned as the app is created.
  6. On your computer, clone the boilerplate code repository:

    git clone https://hub.jazz.net/git/vaadin/vaadin-jpa-app

  7. Change directory to the cloned repository:

    cd vaadin-jpa-app

  8. Build the app, and create the WAR:

    mvn install

  9. Delete manifest.yml from the directory.
  10. Deploy the WAR to Bluemix:

    cf push appname -p target/vaadin-jpa-application.war

  11. Access your deployed boilerplate Vaadin app at http://appname.mybluemix.net/. The app has no Login view or Search view, but the Customer List, Analyze, and Map views are working.

Step 3. Load your project into the Eclipse IDE

To modify and rebuild your code, you can load it into Eclipse and rebuild the WAR. You must use Maven build instead of the default Eclipse project build workflow.

  1. Import the project into Eclipse (File > Import > Existing Maven Project). Then, select the root directory of the project to complete the import.
  2. Find the pom.xml file, right-click it, and select Run as > Maven install. Watch the console for progress, which can take a while because this process downloads artifacts and sets up everything for building the WAR.
  3. Copy the Apache Derby database (derby.jar) to your Liberty Profile instance. Drag derby.jar from the Apache Derby code distribution into the Enterprise Explorer pane and place it in the WebSphere Application Server Liberty Profile/shared/resources/derby folder; the folder might not exist yet, so you might need to create it.
  4. Modify the server.xml file of your Liberty Profile instance to include the Java Naming and Directory Interface (JNDI) data source:

    <jdbcDriver id="DerbyEmbedded" libraryRef="DerbyLib"/>
    <library filesetRef="DerbyFileset" id="DerbyLib"/>
    <fileset dir="${shared.resource.dir}/derby" id="DerbyFileset" includes="derby.jar"/>
    <!-- Configure an in-memory db for the vaadin app configuration -->
    <dataSource id="jdbc/vaadindb" jdbcDriverRef="DerbyEmbedded" jndiName=
        "jdbc/vaadindb" transactional="true">
      <properties createDatabase="create" databaseName="memory:jpasampledatabase"/>
    </dataSource>
  5. To successfully run your Vaadin CDI (Contexts and Dependency Injection) app, you must also include the following lines in your server.xml file. For the best Vaadin CDI compatibility, use these exact lines of code instead of selecting individual Liberty Profile features:

    <featureManager>
        <feature>localConnector-1.0</feature>
        <feature>webProfile-6.0</feature>
    </featureManager>
  6. To rebuild the WAR after any code modifications, select the project and right-click Run As > Maven Build. The first time that you rebuild the WAR, you're prompted for a goal. Enter package for the Maven goal: Screenshot of the Eclipse Edit Configuration dialog box
    Screenshot of the Eclipse Edit Configuration dialog box
  7. To deploy to the local server, right-click the WAR in the project, select Run As > Run on server, and select your Liberty Profile instance.

Step 4. Add the Login view

The boilerplate app uses the Vaadin CDI to handle custom navigation and to inject UI objects as CDI managed beans. The Vaadin CDI add-on is in the Vaadin Add-ons directory.

Also, in the Vaadin Add-ons directory is a set of cdi-helpersUI components (source repo) that the Bluemix Vaadin boilerplate code depends on. Studying the operation of this set of helpers will help you understand how Vaadin CDI is used in the application.

  1. Study the existing code to make sure that you understand how Vaadin CDI works in the app. The entire app UI is an instance of the ViewMenuUI UI. You can see the code for making this instance the main UI of the application in the org.vaadin.presentation.AppUI class. View changes are orchestrated by a Vaadin Navigator instance that's part of the ViewMenu.
  2. To add the Login view, first add a new class named org.vaadin.presentation.views.LoginView, which you can copy from the source repository. The Login view uses a Vaadin component add-on from the Vaadin Add-ons directory — the LoginForm UI component by Ingo Kegel.

    To add this component to your project, you must add its Maven artifacts to the project's pom.xml file, in the dependencies section:


    <dependency>
       <groupId>org.vaadin.addons</groupId>
       <artifactId>loginform</artifactId>
       <version>0.5.2</version>
    </dependency>
  3. In the LoginView class, the add-on makes it simple to display the form:

    final DefaultVerticalLoginForm loginForm = new DefaultVerticalLoginForm();
        	loginForm.addLoginListener(new LoginListener() {
        	    @Override
        ...
    });
    ...
    add(loginForm);
  4. To create the menu item with an icon and text label, and to ensure that it's the last one on the menu, use the @ViewMenuItem() annotation:

    @ViewMenuItem(icon = FontAwesome.SIGN_IN, title = "Login-Logout", order = ViewMenuItem.END)

    To tell the Navigator that this view is the default view, use the @CDIView() with a blank view name:

    @CDIView("")

    If you're following along and modifying the boilerplate, you also need to change the annotation of the AboutView from @CDIView("") to @CDIView("about").

If you build and deploy the app now, it will run with the new Login view, but nothing will happen because you haven't yet hooked in access control.

Step 5. Extend the customers database for authentication

  1. For authentication, you need to add a password field, a role field, and a findByEmail() named query to the customers database. First, modify the domain model POJO in the org.vaadin.backend.domain.Customer class:

    @NamedQueries({
            ...
            @NamedQuery(name="Customer.findByEmail",
            		query="SELECT c FROM Customer c WHERE LOWER(c.email) LIKE :filter")    
    })
        ...
        private String password;
        private String role;
    ...
    public String getPassword() {
    		return password;
    	}
    ...
    	public void setRole(String role) {
    		this.role = role;
    	}
  2. In the ensureTestData() method of the org.vaadin.backend.CustomerService class, populate the two new fields with constants:

    c.setRole("user");
    c.setPassword("abc123");
  3. In the CustomerListView class, in the adjustTableColumn() method, add the fields that you want to be displayed:

    customerTable.setVisibleColumns("firstName", "lastName", "email",
                 "status", "role", "password");
    customerTable.setColumnHeaders("First name", "Last name", "Email",
                 "Status", "Role", "Password");
  4. Make the LoginView functional by injecting an instance of the back-end CustomerService. This service is used to fetch the user's email and password information from the database. Notice the use of the ViewMenuUI.getMenu() navigator to navigate to the AboutView if login is successful:

    public class LoginView extends MVerticalLayout implements View {
        @Inject
        private CustomerService service;
    	...
        Customer cust = service.findByEmail(event.getUserName());
    
    	        if(cust != null) {    
     		...
    	        	System.err.println("PASSWORD verified");
        	             ViewMenuUI.getMenu().navigateTo(AboutView.class);
        	        } else {
        	        		System.err.println("PASSWORD invalid");
        	        		loginForm.clear();
        	        	}
        	   
        	        } else {
        	        	System.err.println("no user found");
        	        	loginForm.clear();
        	        }

If you build and run the app now, and try to log in, it redirects you to AboutView. However, because access control hasn't been added yet to protect the views, you can still click to see the customer list or map.

Step 6. Add CDI access control

  1. The Vaadin CDI CDIViewProvider implementation checks for a special annotation, named javax.annotation.security.RolesAllowed, before it allows access to a view. Access violations are directed to the default view (LoginView in this case). To add this annotation to the project, add the following Maven dependency into the pom.xml file:

    <dependency>
       <groupId>javax.annotation</groupId>
       <artifactId>javax.annotation-api</artifactId>
       <version>1.2-b01</version>
    </dependency>
  2. To use the RoleAllowed annotation to protect the views, add the line @RolesAllowed({"user"}) to each of the views (except LoginView and AboutView).

    This change ensures that only logged-in users with the role of user can access that view. (Recall from Step 5. Extend the customers database for authentication that every customer is set to have the role of user.)

  3. Create an org.vaadin.presentation.views.UserInfo class to contain the current user details. This class is attached to the UIScope (a specialized Vaadin CDI context that exists per UI instance in a session):

    @UIScoped
    public class UserInfo implements Serializable {
    private Customer user;
       private List<String> roles = new LinkedList<String>();
       ...

    See the source code of UserInfo for full details.

  4. Inject the UserInfo into the LoginView, allowing the view to fill the UserInfo on a successful login:

    public class LoginView extends MVerticalLayout implements View {
        ...	
        @Inject
        private UserInfo user;
       ...    
       public void onLogin(LoginEvent event) {
              ... 	    
               Customer cust = service.findByEmail(event.getUserName());
               if(cust != null) {    
        	 if (cust.getPassword().equals(event.getPassword()))  {
              		user.setUser(cust);
        	        	...
                    }
  5. By default, access control is checked against an abstract AccessControl class with only a single concrete Java Authentication and Authorization Service (JAAS)–based implementation. Replace this class with your own AccessControl implementation that checks against the injected UIScoped UserInfo instance:

    @Alternative
    public class CustomAccessControl extends AccessControl {
    
        @Inject
        private UserInfo userInfo;
        
        @Override
        public boolean isUserSignedIn() {
            return userInfo.getUser() != null;
        }
      ...

    See the source of org.vaadin.presentation.views.CustomAccessControl for details.

  6. To ensure that this alternative CustomAccessControl implementation is used by Vaadin CDI, you must add a line to the beans.xml file:

    <alternatives>
        <class>org.vaadin.presentation.views.CustomAccessControl</class>
    </alternatives>
  7. To implement logout, any logged-in user who clicks back to the Login-Logout page is logged out by using a reset of the injected UserInfo instance in the onEnter() method of the view:

    @Override
    public void enter(ViewChangeListener.ViewChangeEvent viewChangeEvent) {
      user.setUser(null);
    }

If you rebuild and run the app now, all the views (except for About) will be protected, and you must log in before the views can be accessed. After you log in, you can log out by selecting the Login view again.

Step 7. Add the Search view

The Search view is an open source third-party add-on UI component from the Vaadin Add-ons directory — the FilteringTable UI component by Teppo Kurki (source repo).

  1. Add the following dependency in the pom.xml file to use this component:

    <dependency>
       <groupId>org.vaadin.addons</groupId>
       <artifactId>filteringtable</artifactId>
       <version>0.9.13.v7</version>
    </dependency>
  2. Add the org.vaadin.presentation.views.SearchView class from the final source. The UI part of the view is constructed in the init() method and is straightforward. This view is also protected with @RolesAllowed({"user"}):

    @CDIView("search")
    @RolesAllowed({"user"})
    @ViewMenuItem(icon = FontAwesome.SUPPORT)
    public class SearchView extends MVerticalLayout implements View {
        private FilterTable filterTable;
         
       @PostConstruct
        void init() {
            filterTable = buildFilterTable();
           add(filterTable);
            setExpandRatio(filterTable, 1);
            add(buildButtons());
           setMargin(new MarginInfo(false, true, true, true));
            setStyleName(ValoTheme.LAYOUT_CARD);
        }
    ...

    The rest of the code for SearchView— inside org.vaadin.presentation.views.SearchView, org.tepi.filterable.demo.DemoFilterDecorator, and org.tepi.filterable.demo.DemoFilterGenerator— is used only in the setup of this demo view. You can explore that code at your leisure.

  3. Build the WAR and run the application. You now have the completed project. Check the README of the source repository for the latest updates. From the Maven project directory, you can also redeploy the completed WAR to Bluemix by using a cf push command:

    cf push appname -p target/vaadin-jpa-application.war

Conclusion

Vaadin on Bluemix gives Java developers the power to create compelling interactive web experiences by using a full-stack Java approach. The Vaadin boilerplate for Bluemix offers a ready-to-deploy app that can be readily extended for your specific needs.


Downloadable resources


Related topics


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java development, Web development, Cloud computing
ArticleID=1016321
ArticleTitle=Develop full-stack Java apps with Vaadin in the cloud
publish-date=09302015