JVx Reference, Custom Components

Post to Twitter

Let's talk about custom components, and how to create them.

The GUI of JVx

We've previously covered how the GUI of JVx works, and now we will have a look on how we can add custom components to the GUI.

In the terminology of JVx there are two different kinds of custom components:

  1. UI based
  2. Technology based

We will look at both, of course.

Custom components at the UI layer

The simplest way to create custom components is to extend and use already existing UI classes, like UIPanel or UIComponent. These custom components will be Technology independent because they use Technology independent components, there is no need to know about the underlying Technology. You can think of those as a "remix" of already existing components.

The upside is that you never have to deal with the underlying Technology, the downside is that you can only use already existing components (custom drawing is not possible, for example).

Let's look at a very simple example, we will extend the UILabel to always display a certain postfix along with the set text:

public class PostfixedLabel extends UILabel
{
    private String postfix = null;

    // We must store the original text so that we can return
    // it if requested. Otherwise we could only return the text
    // with the appended postfix, which works unless the postfix
    // changes.
    private String text = null;

    public PostfixedLabel()
    {
        super();
    }

    public PostfixedLabel(String pText)
    {
        super(pText);
    }

    public PostfixedLabel(String pText, String pPostfix)
    {
        super(pText);

        setPostfix(pPostfix);
    }

    @Override
    public String getText()
    {
        return text;
    }

    @Override
    public void setText(String pText)
    {
        text = pText;

        if (!StringUtil.isEmpty(postfix) && !StringUtil.isEmpty(pText))
        {
            // We translate the text and the postfix now separately,
            // the underlying label will obviously try to translate
            // the concatenated version.
            super.setText(translate(pText) + translate(postfix));
        }
        else
        {
            super.setText(pText);
        }
    }

    public String getPostfix()
    {
        return postfix;
    }

    public void setPostfix(String pPostfix)
    {
        postfix = pPostfix;

        // If the postfix changed, we must update the text.
        setText(text);
    }
}

It will be treated just like another label, but every time a text is set, the postfix is appended to it.

Another example, we want a special type of component, one that always does the same but will be used in many different areas of the application, it should contain a label and two buttons. The best approach for a custom component which should not inherit any specific behavior is to extend UIComponent:

public class BeepComponent extends UIComponent<UIPanel>
{
   public BeepComponent()
   {
       super(new UIPanel());
       
       UIButton highBeepButton = new UIButton("High Beep");
       highBeepButton.eventAction().addListener(Beeper::playHighBeep);
       
       UIButton lowBeepButton = new UIButton("Low Beep");
       highBeepButton.eventAction().addListener(Beeper::playLowBeep);
       
       UIFormLayout layout = new UIFormLayout();        

       uiResource.setLayout(layout);
       uiResource.add(new UILabel("Press for beeping..."), layout.getConstraints(0, 0, -1, 0));
       uiResource.add(highBeepButton, layout.getConstraints(0, 1));
       uiResource.add(lowBeepButton, layout.getConstraints(1, 1));
   }
}

So we extend UIComponent and set a new UIPanel as UIResource on it, which we can use later and which is the base for our new component. After that we added a label and two buttons which will play beep sounds if pressed. This component does not expose any specific behavior as it extends UIComponent, it only inherits the most basic properties, like background color and font settings, yet it can easily be placed anywhere in the application and will perform its duty.

Custom controls at the Technology layer

The more complex option is to create a custom component at the Technology layer. That means that we have to go through a multiple steps process to create and use the component:

  1. Create an interface for the functionality you'd like to expose
  2. Extend the Technology component (if needed)
  3. Implement the necessary interfaces for JVx
  4. Extend the factory to return the new component
  5. Create a UIComponent for the new component
  6. Use the new factory

I will walk you through this process, step by step.

The upside is that we can use any component which is available to us in the Technology, the downside is that it is quite some work to build the correct chain, ideally for every technology.

Creating an interface

The first step is to think about what functionality the component should expose, we will use a progress bar as example. We don't want anything fancy for now, a simple progress bar on which we set a percent value should be more than enough:

/**
 * The platform and technology independent definition for a progress bar.
 */

public interface IProgressBar extends IComponent
{
    /**
     * Gets the current value, in percent.
     *
     * @return the current value. Should be between {@code 0} and {@code 100}.
     */

    public int getValue();
   
    /**
     * Sets the current value, in percent.
     *
     * @param pValue the value. Should be between {@code 0} and {@code 100}.
     */

    public void setValue(int pValue);
}

Might not be the most sophisticated example (especially in regards to documentation) but it will do for now. This interface will be the foundation for our custom component.

Extending the component, if needed

We will be using Swing and the JProgressBar for this example, so the next step is to check if we must add additional functionality to the Technology component. In our case we don't, as we do not demand any behavior that is not provided by JProgressBar, but for the sake of the tutorial we will still create an extension on top of JProgressBar anyway.

public class ExtendedProgressBar extends JProgressBar
{
    public ExtendedProgressBar(int pMin, int pMax)
    {
        super(pMin, pMax);
    }
}

Within this class we could now implement additional behavior independent of JVx. For example, we provide many extended components for Swing, JavaFX and Vaadin with additional features but without depending on JVx. The extension layer is the perfect place to extend already existing components with functionality which will be used by, but is not depending on, JVx.

Creating the Implementation

The next step is to create an Implementation class which allows us to bind our newly extended JProgressBar to the JVx interfaces. Luckily there is the complete Swing Implementation infrastructure which we can use:

public class SwingProgressBar extends SwingComponent<ExtendedProgressBar>
                              implements IProgressBar
{
    public SwingProgressBar()
    {
        // We can hardcode the min and max values here, because
        // we do not support anything else.
        super(new ExtendedProgressBar(0, 100));
    }
   
    @Override
    public int getValue()
    {
        return resource.getValue();
    }
   
    @Override
    public void setValue(int pValue)
    {
        resource.setValue(pValue);
    }
}

That's it already. Again, in this case it is quite simple because we do not expect a lot of behavior. The implementation layer is the place to "glue" the component to the JVx interface, implementing missing functionality which is depending on JVx and "translating" and forwarding values and properties.

Extending the factory

Now we must extend the Factory to be aware of our new custom component, that is equally simple as our previous steps. First we extend the interface:

public interface IProgressBarFactory extends IFactory
{
    public IProgressBar createProgressBar();
}

And afterwards we extend the SwingFactory:

public class ProgressBarSwingFactory extends SwingFactory
                                     implements IProgressBarFactory
{
    @Override
    public IProgressBar createProgressBar()
    {
        SwingProgressBar progressBar = new SwingProgressBar();
        progressBar.setFactory(this);
        return progressBar;
    }
}

Again, it is that easy.

Creating the UIComponent

So that we can use our new and shiny progress bar easily, and without having to call the factory directly, we wrap it one last time in a new UIComponent:

public class UIProgressBar extends UIComponent<IProgressBar>
                           implements IProgressBar
{
    public UIProgressBar()
    {
        // We'll assume that, whoever uses this component,
        // is also using the correct factory.
        super(((IProgressBarFactory)UIFactoryManager.getFactory()).createProgressBar());
    }
   
    @Override
    public int getValue()
    {
        return uiResource.getValue();
    }
   
    @Override
    public void setValue(int pValue)
    {
        uiResource.setValue(pValue);
    }
}

Nearly done, we can nearly use our new and shiny component in our project.

Using thecustom factory

Of course we have to tell JVx that we want to use our factory, and not the default one. Depending on the technology which is used, this has to be done at different places:

Swing and JavaFX

Add the factory setting to the application.xml of the application:

<Launcher.uifactory>your.package.with.custom.components.SwingProgressBarFactory</Launcher.uifactory>
Vaadin

Add the following setting to the web.xml under the WebUI Servlet configuration:

<init-param>
    <param-name>Launcher.uifactory</param-name>
    <param-value>your.package.with.custom.components.VaadinProgressBarFactory</param-value>
</init-param>

Using our new component

And now we are done, from here we can use our custom component like any other.

UIProgressBar progressBar = new UIProgressBar();
progressBar.setValue(65);

// Skip

add(progressBar, constraints);

Wrapping custom components with UICustomComponent

There is a third way to have Technology dependent custom components in JVx, you can wrap them within a UICustomComponent:

JProgressBar progressBar = new JProgressBar(0, 100);
progressBar.setValue(100);

UICustomComponent customProgressBar = new UICustomComponent(progressBar);

// Skip

add(customProgressBar, constraints);

This has the upside of being fast and easy, but the downside is that your code has to know about the currently used Technology and is not easily portable anymore.

Conclusion

As you can see, there are multiple ways of extending the default set of components which are provided by JVx, depending on the use case and what custom components are required. It is very easy to extend JVx with all the components one does require.

EPlug 1.2.6

Post to Twitter

We're happy to announce the release of EPlug 1.2.6. Again this small version bump does not only yield important bug fixes, but also new features which will make your life a lot easier.

Fixes

This release includes bug fixes along with new features. One of the most notable problems fixed was that compile time checks might not be run if the communication with VisionX was active.

Cleaner context menu with more actions

We have restructured our approach to the context menu entries and introduced a new menu item which holds all EPlug related actions:

New context menu

As you can see we've also added new actions to jump to the configuration files.

Resources outside of source folders

We do support autocompletion and compile time checks for resources, like images. But we only supported resources inside of source folders, with this version we do now also support resources anywhere in the project.

Resources

Improved DataBook handling

DataBook handling has been improved once more. There are now additional checks which make sure that a RemoteDataBook receives the correct DataSource and there for if the MetaData can reliably be determined.

Additionally, the type of flag issued if no MetaData could be determined is now a configurable build option on the project.

New context menu

An example:

private void changeSomeValues(RemoteDataBook pDataBook)
{
    pDataBook.setValue("COLUMN_A", "A");
    pDataBook.setValue("COLUMN_B", "B");
    pDataBook.setValue("COLUMN_C", "C");
}

This would have been flagged as warning, because no MetaData could be determined for pDataBook. Now the check determines that determining MetaData for this DataBook is impossible and flags it accordingly. You can configure whether you want to see this flag or not in the project settings.

EPlug does also recognize if a "foreign" datasource has been set:

RemoteDataBook dataBookA = new RemoteDataBook();
dataBookA.setDataSource(getDataSource());
dataBookA.setName("a");
dataBookA.open();

RemoteDataBook dataBookB = new RemoteDataBook();
dataBookB.setDataSource(dataSourceFromSomewhereElse);
dataBookB.setName("a");
dataBookB.open();

// This will be flagged as error.
dataBookA.setValue("NON_EXISTING", BigDecimal.ZERO);

// This will be flagged according to the settings.
dataBookB.setValue("NON_EXISTING", BigDecimal.ZERO);

Usernames for sessions

Last but not least, there is now a project setting which allows to set the username which is used by EPlug for the session it creates.

A little background, to acquire the MetaData (and some other information about the application) EPlug creates a session of the application and executes the server side code. It could be that projects do have checks and manipulations on the username somewhere in their code on the server. Previously EPlug would set null as username, but now it does either use the configured autologin username or the username configured in the project settings. That allows server side code which does operate on the username of the session to run without a problem, which means that there are no checks necessary if the session was initialized by EPlug or not.

How to get it?

Simply update EPlug via Eclipse!

JVx Reference, of Technologies and Factories

Post to Twitter

Let's talk about the UI layer, the implementations and the factory that powers it all.

The basics

For everyone who does not know, JVx allows you to write code once and run it on different GUI frameworks, without changing your code. This is achieved by hiding the concrete GUI implementations behind our own classes, the UI classes, and providing "bindings" for different GUI frameworks behind the scenes. Such a "Single Sourcing" approach has many advantages, and just one of them is that migrating to a new GUI framework requires only the change of a single line, the one which controls which factory is created.

The Factory Pattern

The Factory Pattern is an important pattern in Object-Oriented-Programming, it empowers us to delegate the creation of Objects to another Object which must not be known at design and/or compile time. That allows us to use Objects which have not been created by us but merely "provided" to us by an, for us unknown, implementation.

Like an onion

JVx is separated into different layers, with the UI layer being at the top and of the most concern to users.

JVx Layers

Technology

Obviously, the first one in the chain is the so called "technology" layer. It represents the UI technology, for example Swing, JavaFX or Vaadin, which is used to power the JVx application.

To put it into a more simple term:

public class JButton {}

Extension

Next comes the extension layer, components from the technology are extended to support needed features of JVx. This includes creating bindings for the databook, additional style options and changing of behavior if necessary. From time to time this also includes creating components from scratch if the provided ones do not meet the needs or there simply are none with the required functionality. For the most part, we do our best that these layers can be used without JVx, meaning that they represent a solitary extension to the technology. A very good example is our JavaFX implementation, which compiles into two separate jars, the first being the complete JVx/JavaFX stack, the second being stand-alone JavaFX extensions which can be used in any application and without JVx.

Theoretically one can skip this layer and directly jump to the Implementation layer, but so far it has proven necessary (for cleanliness of the code and object structure and sanity reasons) to create a separate extension layer.

public class JExtendedButton extends JButton {}

Implementation

After that comes the implementation layer. The extended components are extended to implement JVx interfaces. This is some sort of "glue" layer, it binds the technology or extended components against the interfaces which are provided by JVx.

public class SwingButton<JExtendedButton> implements IButton {}

UI

Last but for sure not least is the UI layer, which wraps the implementations. It is completely Implementation independent, that means that one can swap out the stack underneath:

JVx Layers

This is achieved because the UI layer is not extending the Implementation layer, but wrapping instances provided by the factory. It is oblivious to what Technology is actually underneath it.

public class UIButton<IButton> implements IButton {}

SwingButton resource = SwingFactory.createButton()

Why is the UI layer necessary?

It isn't, not at all. The Implementations could be used directly without any problems, but having yet another layer has two key benefits:

  1. It allows easier usage.
  2. It allows to add Technology independent features.

By wrapping it one more time we gain a lot of freedom which we would not have otherwise, when it comes to features as when it comes to coding. The user does not need to call the factory directly and instead just needs to create a new object:

IButton button = new UIButton();

Internally, of course, the Factory is called and an implementation instance is created, but that is an implementation detail. If we would use the implementation layer directly, our code would either need to know about the implementations, which doesn't follow the Single-Sourcing principle:

IButton button = new SwingButton();

It also would be possible to directly use the factory (but this isn't modern coding style):

IButton button = UIFactoryManager.getFactory().createButton();

Both can be avoided by using another layer which does the factory calls for us:

public class UIButton implements IButton
{
    private IButton resource;

    public UIButton()
    {
        resource = UIFactoryManager.getFactory().createButton();
    }

    public void someInterfaceMethod()
    {
        resource.someInterfaceMethod();
    }
}

Additionally this layer allows us to implement features which can be technology independent, our naming scheme, which we created during stress testing of an Vaadin application, is a very good example of that. The names of the components are derived in the UI layer without any knowledge of the underlying Technology or Implementation.

Also it does provide us (and everyone else of course) with a layer which allows to rapidly and easily build compound components out of already existing ones, like this:

public class LabeledButton extends UIPanel
{
    private IButton button = null;
    private ILabel label = null;
   
    public LabeledButton ()
    {
        super();

        initializeUI();
    }

    private void initializeUI()
    {
        button = new UIButton();
        label = new UILabel();
       
        setLayout(new UIBorderLayout());
        add(label, UIBorderLayout.LEFT);
        add(button, UIBorderLayout.CENTER);
    }
}

Of course that is not even close to sophisticated, or a good example for that matter. But it shows that one can build new components out of already existing ones without having to deal with the Technology or Implementation at all, creating truly cross-technology controls.

The Factory

The heart piece of the UI layer is the Factory, which is creating the Implemented classes. It's a rather simple system, a Singleton which is set at the beginning to the Technology specific factory which can be retrieved later:

// At the start of the application.
UIFactoryManager.setFactoryInstance(new SwingFactory());
// Or alternately:
UIFactory.getFactoryInstance(SwingFactory.class());

// Later inside the UI wrappers.
IButton button = UIFactory.getFactory().createButton();

The complexity of the implementation of the factory is technology dependent, but for the most part it is devoid of any logic:

public class SwingFactory implements IFactory
{
    @Override
    public IButton createButton()
    {
        SwingButton button = new SwingButton();
        button.setFactory(this);

        return button;
    }
}

It "just returns new objects" from the implementation layer. That's about it when it comes to the factory, it is as simple as that.

Piecing it together

With all this in mind, we know now that JVx has swappable implementations underneath its UI layer for each technology it utilizes:

JVx Layers

Changing between them can be as easy as setting a different factory. I say "can", because that is only true for Swing, JavaFX and similar technologies, Vaadin, obviously, requires some more setup work. I mean, theoretically one could embed a complete application server and launch it when the factory for Vaadin is created, allowing the application to be basically stand-alone and be started as easily as a Swing application. That is possible.

What else?

That is how JVx works in regards to the UI layer. It depends on "technology specific stacks" which can be swapped out and implemented for pretty much every GUI framework out there. We currently provide support for Swing, JavaFX and Vaadin, but we also had implementations for GWT and Qt. Additionally we do support a "headless" implementation which allows to use lightweight objects which might be serialized and send over the wire without much effort.

Adding a new Technology

Adding support for a new Technology is as straightforward as one can imagine, simply creating the Extensions/Implementations layers and implementing the factory for that Technology. Giving a complete manual would be out for scope for this post, but the most simple approach to adding a new stack to JVx is to start with stubbing out the IFactory and implementing IWindow. Once that one window shows up, it's just implementing one interface after another in a quite straightforward manner. And in the end, your application can switch to yet another GUI framework without the need to change your code.

JVx Reference, Events

Post to Twitter

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.

EPlug 1.2.5

Post to Twitter

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!

JVx and MySQL, Limited Edition

Post to Twitter

If you work with JDBC and MySQL, you will most likely be aware of one shortcoming: MySQL can not stream the results from a query (well, actually it can, but the feature is quite limited). That means that up until now JVx has always received and stored the full result set in memory which it received from MySQL. No paging was performed as it was done in the Oracle implementation.

Limit to the rescue!

MySQL does support the limit clause, which allows to limit the results to either a certain number of rows, or a certain range of rows. How does it look like?

SELECT
    ID,
    NAME
FROM
    TEST
WHERE
    NAME LIKE 'Hans%'
LIMIT 5, 10;

This will fetch the data starting by the 5th row up to the 15th row, so it will skip the first five rows and then return the next ten. As this is a database builtin, no additional data is send over the wire except the actual requested rows. This is perfect if you want to limit your queries, for example, because you know that you don't need more than 5 rows even though there are 50,000 rows.

Fetch all the things!

With the old behavior, without limit clause, the JDBC MySQL driver would fetch the complete result of the query and only we would do some cutting on it (mainly dropping not needed rows at the start). That meant that the complete result set was always loaded into memory, which itself might have caused that you were unable to execute certain queries, especially if they contained bigger blob columns.

Limit all the things!

With the new behavior, the limit clause is appended to the query as needed, which means that the JDBC MySQL driver has to load a lot less data and a lot less data is send over the wire.

The MySQL giveth, the MySQL taketh away...

But there is an additional cost associated with the usage of the limit clause. Because the fetches are separate statements, all rows leading up to the beginning row have to be selected, too. Let us return to our first example, the query of the TEST table. We only want 10 rows starting from the 5th row, that means our result set only contains 10 rows. However, MySQL has (obviously) to query, select and discard the first five rows so that it can start sending us the rows that we actually want. That means that the cost of selecting pages increases. Off to pretty graphics!

Impressions

Note that the fetch time is accumulative.

  • Blue: The original implementation which does perform only one fetch of all data. In this case it is quite fast, but depending on the query and data you could wait a long time for the initial fetch, if it was possible at all.
  • Orange: The current implementation with quite a worst case scenario, it gradually fetches page after page with a row count of 50. As you can see the fetch time gradually increases, but as you can also see the initial fetches are fast.
  • Yellow: An optimization experiment which increases the fetched row count dynamically.

Let us look at this again in detail, to be exact the fetching of the first 1500 rows.

Impressions

What we see here is quite good news, actually, because with the new implementation with the limit clause, you can consecutively fetch 600 rows in the same time as the fetching of the 4400 rows with the old implementation. The big difference here is that the first set of ~113 rows returns close to immediately and consecutive fetches are equally fast. This is awesome because we can now display initial data faster, even few it is fewer data in the end and slows down the more data is fetched afterwards.

Improve all the things!

As you can see from the charts, we already did a short experiment to improve this further, and we are confident that we can implement such a solution which dynamically fetches more rows to reduce the overall fetch time while still preserving that the first rows are displayed fast, further improving GUI responsiveness.

Two years SIB Visions, a look back and ahead

Post to Twitter

Now that my second year at SIB Visions has been wrapping up, it is again time to take a short break and look at the passed year.

JavaFX, the finishing touch

My last years post ended with a look at the work on our JavaFX implementation. That work was shortly after finished and we could release the version 1.0, which still has some rough edges but overall works quite well. There weren't many exciting things going on in the last cycle of development, only a lot of small bugs to be fixed.

In June the JavaFX project migrated from its own JIRA system to the OpenJDK bugtracker, something which sounds like a little and quite unimportant migration turned out to be quite a problem for people like us. The OpenJDK bugtracker is read-only for everyone who is not an OpenJDK author (I believe it is called "author"), tickets can only be created through the web interface for generic Java bugs. That means that we lost the possibility to contribute to the tickets which we created or tracked, we even lost the possibility to track tickets easily, and the forwarding from the old JIRA issues has been removed in the mean time, too. The only possibility to track the tickets which are of interest to us is now via RSS feeds...one feed for every single ticket. If you remember my last years post, that list had grown to over 50 tickets. Contributing to tickets and commenting is only possible through the mailing lists for us. Which is a quite sad state compared to the previous one, but I guess there isn't much one can do about.

Anyway, for our implementation we've already gathered a list of needed improvements which will come next, we just don't know when exactly that will happen, but it will.

The Kitchensink, plumbing not included

During the JavaFX implementation the necessity arose to quickly and easily test most features. The first test runs and verifications had been done using the FirstApp and the DemoERP, which are very good examples if you want to get it to work but lack the detail of most features for the most part. Out of this need the JVx Kitchensink was born.

The Kitchensink is a very, very simple application which doubles as a showcase and as a testbed for new implementations. It includes all controls and allows you to manipulate them on the fly, easily testing the features of every single one. Though, it does not use the Client/Server infrastructure and instead is a simple, stand-alone application which is launched directly using the factory.

This little application allowed us to rapidly test single features of controls and components in Swing and JavaFX without having to click through large applications or the need to change these applications to accommodate our tests. You can check it out, it runs completely standalone and allows you to see and test all of the controls which are offered by JVx.

The JVx Kitchensink Application, Swing and JavaFX running side by side.

EPlug, an update

After the JavaFX implementation I could return to EPlug to include even more exciting features, you can find a full feature list in the 1.2.0 release post, the 1.2.1 release post and the latest 1.2.4 release post. Combined with these releases there also is now a quite big post about all the features of EPlug, which is one big overview about everything that EPlug can do.

One of the features that I personally found important is the DataBook View, it displays all databooks of the current file in a similar manner to the Outline. That means that you can now see which databooks and which columns are in use in the current file. I'm afraid that there isn't much more to say about working on these releases, implementing the new features worked like a charm and was uneventful.

JVxEE, a small fix for the start

For everyone who does not know, we do offer an JavaEE implementation of JVx, which means that you can use JVx powered by POJOs. For the most time I've only seen that implementation from a far, but a quite eerie bug report in the forum required our attention. As it turned out,  the implementation would assign duplicate names for foreign key columns, which of course resulted in undefined behavior for the most part. Fixing this was rather easy, as I just had to come up with a better naming scheme, and v1.2 of JVxEE includes the fix and is now creating better names for foreign key columns.

All over the place

During the summer my working assignments were widespread throughout all our projects. Bug fixes in JVx, maintenance in VisionX, new features in ProjX, you name it.

GUI Testing, an experiment

Back when we ran stress tests on our Vaadin implementation and server we had the idea that a generic GUI testing system for JVx should be possible. During the late summer we actually found the time to pursue this idea and started building a prototype. The goal was to provide an application which allows to record, replay, save/load and export GUI unit tests. Hooking into the toolkits, like Swing, proofed to be rather simple and with our naming scheme in place it was quite easy to gather events and ascribe them to components in a toolkit generic way. For example for Swing/AWT you can register a global event listener which will receive all events, ideal for such a usecase. For JavaFX you have to resort to register a filter for events on a scene level. Regarding Vaadin we opted to refer to the Selenium IDE which already allowed to record whole test cases in the browser. Additionally with our naming scheme we can record test cases in Swing/JavaFX and map them nearly one-to-one to Selenium test cases.

Processing the events which we received from the toolkit proofed to be more difficult than first thought, for example the window close button in Swing fires a single click event, unfortunately that button does not have any information associated with it which would allow us to figure out that it is the close button. Additionally that button might change from LaF to LaF.  There were multiple such instances which made it quite hard for us to determine what event just fired and to which component it belonged to.

At the end we had a working prototype which could be launched with the  application (basically wrapping the application to make it possible to hook into the event loops and similar), record events, replay these events and allowed us to save, load and export these as unit tests. Unfortunately we ran out of time before we could raise this prototype to a production ready software. But the long term goal is still to provide such a functionality to JVx users at some point.

eTV, a small side project

As I will explain further down, I was not happy with the last empty wall in the office and the idea to have some sort of information display was born. Additionally we could use this setup in our conference room as needed and even bring it to events and conferences. Now, if you want to display information you need two things:

  1. A display to display the information on
  2. A system which can power the display

As it turned out later, you also need information to display, but that is a different story. So the first step was to figure out what would display the information and what would power that. We settled quickly on a simple 41" TV and a Raspberry Pi 2. That means we have a low-power setup which is easily portable (unplug it, move the TV over, plug it in). We installed Raspbian and our first tests were promising.

After some tests it turned out that the easiest way would be to create a custom setup which was powered by JVx and utilized all the power the Linux system provided us with. The final stack looks like this:

  • Raspbian
  • Customized boot to directly launch a graphical user session
  • i3 (which might be replaced with Sawfish in future iterations)
  • Custom JVx system which can be remotely controlled
  • "Glue" shell scripts which bridge the gap between JVx and the system applications and act as another layer of abstraction

The customized boot is the easiest of all these, as it simply means to edit the inittab file and add an automatic login:

1:2345:respawn:/bin/login -f YOUR_USER tty < /dev/tty1 > /dev/tty1 2>&1

That will launch a user session everytime the system boots. From there it simply launches X11 and executes the initial setup of the user session (like starting the window manager, setting a wallpaper, starting the JVx server etc.).

We chose i3 because it allows to be controlled from the command line and provides extensive customization options. In the mean time we've looked into replacing it with Sawfish as it provides even more options and provides more control.

The custom JVx system is also not that impressive as it might seem. It is a simple and slim JVx server which one can connect to and execute commands, like to show the next window or launch an application. This also includes the "glue" shell scripts, which basically provide another layer of abstraction between the JVx server and the system, for example if the next window should be displayed the server invokes the "next-window.sh" script which then sends the command to the window manager. That allows to easily tune or swap technologies without having to edit, recompile and restart the server.

One of the first usecases was to show videos and streams on the TV, as it turns out, the options you have when it comes to display videos on a Raspberry Pi are quite limited. The initial idea to use VLC quickly died because it does not support hardware acceleration on the Raspberry Pi, which renders it useless for showing videos. Even though 2.2.0 promised support, we did not get it to work on our device. That left us with OMXPlayer, which comes with a completely different set of problems. The first surprise for me was that OMXPlayer did not use a window, it directly paints to the screen, which means that it can't be controlled with window commands. The second problem is that it behaves very badly if the connection is bad, of course that is to be expected, however OMXPlayer quits at the first sign of a bad connection. If you want to display a livestream, which does not end, it is quite confusing to have the player quit on you without an obvious reason. The workaround to that problem was to wrap it in a while loop inside the shell script which starts it, a quite ugly hack, but unfortunately necessary.

There were other problems to be solved, for example that the USB WLAN dongle would go to sleep after some time, that the network manager would consider it a good idea to assign a completely different IP address and that our WLAN is really unpredictable in some circumstances, but otherwise it was not that bad. After we've figured these things out it was a smooth sailing. As you can see in the other blog post about it, we even built a simple demonstration system of the capabilities of JVx complete with a little gamification. The whole setup can now be controlled over a web interface (which is a JVx Vaadin application deployed to a Jetty) and with an app on a tablet, it can display pictures, videos, streams and of course run applications, including different dashboards (created with JVx) which provide us with information (some vital, some not so much, but who does not want to see the latest Garfield comics at a glance) or some nice views, like the live streams from the ISS.

All in all, we are very happy with how this turned out and we will keep improving this setup in the future. There is also now the Raspberry Pi 3 and the ODROID-C2 which offer even better performance in the same form factor, so there is definitely space for upgrades. Here are a few impressions from the project:

Impressions

JVx and lambdas, let's do it right

With the release of Java 8, Java gained support for lambdas and method references, this is great! It means that a lot of code can be written simpler and more readable. The new method references are also very close to our implementation of listeners and actions, which means that it is only natural to make sure that we support them to the best of our abilities.

To make sure that our events, listeners and actions can be used with lambdas and method references and to provide a clean migration path if wanted, we had to make sure that these could be translated as easily as possible. For that we introduced a new interface called IRunnable, which is the same as Runnable except that the run method can throw any Throwable. With this new interface under our belt, we can now provide 1:1 migration path for everyone who wants to use lambdas instead of our listener scheme.

Vaadin, the new grid

With Vaadin 7.4 a new component was included, the Grid. The Grid set out to fix the shortcomings of the Table and provide more and better features, so of course we wanted to see how it actually performs and works. Thanks to the architecture of JVx, having multiple implementations of the same component is easily possible, all you need is a switch in the factory so that it provides you with the implementation you want.

The new Grid provides a lot of possibilities and integrating it into our implementation was quite painless and straightforward. For us, one of the best things about the new Grid are the custom renderers, that means that we can finally fine tune the representation of every cell in every way, something that was previously only with some hacks possible, but is now painless with our custom renderer. The only downside to the Grid is the missing inline editing support, but that is already remedied in later versions, to which we will update in time.

Prototype, my first

First, you have to know that I was hired as a framework coder, even though JVx is a business application framework, the whole "business application" part does not concern me as long as it is does not directly influence the framework work I'm doing. But at the beginning of this year I was required to create a prototype for a real business application, which is a very exciting opportunity to actually look on the other side of the fence (and as we all know, the grass is always greener on the other side, though in Eden it might be acid). With the power of VisionX strapped to my back it actually was a quite easy task to get the first draft up and running. As usual, the most time went into fine tuning the user interface and the styling.

A few misjudgments on my end included which were later on fixed, it was quite an experience working on this prototype. Even though I do not consider it a requirement, it is always a good idea to use the software that you create, it helps seeing problems early on and also provides a very simple reality and sanity check. But for me personally, I was happy when I was allowed to go back to work on the framework, it is my domain, in job and mind.

Vaadin, the new FormLayout

Since the beginning of the Vaadin implementation the FormLayout was a problematic child, never behaving as it should. The original implementation is based upon the GridLayout of Vaadin, which is nice but comes with quite heavy limitations, for example that components can not overlap. So it was finally time to put all these problems behind us and rewrite the FormLayout to behave the same as in the other implementations.

Implementing something in Vaadin is more complicated than doing it in, for example, Swing. It means that you have a server-side class, a client-side class and a connector stringing the two together. Technically the only touching area is the connector between the server and client side and that is one way only. This is very limiting when it comes to something like our FormLayout, but we found a way to send everything necessary to the client.

Additional problems we faced were that the new FormLayout is required to resize itself whenever its parent changes, something that is not necessarily easily achieved in HTML/CSS, not in the way we needed it. You see, these panel must fulfill two properties: First, it must resize itself to the size of its parent or the size it is set to by the parent. Second, it must resize itself according to its own preferred size. These two sound contradictory, but are very simply explained when put them into proper context. The panel must resize itself whenever the parent changes, this is obviously necessary to make sure that the panel is always correctly layouted. Everyone who does know a little about HTML/CSS will now say "set the width and height to 100%", this is correct, however it also means that the panel inside a container which itself does not have a fixed size will collapse. That is not what we want, we want the panel to dictate a size if the parent does not have one, and everyone will say again "then don't set a width and height", this is also correct, but means that it won't resize itself anymore with the parent. To make the matter even more complicated, all children are positioned absolute, which means that the panel can not have a size of its own. So how can we eat our cake and have it?

The answer is, at least to me, some form of black magic (sacrificing a goat might also help, not sure, we only tried with sheep): You set the minimum width and height of the panel to 100% and you have a second element inside which has an actual size, like this:

  • Panel, minimum-height: 100%, minimum-width: 100%
    • Canvas, height: 500px, width: 500px
      • Child, absolute position
      • Child, absolute position

All children will be added to the canvas instead of the panel itself. This means that the panel will always be the size of the parent but still has its own size dictated by the size of the canvas. The size of the canvas is updated at every layout pass with the values calculated from the children. As this wasn't confusing enough, we had to make sure that certain children behave correctly, for example the TabSheet would only recalculate its size correctly if it was set to 100% on the server side. But Vaadin has some server side checks which make sure that you can't set the size of a component to 100% if the parent (or some parent in the chain) hasn't an absolute size. I have to say that this took some time until I figured that one out. The workaround for this last bit is quite ugly but works, simply set the size of the panel to Float.POSITIVE_INFINITY and PICAS, and then override beforeClientResponse(boolean) and set 100% hardcoded into the state. This disables the Vaadin server side check completely. Additionally we also included and provided a mechanism to allow the server side to set minimum, preferred and maximum sizes for each component, as most people will know from Swing.

The last bit was the positioning of the elements themselves, which was surprisingly easy to do after all these little obstacles had been overcome.

The latest nightlies of JVx are already containing this new FormLayout, which can be activated by setting a property on the factory.

Vaadin, the new Panel and Layouts

As an extension to the work on the FormLayout, we experimented with creating a panel which does accept a layout, just like in Swing. With most of the hard work already done during the rewrite of the FormLayout we could start quickly with a solid base. Implementing the panel itself which does accept a layout and does forward all layout operations to that layout was quickly done, this panel together with the layouts can be found in Vaadin package, as pure Vaadin classes.

The new LayoutedPanel does work very simply: It gets a layout set and all layout operations are forwarded to that layout. The layouts themselves only need to handle constraint creation and how the components are positioned on the client side. A very simple and nice solution.

However, integrating this new Panel into the Vaadin implementation for incorporation into JVx proofed to be difficult. The constraint that it is possible to switch between the old and new panel is necessary to guarantee that already existing applications are not broken, but exactly this became a difficulty. The Vaadin implementation assumes from the first moment that the layout implementations are Vaadin components, which they no longer were. Normally you'd do a big rewrite to change these underlying assumptions, but that was out of the question...a tough nut to crack. In the end we had to postpone any further work on this for a more important project.

On the upside, we've come very, very close to be able to implement the layouts independent of the UI implementation, which means that we will only have the logic ones, not duplicated anymore. Of course this needs some more thinking and work, but I'm very confident that this is actually going to happen.

Office customization

One of the things that I find important is that I feel comfortable in the office and at my workplace, I'm going to spend well over 8 hours a day there so I might as well enjoy the time. Luckily, here at SIB Visions quite relaxed rules are applied when it comes to what is allowed in the office and what is not. Giving me free reign over the decorations in the office made me wish that I would have more walls than just three to put things on.

That is also how our eTV came to be, it was hard to find something for the space between the doors, as most of the time half of the wall would be covered by the door. A TV which would display something seemed like a logical choice here.

And for those of you wondering what we're doing the whole day, here is a timelapse video of nearly a whole week:

A week @ SIB Visions

The look ahead

That was quite an eventful year, a lot of smaller but very interesting projects. What does the future hold? Well, it for sure ain't going any slower, that I can tell you.

Thanks to everyone at SIB Visions for this wonderful year, I'm looking forward to another awesome year with all of you!

JVx and Java 8, Better Lambda support in 2.4

Post to Twitter

Already at the beginning of this year we started to improve the support for Lambdas in JVx. Now with 2.4 only a few days away, I'm happy to announce that we managed to improve it dramatically! Our events are now supporting basically every method which you can imagine as handler.

But let's not get ahead of ourselves, shall we? As most of you know, our own event handler scheme had support for basically five different variations of listeners:

private void initializeUI()
{
    button.eventAction().addListener(new UIActionListener() { ... });
    button.eventAction().addListener(this, "doActionA");
    button.eventAction().addListener(this, "doActionB");
    button.eventAction().addListener(this, "doActionC");
    button.eventAction().addListener(this, "doActionD");
}

public void doActionA()
{
    // A simple method with no parameters.
}

public void doActionB() throws Exception
{
    // A simple method which can throw *any* exception.
}

public void doActionC(UIActionEvent pActionEvent)
{
    // A method with the correct signature.
}

public void doActionD(UIActionEvent pActionEvent) throws Exception
{
    // A method with the correct signature which can throw *any* exception.
}

This scheme allows us to wire up basically any method to the event, and even to wire the same method to different events. Behind the scenes there is some reflection magic going on which I won't describe here, but with Lambdas entering the stage this changes quite a bit. The good thing about Lambdas is that they are fitting neatly into the already existing interface structure, so you can replace any interface implementation which has only one method with a lambda.

That means that you can do something like this:

private void initializeUI()
{
    button.eventAction().addListener(this::doActionA);
}

private void doActionA(UIActionEvent pActionEvent) throws Exception
{
    // The correct implementation.
}

But if you wanted to use a method without parameters you were out of luck until now, because listener interfaces always expect a parameter. With 2.4 there will be a new interface, called IRunnable, which provides a method which does not accept any parameter and can throw any exception and the EventHandler will also accept listeners which implement this interface. That means that the scheme outlined above is now fully possible with lambdas.

private void initializeUI()
{
    button.eventAction().addListener(new UIActionListener() { ... });
    button.eventAction().addListener(this::doActionA);
    button.eventAction().addListener(this::doActionB);
    button.eventAction().addListener(this::doActionC);
    button.eventAction().addListener(this::doActionD);
}

private void doActionA()
{
    // A simple method with no parameters.
}

private void doActionB() throws Exception
{
    // A simple method which can throw *any* exception.
}

private void doActionC(UIActionEvent pActionEvent)
{
    // A method with the correct signature.
}

private void doActionD(UIActionEvent pActionEvent) throws Exception
{
    // A method with the correct signature which can throw *any* exception.
}

And more good news, did you notice that the visibility of these methods changed from public to private? With the new Lambda scheme these methods no longer need to be public, they can have any visibility and will still work as intended.

So JVx 2.4 is the release when it comes to Lambda support, and everyone who has the possibility to already use Java 8 can now enjoy full support for them.

JVxEE 1.2

Post to Twitter

JVxEE version 1.2 is out!

The good news

JVxEE is now available from Maven central, that means that you can add it as dependency to your Maven projects:

<dependency>
    <groupId>com.sibvisions.jvx</groupId>
    <artifactId>jvxee</artifactId>
    <version>1.2</version>
</dependency>

The first of the two major changes are that we fixed possible exceptions that might be thrown by JPAStorage.getEstimatedRowCount(ICondition), it should now work under all situations.

The second change is the handling of foreign key columns. Previously, foreign key columns where named with the pattern "REFERENCEDTABLE_REFERENCEDCOLUMN", which can lead to collisions if there is more than one column referencing the same table and primary key. So it was possible that you would end up with two columns with the same name, which of course can't be handled by the storage and databook correctly. We devised a new naming scheme and from now on the foreign key columns are named with a combination of the referencing column and the referenced column.

An example:

@Entity public class A
{
    @Id private int id;
    private B source;
    private B target;
   
    // Getters/Setters
}

@Entity public class B
{
    @Id private int id;
    private String name;

    // Getters/Setters
}

With 1.1 the generated columns would look like this, for entity "A":

ID          BigDecimal
B_ID        BigDecimal
B_NAME      String
B_ID        BigDecimal
B_NAME      String

And with 1.2:

ID          BigDecimal
SOURCE_ID   BigDecimal
SOURCE_NAME String
TARGET_ID   BigDecimal
TARGET_NAME BigDecimal

This is definitely an improvement!

The bad news

There is always a downside :(

The changes in the foreign key column naming scheme, to avoid collisions, also mean that most foreign key columns do now have a different name. You'll have to check your code for usages of the now differently named columns.

But there is also an upside! With EPlug you will find those easily.

Usage example

JVxEE provides the possibility to utilize the Java Persistence API (JPA) as backend for storages and databooks. JPA is powered by POJOs, like these:

@Entity public class Aircraft
{
    private String country;
    private String description;
    @Id @OneToMany private String registrationNumber;
}

@Entity public class Airport
{
    @Id @OneToMany private String code;
    private String country;
    private String location;
    private String name;
}

@Entity public class Flight
{
    @OneToOne private Aircraft aircraft;
    private String airline;
    @OneToOne private Airport airportDestination;
    @OneToOne private Airport airportOrigin;
    @Id private String flightNumber;
}

This is an extremely simplified model for airline flights.

There is an aircraft that can be used, airports that can be flown to and from and the flight itself. Flight is referencing both, the aircraft and the airport. Now we only need to tell JPA about these classes by placing a persistence.xml in the META-INF directory, like this one that we use for our unit tests:

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence              
                                 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"

             version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">

  <persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
    <class>com.sibvisions.rad.persist.jpa.entity.flight.Aircraft</class>
    <class>com.sibvisions.rad.persist.jpa.entity.flight.Airport</class>
    <class>com.sibvisions.rad.persist.jpa.entity.flight.Flight</class>

    <properties>
      <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" />
      <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:hsql://localhost/db" />
      <property name="javax.persistence.jdbc.user" value="sa" />
      <property name="javax.persistence.jdbc.password" value="" />

      <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
      <property name="eclipselink.ddl-generation.output-mode" value="database" />
      <property name="eclipselink.logging.level" value="FINE"/>
    </properties>
  </persistence-unit>
</persistence>

(Sure, it's also possible without manual XML mapping)

Now all that is left is creating a new storage that uses the JPA:

EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("test");
EntityManager entityManager = entityManagerFactory.createEntityManager();

JPAStorage storage = new JPAStorage(Flight.class);
storage.setEntityManager(entityManager);
storage.open();

And that's it! From here on there is only JVx code.

EPlug 1.2.0

Post to Twitter

Great news for everyone who uses, or plans to use our Eclipse plugin called EPlug, a new version  is available! Version 1.2.0 brings a whole truckload of new features and bug fixes.

Changes (Pro and VisionX)

  • Completion for resources is now more reliable
  • Sped up the time it takes for VisionX to reload a file if a change was made in Eclipse
  • MetaData changes are now properly handled
  • When selecting from VisionX to Eclipse it will be made sure that the server and client class both show up
  • Added the "Checkl File (EPlug)" command, which allows to easily re-run all checks on the current file
  • The hyperlinks for server calls/actions are now "fuzzy", which means that if there is no function with that signature, the next best function will be the target
  • Improved the error messages if there was a problem when checking databooks
  • Added completion for generic resources, which means you now can get completion for any resource in your project
  • The call to UIImage.getImage(String) is now checked at compile time if the resource exists
  • By default, databooks are now checked while you're typing for instant feedback. This can be disabled in the project properties
  • Added a view that displays all databooks in the current file, including column name and type
  • Added support for the constructor of UIEditor
  • Dramatically increased the speed of compile time checks

Eclipse Mars

Also we have tested and developed EPlug with Eclipse Mars, which means that you can use it in the latest and greatest Eclipse release version. Of course we haven't dropped support for older versions, EPlug should continue to work even on Eclipse Juno.

Download

You can install EPlug directly from the Eclipse Marketplace.