Building e4 JavaFX applications with gitlab-ci and docker

We’ve decided internally sometime ago to use a self-hosted gitlab instance for our projects.

To get started quickly we first only used the ticket-system and keep our jenkins-instance to do our builds which works fine but it somehow bothered me that we’ve been unable to use the gitlab-ci system integrated directly into the gitlab-instance.

So yesterday we started to explore how we can do builds using the docker integration of gitlab-ci and after some troubles with FreeBSD & docker (where our gitlab instance is hosted on) we managed to get a build going.

If you want to do that as well. You can make use of a docker-image we prepared containing:

  • Maven 3.3.x
  • Oracle-JDK-8

(we unfortunately could not use the java-images provided by dockerhub because they ship OpenJDK8 who does not include JavaFX).

So if you run your e4 on JavaFX project as well on gitlab all you need to do is to add a gitlab-ci.yml to your git-repository holding the following content:

image: tomsontom/oracle-java8-mvn:latest

build:
  script: "cd my.project.app.releng; mvn clean package"

e(fx)clipse 2.3.0 released

Right for EclipseConNA 2016 next week we released e(fx)clipse 2.3.0. This release mainly provides features in the runtime layer.

Where to get it from

If you are interested in the Tooling you can:

If you want to develop e4 application who use JavaFX instead of SWT you need to point your target-platform and built towards http://download.eclipse.org/efxclipse/runtime-released/2.3.0/site.

Let’s take a look of the most interesting new features and changes.

Source editing

A lot of work has gone into the StyledTextArea where we rewrote the internals and implemented our own virtual-flow element instead of reusing the ListView provided by the JavaFX library.

We also did this to provide many new features:

  • Keyboard navigation like in the Eclipse IDE
  • Support for Error-Markers in the text area (see screenshot below)
  • Support to display white space characters (see video below)
  • Pluggable Rulers for the left Editor side

The following screen shot demonstrates the error markers inside the text:
screen_errormarker

The following video provides you an overview what features the code editor widget provides with the 2.3.0 release.

Object Serialization / Deserialization

We enhanced the ObjectSerializer-API allowing adding support for collections with none basic types (eg. a Set/List of Enums).

@Inject
ObjectSerializer serializer;

enum States {
  STATE_1,
  STATE_2,
  STATE_3
}

public void serializeData() {
   String data = serializer
     .serializeCollection( Arrays.asList( STATE_1, STATE_2 ), States.class );
}

and as the @Preference-System of e(fx)clipse is delegating to the obserializer you can use it there too.

@Inject
@Preference(key="state")
Property<List<State>> stateList;

public void rememberState(List<State> state) {
  stateList.set( state );
}

Accessibility Improvements

We worked a bit on improvements of the accessibility support eg making use of the accessibilityPhrase defined in your E4-Application model, makeing FontIconView mouse transparent, … .

Preparing for JDK9

To implement certain features we need to none public JavaFX APIs, we got rid of most of them but there’s most likely still work do be done.

Using TypeScript LanguageService to build an JS/TypeScript IDE in Java

Yesterday I blogged about my endeavors into loading and using the TypeScript Language Service (V8 and Nashorn) and calling it from Java to get things like an outline, auto-completions, … .

Today I connected these headless pieces to my JavaFX-Editor-Framework. The result can be seen in the video below.

To get the TypeScript LanguageService feeling responsible not only for TypeScript files but also for JavaScript I used the 1.8 beta.

As you notice JS-Support is not yet really at a stage where it can replace eg Tern but I guess things are going to improve in future.

Why I think @UIEventTopic / @EventTopic have been a bad idea

I’ve been working on a document since some time who holds my thoughts on the future direction of Eclipse 4 or better the Eclipse 4 Application Platform.

At first I’d like to mention that these as my personal views, not aligned with the e4 committers, so you’ll most likely find others who disagree.

It’s not my intention put e4 or any e4 committer down and if I’d blame someone it would be myself because I was part of the e4 effort since day 1.

The document is not yet ready but inspired by a tweet from Marcel Bruch

I’d like to take one of the points I’ll mention in this big vision/reflection document and explain why I think in retrospect providing those 2 annotations is wrong.

OSGi-Leakage

The first problem I have with those annotations is not an architectural one but caused by the bundle they are currently shipped in. We currently find them in “org.eclipse.e4.ui.di” and “org.eclipse.e4.core.di.extensions” who themselves require things like the Eclipse-DI-container, Equinox-container.

In my world of e4 components this is a deal breaker, as I want my code have no dependency on any of those bundles at compile time nor runtime but in general I think this is a minor problem and fixable. The architectural is the real blocker.

Event data is different to any other DI-Information

The real problem I have with @UIEventTopic and @EventTopic is the information they carry with them is totally different to any other data available in the DI-System (starting from OSGi-Services to Preference or IContextFunction derived values) because it’s only temporary. I think this characteristic makes @UIEventTopic/@EventTopic data not suited for DI.

The guess I have for those annotations being so popular is that they free you from the useage of IEventBroker (who leaks OSGi at an even larger scale by showing OSGi-Classes in its API, once more for no good reason) and the verbose code you need to write to subscribe (wild guess once more nobody was really worried about the OSGi-Class-Leakage).

@PostConstruct
void init(IEventBroker b) {
   b.subscribe( "my/event/Topic", new org.osgi.service.event.EventHandler() {
     public void handle(org.osgi.service.event.Event event) {
       handleEvent( (String)event.getProperty(IEventBroker.DATA) );
     }
   } );
}

private void handleEvent(String data) {
   // ...
}

In a Java8 world the verbosity can be reduced with the help of lamdas and method refs


import static my.sample.Util.extractEventData;

@PostConstruct
void init(IEventBroker b) {
  b.subscribe( "my/event/Topic", extractEventData(this::handleEvent));
}

private void handleEvent(String data) {
   // ...
}

// Util.java
public static <T> Consumer<Event> extractEventData( Consumer<T> dataConsumer) {
   return e -> (T)e.getProperty(IEventBroker.DATA);
}

The extractEventData could be provided by IEventBroker in a Java8 world BTW.

You loose typesafety for no good reason

IEventBroker and @UIEventTopic/@EventTopic trade IMHO typesafety for no good reason.

One can argue that this is the case for DI in general as well but you trade in this case typesafety against loose coupeling freeing your business code from dependencies on large framework (and yes I consider e4 and OSGi large frameworks) and providing you better testing support – so you get something in return.

This is not true for IEventBroker nor is it true for @UIEventTopic/@EventTopic, while IEventBroker could be fixed to provide a certain amount of typesafety (see e(fx)clipse EventBus) this will never be possible for @UIEventTopic/@EventTopic!

One could argue that on the receiver side you’ll have less framework bindings (in case one splits out the annotations from their existing owner bundle) but because the publisher requires the event bus anyways I don’t see any reason the receiver should not and the EventBus-Service is easy enough to be mocked in Unit-Tests.

And because it is not unlikely that many events are sent through the event system it puts pressure on the DI system which could have been avoid if you used the EventBus directly.

e(fx)clipse 2.2.0 – Typesafe EventBus

With e(fx)clipse we ship as part of our core-bundle (the one able to run in any OSGi and Plain-Java-Env) since 2.1 an org.eclipse.fx.core.event.EventBus which we enhanced in 2.2.0 to provide a certain level of typesafety.

Useage is straight forward:

  1. Define a Topic-Instance
    public class Constants {
      public static final org.eclipse.fx.core.event.Topic<String> MY_TOPIC 
        = new org.eclipse.fx.core.event.Topic<>("my/sample/Topic");
    }
    
  2. Publishing is done with
    @PostConstruct
    public void init(org.eclipse.fx.core.event.EventBus eventBus) {
      eventBus.publish( MY_TOPIC, "Hello World!", true );
    }
    
  3. Subscribing to events
    import static my.sample.Constants.MY_TOPIC;
    import static org.eclipse.fx.core.event.EventBus.data;
    
    @PostConstruct
    public void init(org.eclipse.fx.core.event.EventBus eventBus) {
      eventBus.subscribe( MY_TOPIC, data(this::handleTopic) );
    }
    
    private void handleTopic(String data) {
      // ...
    }
    

If you are interested in other new features of 2.2.0 look at this overview page

e(fx)clipse 2.2.0 – Maximize an UI-Component

I think allowing to maximize a certain UI-Element in your e4 on JavaFX application has been the most demanded features missing for e4 on JavaFX. e(fx)clipse 2.2.0 adds support to maximize an UI-Element as shown in the following video:

All you need to do is:

  • Add org.eclipse.fx.ui.workbench.renderers.base.addons.MinMaxAddon to your Application.e4xmi addons list
  • (Optional) Register an OSGi-Service of type org.eclipse.fx.ui.workbench.renderers.base.services.MaximizationTransitionService if you want some nice transitions, we ship a default transition as see in the above video named org.eclipse.fx.ui.workbench.renderers.fx.services.ProgressiveMaximizationTransitionService

I think this one coolest features we added since a long time and what makes it even cooler this support was contributed by one of the frameworks adopters Sun Volland.

If you are interested in other new features of 2.2.0 look at this overview page