Posts tagged: VisionX

Simple Drop File Support for JVx applications

Post to Twitter

Our next update release of VisionX will support Dropping files. It's a very useful feature and was easy to implement. Sure, it's a Swing specific feature, but our VisionX is more or less JVx Swing UI based.

Get a first impression

VisionX Drop file support

We drop an exported application archive into VisionX and the import wizard is starting. It's also possible to Drop a file directly into the import wizard.

VisionX is a JVx application and it's super easy to implement such feature for your own JVx application. Here's a code snippet how it'll work:

public SimpleFileDropHandler addTarget(IComponent pTarget, IFileHandleReceiver pListener,
                                       String... pExtension)
{
    Object oResource = pTarget.getResource();
   
    if (!(oResource instanceof JComponent) && !(oResource instanceof JFrame))
    {
        throw new IllegalArgumentException("Given object can't be a drop target!");
    }
   
    SimpleFileDropHandler handler = new SimpleFileDropHandler(pListener, pExtension);
   
    if (oResource instanceof JFrame)
    {
        ((JFrame)oResource).setTransferHandler(handler);
    }
    else
    {
        JComponent jcomp = getComponent((JComponent)oResource);
       
        if (jcomp != null)
        {
            jcomp.setTransferHandler(handler);
        }
    }
}

private JComponent getComponent(JComponent pComponent)
{
    if (pComponent instanceof JVxEditor)
    {
        JComponent comp = ((JVxEditor)pComponent).
                          getCellEditorHandler().getCellEditorComponent();
       
        if (comp instanceof JScrollPane)
        {
            Component cView = ((JScrollPane)comp).getViewport().getView();
           
            if (cView instanceof JComponent)
            {
                return ((JComponent)cView);                    
            }
            else
            {
                return null;
            }
        }
        else
        {
            return comp;
        }
    }
    else
    {
        return pComponent;
    }        
}

In principle, we set the TransferHandler for a JComponent. Above code detects the right JComponent because there's a difference if you use an IEditor.

The TransferHandler could be implemented like our SimpleFileDropHandler

public class SimpleFileDropHandler extends TransferHandler
{
    private IFileHandleReceiver listener;
   
    private String[] extensions;
       
    public SimpleFileDropHandler(IFileHandleReceiver pListener, String... pExtension)
    {
        listener = pListener;
        extensions = pExtension;
    }
   
    @Override
    public boolean canImport(TransferHandler.TransferSupport pSupport)
    {
        if (!pSupport.isDrop())
        {
            return false;
        }

        if (!pSupport.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
        {
            return false;
        }

        boolean copySupported = (COPY & pSupport.getSourceDropActions()) == COPY;
       
        if (copySupported)
        {
            pSupport.setDropAction(TransferHandler.COPY);
            return true;
        }            
       
        return false;
    }
   
    @Override
    public boolean importData(TransferHandler.TransferSupport support)
    {
        if (!support.isDrop())
        {
            return false;
        }

        List<File> files;
        try
        {
            files = (List<File>)support.getTransferable().
                    getTransferData(DataFlavor.javaFileListFlavor);
        }
        catch (UnsupportedFlavorException ex)
        {
            // should never happen (or JDK is buggy)
            return false;
        }
        catch (IOException ex)
        {
            // should never happen (or JDK is buggy)
            return false;
        }
       
        if (listener != null)
        {
            for (File file : files)
            {
                try
                {
                    listener.receiveFileHandle(new FileHandle(file));
                }
                catch (Exception e)
                {
                    ExceptionHandler.raise(e);
                }
            }
        }
       
        return true;
    }
}

Have fun ;-)

Smooth Forms 10g, 11i, 12c to Java Migration

Post to Twitter

This is a follow up for Smooth Forms 6i to Java Migration.

The following video demonstrates the integration of a Java screen into a Forms application. Since WebForms, it's possible to embedd Java swing components directly. We did create a compatibility layer to support special mouse features and to fix repaint problems. Our integration layer allows you to integrate a complete Java application, based on JVx.

Smooth Forms 10g, 11i, 12c Java Migration

The application is the standard Summit demo application for Forms. The Java application is very similar to the original application because we want to show how easy a 1:1 migration could be. The application was created with our low code platform VisionX. It offers a modern UI and is based on JVx, the OpenSource Java application framework. The final scene shows the embedded Java screen in Forms. It's super easy and doesn't need additional code. It just works with our compatibility layer.

Smooth Forms 6i to Java Migration

Post to Twitter

Following video demonstrates our Java integration for Forms 6i. In Forms 6i you can't embedd a Java application without complex ActiveX controls. So we chose an alternative for a smooth integration. It's more like an IPC between Forms and Java but with some additional features like automatic window switching.

Our solution is super flexible and it's possible to send custom events from Forms to Java and from Java to Forms. Here's an impression:

Smooth Forms6i Java Migration

Both applications use the same database. The Forms application is like any other Forms application and the Java Application was created with VisionX based on the Open Source Java Application Framework JVx.

VisionX 2.4 is here

Post to Twitter

VisionX 2.4 was released yesterday! It's the biggest update since 1.5. We've spent more time for developing and testing than ever before. The new version has power under the hood. It contains everything which is needed to customize VisionX for your needs. It's possible to create your own VisionX. We have a great set of AddOns which will improve the quality of your applications and some very useful new Features.

What's new?

  • HTML5 Live Reload

    It's now possible to update the application in the browser automatically after design changes. The live preview wizard got a new option for this feature:

    Live reload option

    Live reload option

  • One-click HTML5 live preview

    The application menu got a new icon. A single click is enough to show the application in the web browser.

    One-click live preview

    One-click live preview

  • VisionX Menu

    The VisionX menu in the application has two new items:

    VisionX application menu

    VisionX application menu

    The modules screen is a complete new feature and the Live preview is now available without leaving the application.

  • Module management

    It's now possible to manage application modules. Simply install a module from the solution store or create your own re-usable application modules. The installation is super easy with our new modules screen:

    Super easy module installation

    Super easy module installation

  • Data Links

    The Designer got a new group with the name Data Links:

    Data Links

    Data Links

    All elements in the Data Links group depend on data and will update the shown value automatically on data changes.

    • The Label Control will show the current value of a specific column, as Label instead of an Editor.
    • The Selection Button will show a popup with possible values for a specific column.
    • The Filter Control requires the Profiles AddOn and allows an application user to apply and save custom filter settings, e.g. filter custom columns
  • Application frame automatically saves the last position and your application will be shown at the same position after a restart.

    The Profiles AddOn makes it possible to save also the frames within the application. Your users will love it because they can save their own desktop and continue the work after an application start.

  • Remove HTML5

    It's possible to create smaller application bundles if you remove the HTML5 feature from the bundle, via Deployment Wizard:

    Remove HTML5

    Remove HTML5

  • Customize screen generators

    It's super easy to use your own screen generators:

    Custom screen generators

    Custom screen generators

  • Multiple storages with same database table

    It's now possible to add multiple storages for the same database table. This was a limitation in earlier versions of VisionX.

All customers will find the new version in their download area!

VisionX 2.4 News

Post to Twitter

This is a short announcement of VisionX 2.4. We're near to the finishing line and will release VisionX 2.4 in December. It's an awesome release with a big number of changes and great new features.

VisionX 2.4 is not a real Feature Release but as always, we have great things on board. The focus was on "modularity". This has nothing to do with JDK 9 or Jigsaw! With VisionX 2.4 it'll be super easy to customize VisionX for your needs or to "create your own VisionX". We offer some great new Modules and AddOns.

Some impressions

HTML5 option

Create applications without HTML5

Super easy module installation

Super easy module installation

New components as Data Links

New components as Data Links

Module: User Filter

Module: User Filter

Standard Screen generator wizard

Standard Screen generator wizard

Customized screen generator wizard

Customized screen generator wizard

VisionX will be shipped with Vaadin 7.7 and latest versions of JVx and sub projects.
We offer some great Modules and AddOns like Maintenance management and User Profiles.

With User Profiles, it'll be possible to save the application state per User. This means that the position of screens can be saved as well as divider positions of split panels or it'll be possible to configure visible columns of grids.

This was a very short overview of VisionX 2.4, but I guess you'll like it!

HANA Express and VisionX

Post to Twitter

HANA Express is available for some days. HANA is the In-Memory Database solution of SAP.

What is HANA Express?

SAP HANA, express edition is a streamlined version of SAP HANA that can run on laptops and other resource-constrained hosts, such as a cloud-hosted virtual machine, for free up to 32G of memory use.

reference: https://go.sap.com/developer/topics/sap-hana-express.html

We wrote an article about our HANA experiments in December 2014. We had a test account for the online HANA. Our tests were successful but we weren't convinced from the system because it was slow and had many JDBC driver problems. Our bug reports were never answered.

But we never give up and the Express edition was interesting for us. We thought it might be worth some hours for our R&D team. The result is awesome!

We think that VisionX is the best tool for application development with HANA databases. Your web application is ready in 1 minute without coding!

Some details?

The installation of the Express edition wasn't tricky. The documentation is straight forward. The database is up and running in some minutes.

We had some problems with JDBC driver because it wasn't available as separate download and we didn't find any documentation. But it was part of the HANA plugin for Eclipse. Not that easy, but it was part of a jar file: com.sap.ndb.studio.jdbc_2.3.8.jar.

The next tricky thing was the JDBC connect string: jdbc:sap://hxehost:30013/?currentschema=System. The username was SYSTEM.

With all this information, it was super easy to create an application with VisionX for HANA express. We guess it makes no difference if you use HANA or HANA express.

How it works? Check the video. It's from 2014 but still impressive.

The current JDBC driver works much better than in 2014 and the performance of the database is great - compared to 2014.

If you're interested in more details, write a comment ;-)

Quality check AddOn for VisionX

Post to Twitter

We have a brand new AddOn for you! It's simply awesome.

Imagine you have a large application with many screens and life-cycle objects. The deployent date is tomorrow. All manual tests today were successful. You leave the office and your colleague updates the database and doesn't tell you something about the changes. The deployment could be a destroyment :) without retesting!

Sure, a manual test of application functionality is great and also automatic UI tests are helpful. But both tests need some time and a test tool for automatic UI tests. We had the simple idea that a great improvement would be an automatic screen and life-cycle object test by an ANT task.

You could reduce error sources if it's guaranteed that a screen can be opened at runtime! This means that the object in the life-cycle object will work as well. But it's also possible that you have some database access objects in the life-cycle object, without GUI references, e.g. for Reporting purposes. Such objects can't be found with simple screen open tests.

Our idea was that we could check all database objects from your life-cycle objects automatically and we could start the application in a headless mode to open/close your screens. Both checks could be executed as ANT task before war file creation. Sounds interesting?

We have an AddOn with above features for VisionX.

Here are some screenshots of the build results:

Project view with ANT results

Project view with ANT results

The life-cycle object MasterData contains the DBStorage errorData. The storage uses the write-back table ERRORDATA wich isn't available in the database. The quality check shows:

Found LCO: com.sibvisions.apps.example1.screens.MasterData
        -> masterdata [OK] => [ID, FIRSTNAME, LASTNAME, DOB]
        -> errorData [ERROR: Meta data couldn't load from database! - SELECT * FROM ERRORDATA
           WHERE 1=2]

Only the ANT output:

Quality checks ANT results

Quality checks ANT results

The life-cycle object had an error, but the MasterDataWorkScreen works because errorData wasn't used while opening the screen.

The screens SimpleErrorWorkScreen and ShowErrorWorkScreen can't be opened because initialization failed. The life-cycle objects work without problems!

The checks are fast and can be executed without GUI. The application will be started with headless UI and it acts like any other JVx application with all supported features.

The AddOn is a massive improvement for your quality requirements.

Monitoring AddOn for VisionX

Post to Twitter

Our Monitoring tool for JVx applications is very useful for application maintenance but also for application development. It safes time, problems and costs. The tool itself is a standalone JVx application and it connects to another JVx application which was configured with the monitoring plugin. It's not a hard job to configure a JVx application for monitoring, but it's boring.

We now have a really great VisionX AddOn which does all the boring work for you. It configures your applications for monitoring and makes it possible to monitor your applications during development time. It's very helpful to find bottlenecks or to do tuning before deployment :)

The plugin comes with an additional awesome Feature, which isn't available without the AddOn. It's the maintenance module. This module allows you to switch your application(s) in maintenance mode. You could use the maintenance mode to do manual database updates, config updates or simple health checks.

We have a short demo video which shows how it works:

VisionX Monitoring AddOn

The AddOn will be available in our Solution store, but not for free. The monitoring tool needs a separate license.

VisionX 2.3 Update Release

Post to Twitter

The current update release of VisionX 2.3.235 is available for our customers or as trial.
It's a smaller update release with some nice features:

  • VisionX listener

    It's now possible to get events of VisionX in you custom AddOns or Modules.

  • Guides

    VisionX got Guides (Read more...). The feature is still in a test phase.

  • Synonyms pointing to a view

    The Data Edit wizard supports synonyms pointing to a view. But be careful, because automatic metadata detection is limited in that case.

  • Lib update

    All libs (JVx, ProjX, VaadinApps, ...) were updated to their latest versions.

The rest are fixes for smaller bugs (most are only relevant for developers):

  • Support for BooleanDataType
  • Help creation works if you didn't set a group label
  • Designer view doesn't toggle the width while dragging
  • Better variable naming for DBStorage types

Have fun with VisionX 2.3.235.

Using Oracle JET with VisionX/JVx

Post to Twitter

The shiny new technology from Oracle is JET (Javascript Extension Toolkit). It's a really interesting thing because it bundles relevant technologies like jQuery, jQuery UI, Knockout, Require, Hammer, ...

You don't need know-how for every used technology, only JET is enough. This is a nice and new approach in the JS world. A possible problem with such an approach could be the update of single libraries, but this isn't your problem because Oracle has to maintain the right versions and bugfixes in JET. So it's not our problem :)

I'm not a big fan of Javascript libraries/technologies but from time to time I like to play around with such things and proof the interaction with JVx. Some time ago my new friend was AngularJS.

This time, I tried to work with Oracle JET.

The use-case was trivial: I'd like to visualize a list of contacts as simple table. The contacts are available as REST service. The REST service needs basic authentication.

Foreword: JET has much documentation and some useful examples, but it's inconsistent because the documentation shows different solutions for the same problem and you don't know which is best or recommended. And the examples are sometimes too complex. The start with existing examples is simple but if you start coding, it's not so simple. But this is a documentation problem and has nothing to do with the product itself. I prefer source code to find out how things work and this procedure worked without problems for JET.

Foreword 2: I couldn't find a description for Basic authentication. Not in the forum, not in the documentation and not in different blog posts. But I found many questions regarding Basic authentication. I found a solution for the problem but if someone has a better solution, please add a comment. My solution is more or less not API compliant - but works with JET version 1.1.2 and hopefully with newer versions as well.

Conditions

I've used our VisionX tool and the Contacts demo application for this example because VisionX has an embedded tomcat and REST access is pre-configured. It's not tricky to use any other simple JVx application but it requires more work because you need an application server and a deployed application.

The Trial version of VisionX is a good start. Before I show you the source code, I'll show you the result:

Contacts table

Contacts table

You're right, this isn't rocket science. But it's not hard to add more columns and some css.

What about the source code?

We have one html page, index.html:

<!DOCTYPE html>

<html>
  <head>
    <title>JET with VisionX/JVx</title>
   
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" href="css/images/favicon.ico" type="image/x-icon" />

    <link rel="stylesheet" href="css/libs/oj/v1.1.2/alta/oj-alta-min.css" type="text/css"/>
    <link rel="stylesheet" href="css/demo-alta-patterns-min.css"/>
    <link rel="stylesheet" href="css/override.css" type="text/css"/>

    <script data-main="js/main" src="js/libs/require/require.js"></script>
  </head>
 
  <body>
    <br/>
    <div id="mainContent" class="oj-md-12 oj-col page-padding">
      <div class="demo-page-content-area page-padding">  
        <h1>Contacts via VisionX</h1>
        <br/>
        <table id="table"
          data-bind="ojComponent: {component: 'ojTable',
                                   data: dataSource,
                                   columns: [{headerText: '#',
                                              field: 'ID', sortable: 'enabled'},
                                             {headerText: 'First name',
                                              field: 'FIRSTNAME', sortable: 'enabled'},
                                             {headerText: 'Last name',
                                              field: 'LASTNAME'}]}">

        </table>
      </div>
    </div>    
  </body>
</html>

We need two javascript files, main.js:

requirejs.config({
    paths: {
        'knockout': 'libs/knockout/knockout-3.3.0',
        'jquery': 'libs/jquery/jquery-2.1.3.min',
        'jqueryui-amd': 'libs/jquery/jqueryui-amd-1.11.4.min',
        'promise': 'libs/es6-promise/promise-1.0.0.min',
        'hammerjs': 'libs/hammer/hammer-2.0.4.min',
        'ojdnd': 'libs/dnd-polyfill/dnd-polyfill-1.0.0.min',
        'ojs': 'libs/oj/v1.1.2/min',
        'ojL10n': 'libs/oj/v1.1.2/ojL10n',
        'ojtranslations': 'libs/oj/v1.1.2/resources',
        'signals': 'libs/js-signals/signals.min',
        'text': 'libs/require/text'
    },
    shim: {
        'jquery': {
            exports: ['jQuery', '$']
        },
        'crossroads': {
            deps: ['signals'],
            exports: 'crossroads'
        }
    },
    config: {
        ojL10n: {
            merge: {
                //'ojtranslations/nls/ojtranslations': 'resources/nls/menu'
            }
        }
    }
});

require(['ojs/ojcore',
         'knockout',
         'jquery',
         'app',
         'ojs/ojknockout',
         'ojs/ojknockout-model',
         'ojs/ojdialog',
         'ojs/ojinputtext',
         'ojs/ojinputnumber',
         'ojs/ojbutton',
         'ojs/ojtable',
         'ojs/ojdatacollection-common'],
        function(oj, ko, $, app)
        {
            var vm = new app.contactsVM();
         
            $(document).ready(function()
            {
                ko.applyBindings(vm, document.getElementById('mainContent'));

                //Show the content div after the REST call is completed.
                $('#mainContent').show();
            });
        });

and app.js

define(['ojs/ojcore', 'knockout', 'ojs/ojmodel'],
       function(oj, ko)
       {
           function viewModel()
           {
                var self = this;
                self.serviceURL =
                   'http://localhost/services/rest/vxdemo/ContactsWorkScreen/data/contacts';
                self.dataSource = ko.observable();
                self.ContactsCollection = ko.observable();
               
                self.myBasicAuth = function() {};
                self.myBasicAuth.prototype.getHeader = function ()
                {
                    var headers = {};
                    headers['Authorization'] = 'Basic ' + btoa("admin:admin");
                   
                    return headers;
                };
               
                parseContact = function(response)
                {
                    return {ID: response['ID'],
                            FIRSTNAME: response['FIRSTNAME'],
                            LASTNAME:response['LASTNAME']};
                };

                var Contact = oj.Model.extend(
                {
                    urlRoot: self.serviceURL,
                    parse: parseContact,
                    idAttribute: 'ID'
                });
   
                var myContact = new Contact();
               
                var ContactsCollection = oj.Collection.extend(
                {
                    url: self.serviceURL,
                    model: myContact,
                    oauth: new self.myBasicAuth(),
                    comparator: "ID"
                });
               
                self.ContactsCollection(new ContactsCollection());
               
                //simple Request test
                //self.ContactsCollection().fetch({headers: {"Authorization": 'Basic ' + btoa("admin:admin")}});
               
                self.dataSource(new oj.CollectionTableDataSource(self.ContactsCollection()));      
           }

           return {'contactsVM': viewModel};
        }
    );

Above files are not enough to run the example because you need a full JET application. You can download a JET application from the official site (-> Getting started with Oracle JET -> Downloading Oracle JET). The QuickStart template works well. Unzip the application into the directory: <VisionX_folder>/rad/apps/visionx/WebContent/ojet (ojet must be created manually). Simply copy the example files in the ojet, ojet/js folder.
Open the browser and navigate to: http://localhost/ojet/

My source code is small and simple but I don't know if it could be optimized. The official CRUD example application has more features and doesn't connect to a real REST service.
It wasn't funny to use/read the example because it's much for such a simple use-case. I found a similar but inofficial example. This was nice but didn't solve the Basic authentication problem!

Long story, short:

I found no option for Basic authentication and no documentation, but found that OAuth is supported. Not the same as Basic authentication but something I could search in the source code. The Model file was the right place to search (-> oauth).

And my simple solution for Basic authentication was:

self.myBasicAuth = function() {};
self.myBasicAuth.prototype.getHeader = function ()
{
  var headers = {};
  headers['Authorization'] = 'Basic ' + btoa("admin:admin");
                   
  return headers;
};

Username and password are hardcoded, but it's easy to replace the code with a better solution.

The "authenticator" will be set as oauth property:

var ContactsCollection = oj.Collection.extend(
{
    url: self.serviceURL,
    model: myContact,
    oauth: new self.myBasicAuth(),
    comparator: "ID"
});

The problem with this API is that it's not guaranteed that the getHeader method will be used in future releases. And it's also not perfect to use oauth for Basic authentication, but whatever.

Our example runs with VisionX' embedded tomcat. If you want to test with your own application server, you should enable CORS for VisionX to use the REST services from an external server:

To enable CORS, change the web.xml in <VisionX_folder>/conf/ and add

<init-param>
  <param-name>cors.origin</param-name>
  <param-value>http://localhost:8080</param-value>
</init-param>

to RestletServlet definition.

Example Download