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

JVx Reference, Events

Let's talk about events and event handling in JVx.

What are events...

Events are an important mechanism no matter to what programming language or framework you turn to. It allows us to react on certain actions and "defer" actions until something triggered them. Such triggers can be anything, like a certain condition is hit in another thread, the user clicked a button or another action has finally finished. Long story short, you get notified that something happened, and that you can now do something.

...and why do I need to handle them?

Well, you can't skip events, they are a cornerstone of JVx. Theoretically, you could use JVx without using any of its events, but you would not only miss out on a lot of functionality but also be unable to do anything useful. But don't worry, understanding the event system is easy, using it even easier.

Terminology

For JVx the following terminology applies: An event is a property of an object, you can register listeners on that event which will get invoked if the event is dispatched (fired). Every event consists of the EventHandler class which allows to register, remove and manage the listeners and also dispatches the events, meaning invoking the listeners and notifying them that the event occurred. There is no single underlying listener interface.

Within the JVx framework, every event-property of an object does start with the prefix "event" to make it easily searchable and identifiable. But enough dry talk, let's get started.

Attaching listeners as class

The easiest way to get notified of events is to attach a class (which is implementing the listener interface) to an event as listener, like this:

public class MainFrame extends UIFrame
{
    public MainFrame()
    {
        super();
       
        UIButton button = new UIButton("Click me!");
        button.eventAction().addListener(new ActionListener());
       
        setLayout(new UIBorderLayout());
        add(button, UIBorderLayout.CENTER);
    }
}

private static final class ActionListener implements IActionListener
{
    public void action(UIActionEvent pActionEvent) throws Throwable
    {
        System.out.println("Button clicked!");
    }
}

Attaching listeners as inlined class

Of course we can inline this listener class:

public class MainFrame extends UIFrame
{
    public MainFrame()
    {
        super();
       
        UIButton button = new UIButton("Click me!");
        button.eventAction().addListener(new IActionListener()
        {
            public void action(UIActionEvent pActionEvent) throws Throwable
            {
                System.out.println("Button clicked!");
            }
        });
       
        setLayout(new UIBorderLayout());
        add(button, UIBorderLayout.CENTER);
    }
}

Attaching listeners JVx style

So far, so normal. But in JVx we have support to attach listeners based on reflection, like this:

public class MainFrame extends UIFrame
{
    public MainFrame()
    {
        super();
       
        UIButton button = new UIButton("Click me!");
        button.eventAction().addListener(this, "doButtonClick");
       
        setLayout(new UIBorderLayout());
        add(button, UIBorderLayout.CENTER);
    }
   
    public void doButtonClick(UIActionEvent pActionEvent) throws Throwable
    {
        System.out.println("Button clicked");
    }
}

What is happening here is that, internally, a listener is created which references the given object and the named method. This allows to easily add and remove listeners from events and keeping the classes clean by allowing to have all related event listeners in one place and without additional class definitions.

Attaching listeners as lambdas

Yet there is more, we can of course attach lambdas to the events as listeners, too:

public class MainFrame extends UIFrame
{
    public MainFrame()
    {
        super();
       
        UIButton button = new UIButton("Click me!");
        button.eventAction().addListener((pActionEvent) -> System.out.println("Button clicked"));
       
        setLayout(new UIBorderLayout());
        add(button, UIBorderLayout.CENTER);
    }
}

Attaching listeners as method references

And last but not least, thanks to the new capabilities of Java 1.8, we can also use method references:

public class MainFrame extends UIFrame
{
    public MainFrame()
    {
        super();
       
        UIButton button = new UIButton("Click me!");
        button.eventAction().addListener(this::doButtonClick);
       
        setLayout(new UIBorderLayout());
        add(button, UIBorderLayout.CENTER);
    }
   
    private void doButtonClick(UIActionEvent pActionEvent) throws Throwable
    {
        System.out.println("Button clicked");
    }
}

Parameters or no parameters? To throw or not to throw?

By default we actually support two different classes of listeners, the specified event/listener interface itself, and (javax.rad.util.)IRunnable. Which means that you can also attach methods which do not have any parameters, like this:

public class MainFrame extends UIFrame
{
    public MainFrame()
    {
        super();
       
        UIButton button = new UIButton("Click me!");
        button.eventAction().addListener(this::doButtonClickNoParameters);
        button.eventAction().addListener(this::doButtonClickWithParameters);
       
        setLayout(new UIBorderLayout());
        add(button, UIBorderLayout.CENTER);
    }
   
    private void doButtonClickNoParameters() throws Throwable
    {
        System.out.println("Button clicked");
    }

    private void doButtonClickWithParameters(UIActionEvent pActionEvent) throws Throwable
    {
        System.out.println("Button clicked");
    }
}

Additionally, all listeners and IRunnable itself do support to throw Throwable, which is then handled inside the EventHandler. So you are very flexible when it comes to what methods you can attach and use as listeners.

Creating your own events

You can, of course, create your own EventHandlers and listeners to create your own events. All you need are two classes, an extension of EventHandler and a listener interface.

public class CustomEvent extends EventHandler
{
    public CustomEvent()
    {
        super(ICustomListener.class);
    }
}

public interface ICustomListener
{
    public void somethingHappened(String pName);
}

And that's it, from here on you can use it:

CustomEvent event = new CustomEvent();
event.addListener((pName) -> System.out.println(pName + " 1"));
event.addListener((pName) -> System.out.println(pName + " 2"));
event.addListener((pName) -> System.out.println(pName + " 3"));

event.dispatchEvent("Adam");

More methods!

You can also use an interface for listeners which has multiple methods, specifying in the constructor which method to invoke:

public class CustomEvent extends EventHandler
{
    public CustomEvent()
    {
        super(ICustomListener.class, "somethingOtherHappened");
    }
}

public interface ICustomListener
{
    public void somethingHappened(String pName);
    public void somethingOtherHappened(String pName, BigDecimal pValue);
    public void nothingHappened();
}

Now every time the event is dispatched, the somethingOtherHappened method will be invoked. Anyway, don't use this. The upside of having a "simple" listener interface with just one method (SAM-type) is that it allows to use lambdas with it. A listener interface with multiple methods won't allow this.

In JVx we reduced our listener interfaces to just one method (in a backward compatible way) to make sure all events can be used with lambdas.

Fire away!

That's it for this short reference sheet, that is how our event system can and should be used. Of course, there is much more to it under the hood, for example listeners being wrapped in proxy classes, reflection used for invoking methods and some more stuff. If you feel adventurous, be my guest and have a good look at the internals of EventHandler, it is quite an interesting read.

pfSense 2.3 + APU2C4 + Temperature

With current pfSense 2.3.2 and APU2C4 it's not possible to read the CPU temperature of. The problem isn't new but it's not solved in official images.

I found a solution for the problem in this forum (Thanks to Stephan).

It wasn't tricky, but if you want the short story:

  1. Download the changed kernel module
  2. Extract the archive and copy the amdtemp.ko file to your box, to /root
  3. Execute following commands:
    kldunload amdtemp
    cp /root/amdtemp.ko /boot/kernel/
    kldload /boot/kernel/amdtemp.ko

After this steps, you'll see the current temperature in the Dashboard view.

HANA Express and VisionX

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 ;-)

EPlug 1.2.5

We're happy to announce the release of EPlug 1.2.5. Even though the change in the version number is quite small, the changes which have gone into this version are very interesting.

Better hover information and improved DataBookView

The biggest visual change in this new version is the new hover information for columns:

New hover information

New hover information

As you can see it has been vastly extended, with nearly all information about the column which you might want to know about, including its type, the label and all other properties.

Also the image preview is now more useful and is displaying the complete image but scaled to fit the hover:

New hover information

Additionally the DataBookView has been restructured to display the information in a more easily digestible way, structured by variable name and source of the columns:

Improved DataBookView

Improved DataBook support

The support for DataBooks/DataRows has been greatly improved and the plugin does now support a lot more variations on how to achieve the metadata. For example cloning of ColumnDefinitions, assigning of RowDefinitions and even getDataRow(...) and similar methods are now processed to acquire the metadata and column information.

Objects in server calls

One of the build-time checks is the type-check of parameters in server calls. Let's look at a simple example:

// Server side
public void serverSideAction(ActionType pActionType, String pLogMessage, BigDecimal pId);

// Client side
getConnection().callAction(
    "serverSideAction",
    ActionType.DO_IT_LATER,
    "Some message which will be logged",
    dataBook.getValue("ID"));

While this compiles completely fine in pure Java (because callAction(...) does accept an Object vararg), EPlug would flag it with an error because getValue(...) returns an Object but the server-side expects a BigDecimal. With this update there is now a build option available in the Project/EPlug settings to ignore such errors, allowing to pass Objects to the server side without checks.

Misspelled a column name? No problem!

We do now offer QuickFixes for column names with typos:

Column name QuickFixes

Automatic check of complement files

There is now a new build option in the Project/EPlug settings which allows to enable the automatic check of complement files. A "complement" file is simply the "other side", for example for the lifecycle-object the complement file is the workscreen, and vice versa. That means that now workscreens are automatically checked if the lifecycle object changes.

Preliminary String array support

There are various functions which do accept a String array of column names, for example getValues(...). Because of limitations coming up from the JDT infrastructure which we are using, we've been unable to provide autocompletion for column names in such circumstances:

dataBook.getValues(new String[] { "|

We are still unable to determine the exact databook in such circumstances, but we do now simply provide all columns as completion suggestions. What we can do is provide full hover and build support for these functions.

Improved VisionX/EPlug communication

VisionX is now a lot more talkative, it informs EPlug about file changes. If "Auto Reload" is enabled in EPlug, all files that have been changed by VisionX will now be reloaded and checked automatically. The same accounts for changed metadata.

Changes

  • Updated JVx version
  • Cached MetaData is now correctly invalidated and refreshed
  • DataBookView is now not constantly refreshed
  • Markers (Errors, Warnings) are now only placed on the names of the columns, instead of the whole statement
  • Inserted methods (from quick fixes) should now always be correctly formed
  • Fixed "phantom" markers which could pop up during build
  • Fixed that the DataBookView might not display all metadata
  • Fixed that folding nodes in the DataBookView made the child-nodes vanish
  • Various bug fixes

Simply update EPlug via Eclipse!

Vaadin 7.7

Vaadin 7.7.0 is out since 2016-08-24 and 7.7.1 since 2016-09-14.

We're happy to announce that our vaadin UI is based on vaadin 7.7.1 since 2016-09-16. Use our nightly builds or checkout the repository.

And the maven snapshots:

<dependency>
    <groupId>com.sibvisions.vaadin</groupId>
    <artifactId>jvxvaadin-client</artifactId>
    <version>1.5-SNAPSHOT</version>
</dependency>

<dependency>
    <groupId>com.sibvisions.vaadin</groupId>
    <artifactId>jvxvaadin-server</artifactId>
    <version>1.5-SNAPSHOT</version>
</dependency>

<dependency>
    <groupId>com.sibvisions.vaadin</groupId>
    <artifactId>jvxvaadin-themes</artifactId>
    <version>1.5-SNAPSHOT</version>
</dependency>

Your feedback is appreciated :)

Quality check AddOn for VisionX

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.

Mavenized everything

We're happy to announce that all our projects are available as Maven artifacts.
Not all of our projects are public and aren't available in public Maven repositories, but we offer our own nexus for all this projects.

Which projects aren't public?

  • Vaadin Charts UI
  • Vaadin responsive application frame
  • Application client
  • Application server
  • Application Services
  • JavaFX mobile UI
  • Oracle Forms extension

We provide snapshot and release artifacts. All other - public - projects are available via maven central as release or snapshot artifacts.

  • JVx
  • JVx EE
  • Vaadin UI
  • JavaFX UI
  • Headless UI
  • Online help
  • JVx mobile

Our private Maven repository is available on a subscription basis. This doesn't mean that our private projects aren't open source projects, but we don't offer snapshot or release artifacts for them!

ProjX/Applications API changes

We'll chang the API of ProjX applications for some listeners. The changes are available in our nightly/weekly builds and in our repository. Please be sure to test your applications because generic listeners won't throw an exception at compile time, only at runtime.

IBeforeOpenWorkScreenListener

public void beforeOpenWorkScreen(ProjX pApplication, String pClassName, Modality pModality, AbstractConnection pConnection) throws Throwable;

to

public void beforeOpenWorkScreen(WorkScreenEvent pEvent) throws Throwable;

IAfterOpenWorkScreenListener

public void afterOpenWorkScreen(ProjX pApplication, IWorkScreen pScreen) throws Throwable;

to

public void afterOpenWorkScreen(WorkScreenEvent pEvent) throws Throwable;

IBeforeCloseWorkScreenListener

public void beforeCloseWorkScreen(ProjX pApplication, IWorkScreen pScreen) throws Throwable;

to

public void beforeCloseWorkScreen(WorkScreenEvent pEvent) throws Throwable;

IAfterCloseWorkScreenListener

public void afterCloseWorkScreen(ProjX pApplication, IWorkScreen pScreen) throws Throwable;

to

public void afterCloseWorkScreen(WorkScreenEvent pEvent) throws Throwable

IOpenWorkScreenExceptionListener

public void openWorkScreenException(ProjX pApplication, String pClassName, Modality pModality, Throwable pCause) throws Throwable;

to

public void openWorkScreenException(WorkScreenExceptionEvent pEvent) throws Throwable;

IVetoOpenWorkScreenListener

public void vetoOpenWorkScreen(ProjX pApplication, String pClassName, Modality pModality, Map<String, Object> pParameter) throws Exception;

to

public void vetoOpenWorkScreen(WorkScreenEvent pEvent) throws Exception;

Monitoring AddOn for VisionX

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.

DOAG 2016 - I'm a Speaker

I'm a Speaker I'm a speaker at DOAG 2016 in Nuremberg.
My talk will be about "JVx introduces itself. Back to efficiency"