LSPS documentation logo
LSPS Documentation
Application

In the previous chapters, you uploaded your modules to Designer Embedded Server. This is an application server with the LSPS Application already deployed.

In real-world scenarios, such a solution is obviously not sufficient since it is not possible to customize the LSPS Application User Interface or add new business logic to the application.

To perform such customizations, you need the LSPS Repository delivered as a separate file. With the repository set up, you can generate the Application User Interface source and LSPS Application sources with their API, so you can modify the application:

  • customize the Application User Interface
  • add Java code, EJBs
  • add custom task types, functions, form components.

Prerequisites

  1. Make sure you have Designer and the LSPS Repository installed.
  2. Generate an LSPS Application:
    1. Go to File > New > Other
    2. Select LSPS Application.
      ticket-app-generating.png
    3. Provide application details:
      • Application name: ticketapp
      • Application namespace: org.acme
      • Application namespace: org.acme
      • Base java package name: org.acme.ticketapp
    4. Wait until the notification popup appears.

      Note that Designer generates not only the application but also an embedded server and related resources.

  3. Put the resources including your model under version control. Consider excluding the following from version control:
    # builds:
    target/
    # eclipse project information
    #(generated by maven build):
    .project
    # eclipse workspace data:
    .metadata
    eclipse-target
  4. For directories with GO-BPMN projects, make sure to add the .project directories to version control since these are not generated by maven: If using git, add !.project to .gitignore in the directories.

    Local git repo setup

    ~/ticketing-app$ ls
    ticketingapp ticketingapp-model
    ~/ticketing-app$ ls ticketingapp/
    archetype-resources pom.xml ticketingapp-ear ticketingapp-ejb
    ticketingapp-embedded ticketingapp-tester ticketingapp-vaadin
    ticketingapp-vaadin-war
    ~/ticketing-app$ echo "target/
    > .project
    > .metadata
    > eclipse-target" > .gitignore
    ~/ticketing-app$ echo '!.project' > ticketingapp-model/.gitignore
    ~/ticketing-app$ git init
    Initialized empty Git repository in /home/eko/ticketing-app/.git/
    ~/ticketing-app$ git add *
    ~/ticketing-app$ git add .gitignore
    ~/ticketing-app$ git commit -am"init"
  5. Back in Designer, run the SDK embedded server with the application.
    app-server-run.png
    The server is located in the ticketapp-embedded project:
    • The Launcher you just used is in its embedded package.
    • The database in the h2 directory.
  6. Since we are going to work with the LSPS Application API, switch to the Java perspective.
    app-embedded-structure.png
    Note also that the connection has been added to the Server Connections list and you can define its properties including the database-schema update strategy.
    app-embedded-configuration.png
    If you go to localhost:8080/lsps-application/ui, you will access the LSPS Application of the SDK Embedded Server you have just started up.

Displaying Only Relevant Items in Navigation Menu

User story: In the Application User Interface, users can access from their navigation menu only the documents they have access to and the to-do list.

Create your implementation of the menu:

  1. In the core package of the <YOUR_APP>-vaadin project, create the AppMainMenu class that extends DefaultMainMenu.
  2. Create the getNavigator() method to allow integration with View switching.
  3. Copy the implementation of the DefaultMainMenu.createMenu() method to the AppMainMenu implementation.
  4. Remove the addRunModelMenuItem(navigationMenu) and addDocumentsMenuItem(navigationMenu) calls.
  5. Add navigation to the documents for raising a ticket and the list of tickets with with adddDocumentMenuItem().
  6. Make the AppAppLayout.createMainMenu() method return AppMainMenu.
      @Override
      protected Component createMainMenu() {
        return new AppMainMenu(CONTENT_AREA_ID);
      }
  7. Rebuild your application (you can use the maven launcher in the drop-down of the Run button on the main toolbar).
  8. Restart the server.
  9. Upload the raising and list modules
  10. Assign the SupportSpecialist and Customer roles to users.
  11. Check the main menu of the users.

AppMainMenu class

public class AppMainMenu extends DefaultMainMenu {
 
  public AppMainMenu(String closeOnTapAreaId) {
    super(closeOnTapAreaId);
  }
 
  private AppNavigator getNavigator() {
    LspsUI ui = (LspsUI) UI.getCurrent();
    return ui.getNavigator();
  }
 
  @Override
  protected NavigationMenu createMenu() {
    NavigationMenu navigationMenu = new NavigationMenu(createUserMenu());
 
    LspsUI ui = (LspsUI) UI.getCurrent();
    UserInfo user = ui.getUser();
 
    if (user.hasRight(HumanRights.READ_ALL_TODO) || user.hasRight(HumanRights.READ_OWN_TODO)) {
      addTodoListMenuItem(navigationMenu);
    }
    if (hasRightToOpenDocument("raising::raiseTicketDoc")) {
      navigationMenu.addDocumentItem("New Ticket", "raising::raiseTicketDoc", null, VaadinIcons.AMBULANCE, null);
    }
    if (hasRightToOpenDocument("list::ticketListDoc")) {
      navigationMenu.addDocumentItem("My Tickets", "list::ticketListDoc", null, VaadinIcons.CLIPBOARD_CHECK, null);
    }
 
    return navigationMenu;
  }
}

Tips and Tweaks

  • You can now access the document directly from the navigation menu, but the menu items contain the ??? characters: these signalize that the system failed to find the localization string. Let's create the string:
    1. Instead of String literals for the navigation item labels, use a localization key name:
      ...
          if (hasRightToOpenDocument("raising::raiseTicketDoc")) {
            navigationMenu.addDocumentItem("nav.newticket", "raising::raiseTicketDoc", null, VaadinIcons.AMBULANCE, null);
          }
          if (hasRightToOpenDocument("list::raiseTicketDoc")) {
            navigationMenu.addDocumentItem("nav.usertickets", "list::ticketListDoc", null, VaadinIcons.CLIPBOARD_CHECK, null);
          }...
    2. Open properties file in the com.whitestein.lsps.vaadin.webapp package (<YOUR_APP>-vaadin project), for example, the localization.properties file with the default localizations.
    3. Add the localization keys with their values:
      # navigation menu items
      nav.todoitems = To-do List
      nav.documents = Documents
      nav.runProcess = Run Model
      # These are new keys:
      nav.newticket = New Ticket
      nav.usertickets = My Tickets
  • Run the embedded server preferably in debug mode so your changes can be applied on the fly when possible.
  • To delete the server database, stop the server remove the h2 directory in the embedded project.
    ticket-resolving-tweaks-deleting-database.png

Changing Application Colors

User story: The Application User Interface follows the black-and-white color schema.

You can switch between the available style themes on the Settings page: click Settings in your profile menu to navigate to the page. By default the lsps-valo is used. You will use this theme as base for a customized theme; you can pick the dark or blue theme if it is closer to the look you want to achieve.

  1. Back in Designer, first set up your theme:
    1. Create a copy of the lsps-valo theme in the vaadin-war project.
      ticket-theme-copy.png
    2. In style.scss in the theme directory, change the theme class name to the name of the theme directory.
        .ticketapp {
        @include addons;
        @include lsps-valo-base;
        @include theme-app;
         }
    3. In ticketapp-vaadin, go to org.acme.ticketapp.core.AppUIProvider and add the getThemeManager() method:
      @Override
        protected ThemeManager getThemeManager() {
          ImmutableSet<String> themes = ImmutableSet.of("lsps-dark", "lsps-valo", "lsps-blue", "ticketapp");
          return new ThemeManager("ticketapp", themes);
        }
    4. Rebuild the application and restart the sdk embedded server.
    5. Go to localhost:8080/lsps-application and log in to make sure that the theme has been loaded successfully.
  2. Set up a sass compiler configuration, so you can easily preview the changes of the theme:
    1. Go to Run > Run Configurations.
    2. In the left pane, select Java Application and click the New button in the caption area of the pane.
    3. On the right, define the following:
      • Name: a name of the configuration
      • Project: <YOUR_APP>-vaadin-war
      • Main class: com.vaadin.sass.SassCompiler
    4. Switch to the Arguments tab and define the input scss file and output css file as input Program arguments: the output css file must be located in the theme directory of the target directory and have the name styles.css:
      src/main/webapp/VAADIN/themes/ticketapp/styles.scss
      src/main/webapp/VAADIN/themes/ticketapp/styles.css
  3. Set the productionMode parameter in ticketapp-vaadin-war/src/main/webapp/WEB-INF/web.xml to false.
  4. In ticketapp-vaadin-war/src/main/webapp/VAADIN/themes/ticketapp/sass/_variables.scss, edit or add the theme properties:
    
    $valo-menu-background-color:  hsl(210, 0%, 98%);
    $v-background-color: hsl(210, 0%, 98%);
    $v-focus-color: #adadad;
    
  5. Run the Sass compiler configuration.
  6. Run the embedded server in debug.

Customizing the Login Page

User story: Login and logout pages follow the style.

  1. Open ticketapp-vaadin-war/src/main/webapp/login.jsp.
  2. Change the title to <title>Trouble Ticket Application</title>.
  3. In ticketapp-vaadin-war/src/main/webapp/VAADIN/themes/ticketapp/sass, create *_login.scss* with the rules for the login page:
    @mixin _login {
        &.login-page #loginHeader {
           background-color: white !important;
           background-image: url("../img/logo_splash.png") !important;
           background-position: center bottom;
           background-repeat: no-repeat;
           background-size: 300px auto;
        }
        &.login-page form table {
           background-color: white;
           background-image: none;
        }
        &.login-page input{
           border: 1px solid #c9c9c9;;
        }
        &.login-page .v-button .v-button-caption {
           color: #c9c9c9 !important;
        }
    }
  4. Import the mixin in styles.scss and include it in your theme:
    @import "sass/_variables";
    //added:
    @import "sass/_login";
    ...
    .ticketapp {
      @include addons;
      @include lsps-valo-base;
      @include theme-app;
      //added:
      @include _login;
    }
    
  5. Run Sass compiler and check the login page in your browser.

Removing the Logo from the Top Bar

To remove logo located in the upper-left corner, you need to remove TopBanner from NavigationMenu:

  1. In the core package in ticketapp-vaadin, create AppNavigationMenu that extends NavigationMenu.
  2. Override createTopBanner() method.
     public class AppNavigationMenu extends NavigationMenu {
     
      public AppNavigationMenu(Component userSubmenu) {
        super(userSubmenu);
      }
     
      //this removes the logo slot:
      @Override
      protected Component createTopBanner() {
        return null;
      }
    }
  3. Make AppMainMenu use AppNavigationMenu instead of the default NavigationMenu:
    ...
      @Override
      protected NavigationMenu createMenu() {
        //changed NavigationMenu to AppNavigationMenu:
        NavigationMenu navigationMenu = new AppNavigationMenu(createUserMenu());
    
  4. Rebuild the application and restart the server.

Exporting a Ticket to PDF

User story: Users can export the details of a ticket to a PDF from ticket details.

There is no support for PDF export out-of-the-box: You will use the Apache pdfbox to implement a custom function for PDF-export.

  1. Add the pdfbox dependency to your ejb project:
    1. In a text editor, add the dependency to the root pom.xml in <WORKSPACE>/ticketappfile
      ...
            <dependency>
              <groupId>com.whitestein.lsps.monitoring</groupId>
              <artifactId>lsps-monitoring-client</artifactId>
              <version>${lsps.version}</version>
            </dependency>
            <!-- Added: -->
            <dependency>
              <groupId>org.apache.pdfbox</groupId>
              <artifactId>pdfbox</artifactId>
              <version>2.0.12</version>
            </dependency>
      
    2. In the pom.xml in ticketapp-ejb, add the pdfbox dependency:
      ...
              <artifactId>lsps-os-exec</artifactId>
              <scope>provided</scope>
            </dependency>
            <!-- Added: -->
            <dependency>
              <groupId>org.apache.pdfbox</groupId>
              <artifactId>pdfbox</artifactId>
            </dependency>
      ...
      
    3. Run maven build.
  2. In the common module, create a function definition file with the definition of the exportTicketToPdf() function:
    public void exportTicketToPdf(Ticket t)
      native org.acme.ticketapp.pdf.PdfExporter.exportTicketToPdf;
  3. In the ticketapp-ejb project, create the org.acme.ticketapp.pdf package
    1. Create the PdfExporter class.
    2. Implement the exportTicketToPdf(ExecutionContext ctx, RecordHolder ticket) method.

      Example demo implementation of the PdfExporter class:

      public class PdfExporter {
       
        private PDPage myPage = new PDPage();
        private PDDocument doc = new PDDocument();
        private PDPageContentStream content;
       
        public void exportTicketToPdf(ExecutionContext ctx, RecordHolder ticket) {
       
          SetHolder coms = (SetHolder) ticket.getProperty("comments");
       
          String title = ticket.getProperty("id") +
              (String) ticket.getProperty("subject") +
              ticket.getProperty("created");
       
          try {
            content = new PDPageContentStream(doc, myPage);
            doc.addPage(myPage);
       
            content.setFont(PDType1Font.TIMES_ROMAN, 12);
            content.setLeading(14.5f);
       
            printTitle(title);
            printComments(coms);
       
            content.close();
       
            doc.save("ticket.pdf");
            doc.close();
       
            Desktop.getDesktop().open(new File("ticket.pdf"));
          } catch (IOException e) {
            throw new RuntimeException("PDF export failed", e);
          }
       
        }
       
        private void printTitle(String title) throws IOException {
          content.beginText();
          content.newLineAtOffset(25, 700);
          content.showText(title);
          content.endText();
        }
       
        private void printComments(SetHolder comments) throws IOException {
       
          int y = 680;
          for (Object commentRecordHolder : comments) {
            String commentText = (String) ((RecordHolder) commentRecordHolder).getProperty("text");
            Date commentDate = (Date) ((RecordHolder) commentRecordHolder).getProperty("created");
            RecordHolder author = (RecordHolder) ((RecordHolder) commentRecordHolder).getProperty("createdBy");
       
            content.beginText();
            content.newLine();
            content.newLineAtOffset(25, y);
            content.showText(commentText + " on " + commentDate + " by " + author.getProperty("name"));
            content.endText();
       
            y -= 20;
          }
        }
      }
      

      Note the following:

      • The com.whitestein.lsps.engine.lang.ExecutionContext parameter is passed automatically and gives you access to such data as the current namespace, model instance, module variables, etc.
      • To acquire related records, we are using the getProperty() call.
      • Records are reflected as RecordHolder objects, sets as SetHolder object, etc.
  4. In ProcessTicketForm, add the Export button that calls the function.
    ticket-pdfexport-form.png
  5. Rebuild the application.
  6. Restart the SDK Embedded Server.
  7. Upload the process model.
  8. Test the PDF export.

Relevant Documentation

Further information and instructions on how to customize LSPS Application are available in the Development Guide and in Javadoc.

What to do next?

Consider taking a look at tutorials.