Presents for the community

Post to Twitter

We got awesome mail!

Our community T-shirts are in-da-house!

JVx, original green

JVx, original green

JVx, white

JVx, white

VisionX

VisionX

The text is on the front and logos are on the back. Simple and Smart as JVx and our Source Code.

The first chance to get a shirt will be in Hamburg, November 3rd. We'll present JVx at the Java User Group.

Details about LIVE css hacking

Post to Twitter

We have a short video about our LIVE css hacking feature for mobile JavaFX applications on YouTube:

JavaFX mobile LIVE CSS hacking


We demonstrate a mobile JavaFX application, running on a Nexus 9 Tablet. It's a pure JavaFX application with our mobile application frame and it was deployed with JavaFXPorts. In the video, we change some styles on our Laptop and the application updates its styles on demand. This is really useful because resolution/screen size can be different. Sometimes the background color looks different than on a Desktop, ... And it's easy to try out new styles without application restarts - same principle as developer tools for Chrome or FireBug for Firefox.

But how did we implement this feature?

It was too easy :)

Here are the "secrets":

  • A simple socket server for the application
  • A custom URL handler for loading remote-retrieved styles
  • A simple File watcher for the client

That's it!

But to be honest, the custom URL handler was very tricky, because we tried to find a very smart, non-static, solution. And every platform has its specific handling and URL loading mechanism. But one step after another.

I guess you know that a socket server isn't a real problem. We wrote our own "generic" socket server some years ago, for JVx and it's not tricky. In principle, it works like this snippet:

ServerSocket serverSocket = new ServerSocket(9999);
Socket clientSocket = serverSocket.accept();

PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

The problem is that you need a sort of protocol for the content. We've used our UniversalSerializer and send simple POJOs. The stylesheet POJO contains the css file as byte[]. Here's our server code:

CommunicationServer server = new CommunicationServer(findHost(), 9999);
server.addReceiver(r ->
{
    javafx.application.Platform.runLater(() ->
    {
        synchronized (oSync)
        {
            if (sLastCss != null)
            {
                logger.info("Remove remote CSS file ", sLastCss);

                launcher.getScene().getStylesheets().remove("remotecss://" + sLastCss);
               
                ObjectCache.remove(sLastCss);
            }

            sLastCss = ObjectCache.createKey() + ".css";
       
            ObjectCache.put(sLastCss, r.getObject(), -1);

            logger.info("Install remote CSS file ", sLastCss);
       
            launcher.getScene().getStylesheets().add("remotecss://" + sLastCss);
        }
    });
   
    return null;
});
server.start();

We add custom stylesheets with remotecss as protocol. The resource loading mechanism of Java(FX) tries to load the URL automatically. The protocol isn't a standard protocol and so we had to create a custom URL handler. The problem wasn't the handler itself because it's straight forward:

public class Handler extends URLStreamHandler
{
    @Override
    protected URLConnection openConnection(URL url) throws IOException
    {
        if (url.toString().toLowerCase().endsWith(".css"))
        {
            return new CssURLConnection(url);
        }
       
        throw new FileNotFoundException();
    }
}

And the CssURLConnection also wasn't a problem:

private class CssURLConnection extends URLConnection
{
    public CssURLConnection(URL pUrl)
    {
        super(pUrl);
    }

    @Override
    public void connect() throws IOException
    {
    }

    @Override
    public InputStream getInputStream() throws IOException
    {
        Object oCss = ObjectCache.get(getURL().getHost());
       
        if (oCss instanceof String)
        {
            return new ByteArrayInputStream(((String)oCss).getBytes("UTF-8"));
        }
        else if (oCss instanceof byte[])
        {
            return new ByteArrayInputStream((byte[])oCss);
        }
       
        throw new FileNotFoundException();
    }    
}

The problem was that the JVM didn't know how to load remotecss:// URLs because it doesn't have a default handler. The JVM offers different solutions for this problem and the well known is:

URL.setURLStreamHandlerFactory(factory);

But this is a static mechanism and we didn't know if another library uses the same method. There's no getURLStreamHandlerFactory in URL and the solution wasn't good enough for us. For a simple test application this restriction shouldn't be a problem, but we didn't like it because we're framework developers.

There's another solution for the problem, because the source code of URL contains the static method:

static URLStreamHandler getURLStreamHandler(String protocol)

This method tries to load protocol handlers automatically, if definded via system property java.protocol.handler.pkgs or from package: sun.net.www.protocol.protocolname.Handler

After reading the source code, we found a blogpost about this feature, read more. It was easy to search with the right keyword after we knew the solution.

...be careful with security manager, but this shouldn't matter.

The URL implementation for Android is a little bit different because but if you set the system property, it'll work as expected.

The hardest parts were done and the last thing was the file watcher client because we planned to send the changed CSS file(s) to the app automatically. Here's our solution (Java8 style):

thWatcher = new Thread(() ->
{
    File fi = ResourceUtil.getFileForClass("/live.css").getParentFile();

    FileSystem fsys = FileSystems.getDefault();

    Path pathCss = fsys.getPath(fi.getAbsolutePath());

    try
    {
        try (final WatchService service = fsys.newWatchService())
        {
            WatchKey wkey = pathCss.register(service, StandardWatchEventKinds.ENTRY_MODIFY);

            while (!ThreadHandler.isStopped(thWatcher))
            {
                WatchKey key = service.take();

                for (WatchEvent<?> event : key.pollEvents())
                {
                    Kind<?> kind = event.kind();

                    if (kind == StandardWatchEventKinds.ENTRY_MODIFY)
                    {
                        Path changed = (Path)event.context();

                        if (changed.toString().equals(FileUtil.getName(CSS)))
                        {
                            File fiModified = new File(fi, changed.toString());

                            if (fiModified.lastModified() > 0)
                            {
                                if (lLastModified != fiModified.lastModified())
                                {
                                    try
                                    {
                                        client = getClient();
                                        client.send(FileUtil.getContent
                                           (ResourceUtil.getResourceAsStream("/live.css")));

                                        lLastModified = fiModified.lastModified();

                                        System.out.println("Sent CSS to application");
                                    }
                                    catch (Exception e)
                                    {
                                        // next try
                                        client = CommonUtil.close(client);
                                    }
                                }
                            }
                        }
                    }
                    else if (kind == StandardWatchEventKinds.OVERFLOW)
                    {
                        continue;
                    }
                }

                if (!key.reset())
                {
                    thWatcher = ThreadHandler.stop(thWatcher);
                }
            }

            wkey.reset();
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();

        synchronized (TestCommunication.this)
        {
            TestCommunication.this.notify();
        }
    }
});

thWatcher.start();
ThreadHandler.add(thWatcher);

The source code examples aren't complete but I guess you can implement your own solution based on them. We made tests with iOS, Android and Desktop applications and didn't have any problems. The CSS editing feature would be a very useful extension for ScenicView but it's not available right now.

Our test devices:

Test devices

CSS hacking - test devices

Code once. Run anywhere.

Post to Twitter

It's some time since my last post about JVx. But I have a good excuse - Coding :)

I tried to improve our JavaFX UI for mobile devices. It was a hard fight but I won. Not everything is done right now, but the result is soo awesome!

Many of you know that JVx is an Application Framework. It's small and simple but still very powerful. It follows the convention over configuration principle and it was designed to be UI technology independent. Oh, it follows the Single sourcing principle too, it's a Full-Stack-Framework, contains a very smart persistence implementation, and so on.

What means UI technology independent?

We define the term as follows:

Code an application once and use it on different platforms and with different devices and different technologies.

As platform, we recommend Windows, Linux or MacOS. Devices are Desktop PCs/Notebooks, Smartphones, Tablets or embedded Hardware like RaspberryPi. We use the term technology for UI toolkits/standards like HTML5, Java Swing or JavaFX.

JVx isn't a JavaScript framework or library because it supports every platform with maximum power. This means that a desktop application runs as standalone application on your desktop computer with full access to connected hardware. A HTML5 application runs in a web browser and has limited access to the device but you have full css features and websockets. If your application runs on mobile devices, simply use all available hardware features and gesture support.

All the platform/device/technology specific problems were solved in JVx and a developer simply has a standard API to create applications. If the standard API isn't enough, it's easily possible to access the technology features without limitations. JVx encapsulates but doesn't hide anything.

With JVx you can code desktop applications, browser based HTML5 applications or native mobile applications without know-how of every platform/device/hardware.

I guess it's time for facts and some screenshots should clarify what I mean.

Desktop Swing UI

Desktop Swing UI

Desktop JavaFX UI

Desktop JavaFX UI

vaadinUI corporate

vaadinUI corporate

vaadinUI simple

vaadinUI simple

vaadinUI legacy

vaadinUI Legacy

mobile fxUI

mobile fxUI

mobile fxUI menu

mobile fxUI menu

mobile fxUI legacy

mobile fxUI legacy

All screenshots show the same application (same source code) with different UI technologies and on different devices. We have UI implementations for vaadin, JavaFX, Swing. We have different application styles because the application shouldn't look like a desktop application, on mobile devices or in your browser (but it's possible).

The application style itself is fully customizable and it's only one possible implementation. It's not a problem to change it or create a new one from scratch. We've defined that our standard applications have a menu, a toolbar a content are (for screens) and an authentication mechanism (login).

If you compare the vaadinUI with Swing or JavaFX UI, you'll see that the vaadin style has a completely different menu. There's also a legacy mode which shows windows for every screen, but this style isn't the preferred one. Sure, sometimes this style makes sense but it's not very user-friendly. If you have an application with few screens, a simple menu would be useful and if your application has many screens, the corporate style could be better because it has a menubar and a sidepane for quick navitation.

The mobile variant is our latest style and it's really different. You won't use apps in MDI style. Sure, we have this style but it's ugly. We like hamburger menus as shown in the screenshots.

JVx is very fast, flexible and powerful. Don't waste time for platform problems, simply implement your requirements by using JVx.

Talk: JVx stellt sich vor. Zurück zur Effizienz

Post to Twitter

Wir sind am Dienstag, 03. November zu Gast bei der JUG Hamburg.

Nähere Details gibt es hier.

Im Moment sieht die Teilnehmerzahl verblüffend aus und das Thema dürfte auch für viele passen. Wir können allen interessierten schon jetzt versprechen, daß wir einige Überraschungen mitbringen. An einem zusätzlichen Highlight arbeiten wir noch und lasst euch einfach überraschen. Es wird auf jeden Fall etwas neues sein!

Official FontAwesome support in JVx

Post to Twitter

We're happy to announce that JVx got "official" (experimental) support for FontAwesome icons. We made some changes to our internal image management but it wasn't a big change and no API was touched!

How it works?

Simple, as usual :)

An example:

UIButton button = new Button("Press me");
button.setImage(UIImage.getImage(IFontAwesome.USER_SMALL);

But that's not all because we support special things like coloring, e.g.:

UIButton button = new Button("Press me");
button.setImage(UIImage.getImage(IFontAwesome.USER_SMALL + ";color=orange");

and it's also possible to set the size:

UIButton button = new Button("Press me");
button.setImage(UIImage.getImage(IFontAwesome.USER_SMALL + ";size=24;color=orange");

The support was split in different parts. JVx got the IFontAwesome interface which defines FontAwesome icon names. This doesn't mean that every UI implementation supports FontAwesome!

Every UI has to support FontAwesome because it's UI dependent how font icons will be rendered.

We have support in our Swing UI and vaadin UI, but currently we don't have support in our JavaFX UI (not yet). This means, that you can use FontAwesome directly in your JVx application out-of-the-box without manual configuration and without accessing resources directly.

Pure Swing

We have a read-to-use FontAwesome ImageIcon for Swing developers. It's called JVxFontAwesome. It's easy to use this icon in your Swing application, also without JVx UI.

vaadinUI

There are some limitations in Vaadin, because it's not possible to add custom style properties to menu items via API calls. It's possibel via css files, but this is a limitation you should know. Sure, it shouldn't be a big problem but vaadin doesn't support this feature right now.

Vaadin up to 7.5.6 has support for FontAwesome 4.1.0 and JVx has support for 4.4.0. Not all icons are available in vaadin UI right now! There's a ticket about an update to 4.4.0.

JavaFX UI, native mobile clients

We didn't implement FontAwesome in JavaFX UI or our Android, iOS clients - not yet. It shouldn't be a big problem to implement the support but we're still in an experimental phase ;)