Proper OSGi access restriction warnings for e(fx)clipse maven projects

In the last few days I worked on the last required feature to abandon PDE and use maven (with the bnd-maven-plugin) and m2e.

Does anyone reading my blog know if IntelliJ and Netbeans also have a feature like this?

Advertisements
Posted in e(fx)clipse, Uncategorized | Leave a comment

Cross IDE Dev-Support for “e4 on JavaFX” –¬†We are almost there

In the last few days I made a major step towards supporting all major Java-IDEs (Eclipse, Netbeans, IntelliJ IDEA) to develop “e4 on JavaFX” applications.

The key to this multi-IDE support is that we don’t use the MANIFEST-First approach from PDE but we use:

  • Maven 3.5
  • bnd-maven-plugin
  • A custom maven-plugin for launching in Netbeans and IntelliJ

Eclipse

For every member on your team who likes the Eclipse IDE.

In Eclipse we use a custom launcher who uses the maven-project dependency information to launch OSGi and install all necessary bundles.

Netbeans

For every member on your team who likes Netbeans

As you notice hot-code replacement is not yet working (or maybe I’m using Netbeans wrong?) Is there anything i need to do after having changed the file to hot-swap it?

IntelliJ IDEA

For every member on your team who likes IntelliJ

As you notice hot-code replacement is not yet working (or maybe I’m using IntelliJ IDEA wrong?) Is there anything i need to do after having changed the file to hot-swap it?

Posted in e(fx)clipse, Uncategorized | 10 Comments

Introducing (another/additional) JavaFX TestFramework

Let me start with the statement that TestFX is somewhat the default JUnit-Testframework for JavaFX application and is what we proposed to use to all our customers and our projects until today where we introduce our own one.

There are 2 different problem vectors we have:

  • A licensing issue we have with it at Eclipse.org: TestFX is licensed under EUPL which to me as a software developer looks ok but it looks like the IP-Department at Eclipse.org is not happy about it and refused me to use it. I don’t blame anyone but need to cope with the situation as is!
  • Implementing JUnit-Tests for OSGi-JavaFX applications: This is a pure technical issue and something we could have solved (although it would have meant to change the way TestFX works) but after having hit the licensing problem my motivation to resolve that problem was not really there

Anyways let’s look at what I’ve started to implement as a replacement for TestFX.

BestSolution FX-Test

First of all we decided for now that we don’t integrate the test-framework into e(fx)clipse but treat it as an independent entity at github and release it under EPL from there.

Writing JUnit-Tests is done by subclassing a base class (current only one available is FXComponentTest) and implementing your JUnit-Tests might look like this:

@Test
public void sample() {
  // Search with a css-selector query
  // and generated a click on the button
  rcontroller().cssFirst(".button").get().click();
}

In contrast to TestFX, tests written with our API can not run directly but you need to decided if you want to:

  • Use a specific runner using @RunWith(FXRunner.class)
  • Use a Rule @FXTest and annotate all UI-Test methods with it

which on the plus-side means that the @Test-methods are executed on the JavaFX-UI-Thread (unlike TestFX where they are executed on another thread most like the main-thread)

For more information that a look at the project README.md.

Let me close this post saying that we are very early in the development and things are still in the flux so we are happy for any feedback we get.

Posted in e(fx)clipse | 4 Comments

e(fx)clipse 3.0.0 is released

e(fx)clipse has been released on June 6th but because of the high load of JavaFX projects we are working on I did not have time to write the public release announcement.

In total we have worked on ~100 tickets most of them adding new features. We also moved our dev infrastructure to github.com and while doing that we’ve split the project into 2 repositories:

We believe that moving to github and the upcoming pure maven-build-story we currently work on in an extra branch will make it easier for others to consume our libraries in none OSGi/Eclipse/e4-Projects.

While we are switching our project structure to pure maven you can already consume our libraries from a maven-repository we host ourselves (see http://maven.bestsolution.at/)

Let’s take a short tour through some of the 3.0 highlights.

Support for Java 9

3.0 is the first release who is fully compatible with Java9 and JPMS. Historically we used non-public APIs and even used reflection to eg “hack” DnD in TabFolder. All code that would be broken in Java9 has been reworked to run on Java8 and Java9.

Some of the none public APIs we used in Java8 have been promoted to public API in Java9 and to support both Java 8 and 9 in the same codebase we extracted those into utility class org.eclipse.fx.ui.controls.JavaFXCompatUtil:

Java 8 Java 9 JavaFXCompatUtil
Window#impl_getWindows() Window#getWindows() getAllWindows()
KeyCode#impl_getChar() KeyCode#getChar() getChar(KeyCode)
KeyCode#impl_getCode() KeyCode#getCode() getCode(KeyCode)

Utilities to work with JavaFX Properties

FXBindings

JavaFX has a Bindings class to setup bindings between different Observables but we missed some features we frequently need in our application code hence we added an org.eclipse.fx.core.bindings.FXBindings who eg has:

  • tenaryBinding(ObservableBooleanValue, ObservableValue<T>, ObservableValue<T>) : Binding<T>
    allowing you to defined if-else in a JavaFX binding way
  • concat(ObservableList<? extends A>...) : ListBinding<A>
    to concat the lists to one and keep the target updated when one of the source lists change
  • concat(String, ObservableValue<T>...) : StringBinding
    concat the lists and concat the items with the given delimiter and keep the binding updated
  • bindContent(List<T>, ObservableList<E>, Function<E, T>) : Subscription
    similar to Bindings.bindContent but allows to use a converter function

A very special feature is a BindingStream you can create with bindStream(ObservableValue<T>) who is similar to Bindings.select but is:

  • Typesafe
  • Provide a Property as the leaf

Let’s look at a concrete example.

class Person {
  public ObjectProperty<Address> address();
}

class Address {
  public StringProperty street() { /* ... */ }
}

class UI {

  ObjectProperty<Person> currentPerson = /* ... */;

  TextField street;

  bindUI() {
     street.textProperty().bindBidirectional( 
      FXBindings.bindStream( currentPerson )
        .map( Person::address )
        .collect( 
           FXCollectors.toProperty( Address::street ) 
        )
     );
  }

}

@ContextValue improvements

@ContextValue is IMHO one of the coolest concepts we introduced in e(fx)clipse to make reuseable components. In 3.0 we added a scope-Property who allows you to fix a publishing scope.

As of 3.0 we support:

  • APPLICATION: Publish the value in the IEclipseContext of the application
  • LOCAL: Publish the value in the local IEclipseContext
  • DYNAMIC: Publish the value using IEclipsContext#modify and the application container is responsible to mark the target context

with DYNAMIC as the default.

ThreadSynchronize improvements

Halt program flow

We added a new API to halt the program flow (NOT the event loop) like this:


ThreadSynchronize t = ...;
TextField username = new TextField();

BlockCondition<String> w = new BlockCondition<>();
username.setOnAction( 
  e -> w.release( username.getText() ) );

System.out.println(t.block( w ));

Headless implementation

We at BestSolution use the MVVM-Pattern for our JavaFX applications and there we fetch data from backend-services in none-ui-threads and so we need to synchronize from a Background- to the UI-thread using ThreadSynchronize.

While things work perfectly fine in the real application because the JavaFX Framework is up and running things fall apart when you test your ViewModel in a headless JUnit-Tests. For that purpose there’s now the possibility to create a ThreadSynchronize instance like this:

ThreadSynchronize t = 
  ThreadSynchronize.createBasicThreadSyncronize(
    new EventLoop()
  );
Posted in e(fx)clipse, Uncategorized | 1 Comment

e(fx)clipse runtime library – Working with the (JavaFX) UI-Thread

When developing UI-Application a very frequent task is

  • to synchronizes yourself back from an worker-thread to the UI-Thread
  • schedule task to run in the future
  • Block the program flow and wait for a condition being met (in SWT called spinning the event loop)

JavaFX 8 has a public API for most of those building blocks (only exception is Event-Loop-Spinning who was an internal API in Java8 and is public API in 9) but using higher level API reduces the boilerplate code you need to implement.

Before we start let’s see how you can access to it in your maven-driven projects (I’m not gradle safey enough to show how it works there) you need to

  • add the efxclipse maven repository (at the time of this writing you need to nightly repository because you need at least 3.0.0)
  • add the following dependency
    <dependency>
      <groupId>at.bestsolution.efxclipse.rt</groupId>
      <artifactId>org.eclipse.fx.ui.controls</artifactId>
      <version>3.0.0-SNAPSHOT</version>
    </dependency>
    

Let’s take a look at some of those APIs and how they can help you write better code:

Writing back from worker thread

Let’s suppose we have a service who returns a search result as a CompletableFuture and we want to push the result – once available – to JavaFX ObjectProperty:

import org.eclipse.fx.core.ServiceUtils;

// Lookup the domain service in the service registry
PersonSearchService service = 
  ServiceUtils.getService(PersonSearchService.class);

ObjectProperty<Person> person = ...;

CompletableFuture<Person> result = 
  service.findByName("Tom","Schindl");

Let’s for a second suppose we can interact with our UI-Toolkit on ANY-Thread we could simply write:

result.thenAccept( person::set );

Unfortunately none of the UI-Toolkits I know would support this because they require you to sync on a special thread called the UI-Thread. JavaFX is not different in this aspect.

Plain JavaFX APIs:

result.thenAccept( p -> {
   Platform.runLater( () ->
     person.set(p);
   );
} );

Using e(fx)clipse’ ThreadSynchronize#asyncExec(T,Consumer<T>):

import org.eclipse.fx.core.ThreadSynchronize;

// ...

// Lookup the thready service in the service registry
ThreadSynchronize threadSync = 
  ServiceUtils.getService(ThreadSynchronize.class).get();

result.thenAccept( p -> {
   threadSync.asyncExec( p, person::set );
});

We got rid of the inner lambda and replaced it with a method reference, so the code got more readable but

Using e(fx)clipse’ ThreadSynchronize#wrap(Consumer<T>):

// ...
result.thenAccept( threadSync.wrap(person::set) );

we can get rid of all outer lambda as well and are back to fairly the same code as if we’d not had to worry about thread-synchronization at all.

Reading from a worker thread

Let’s suppose you have a Timer running who wants to read a JavaFX-Property from a TextField in 1 second from now you’d:

  • You’d better rewrite it to use a Timeline so that no thread sync is needed
  • You’d write the following magic lines of code:
TextField textField = ...

Timer t = new Timer();
t.schedule( new TimerTask() {
  @Override
  public void run() {
    CountDownLatch ll = new CountDownLatch(1);
    AtomicReference<String> data = new AtomicReference<>();
    Platform.runLater( () -> {
      data.set( textField.getText() );
      ll.countDown();
    });
    ll.await();
    String d = data.get();
    // further process the data 
  }
}, 1000 );

Let’s for a moment forget that this code fairly dangerous because it might create a dead lock situation (hence JavaFX only provides Platform.runLater(Runnable)) this is a huge amount of code to write! Let’s see what APIs e(fx)clipse has to improve the situation.

Using ThreadSynchronize#syncExec(Runnable):

ThreadSynchronize threadSync = 
  ServiceUtils.getService(ThreadSynchronize.class).get();

public void run() {
  AtomicReference<String> data = new AtomicReference<>();
  threadSync.syncExec( () -> {
    data.set( textField.getText() );
  } );
  String d = data.get();
  // further process the data 
}

Removes the need for the CountDownLatch

Using ThreadSynchronize#syncExec(Callable<V>, V):

public void run() {
  String d = threadSync.syncExec( textField::getText, "" );
}

Removes the need for the AtomicReference

Using ThreadSynchronize#scheduleExecution(long, Runnable):

ExecutorService s = ...;
threadSync.scheduleExecution( 1000, () -> {
   String data = textField.getText();
   s.submit( () -> ... );
} );

Removes the thread synchronization problems arising from Platform.runLater() call

Using ThreadSynchronize#scheduleExecution(long, Callable<T>) : CompletableFuture<T> :

threadSync.scheduleExecution( 1000, textField::getText )
  .thenAcceptAsync( d -> ... );

Removes the lambda and gets you to the wonderful CompletableFuture-API.

Block program flow

Generally speaking halting the program flow is a discouraged software pattern and you’d better work with Future and callbacks like Consumer but there might be (existing) API you have to support who requires you to halt the program flow and continue after a certain condition has been met.

To support such a usecase e(fx)clipse has org.eclipse.fx.ui.controls.Util#waitUntil( BlockCondition blockCondition ) you can use like this


Pane p = ...;

// Ask for name in an overlay
String askForName() {
  BlockCondition<String> condition = new BlockCondition<>();

  TextField t = new TextField();
  Button b = new Button("Proceed");
  b.setOnAction( e -> { condition.release(t.getText()); } );
  HBox box = new HBox(
    new Label("Name:"),
    t,
    b);
  box.setManaged(false);
  box.autosize();
  box.relocate( 
    p.getWidth() / 2 - box.getWidth() / 2, 
    p.getHeight() / 2 - box.getHeight() / 2 );
  p.getChildren().add( box );
  return Util.waitUntil( condition );
}
Posted in e(fx)clipse | 1 Comment

e4 on JavaFX with the bnd-maven-plugin (with VS Code)

Just a few minutes ago I blogged about our future plans for e(fx)clipse and to show you that we take the things mentionned there really serious I can provide you an initial report on the first 2 points from the the list:

  • Freedom of development style
  • Freedom of development tool

Since its inception the way to develop “e4 on JavaFX” meant:

  • useage Eclipse PDE inside your Eclipse IDE
  • useage Maven-Tycho as the headless build system

We will start to change that and in the weeks to come!

First and most important

We won’t take away ANYTHING – if you want to use PDE and Tycho please do so – we are going to support that development style like did in the past!

The future is pure maven/gradle

I’ve played around a lot in the past weeks with Eclipse, IntelliJ IDEA, Netbeans and VS Code to find what would work out best and I think I’ve reached a point where I can provide you some screenshots and screen casts.

Eclipse

In Eclipse all I need to develop my application is the m2e extension.

screen-maven-pure-eclipse

VS Code

To give me the extra kick I decided to give VS-Code and the Java-Extension from RedHat a shot.

The technology

Now that you have looked at the cool screen-cast let’s talk about the boring technology in the backend. We rely on 2 things:

Posted in Uncategorized | 9 Comments

e(fx)clipse and the future of e4 on JavaFX

We’ve been a bit silent in the last few months but the reason is not that our investment in e(fx)clipse has been stopped – it’s the complete opposite. We are involved in HUGE JavaFX projects built on top of e4 and JavaFX.

At EclipseCon Europe I gave a talk on the future direction of e(fx)clipse who is driven by 3 main topics who are going build the Foundation for a bright future of e4 on JavaFX:

  • Freedom of development style
  • Freedom of development tool
  • Freedom of runtime

Freedom of development style

As of today e(fx)clipse e4 development style is called “MANIFEST-first” which means you create your OSGi-MANIFEST and from there

  • Eclipse PDE derives Classpaths, … while you are in your Eclipse IDE
  • Eclipse Tycho derives Build-Paths, … to build applications on your CI-Instance

In future we are going to support other development styles as well:

  • bnd/bnd-tools for those of you who’d like to use what OSGi-gurus like Peter Kriens, Neil Bartlett, … prefer for OSGi-Development, we are already publishing an r5-index since some time. A nice side effect is that bnd support is also available eg in IntelliJ IDEA
  • pom/gradle-first for those of you who’d like to stay with maven/gradle but not all team-members are using Eclipse as their main IDE (or you are not using OSGi as the module system of choice – see more on that below)

Freedom of development tool

Since the first day I’ve spoken about “e4 on JavaFX”, I said that we – the e(fx)clipse project – don’t mind people using other IDEs like Netbeans or IntelliJ IDEA because we are an RCP framework allowing you to built sophisticated applications on top of the brand new Eclipse 4 Application Platform and if you don’t like the Eclipse IDE that’s fine with us.

Yes one part (the smaller one) of the Eclipse-project provides tooling to support developers who’ve chose Eclipse as the IDE, and yes we are an Eclipse project (like Jetty, Vert.x) and Eclipse is our primary development environment but just because it is our IDE of choice this must not mean that it is yours as well.

People already managed to use e(fx)clipse to develop application inside IntelliJ IDEA but in future we’d like to provide all developers an excellent out-of-the-box experience.

Freedom of Runtime-System

As of today you can run e4 applications only on the Eclipse Equinox OSGi-Container. In future we’d like to provide you many more options:

  • Run on ANY r5-OSGi-Container
  • Run without OSGi using NO Module-Container at all
  • Run on Java Platform Module System (JPMS)

Don’t get me wrong! We love OSGi and support for OSGi is still one of the primary targets of e(fx)clipse but we also understand the OSGi might not be the right tool for you and your team.

What’s next

As you might imagine all this is a HUGE amount of work but we (BestSolution.at) are committed to the future e(fx)clipse and we think it is crucial for e(fx)clipse’ future and initial steps have already been made.

Stay tuned for more exciting news in the next few weeks.

Posted in e(fx)clipse, Uncategorized | 2 Comments