Eclipse NEON with ANT and JRE6

Post to Twitter

This is a follow-up post for: Eclipse MARS with ANT and JRE 6 (story).

New Eclipse version, same problem. We have an updated ant plugin for you.
The plugin was created for:

Version: Neon Release (4.6.0)
Build id: 20160613-1800

Don't forget the -clean start (read the original article for more details).

Download the plugin from here. It works for us - no warranty!

JVx 2.5 - summer release

Post to Twitter

The next JVx release will be version 2.5. It will be available by the end of this week (beginning of July). It's a really cool release because JVx got awesome new features. We had to change the API a little bit but it shouldn't be a problem for your existing applications.

What will be interesting?

  • Push-light

    Our push support has nothing to do with Websockets. It's a technology independent solution for JVx. The Push-light mechanism is available on server-side and enables you to send objects from the server to the client. If you use a direct connection betwenn client and server, the objects wil be sent immediate (e.g. vaadin UI). If you use a serialized connection, the objects will be sent with next client call or alive check.

    The API is simple:

    SessionContext.publishCallBackResult("MESSAGE", "Please logout!");

    or, in a Thread

    final ICallBackBroker broker = SessionContext.getCurrentInstance().getCallBackBroker();

    Thread th = new Thread(new Runnable()
    {
        public void run()
        {
            try
            {
                int i = 0;

                while (isMessageLoopEnabled(i))
                {
                    Thread.sleep(200);
                   
                    broker.publish("MESSAGE", getMessage(i++));
                }
            }
            catch (InterruptedException ie)
            {
                //done
            }
        }
    });
    th.start();

    It's also possible to publish to all clients, via ICallBackBroker.

    The client code is short and simple:

    connection.addCallBackResultListener(new ICallBackResultListener()
    {
        public void callBackResult(CallBackResultEvent pEvent)
        {
            if ("MESSAGE".equals(pEvent.getInstruction()))
            {
                showMessage((String)pEvent.getObject());
            }
        }
    });

    More details: Tickets #25, #1635

  • H2 DB support

    We support H2 with a custom H2DBAccess. The auto detection works with URLs: jdbc:h2:.

  • SQLite DB support

    We support SQLite with a custom SQLiteDBAccess. The auto detection works with URLs: jdbc:sqlite:.

  • MySql limit support

    Read more...

  • Life-cylcle object method inheritance
  • Pie control
  • Set individual cells of a table readonly
  • Connection retries

    We try to re-send requests, if errors occur during transmission. This feature will be available for serialized connections only.

  • Security improvements

    see Tickets: #1605, #1606, #630.

  • API changes

    ICellFormat got a Style attribute and the createCellFormat of IFactory got one more parameter

IT-Tage 2016 - I'm speaker

Post to Twitter

Logo-itt2016-Web   I'm a speaker at IT-Tage 2016 in Frankfurt - December, 14th.
My talk will be about "JVx – Zurück zur Effizienz! "

Read more.

The full time table.

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.

VisionX 2.3 Update Release

Post to Twitter

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

  • VisionX listener

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

  • Guides

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

  • Synonyms pointing to a view

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

  • Lib update

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

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

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

Have fun with VisionX 2.3.235.

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!

Effiziente Software Entwicklung mit JavaFX und JVx

Post to Twitter

javaaktuell2016 Ein spannender Artikel über JVx und JavaFX ist im aktuellen JavaAktuell zu finden.

Der Artikel wurde von Roland Hörmann verfasst und behandelt das Thema Effiziente Software Entwicklung mit Java und insbesondere mit JavaFX bzw. dem OpenSource Java Framework JVx.

Wer das Magazin nicht zur Hand hat, kann den Artikel auch von hier laden und sofort lesen.

EPlug 1.2.4 is available

Post to Twitter

Our Eclipse plugin for JVx and VisionX is available as version 1.2.4.
It's a small bugfix release.

Changes

  • Proxy support (tests)

    Some customers had problems with http(s) proxies and our trial activation. We made extended tests with (win/linux) proxies and didn't find any problems. We reduced the communication timeout because it was too long. Please send us your feedback.

  • Additional checks for client/server code mixing

    It might be a problem if you use a server class (src.server) in your client classes (src.client). This depends on the deployment mode (Web, Desktop, ...), but it's better to separate client and server code. The new check can be dis/enabled but it checks by default if your client has direct server references.

  • Using Metadata independent of AbstractCachedStorage

    It's now possible to use column name autocompletion, even if the storage isn't an instance of "AbstractCachedStorage".

Simply update EPlug via Eclipse or jump to the info page.

Using Oracle JET with VisionX/JVx

Post to Twitter

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

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

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

This time, I tried to work with Oracle JET.

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

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

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

Conditions

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

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

Contacts table

Contacts table

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

What about the source code?

We have one html page, index.html:

<!DOCTYPE html>

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

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

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

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

We need two javascript files, main.js:

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

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

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

and app.js

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

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

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

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

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

Long story, short:

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

And my simple solution for Basic authentication was:

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

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

The "authenticator" will be set as oauth property:

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

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

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

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

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

to RestletServlet definition.

Example Download

Use OBridge together with JVx

Post to Twitter

OBridge is a nice Java FOSS project. The description according to the website:

OBridge generates standard Java source code for calling PL/SQL stored procedures and functions.

It's focus is on Oracle but this wasn't a limitation for us to test it with JVx.

Most of you know that JVx has generic support for procedure/function calls which is DB independent. The implementation is not really type-safe but it's simple.
If type-safety is preferred, you could use OBridge for your application.

I write about this library, because it's super small and simple. We love small and simple things :)

Assume, we have following PL/Sql procedure:

CREATE OR REPLACE PROCEDURE execProcedure(pNumber IN OUT NUMBER,
                                          pInText IN VARCHAR2,
                                          pOutText OUT VARCHAR2) IS
  nr NUMBER := pNumber;
BEGIN
  pOutText := 'Out: '|| pOutText ||' In: '|| pInText;

  pNumber := pNumber + pNumber;
END execProcedure;

and function:

CREATE OR REPLACE FUNCTION execFunction(pNumber IN OUT NUMBER,
                                        pInText IN VARCHAR2,
                                        pOutText OUT VARCHAR2) RETURN VARCHAR2 IS
  res VARCHAR2(200);
  nr NUMBER := pNumber;
BEGIN
  pOutText := 'Out: '|| pOutText ||' In: '|| pInText;

  pNumber := pNumber + pNumber;

  RETURN 'IN-Param Nr: '|| nr;
END execFunction;

 

With JVx, the procedure and function call will look like following JUnit test:

@Test
public void testCall() throws Exception
{
    DBAccess dba = DBAccess.getDBAccess("jdbc:oracle:thin:@localhost:xe", "test", "test");
    dba.open();
   
    /**
     * Procedure call.
     */

    OutParam ouTextParam = new OutParam(InOutParam.SQLTYPE_VARCHAR);
    dba.executeProcedure("execProcedure", BigDecimal.valueOf(25),
                         "Hello JVx' procedure", ouTextParam);

    Assert.assertEquals("Out:  In: Hello JVx' procedure", ouTextParam.getValue());

    /**
     * Function call.
     */

   
    ouTextParam = new OutParam(InOutParam.SQLTYPE_VARCHAR);
    Object oResult = dba.executeFunction("execFunction", Types.VARCHAR,
                                         BigDecimal.valueOf(25),
                                         "Hello JVx' function", ouTextParam);
   
    Assert.assertEquals("IN-Param Nr: 25", oResult);
    Assert.assertEquals("Out:  In: Hello JVx' function", ouTextParam.getValue());
}

 

and the same with OBridge:

@Test
public void testCall() throws Exception
{
    DBAccess dba = DBAccess.getDBAccess("jdbc:oracle:thin:@localhost:1521:xe", "test", "test");
    dba.open();
   
    /**
     * Procedure call.
     */

    Execprocedure proc = ProceduresAndFunctions.execprocedure(BigDecimal.valueOf(35),
                                           "Hello OBridge procedure", dba.getConnection());
   
    Assert.assertEquals("Out:  In: Hello OBridge procedure", proc.getPouttext());

    /**
     * Function call.
     */

   
    Execfunction func = ProceduresAndFunctions.execfunction(BigDecimal.valueOf(35),
                                            "Hello OBridge function", dba.getConnection());
   
    Assert.assertEquals("IN-Param Nr: 35", func.getFunctionReturn());
    Assert.assertEquals("Out:  In: Hello OBridge function", func.getPouttext());
}

 

The OBridge code saves two LoC for the call, but it needs some additional classes and packages in your application. If you change your procedure or function definition in the database, you have to recreate the Java files.
This is not needed with pure JVx, but it's your choice.

The code generation is not tricky, simply follow the official documentation. Our steps:

  • Create the file config.xml in the working directory of your project
    <?xml version="1.0" encoding="UTF-8"?>

    <configuration>
        <jdbcUrl>jdbc:oracle:thin:test/test@localhost:1521:xe</jdbcUrl>
        <sourceRoot>./src/</sourceRoot>
        <rootPackageName>com.sibvisions.apps.obridge.db</rootPackageName>
        <packages>
            <entityObjects>objects</entityObjects>
            <converterObjects>converters</converterObjects>
            <procedureContextObjects>context</procedureContextObjects>
            <packageObjects>packages</packageObjects>
        </packages>
    </configuration>

  • Run the main class: org.obridge.OBridge with argument: -c config.xml
    (or use -c fullqualified_path_to_config.xml)
 

If you love our generic built-in solution, you don't need OBridge but if you prefer type-safety it's definitely an option.