This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information

Category: Development

JVx 2.1 is in da house

Happy birthday :) JVx is 2.1

It's another great release today and ~ 6 month after 2.0. We have soo many cool features for you and of course some bugfixes.
The complete changelog is available on our sourceforge project site.

I want to highlight some features for you

  • Configuration via JNDI or Classpath

    It's now possible to have custom configuration files without our recommended directory structure. We still recommend our structure for multi-application deployments, but it's not important for single deployments or complex enterprise deployments. Find more details about loading strategy in the corresponding ticket #1126.

  • Server-side plugin support

    We introduced IServerPlugin. It allows adding plugins and changing server handling on demand. It's easy to write custom protocol recorder or configure session management via plugin.

  • ServerContext and HttpContext

    We introduced HttpContext and ServerContext. The HttpContext allows live access to servlet request and response (if an application server is in use). It makes no difference if you use REST or standard communication. We set the right instances into the context and your application will work without specific technology checks. We also use HttpContext for JVx.mobile.

    The ServerContext is comparable with SessionContext, but it's earlier in the execution process, because it offers access to sessions directly after creation or detection. It's useful for e.g. plugins.

  • Tab/Focus Index

    We introduced set/getTabIndex in IComponent. This API change allows user-defined component navigation via tabulator or Enter key.

  • CommunicationException details

    It's now possible to find out the connection which throwed a CommunicationException.

  • Alignment for IEditor (API change)

    It's now possible to set the alignment on IEditors instead of the cell editors. Small but very useful API change.

  • Autolink with storages

    It's now possible to create automatic link references with other storage. We had this feature already in 2.0 but only for simple storages without conditions - only from clause was used. Now it's possible to configure custom storages with user-defined sort in the same LCO and set this storages as automatic link reference to other storages in the same LCO.

  • Server side bean processing boost

    We change and improved server side bean handling of our AbstractStorage. Here are some numbers for you:

    ....................... Before | After

    Insert Object[] ... Beans: 200 |   0
    Update Bean ....... Beans: 900 | 200
    Update T .......... Beans: 900 | 400
    Fetch Bean ........ Beans: 600 | 200
    Fetch Object[] .... Beans: 300 |   0
    Update Object[] ... Beans: 500 |   0
    Insert Bean ....... Beans: 400 | 100
    Delete Object[] ... Beans: 300 |   0
    Delete Bean ....... Beans: 600 | 200
    Delete T .......... Beans: 600 | 300
    Insert T .......... Beans: 400 | 200

    Created Beans after processing 100 records.
    The current solution is a performance boost and using Object[] is always faster than everything else.

  • Lazy blob loading

    We don't load Blobs immediate. We load it on request. This doesn't need any actions on client side but be aware of server-side handling because the value of a blob column will be RemoteFileHandle instead of byte[]. You should run your unit tests for your business logic. It's possible to disable lazy fetching, per storage with

    setLazyFetchEnabled(boolean);

    It's also possible to define the threshold for loading immediate or loading lazy. Check

    setLargeObjectLimit
    setDefaultLargeObjectLimit

    of DBAccess.

    This is an awesome new feature because is speeds up data transfer.

  • Custom UI properties

    UIResource got:

    public Object getObject(String pObjectName)
    public Object putObject(String pObjectName, Object pObject)

    It's possible to add custom objects per UI instance, e.g. save custom states.

  • REST services refactored

    We refactored our REST services. The implementation now works without problems and is easier to use becasue we don't need full qualified java names in the URL. We try to find the class via accesscontroller. The accesscontroller got a new method for this.

  • Unique component names

    For all lovers of automated UI tests. We have unique names for all our components. It's easy to create GUI tests with tools like Selenium (web tests) or FEST (swing tests) or whatever you use :)

We have about 107 tickets in this release and it's not possible to explain every change in this blog posting, but be sure - it's great!

The Maven archetype should be available in the next few days, because sonatype archetype listings are not live.

VaadinUI 1.2 released

Our VaadinUI 1.2 is available!
It's a feature release with some bugfixes.

The biggest change was the update to vaadin 7.1.15 and we've already 7.3.3 in our development branch (welcome Valo theme).

What's new?

  • Download extension

    Download dynamic content on-demand or whenever you want via WebSockets. More information and an example project for this extension.

  • Configuration of preserveOnUIRefresh

    Simply use preserveOnRefresh as init-param (true | false) in your web.xml or as URL parameter to preserve the application on browser refresh.

  • Use external CSS

    Use an external CSS file to configure your application style. There's no need to change genereated styles.css for simple tasks. Simply configure the init-param externalCss, e.g.

    <init-param>
      <param-name>externalCss</param-name>
      <param-value>../demoapp.css</param-value>
    </init-param>

    Place the demoapp.css in the root directory of your application (not application server ROOT).

    The css will be placed at the end of the stylesheet links in the generated index.html page.

  • Mobile check

    We check if the UI is running on mobile browsers and set parameters for your application: Web.mobile (= VaadinUI.PROP_MOBILE) and Web.mobile.tablet(only for iPad at the moment) (= VaadinUI.PROP_TABLET). Simply check the parameter in your application.

  • Cache for dynamic images

    If you use images from your classpath, vaadin generates internal URLs for you. This URLs are different per image and the browser cache doesn't work. This handling produces unnecessary requests. We solved the problem with an image cache on server side and custom Image resources. With this changes, the browser cache works as expected.

  • IDs for menu items

    We have an experimental solution for setting IDs on menu items. It's experimental because it's possible that vaadin implements support for that. In that case we won't need our solution anymore. But till then, it works. More information...

  • Responsive support

    It's now possible to register a resize event on the application launcher. Use this event to change your application on-demand. We have some impressions for you.

  • Self-contained packages for Portlets

    We have built-in support for self-contained portlets. It's possible to toggle between global and self-contained mode. Simply set the init-param vaadin.shared (true | false) in your web.xml to use vaadin shared from your application server or the self-contained vaadin.

    General information about self-contained packages.

  • invokeLater and WebSockets

    We've completely changed our invokeLater mechanism because it didn't work in previous versions.

Please check the changelog for a complete list.

toPDF update

Some time ago, I wrote about toPDF. It's a simple web application that allows office format to PDF conversion using PDFCreator. It's open source and allows synchronuous conversion via http post requests or REST calls.

We made some changes in toPDF that makes it possible to use different converter tools/SDKs. It's now possible to use PDFCreator or easyPDF SDK. The first solution is OpenSource and the last is commercial. I prefer the commercial SDK because it has a lot of useful features, offers a Java bridge and works super fast in server environments. The OpenSource solution also works, but needs some tinkering.

Anyway, the toPDF application supports both and it's easy to integrate other converter. Simply implement the interface

public interface IPdfOperator
{
    public void convert(File pDocument, File pPdf, PdfSettings pSettings) throws Exception;
}

Set the context parameter: operatorClass in your web.xml, e.g.

<context-param>
  <description>PDF operator</description>
       
  <param-name>operatorClass</param-name>
  <param-value>com.sibvisions.topdf.operator.pdfforge.PdfCreatorOperator</param-value>
</context-param>

The default operator is com.sibvisions.topdf.operator.bcl.EasyPdfOperator.

Responsive Web Design

Hurray, we have a new buzzword: Responsive.

It's not brand new, but nowadays it's important because we use applications on different devices and the same application should work on different screen sizes/resolutions.

What does responsive mean?

Wikipedia:

Responsive web design (RWD) is a web design approach aimed at crafting sites to provide an optimal viewing experience—easy reading and navigation with a minimum of resizing, panning, and scrolling—across a wide range of devices (from mobile phones to desktop computer monitors).

My opinion:

Don't waste space for unnecessary information.

If you have big menus and toolbars in your application, you should reduce the used space dependent of the available space.

We did some experiments with our vaadin UI and have some impressions for you:

App full space

App full space

 
App with limited space

App with limited space

The application on the right has a small menu without additional text and with small padding. All gaps are smaller than in the orginal application on the left.

We used custom css and source code to change the UI because not everything was possible with CSS e.g. set tooltips instead of button text. A set of instructions was posted from Matti Tahvonen.

We made some smaller changes in our Vaadin UI to support technology independent handling of resize changes.

It will be possible to do following:

launcher.eventComponentResized().addListener(this, "doLauncherResized");

...

public void doLauncherResized(UIComponentEvent pEvent)
{
    IDimension dim = ((ILauncher)pEvent.getSource()).getSize();
   
    if (dim != null)
    {
        int iWidth = dim.getWidth();
       
        if (iWidth < 800)
        {
            layoutMode = LayoutMode.Small;
        }
        else
        {
            layoutMode = LayoutMode.Full;
        }

        resizeMenu();
    }
}

One application, different styles

Impressions

The first image shows the legacy mode of our standard application style (check last image). It turns a SDI application to MDI - without coding or re-deployment. Simply awesome :)

The second image doesn't use a toolbar and the third one is without a menubar. Not all applications need multiple navigation elements, known from desktop applications.

The fourth image shows, what we prefer.

Legacy mode (MDI)

Legacy mode (MDI)

 
Legacy mode (no toolbar)

Legacy mode (no toolbar)

Legacy mode (no menubar)

Legacy mode (no menubar)

Modern mode (SDI with popups)

Modern mode (SDI with popups)

One more ;-)

Modern style (menu right)

Modern style (menu right)

[Update]

The same application with Swing UI

Swing UI

Swing UI

Add IDs to your Vaadin Menu items

It's a shame :) but Vaadin doesn't have built-in support for setting an ID on menu items. There are several tickets about this problem: http://dev.vaadin.com/ticket/3873, http://dev.vaadin.com/ticket/11307, http://dev.vaadin.com/ticket/14294

BTW, the whole menu solution is a little bit tricky and wrapped.

There are no excuses - a web technology should fully support web concepts. We tried to touch menu items, by ID, during our UI test automation efforts. It wasn't a problem to find an xpath for accessing menu items, but... it's a principle thing.

It was a nice task to implement ID support for menu items. We found a "general" solution - it's still a workaround, but as long as vaadin doesn't support it, it might help you.

Summarized

Extend server-side MenuBar and add a map for menuitem ids. Send the map to the client and add the id to the matching menu item. The client-side needs an extended VMenuBar and an extended MenuBarConnector.

We've used MenuBar for caching ids because it wasn't possible to extend menu item handling and MenuBar already has a connector.

An example

Menuitem IDs

Menuitem IDs

Details

The implementation is available in our Vaadin UI implementation. Simply use following classes:

MenuBar
VMenuBar
MenuBarConnector

And don't forget the replacement mappings for your widgetset before you start the compiler:

Widgetset replacements

The solution was built with vaadin 7.1 but we checked the implementation in 7.3.0 and it didn't change. So our workaround should work without problems.

We didn't need a lot LoC to solve the problem and it should be easy for you to understand what we did. If you want to know more details - simply ask.

Usage

A short code snippet:

MenuBar bar = new MenuBar();

MenuItem miInsert = bar.addItem("Insert");
MenuItem miUpdate = bar.addItem("Update");

bar.setId(miInsert, "mi_insert");
bar.setId(miUpdate, "mi_update");

As written before, it's not possible to set the ID on the item because of original implementation in vaadin. Don't use getId of menu item because this will return the "internal" id.

Keep coding :)

Next big feature - Automate your GUI Tests

It's not a problem to automate GUI tests, nowadays. There are different approaches and tools. A nice tool overview is available on wikipedia.

The tools have different techniques to perform tests. On technique is sending/simulating mouse clicks to components. The problem is that the GUI shouldn't be changed between tests and you should use a special test environment/system. Another technique is tricky but there's a nice implementation from MIT. It works with image recognition. And finally there's a solution based on unique component identifiers.

We like the last technique, based on unique component identifiers because it allows changing the UI without changing test cases - we love flexibility. The only problem with JVx was that we didn't have unique identifiers and a developer won't set an identifier for every component. We didn't have a mechanism to create unique identifiers... BUT now... we have.

With upcoming JVx releases, it will be possible to test GUIs automatically based on unique identifiers. This identifiers will be available also for VaadinUI. Another advantage for VaadinUIs will be that the id could be used for styling via CSS.

There are still some todos for us but we're happy to be able to show you some examples.

We made some test-cases with different test tools. To test our VaadinUI, we use Selenium together with PhantomJS.

The source code might look like this one:

public class TestCaseB
{
    private static final int TIMEOUT_IN_SECONDS = 10;
   
    private static final String TIMEOUT_IN_MILLISECONDS_AS_STRING =
                        Integer.toString(TIMEOUT_IN_SECONDS * 1000);

    private WebDriver driver;
    private Selenium selenium;
   
    @Before
    public void setUp()
    {
        driver = configureDriver(createPhantomJsDriver());
       
        String baseUrl = "http://localhost:8080/";
       
        selenium = new WebDriverBackedSelenium(driver, baseUrl);
        selenium.setTimeout(TIMEOUT_IN_MILLISECONDS_AS_STRING);
    }
   
    @Test
    public void testDemoerptest()
    {
        selenium.open("/VisionX.Server/app/web/ui/DemoERP/");
        waitForPage();
       
        selenium.type("id=UserName", "admin");
        selenium.type("id=Password", "admin");
        selenium.click("id=OK");
        waitForPage();
       
        selenium.click("id=DemoERP_P1_P1_P2_B1");
        waitForPage();
        selenium.click(
          "//div[@id='NavigationTable']/div[2]/div/table/tbody/tr[2]/td[2]/div");
        selenium.click(
          "//div[@id='NavigationTable']/div[2]/div/table/tbody/tr[3]/td[2]/div");
        selenium.click(
          "//div[@id='NavigationTable']/div[2]/div/table/tbody/tr[2]/td[2]/div");
        selenium.click(
          "//div[@id='NavigationTable']/div[2]/div/table/tbody/tr/td[2]/div");
       
        selenium.click("id=DemoERP_P1_P1_P2_B2");
        waitForPage();
        selenium.click(
          "//div[@id='NavigationTable']/div[2]/div/table/tbody/tr[2]/td/div");
        selenium.click(
          "//div[@id='NavigationTable']/div[2]/div/table/tbody/tr[3]/td/div");
        selenium.click(
          "//div[@id='NavigationTable']/div[2]/div/table/tbody/tr[4]/td/div");
       
        selenium.click("id=DemoERP_P1_P1_P2_B3");
        waitForPage();
       
        selenium.click("xpath=(//button[@type='button'])[7]");
        waitForPage();
    }
   
    @After
    public void tearDown()
    {
        driver.quit();
        selenium.stop();
    }
   
    private WebDriver configureDriver(WebDriver pWebDriver)
    {
        pWebDriver.manage().timeouts().implicitlyWait(TIMEOUT_IN_SECONDS,
                                                      TimeUnit.SECONDS);
        pWebDriver.manage().timeouts().pageLoadTimeout(TIMEOUT_IN_SECONDS,
                                                       TimeUnit.SECONDS);
        pWebDriver.manage().timeouts().setScriptTimeout(TIMEOUT_IN_SECONDS,
                                                        TimeUnit.SECONDS);
        pWebDriver.manage().window().setSize(new Dimension(1920, 1080));
       
        return pWebDriver;
    }
   
    @SuppressWarnings("unused")
    private WebDriver createChromeDriver()
    {
        ChromeOptions options = new ChromeOptions();
        options.addArguments("-incognito");
       
        return new ChromeDriver(options);
    }
   
    private WebDriver createPhantomJsDriver()
    {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability(
                 PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY,
                 "D:\\opt\\phantomjs\\phantomjs.exe");
       
        return new PhantomJSDriver(capabilities);
    }
   
    private void waitForPage()
    {
        selenium.waitForPageToLoad(TIMEOUT_IN_MILLISECONDS_AS_STRING);
    }
}

We use FEST (doc) for Swing UIs. The library is old (like Swing) but still works!

A very simple example with FEST:

public class TestUI extends FestSwingTestCaseTemplate
{
    private FrameFixture window;
   
    @After
    public void cleanItUp()
    {
        super.cleanUp();
    }
   
    @Before
    public void setUp()
    {
        super.setUpRobot();
       
        UIFactoryManager.getFactoryInstance(SwingFactory.class);
       
        WorkScreenCreatingGuiQuery query = new WorkScreenCreatingGuiQuery();
        Frame frame = GuiActionRunner.execute(query);
       
        window = new FrameFixture(robot(), frame);
        window.show();
       
        query.afterShow();
    }
   
    @Test
    public void testTheUIStuff()
    {
        // Check if the editor does have the correct value.
        // The WorkScreen does select the first line for us.
        Assert.assertEquals("John Smith",
                            window.textBox("UITWS_E_TESTDATABOOK_NAME").text());
       
        // Select the next line in the table.
        window.table("UITWS_T_TESTDATABOOK").selectRows(1);
        Assert.assertEquals("Ian McIrish",
                            window.textBox("UITWS_E_TESTDATABOOK_NAME").text());
       
        // Select the tab that has that TextField-Button-Label combo on it.
        window.tabbedPane("UITWS_TP1").selectTab(1);
        window.tabbedPane("UITWS_TP1_P2_TP1").selectTab(2);
       
        // Enter something into the textfield, press the button and the label
        // should now have the same text.
        window.textBox("UITWS_TP1_P2_TP1_P3_P1_TF1").setText("This is an automated test.");
        window.button("UITWS_TP1_P2_TP1_P3_P1_B1").click();
        Assert.assertEquals("This is an automated test.",
                            window.label("UITWS_TP1_P2_TP1_P3_P1_L2").text());
    }
   
    private static final class WorkScreenCreatingGuiQuery extends GuiQuery<Frame>
    {
        private UIFrame frame;
       
        private WorkScreen workscreen;
       
        void afterShow()
        {
            // Important so that everything gets a name.
            // There is a window constructed, but outside of the JVx scope.
            frame.addNotify();
            workscreen.notifyRepaint();
        }
       
        @Override
        protected Frame executeInEDT() throws Throwable
        {
            frame = new UIFrame();
            workscreen = new UITestingWorkScreen();
           
            frame.add(workscreen);
           
            return (Frame) frame.getResource();
        }
       
        private String dumpStructure()
        {
            return dumpStructure(frame, 1);
        }
    }
}

Eclipse Plugin - EPlug

Our first Eclipse Plugin for JVx and VisionX will be available in a few weeks. We're feature complete and are in the internal test phase. We're extremely surprised about the productivity boost. With VisionX it's currently possible to create and deploy professional database applications in few minutes. The development process is super fast because of VisionX and some really useful features like Action wizard and GUI designer. The missing piece was the IDE integration. It was possible to use Eclipse as IDE to modify VisionX applications, live and bidirectional. The only problem was that it was not easy to find the right line of code or member to do modifications. It wasn't a big problem but it was a waste of time.

Our Plugin helps to save development time, again. The combination of VisionX with EPlug is awesome.

The name of the Plugin is EPlug (not very creative but simple). It will be available in different editions: Lite, Pro and VisionX.

The Lite edition will be free and doesn't offer full power but will be useful.
The Pro edition won't have any limits but won't interact with VisionX.
The VisionX edition adds interaction to Pro edition. It will be possible to use VisionX to jump to Source Code in Eclipse and to show changes directly in VisionX (means live live).

I've an amazing feature for you as screenshot:

Preview image (hover)

Preview image (hover)

 
Preview image (completion)

Preview image (completion)

Really useful :)

New application frame feature - No menu

All our applications have a menu and a toolbar. This is great for backend applications but not always good for web frontends. Our web UIs have a different menubar, styled for web, but it's always visible. If you have simple web forms, you won't use a menu. We did some changes and have new options for applications without menu and toolbar :)

Some impressions with standard (backend) Desktop application and as (frontend) web application:

Backend application (Swing)

Backend application

 
Frontend application (Vaadin)

Frontend application

It's very simple to hide the menu. Simply set an application property via application.xml or directly via launcher - that's it. We changed our web menu and allow access to internal panels and components. It will be possible to hide buttons, change layouts, etc.

It's still possible to create your own, custom, application frame or extend our pre-defined frame. The new feature will be available in the next VisionX update.

Popup menu feature

We have another useful VisionX feature for you in the queue. It's the support for popup menus. It'll be possible to create and use popup menus for UI components. We had to change JVx to support this feature. It's now easily possible to work with popups because UIComponent got a new method: setPopupMenu(IPopupMenu).

The feature will be easy to use for end-users because it's not rocket science and we re-used existing VisionX concepts. Here's a first screenshot:

Popup menu integration

Popup menu integration