EMF Forms 1.6.0 Feature: Improved Rendering Architecture

by Maximilian Koegel and Jonas Helming at August 31, 2015 11:42 AM

With the Mars Release, we released EMF Forms 1.6.0. EMF Forms makes it really simple to create forms, which edit your data based on an EMF model. To get started with EMF Forms please refer to our tutorial.

One of the major things we worked on for the 1.6 release was a refactoring of the rendering architecture of EMF Forms. The goal was to improve the testability, adaptability and reusability of the EMF Forms renderers. Before we go into details about the changes, let us quickly explain what a renderer is responsible for in EMF Forms and why it is such an important component for the framework.

Instead of manual and tedious UI coding, EMF Forms allows you to describe form-based UIs in simple language, the view model.Because it is focussed on forms, it is much more concise and easier to understand than manually written code, whether the UI technology is SWT, JavaFX or a web framework. A simple view model is shown in the following screenshot. The second screenshot shows, how the view model would be rendered in SWT.

image05

image02

Translating the view model to a concrete usable UI is the responsibility of the renderers. Instead of generating code again, as most WYSIWYG-Editors do, EMF Forms interprets the view model at runtime. This allows for a lot of flexibility, e.g. to adapt renderers or even completely replace them without the need to change the view model at all.

To keep the rendering component as flexible as possible, it consists of single renderers, each responsible for a single view model element. As an example, there is a renderer for the element HorizontalLayout, another one for Group. For the control element in the view model, which represents a data field including label shown in the UI, there is a dedicated renderer for each attribute type, e.g. String, Integer or Enum. All renderers are registered in a central registry. When a certain element is rendered, a renderer factory is called to retrieve the correct renderer for an element. You can provide testers along with a renderer, which allows you to return different renderers for the same element based on certain rules, e.g. special renderers for certain domain model attributes.

image04

This architecture of dedicated elements and a factory is very flexible and allows for existing renderers to be replaced or adapted. It has been implemented since the beginning in EMF Forms. However, there are a few details, that we improved with the 1.6.0 release.

In the previous release, renderers needed to implement a given interface, which was used to call rendering methods and to fill in required parameters. This does not sound bad on first glance, but this architecture has drawbacks. The set of parameter is fixed for every renderer. While most renderers share a common set of required parameters, there are others, especially custom adaptations, which required some very specific parameters. These might even be objects or services, which are project specific and not part of the framework. With the fixed set of parameters given by the defined interface, it was difficult, to retrieve additional ones. Luckily, there is a well-known solution for this issue: dependency injection. It allows you to let the implementation of the renderer define itself, as well as which parameters it requires. EMF Forms will then take care to inject the required objects into the renderer on initialization. Further, renderers typically inherited from certain superclasses to share existing functionality. An example for such a reused feature is the creation of a data binding for a control. For the 1.6 release we have refactored these reusable features into independent services.

The architectural shift to small reusable components, which are wired using dependency injection has been pretty common pattern in recent years. Those components have typically much less dependencies and are therefore easier to test. Additionally, if you want to test renderers, it is easy to mock all external components.  More importantly, this approach enables framework users to adapt, extend or exchange the implementation of these services.

image06

As you can see in the diagram, we still use a interface for the renderer to define methods, which are called by the framework, e.g. the render method. This could be removed by defining annotations to mark the respective methods and to call them via dependency injection. Eclipse 4 does that with the behavior annotations, e.g. @Focus or @Execute. However, we currently do not see a major advantage in introducing this into the rendering architecture. The affected methods have had a stable and very minimal parameter set since years, now (typically one or even no parameters). In addition, we sometimes expect pretty specific return values, which cannot be assured during compile time when using dependency injection, which is an advantage for keeping the interface. Finally, renderers are stateful, as they control the current state of the rendered UI. That means, there is currently no real issue with injecting services as a fields or in the constructors. We might revise this and even introduce dependency injection for those methods, but the current solution already resolves the problem of differing parameter sets and support completly custom parameters.

We updated our code examples and tutorials to the new rendering architecture, please have alook at this tutorial to learn more about how to implement custom renderers for EMF Forms and how to adapt existing ones.


TwitterGoogle+LinkedInFacebook

Leave a Comment. Tagged with eclipse, emf, emfforms, mars, eclipse, emf, emfforms, mars


by Maximilian Koegel and Jonas Helming at August 31, 2015 11:42 AM

Eclipse IDE: Get rid of the "java.awt.List" proposal in "organize imports"

August 31, 2015 07:44 AM

As I always use the “Organize Imports” feature of Eclipse my Eclipse IDE is always configured accordingly (at workspace or at project level).


August 31, 2015 07:44 AM

Vert.x3 real time web apps

by pmlopes at August 31, 2015 12:00 AM

One of the interesting features of Vert.x is the SockJS event bus bridge. This piece of software
allows external applications to communicate with Vert.x event bus using Websockets and if your browser does not
support it then it gracefully degrades to pooling AJAX calls.

WebSockets bring a new level of interaction to the web, they really bring real time to web applications due to the
fact that its communication model is bi-directional in contrast to the traditional HTTP model where a client can
initiate a data request to a server but not the other way around.

In this small post I will demonstrate how you can create a simple collaborative drawing app. The idea is simple, all
users that open the app will be be presented with a empty canvas and what they draw or is drawn on other canvas is
shared in real time on their screen.

For the sake of simplicity and making this post light there is no security involved so, everyone is free to listen to
what is being drawn, however the external application has limited read write access to a single address on Vert.x
event bus, ensuring that other services running on the cluster will not be exposed.

This is what you should expect to see:

screecast

Bootstrap a project

If you followed the previous series on Vert.x development, you saw
that Java and Maven were the main topic, since Vert.x is polyglot I will focus on JavaScript and
NPM as my programming language and package management tool.

With NPM start by creating a package.json, in order to do this we should run:

npm init

This will present a selection of questions and in the end you should have a basic package.json file. This
configuration is very basic so you need to add a dependency to Vert.x so
you can run the application. You can add it to the dependencies property and it should look more or less like this:

{
  "name": "draw",
  "private": true,
  "dependencies": {
  "vertx3-full": "3.0.0-1"
  },
  "scripts": {
  "start": "vertx run server.js"
  },
  "version": "1.0.0",
  "main": "server.js",
  "devDependencies": {},
  "author": "",
  "license": "ISC",
  "description": "A Real Time Drawing App"
}

If you do not know why there is the dependency on vertx3-full or why the added scripts property please check the
older blog post about it.

Project Structure

This post has no preference over project structure, so if you do not agree with the structure used here feel free to
use what you feel best. For this example I will keep it to:

├── package.json
├── server.js
└── webroot
  ├── assets
  │   └── js
  │     ├── script.js
  │     └── vertxbus.js
  └── index.html

3 directories, 5 files

As you can imagine server.js will be our Vert.x application and everything under webroot will be the client
application.

The client application is not really Vert.x specific and could in theory be used by any other framework so I will go
lightly over its code.

Client Application

Our application main entry point is as one can expect index.html. In the index file define the following HTML:


<html>
<head>
  <meta charset="utf-8"/>
  <title>Real time drawing Apptitle>
  
head>

<body>
<canvas id="paper" width="1900" height="1000">
  Your browser needs to support canvas for this to work!
canvas>


<script src="http://code.jquery.com/jquery-1.8.0.min.js">script>
<script src="//cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js">script>
<script src='assets/js/vertxbus.js'>script>
<script src="assets/js/script.js">script>

body>
html>

As I previously wrote, the idea is to keep it as simple as possible so it is all about having a canvas element and a
application main script script.js. All the rest are files served by CDNs that provide common web application
libraries such as jQuery, HTML5 shim for older browsers, SockJS client and vertxbus bridge.

The main code is on script.js file:

$(function () {

  // This demo depends on the canvas element
  if (!('getContext' in document.createElement('canvas'))) {
    alert('Sorry, it looks like your browser does not support canvas!');
    return false;
  }

  var doc = $(document),
    canvas = $('#paper'),
    ctx = canvas[0].getContext('2d');

  // Generate an unique ID
  var id = Math.round($.now() * Math.random());

  // A flag for drawing activity
  var drawing = false;

  var clients = {};
  // create a event bus bridge to the server that served this file
  var eb = new vertx.EventBus(
      window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');

  eb.onopen = function () {
    // listen to draw events
    eb.registerHandler('draw', function (data) {
      // Is the user drawing?
      if (data.drawing && clients[data.id]) {

        // Draw a line on the canvas. clients[data.id] holds
        // the previous position of this user's mouse pointer

        drawLine(clients[data.id].x, clients[data.id].y, data.x, data.y);
      }

      // Saving the current client state
      clients[data.id] = data;
      clients[data.id].updated = $.now();
    });
  };

  var prev = {};

  canvas.on('mousedown', function (e) {
    e.preventDefault();
    drawing = true;
    prev.x = e.pageX;
    prev.y = e.pageY;
  });

  doc.bind('mouseup mouseleave', function () {
    drawing = false;
  });

  var lastEmit = $.now();

  doc.on('mousemove', function (e) {
    if ($.now() - lastEmit > 30) {
      eb.publish('draw', {
        'x': e.pageX,
        'y': e.pageY,
        'drawing': drawing,
        'id': id
      });
      lastEmit = $.now();
    }

    // Draw a line for the current user's movement, as it is
    // not received in the eventbus

    if (drawing) {

      drawLine(prev.x, prev.y, e.pageX, e.pageY);

      prev.x = e.pageX;
      prev.y = e.pageY;
    }
  });

  // Remove inactive clients after 10 seconds of inactivity
  setInterval(function () {

    for (var ident in clients) {
      if (clients.hasOwnProperty(ident)) {
        if ($.now() - clients[ident].updated > 10000) {
          // Last update was more than 10 seconds ago.
          // This user has probably closed the page
          delete clients[ident];
        }
      }
    }

  }, 10000);

  function drawLine(fromx, fromy, tox, toy) {
    ctx.moveTo(fromx, fromy);
    ctx.lineTo(tox, toy);
    ctx.stroke();
  }

});

The most important part in this code is all the code related to eb. The variable eb is our bridge to the event
bus, Start by creating a bridge using the vertx.EventBus object and define where to connect, using the details
of the current window location.

Then add a onopen listener that will subscribe to the address draw on the event bus so it can listen to all
messages regarding drawing and perform the drawing actions. Since listening is not enough I also add a mouse listener
to the document so when it moves it publishes events to the draw address.

Note that I am using publish and not send, the reason should be obvious, I want everyone to know this users mouse
movements, I am not interested on sending the events to just a single user. You can see now that if you want to have
a drawing app in a one on one user basis then instead of publish() you should use send().

Server Application

The server code is quite straight forward, all you need is:

var Router = require("vertx-web-js/router");
var SockJSHandler = require("vertx-web-js/sock_js_handler");
var StaticHandler = require("vertx-web-js/static_handler");

var router = Router.router(vertx);

// Allow outbound traffic to the draw address

var options = {
  "outboundPermitteds" : [{"address" : "draw"}],
  "inboundPermitteds" :  [{"address" : "draw"}]
};

router.route("/eventbus/*").handler(SockJSHandler.create(vertx).bridge(options).handle);

// Serve the static resources
router.route().handler(StaticHandler.create().handle);

vertx.createHttpServer().requestHandler(router.accept).listen(8080);

We start with the usual imports, we import a reference to the Router object and a couple of helper handlers
SockJSHandler and StaticHandler. As their names should tell you one handler will be responsible to handle all
SockJS data and the other all HTTP file serving requests.

We then add then to a router and start a HTTP server that will handle all incoming request using the handler accept
function. Finally we listen on port 8080 and we are ready.

Note that there is a options object where a couple of properties are defined outbound/inbound permitted addresses.
Without this configuration the external application will not be allowed to connect to the vert.x bus, in fact the
default configuration of the SockJSHandler is deny all. So you must specify explicitly which address are allowed to
receive messages from SockJS and which ones are allowed to send/publish to SockJS.

Now you can start your application, don’t forget to install the dependencies for the first time:

npm install

And then run the application:

npm start

If you now open 2 browser windows you will be able to draw nice pictures and see the drawing showing in “real time”
on the other window, if you then draw on the second you should get the mirror effect on the first window.

Have fun!


by pmlopes at August 31, 2015 12:00 AM

Presentation: Jekyll and Hyde with Jubula

by Alexandra Schladebeck, Markus Tiede at August 30, 2015 07:57 PM

This talk will present participants with both aspects of Jubula’s personality: Dr Jekyll: writing tests with the Jubula actions in the ITE; Mr Hyde: writing Jubula tests in Java. We’ll show how the steps to start AUTs, write tests and perform test execution can be done using both aspects of Jubula. The talk will show participants their way around the tool and its features from both perspectives.

By Alexandra Schladebeck, Markus Tiede

by Alexandra Schladebeck, Markus Tiede at August 30, 2015 07:57 PM

Candidate bugs for the EclipseCon Europe 2015 Hackathon

by waynebeaton at August 27, 2015 07:55 PM

Alternate title: What I saw at the EclipseCon Europe Hackathon made my jaw drop!

I’m pretty excited about the hackathon we’re running at EclipseCon Europe.

Hacker's Keyboard

In past hackathons, we’ve let attendees pick the bug that they want to work on. We’re going to encourage this sort of thing this time around, but want also to provide some help for those potential contributors who want to help, but don’t already have an idea.

We need some candidate bug reports.

It occurred to me that we have many open bugs reports annotated with helpwanted, indicating that committers feel that the issue addressed by the report is valid, but that they have no plans to resolve it. Some of these reports, however, are relatively large problems that could day hours, days, and weeks to resolve.

We also have many bug reports annotated with bugday. This keyword was originally used to flag reports that were candidates for a Bug Day event, but has grown to represent issues that committers feel can be addressed by a new contributor with modest effort (e.g. one or two hours).

The bugday bugs seem like a reasonable subset of candidates for the hackathon. As of this moment, there are 54 open bug reports annotated with bugday. That number drops to 40 if you include helpwanted in the search (i.e. there are 40 helpwanted bugday bugs). Both of these numbers are a little large, but are a pretty good starting point. I’m thinking that a list of 20 would be ideal.

I’m hopeful that committers will step up and annotate more bugs. Should an embarrassment of riches result, we’ll have to sort out a reasonable means of whittling this list down to a manageable size (e.g. an age limit).

I’m curious to hear if anybody has thoughts on how we select good candidates.

The EclipseCon Europe 2015 Hackathon runs from noon on Tuesday, November 3rd until the end of the day on Wednesday, November 4th. We’re setting up office hours where you can meet and work with Eclipse committers (more on this later).



by waynebeaton at August 27, 2015 07:55 PM

Eclipse Newsletter - Discover the Eclipse Marketplace

August 27, 2015 03:06 PM

The articles highlight some of the most popular solutions including EclEmma, Spring Tool Suite, JBoss Tools, and PyDev.

August 27, 2015 03:06 PM

Exposing a REST service as an OSGi Service

by Scott Lewis (noreply@blogger.com) at August 27, 2015 02:25 PM


I've produced a tutorial describing an additional use case for Remote Services:  Exposing a Jax REST service as an OSGi Remote Service.

This describes how one can take an existing REST service and expose to consumers as an OSGi Remote Service.





by Scott Lewis (noreply@blogger.com) at August 27, 2015 02:25 PM

Eclipse Scout Day 2015

August 27, 2015 12:03 PM

On November 2nd we are organizing the Scout user group meeting as part of the Unconference right before the Eclipsecon Europe. Participation requires registration but the Event is open for anyone interested.

 

 


August 27, 2015 12:03 PM

Access Dart Analysis Server from Java

by Tom Schindl at August 25, 2015 03:24 PM

In my last few blogs (here, here and here) I started implementing a smart dart editor with syntax highlighting, auto complete, … for google dart.

While the first posts have been dedicated to getting syntax highlighting working we’ll now start with the higher level features you are used to from full blown IDEs.

In this first blog post we’ll look how we can interface with the Dart Analysis Server which is the reason I’ve chose dart as the example language.

The communication with the Dart Analysis is done through the input and output stream. An example will probably help.

Let’s suppose we have a /home/tomschindl/dart-samples/test.dart with the following content:

class Rectangle {
  num left;   
  num top;
  num width; 
  num height;          
  
  num get right             => left + width;
      set right(num value)  => left = value - width;
  num get bottom            => top + height;
      set bottom(num value) => top = value - height;
}

// This is where the app starts executing.
main() {
  var r = new Rectangle();
  r.
}

If you now want to get all auto completetion proposals after r. you issue the following commands/requests to the server:

  • You launch the dart analysis server eg on my workstation it is:
    /Users/tomschindl/Downloads/dart-sdk/bin/dart \
     bin/snapshots/analysis_server.dart.snapshot
  • You inform the server about the root directory:
    { 
      "id" : "default_1", 
      "method" : "analysis.setAnalysisRoots" , 
      "params" :  {
         "included":["/Users/tomschindl/dart-samples/"],
         "excluded":[]
      }
    }
    
  • Which will synchronously return the following result

    {
      "id":"default_1"
    }
    
  • Requesting all auto completetions at offset 367 which is directly after r.

    { 
      "id" : "default_2", 
      "method" : "completion.getSuggestions" , 
      "params" :  {
        "file":"/Users/tomschindl/dart-samples/test.dart",
        "offset":367
      }
    }
    
  • Which will synchronously return the following result
    {
      "id":"default_2",
      "result":{
        "id":"0"
      }
    }
    
  • And asynchronously the following events will occur

    {
      "event":"completion.results",
      "params":{
        "id":"0",
        "replacementOffset":367,
        "replacementLength":0,
        "results":[],
        "isLast":false
      }
    }
    
    {
      "event":"completion.results",
       "params":{
         "id":"0",
         "replacementOffset":367,
         "replacementLength":0,
         "results": [
           {
             "kind":"INVOCATION",
             "relevance":1000,
             "completion":"left",
             "selectionOffset":4,
             "selectionLength":0,
             "isDeprecated":false,
             "isPotential":false,
             "declaringType":"Rectangle",
             "element":{
               "kind":"FIELD",
               "name":"left",
               "location":{
                 "file":"/Users/tomschindl/dart-samples/test.dart",
                 "offset":24,
                 "length":4,
                 "startLine":2,
                 "startColumn":7
               },
               "flags":0,
               "returnType":"num"
             },"returnType":"num"
           },
           {
             "kind":"INVOCATION",
             "relevance":1000,
             "completion":"right",
             "selectionOffset":5,
             "selectionLength":0,
             "isDeprecated":false,
             "isPotential":false,
             "declaringType":"Rectangle",
             "element":{
               "kind":"GETTER",
               "name":"right",
               "location":{
                 "file":"/Users/tomschindl/dart-samples/test.dart",
                 "offset":95,
                 "length":5,
                 "startLine":7,
                 "startColumn":11
               },
               "flags":0,
               "returnType":"num"
             },
             "returnType":"num"
           }
           // Many more
         ],
        "isLast":true
      }
    }
    

I guess you get the idea – not really rocket science but in java we don’t want to deal with this low-level stuff. So as part of the editor work we also developed a Java interface for the Dart Analysis Server available from maven-central.

If we want to issue the same commands as above through the Java-API.

Create a maven-project and make the pom.xml look like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>at.bestsolution</groupId>
	<artifactId>at.bestsolution.dart.server.sample</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<repositories>
		<repository>
			<id>sonatype-snapshots</id>
			<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
		</repository>
	</repositories>
	<dependencies>
		<dependency>
			<groupId>at.bestsolution.eclipse</groupId>
			<artifactId>org.eclipse.fx.core</artifactId>
			<version>2.1.0-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>at.bestsolution</groupId>
			<artifactId>at.bestsolution.dart.server.api</artifactId>
			<version>1.0.0</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

And a java class with the following content:

package at.bestsolution.dart.server.sample;

import java.io.IOException;
import java.util.stream.Stream;

import org.eclipse.fx.core.Util;

import at.bestsolution.dart.server.api.DartServer;
import at.bestsolution.dart.server.api.DartServerFactory;
import at.bestsolution.dart.server.api.Registration;
import at.bestsolution.dart.server.api.model.CompletionResultsNotification;
import at.bestsolution.dart.server.api.services.ServiceAnalysis;
import at.bestsolution.dart.server.api.services.ServiceCompletion;

public class DartServerSample {
	public static void main(String[] args) {
		// Get the server factory from the service registry
		DartServerFactory serverFactory = Util.lookupService(DartServerFactory.class);
		// Create a server instance
		DartServer server = serverFactory.getServer("server");

		// Get the analysis and completion service
		ServiceAnalysis analysisService = server.getService(ServiceAnalysis.class);
		ServiceCompletion completionService = server.getService(ServiceCompletion.class);

		// set the root
		analysisService.setAnalysisRoots(new String[] {"/Users/tomschindl/dart-samples/"}, new String[0], null);
		// register for completion notifcations
		Registration proposalRegistration = completionService.results(DartServerSample::handleHandleResults);

		// Request completion at offset 367
		completionService.getSuggestions("/Users/tomschindl/dart-samples/test.dart", 367);

		// Wait for a key press
		try {
			System.in.read();
		} catch (IOException e) {
		}

		// unregister the notification listener
		proposalRegistration.dispose();
		// shutdown the server instance
		server.dispose();
	}

	private static void handleHandleResults(CompletionResultsNotification notification) {
		Stream.of(notification.getResults()).forEach( c -> System.err.println(c.getCompletion()));
	}
}

And then you have to launch the class with

java -Ddart.sdkdir=/Users/tomschindl/Downloads/dart-sdk at.bestsolution.dart.server.sample.DartServerSample

where you replace /Users/tomschindl/Downloads/dart-sdk with the path to your dart-sdk installation.



by Tom Schindl at August 25, 2015 03:24 PM

Gerrit inline editing Feature

August 25, 2015 08:56 AM

We have moved our Scout Blog to a new location:
https://www.bsi-software.com/en/scout-blog/

I have opened Bug 473139 to update our RSS Feed URL in the Eclipse planet configuration file.

This was for me a perfect opportunity to test the new inline editing feature of Gerrit. (See Denis Roy email on the “eclipse.org-committers” mailing list: New version of Gerrit deployed)

Here is how I created a new change for my Bug, directly on Gerrit:

1/ Search for the corresponding repository in the projects list.


August 25, 2015 08:56 AM

by Peter Kriens (noreply@blogger.com) at August 24, 2015 07:56 AM

Building the Internet of Things with OSGi by Tim Verbelen, iMinds, Ghent University One year ago, I was speaking on my first EclipseCon Europe about the results of my PhD research (Mobilizing the Cloud with AIOLOS). Since then, I have been working for iMinds as a research engineer. iMinds is a digital research centre in Belgium, which joins the 5 Flemish universities in conducting

by Peter Kriens (noreply@blogger.com) at August 24, 2015 07:56 AM

Presentation: Tasty Recipes for OSGi Bundles

by Gunnar Wagenknecht at August 23, 2015 11:31 PM

Gunnar Wagenknecht introduces the Eclipse Bundle Recipes project, explaining how to turn a library from Maven into an OSGi bundle, and how to deploy recipes and build systems to a local environment.

By Gunnar Wagenknecht

by Gunnar Wagenknecht at August 23, 2015 11:31 PM

Presentation: Model Migration with Edapt

by Maximilian Koegel at August 23, 2015 08:50 PM

Maximilian Koegel introduces Edapt, describing its basic features and demonstrating how it can be used for migrating models in real life applications.

By Maximilian Koegel

by Maximilian Koegel at August 23, 2015 08:50 PM

Introducing the EclipseCon Europe 2015 Hackathon

by waynebeaton at August 20, 2015 07:52 PM

Alternate title: I Went to EclipseCon Europe and What I Saw There Blew My Mind…

EclipseCon has great tutorials and sessions. The speakers are second-to-none, and the networking opportunities are fantastic. if you’re looking for it, you’ll find software developers doing amazing things together. For EclipseCon Europe 2015, we’re going to formalize this a bit. At very least, we’re going to give it a nice home and a lot of love.

10553673244_84713e4157_z We’re extending our usual notion of a hackathon: instead of just having a single evening session, we’re going to host a hacking area for two full days during the conference. We’ll have a few things happening in this hacking area.

There will be multiple tables arranged in perfect order for pair programming. The tables will have wired connections so that participants don’t have to wrestle with the wifi. We’re going to set up a server with mirrors of our Git and Mars p2 repositories so you don’t have to make the long trip back to our servers in Ottawa to get started (once you’ve cloned, you can connect to the master repository to get updates and push patches).

We’ll have Eclipse Foundation staff and others there to help. We can help with things like creating Eclipse Foundation accounts, setting up Contributor License Agreements (CLA), configuring development environments, understanding the development and intellectual property (IP) processes, and more. We can even help you find a problem to solve and a partner to solve it with (if you need that sort of help). We’ll have a little presentation area set up where we’ll run short how to contribute sessions throughout the day.

You are most certainly welcome to work on your own problem. Or, you can select from our short list of issues that we feel can be solved with up to two hours of effort: pick something from the list and we’ll help you get started and sort through the development process. If you’re not quite ready to submit patches, you can help us test by downloading one of the packages, the installer, or a feature; we’ll help you create bug reports for issues that you find. Or we can help you just create a bug report for some aspect of Eclipse that’s been driving you batty.

We’re going to set up some office hours: specific times set aside when we’ll have subject matter experts on hand to help with specific sorts of problems. Use the office hours to connect with experts on topics such as building Oomph configurations, testing your plug-ins, or using the Common Build Infrastructure; and committers from specific Eclipse projects.

Eclipse committers are, of course, welcome to use the hacking area to collaborate with fellow committers that you don’t normally get to work with directly.

I think that you’ll find that we have a little something for everybody.

EclipseCon Europe 2015



by waynebeaton at August 20, 2015 07:52 PM

Improved TextMate bundles integration and instant searches on Eclipse (LiClipse 2.3.0)

by Fabio Zadrozny (noreply@blogger.com) at August 20, 2015 07:02 PM

Yeap, LiClipse 2.3.0 is out now.

The main change in this release was a restructuring on how the parsing works...

This deserves some better explanation: in Eclipse, the default parsing structure is done by separating a document in many top-level partitions and later on those partitions are scanned to give syntax highlighting.

The issue here is that in LiClipse when parsing with TextMate rules, a single parse will provide all the information at once (top-level partitions and internal scopes in the partition), so, the code was restructured so that a single parse is done and the information is properly saved to be accessed later on, so, a single parse will provide the partitions, colors, outline, etc.

This means that LiClipse became even more responsive, especially when dealing with TextMate rules and the scope information is available to better support TextMate snippets for code-completion.

Also, the searching structure created on LiClipse 2.2.0 was ironed out (and its really pleasant getting instant searches even on big codebases).

Enjoy!

by Fabio Zadrozny (noreply@blogger.com) at August 20, 2015 07:02 PM

Users can now fund development work on Eclipse

by Mike Milinkovich at August 19, 2015 03:00 PM

Today, we are significantly lowering the barriers for companies and individuals to actively invest in the ongoing development of the Eclipse platform. Eclipse has an amazing community of individuals and companies that invest significant amount of resources in the development of Eclipse open source projects. We also have a huge community of users that benefit from Eclipse technology. They use Eclipse tools and technology to build their software products and applications. Most of these users don’t have the time required to participate in an open source project but they do want to see ongoing improvements and investment in Eclipse. We now have a way for these users to invest in Eclipse improvements.

We are pleased to announce the Eclipse Foundation has begun to fund development work on Eclipse projects.  In fact, there are a number of features and issues in the Mars release that were funded through the Foundation. The initial focus is on improving the core Eclipse platform, JDT and Web Tools. As the program expands we expect the list of projects will grow too. The process by which funds will be allocated is still a work in progress, but will be made available soon. It will be based on the core principles of openness and transparency.

The funding for the development work will come from individuals and corporate users. Earlier this year, Ericsson provided the Eclipse Foundation funds to improve the Eclipse platform which resulted in SWT, GTK3 and PDE improvements available in the Mars release. Ericsson is a large user of Eclipse and they see the value of investing in ongoing improvements. We hope other large corporate users of Eclipse will follow Ericsson’s lead.

We are also pleased to announce that all users’ donations to our Friends of Eclipse program will be used to fund Eclipse development work. Last year we raised over $120,000 from the Friends of Eclipse program, so we hope the ability to directly fund Eclipse development will significantly increase the donations we gain from our individual user community. To make things even easier, we have added Bitcoin as a payment option. Please take this opportunity to help improve Eclipse by making a donation.

Eclipse open source development will continue to move forward through work of our committer community. Committers are the heart and soul of any open source project. However, we are confident having additional investment from our user community will help accelerate future improvement to Eclipse. If you are a user of Eclipse, individual or corporate, it is now simple to participate in the future of Eclipse.


Filed under: Foundation

by Mike Milinkovich at August 19, 2015 03:00 PM

OSGi Residential Release 6 Specification

by Kai Hackbarth (noreply@blogger.com) at August 19, 2015 02:45 PM

The OSGi Residential Expert Group is excited about the new specifications introduced in the OSGi Residential Release 6 Specification. You can find it at: http://www.osgi.org/Specifications/HomePage. It contains a number of new specifications mostly dealing with device interoperability and configuration, monitoring and management services. As with the previous Residential 4.3 Specification, the

by Kai Hackbarth (noreply@blogger.com) at August 19, 2015 02:45 PM

Users can now fund development work on Eclipse

August 19, 2015 01:39 PM

We significantly lowered the barriers for companies and individuals to invest in the ongoing development of the Eclipse platform.

August 19, 2015 01:39 PM

More jars on Maven Central and JCenter

by BJ Hargrave (noreply@blogger.com) at August 19, 2015 12:45 PM

In my last blog post, I announced the availability of the Release 6 specifications including their companion code jars which were released to Maven Central and JCenter. Those companion code jars were collections of companion code associated with the specification documents. For example, the osgi.enterprise jar contained all the packages for the all the APIs specified in the OSGi Enterprise

by BJ Hargrave (noreply@blogger.com) at August 19, 2015 12:45 PM

Building Eclipse Plugins with Maven Tycho and Travis-CI

by Andreas Mülder (noreply@blogger.com) at August 19, 2015 12:01 PM



A couple of weeks ago, we moved our open source project Yakindu Statechart Tools from google code SVN to GitHub. Until today we packaged and deployed our software using a self hosted Jenkins Server, but since Travis CI integrates seamlessly with GitHub and is free for open source projects we decided to give it a try. This blog post tries to explain how to set up Travis CI for a Maven Tycho based eclipse build.

There are plenty of blog posts out there, that stated how easy it was to setup a Travis CI build for a 10 lines of Java code 'Hello World' example. This is great, but our builds have a lot more work to do:
  • 170,000 lines of Java code
  • Code generation of Xtend classes and Xtext grammars
  • more than 1000 JUnit Tests (including UI Tests)
  • ~100 C and C++ Google Tests to run 
Let's see how well Travis can handle this.
 
Initial Setup

To get started with Travis you first have to log in to travis-ci.org with your GitHub account and grant access to your GitHub repositories This requires admin access to the repository. It is well documented in the User Guide. Next, you have to create a file .travis.yml in the root folder of your repository to tell Travis what to do. By the way, there is a really useful online syntax checker for yml files available here.

This is the simplest possible .travis.yml file for our build based on Maven Tycho:
 language: java   
script:
- cd releng/org.yakindu.sct.releng
- mvn clean verify

Immediately after pushing the .travis.yml file to our Git repository Travis started a new build.
and we ended up in a 5 MB log file full of exceptions like this one:

Caused by: org.eclipse.swt.SWTError: No more handles [gtk_init_check() failed]
    at org.eclipse.swt.SWT.error(SWT.java:4517)
    at org.eclipse.swt.widgets.Display.createDisplay(Display.java:908)


org.yakindu.sct.generator.genmodel.ui.SGenExecutableExtensionFactory
    at org.eclipse.swt.SWT.error(SWT.java:4517)
    at org.eclipse.swt.widgets.Display.createDisplay(Display.java:908) 

Running UI Tests

After analyzing the log files it points out that our UI dependent tests are not able to create an SWT Display object. Luckily, Travis allows the use of the virtual framebuffer xvfb for UI tests. It can be started as follows:

  language: java    
env:
global:
- DISPLAY=:99.0

before_install:
- sh -e /etc/init.d/xvfb start - sleep 10

script:
- cd releng/org.yakindu.sct.releng
- mvn clean verify

After pushing these changes to Git the build finished successful!

User Interface

Travis provides a simple yet powerful web based user interface that displays a list of all your repository builds and the console output. This is really helpful to see what is going wrong with your build. It also allows to start a build without pushing something to your repository.
What I really miss in the UI is a better integration for Unit Tests, like the Jenkins JUnit plugin. But such a feature is unfortunately not planned and one has to browse the (huge) log files for failed Unit tests.

 GitHub Integration

Per default, the master branch as well as all pull requests are build. The integration with GitHub works out of the box, the running CI jobs are shown in the GitHub UI as checks and updated automatically when the job finishes. This is really awesome for a configuration file with only 9 lines!


 Caching and container based infrastructure

Every time a new build job starts, a new Linux image is setup. To prevent that Maven downloads the internet every time a new build is started, Travis provides a container based infrastructure that allows the use of caches. One drawback of this is that the use of the sudo command is prohibited.

 sudo: false  
language: java
cache:
directories:
- $HOME/.m2

env:
global:
- DISPLAY=:99.0
before_install:
- sh -e /etc/init.d/xvfb start - sleep 10
script:
- cd releng/org.yakindu.sct.releng
- mvn clean verify

As shown above, starting the .yml configuration file with sudo: false allows the use of caches. When the build starts and a new Linux image is created, all cached directories (in our example the maven repository .m2) are restored at the beginning. This really boosts up the build time.

Performance

Our existing Jenkins CI Server is hosted on a Linux KVM virtual machine with 12 core Opteron 2,6 Ghz, 32 GB RAM and  Raid 10 HDD. The average build time is about 13 - 20 minutes.
Travis, running somewhere on Amazon cloud services, took about 10 - 11 minutes for a build. I don't know how they do it, but this is incredibly fast!


Adding google test framework for C and C++

Since Yakindu Statechart Tools is shipped with a C and C++ code generator, we have a couple of C and C++ tests that have to be run during build. This was the not-so-funny part of the configuration, because google recently decided to ship libgtest only as source code and without the static libraries. On the Linux machine we are running Jenkins it was straight forward to install google test, compile it and copy the static library to /usr/lib with the following commands:

 sudo apt-get install libgtest-dev  
cd /usr/src/gtest
sudo cmake CMakeLists.txt
sudo make
sudo cp *.a /usr/lib

Running these commands at the beginning of the Travis build would be possible, but we want to use caching so we are not allowed to use sudo, as explained above. Fortunately, there is an apt get whitelist that allows the installation of external libraries via addons.apt.packages:

 sudo: false  
language: java
addons:
apt:
packages:
- libgtest-dev

... 

Now the GTest source code is available on the image, but it has to be compiled. The - somehow quite hacky - solution is to copy the source into the build dir, compile it and create a environment variable GTEST_DIR that is used in our C Tests for the library lookup. Copying to usr/lib did not work because without sudo the permission is denied.
 env:  
global:
- GTEST_DIR=${TRAVIS_BUILD_DIR}/gtest
  before_script:  
- mkdir gtest
- cd gtest
- cp -r /usr/src/gtest/. .
- ls
- cmake CMakeLists.txt
- make
 
... 

 At least this works, if you know a better solution please let me know :)
  
Publish Releases
Last but not least, we want to publish successful release builds to GitHub releases automatically.
To publish artifacts to GitHub releases a secret api_key is required for Travis to get access. These api_key should be encrypted, especially when the .travis.yml file is part of an open source project. ;-)
To set up the deploy section of the configuration, you need to install the Travis Ruby Gem.
First, download Ruby version 2.0.0 (I tried to install the Travis Gem with a newer version but it did not work) and install the ruby gem as described here.
If everything works properly, run the following command in the root folder of your GIT repository:

travis setup releases

This will setup a basic deployment section to your .travis.yml file. Do not forget to add the skip_cleanup: true, otherwise the build artifacts you want to release got deleted before the deployment step. In our case, a release is indicated with a tag that follows the naming convention release.x.x.x and we only want those tags to be automatically published, so we added a condition to the deployment section.

... 
 deploy:  
skip_cleanup: true
provider: releases
api_key:
secure: BSEYtMYXInrXum0eO........
file: releng/org.yakindu.sct.repository/target/updatesite.zip
on:
tags: Yakindu/statecharts
condition: "$TRAVIS_TAG =~ ^release.*$"

Now, every time Travis indicates a release tag, it will automatically publish the release to GitHub in case of a successful build.

Conclusion: Travis provides an incredibly powerful and customizable infrastructure to open source projects for free. Thank you very much for that and keep up the good work!



by Andreas Mülder (noreply@blogger.com) at August 19, 2015 12:01 PM