WildFly/EAP team are hiring

by maxandersen at February 20, 2017 09:12 AM

The WildFly/EAP team is looking for a Eclipse developer to help move forward the Eclipse IDE tooling around WildFly/EAP server, Java and JavaEE.

If you are into making developers life easier and like to be able to get involved in many different technologies and get them to work great together then do apply for this one.

The official job listing are here: Senior Software Engineer

Have fun!
Max Rydahl Andersen
@maxandersen


by maxandersen at February 20, 2017 09:12 AM

The Anatomy of Smart Homes

by Kai Kreuzer at February 20, 2017 12:00 AM

Scott Jenson published a very good article last week, where he nicely showed how far away we still are from the shiny Jetson-like marketing promises about smart homes. He asked us to take a step back so that we can think about the holistic shape of the “right” solution for smart homes. Let’s do so!

Missing Technology?

Doing a shameless shortening of his thoughts, he concluded that many issues would be solved if all devices had

  1. a smart setup that allows users a very simple way of commissioning
  2. auto-arrangement through proximity-detection
  3. a globally accepted way of announcing their capabilities
  4. a mechanism to share their data instead of keeping it in a silo

These are the technologies that we as a community are still lacking and that need to be tackled. Only if these are in place, it will enable devices to automatically form a distributed ensemble which we all aim for.

While I very much agree with all his points, I believe that solving the technological issues alone won’t suffice, but that we need to take yet another step back to see the big picture.

Taking Another Step Back

When talking about adding IoT devices to “the network”, it is out of question for most people to wonder “which network” - since we are talking about the Internet of Things, the network can only be The Internet where everything is connected, right?

Silos and Accounts

If we have a closer look at today’s smart home devices (and also other IoT setups), the truth is that everyone uses IP, i.e. Internet technology. But are the devices available “on the Internet”? No, many of them effectively do not allow you to communicate in any direct way with them. Instead, they open an encrypted tunnel to a cloud service, which then acts as a portal to the device for the user - all data is kept secretly (not saying securely) in the cloud under full control of the manufacturer. Effectively, we have a big number of siloes that can be regarded as VPNs. It is important to note that these are deliberate silos - this choice is not (only) the fault of missing interoperability standards!

This setup is a major reason for Scotts points 1 (smart setup) and 4 (sharing data): The manufacturers do not want to give control to the users, but instead force them to create accounts at their cloud service, accept the manufacturers terms and conditions and let the manufacturer decide how and with whom to share the data.

This is the major issue that needs to be addressed: The mindset of people that are building IoT devices must move away from this omni-present IoT architecture. The outlook that users will have to create web accounts for every single household object (everything’s going to be connected, right?) they buy in the future is ridiculous. This works as long as only nerds with a dozen devices play around with smart homes, but it definitely won’t scale. Manufacturers must let their devices go - only if they are unleashed the devices will have a chance to communicate with each other and form distributed ensembles.

Internet vs. Intranet

Let’s for the moment assume the devices were unleashed. Is the Internet then really the best place for them? Even if all potential authentication and authorization issues were solved, we all know that all those devices are hackable. Do we really want to see them publicly listed on Shodan.io? Having isolated VPNs isn’t such a bad idea after all and in the case of the smart home the most natural fit is the local Intranet. What you want to have on the public Internet are services (hosted on “real” servers that are hardened against attacks) and not household devices. A good compromise is in my opinion the concept of the Physical Web, where the discovery and authorization could be done through low-range radio like BLE, while the heavy lifting is done through cloud servers - but this really hardly applies to the smart home itself. If services of a home should be shared (this decision should really be up the user), it could be made available on any standard-compliant cloud service (i.e. no vendor lock-in), once Lego brick 3 (Standard Descriptions) is in place. Unfortunately, I am not as optimistic as Scott to have a “shared, common approach soon” - maybe for technical operability, but most likely not for semantical interoperability.

A Matter of Perspective

Taking the perspective of the user instead of the perspective of the manufacturer definitely brings us much closer to the desired solution. But putting the user in the center also causes some dilemma in the context of a smart home: After all, a home usually has multiple inhabitants, furthermore there are visitors, pets, burglars (hopefully not), etc. For the home to become smart and autonomous, the devices must become an integral part of the home and must not be a property of a single user. This is another clear indicator that we are still in an early phase: Most devices are bought off-the-shelf, installed DIY and registered to a certain user, who configures it to meet his needs. The devices are the personal objects of a person; they are not a part of the home. If this person moves the house, he will take his personal belongings with him. This works as long as you have only a dozen smart bulbs, a door lock and a web cam. It won’t work - and especially it does not make any sense - for a photovoltaic system, a complex central heating, the in-wall motion sensors, the smart frontdoor,… you get the point. You are also not ripping out the wall switches and your windows when you sell a house. A smart home should be allowed to exist on its own, even if nobody lives there. What brings it into existence are its bricks and its infrastructure - including the local IP network as the communicatin backbone for its parts.

Water, Electricity, Smartness

Smart home features and connectivity thus have to become a matter of course, just like electricity or water - it should not be treated as something that is retrofitted by the owner; instead, it must be an integral part of a home, which in turn becomes a smart, self-organizing entity. Having the devices build a local private network would ensure data privacy and the smallest possible attack target. This should be the long-term vision when designing smart home devices. In consequence, this means that devices must

  1. not require a mandatory user registration
  2. work (at least in a basic way) without a cloud connection
  3. provide a local API for interaction with other devices (and not limiting access to a small set of business-oriented partnerships) and expect the same from the others

In short, things should focus again on being things in the first place and not cloud-connected devices - they must be unleashed to show their full potential.

This might sound trivial, but unfortunately these features are widely ignored in the industry - although they would secure the adoption of smart home technology in the long-term. How can the industry possibly be influenced to see that a bit more communism will eventually grow the cake for everyone?


by Kai Kreuzer at February 20, 2017 12:00 AM

What is new in Eclipse 4.x?

by Andrey Loskutov (noreply@blogger.com) at February 19, 2017 09:39 PM

A look on Eclipse 4.6 from Eclipse 3.8 point of view

The good, the bad and the ugly

Preface

This is my personal, condensed, not comprehensive overview of changes in the Eclipse platform happened between last major 3.x release (3.8.0) from September 2012 and now (4.6.3). This overview is written from a user perspective and is for end-users, API changes are not part of the discussion.

Here are official "New and Noteworthy" links for each release:

4.2 N&N (2012)
4.3 N&N (2013)
4.4 N&N (2014)
4.5 N&N (2015)
4.6 N&N (2016)

Please note that Eclipse 3.8.0 was released at same time with 4.2.1 but did not contain some features related to the UI programming model change. The difference between 3.8.0 and 4.6.3 are not just 5 years or 5 major Eclipse releases, it is also a bigger change of the UI programming model from 3.x to 4.x API (aka e4).

Why to talk about 3.x to 4.x changes today?

Because Eclipse 3.8.2 was exceptionally well made, stable and reliable release. It required five (!) 4.x releases to reach similar stable state (may be not even same state, but at least some usable state). Also because most plugins till recently were still supporting 3.x stream and because 3.x was good enough to support development of Java 7 based software.

But as soon as your business switches to Java 8, the time is for Eclipse 4.x, because JDT in 3.8 does not know and does not support Java 8.

Themes aka L&F

Eclipse 4.x introduces "themed UI", where many UI elements can be "styled" with CSS rules. This is a highly controversial change, which from the one side allowed such features like "dark theme" but from the other side ruined UI performance, especially in distributed environments.

A good example how NOT to design ergonomic IDE theme (4.2. on Windows)

Same misery (4.2.1) on Linux
3.8.0 on same system
Either way (with or without themes), Eclipse 4.x doesn't look like Eclipse 3.8. Initial 4.2.1 in the default theme was simply ugly, on every operating system. With the time, 4.x stream got some polishing and starting with 4.6 reached the state of 3.8, more or less. From the performance point of view, CSS themes add a considerable computational overhead for complex UI's (plus extra layer of code which can be broken) and can significantly slow down Eclipse (to completely unusable state) in specific environments, like remote usage via vncviewer, rdesktop and Co.


Recommendation: don't use CSS themes to have less bugs, slicker and faster UI experience. Here is the how Eclipse looks like on Windows 10 without CSS themes:
4.6.3 with themes disabled, Windows 10

High-DPI monitors support

SWT now automatically scales images on high-DPI monitors on Windows and Linux, similar to the Mac's Retina support on OS X. In the absence of high-resolution images, SWT will auto-scale the available images to ensure that SWT-based applications like Eclipse are scaled proportionately to the resolution of the monitor.

Sometimes this automatic scale doesn't work or looks not nice - in this cases there are ways to tweak the default behavior

GTK3 support 

As if it would be not enough UI nonsense introduced with new themes, Eclipse 4.5+ uses GTK3 instead of GTK2 on Linux by default. Slick, useful, clean widgets from GTK2 are replaced by a pixel eating monsters from GTK3. The only solution for that is to use GTK3 themes with more "human" button sizes, but good GTK3 themes are very rare. Unfortunately, GTK3 is here to stay and GTK2 will be obsoleted sooner or later.

One can still switch to GTK2 however: either export SWT_GTK3=0 in the shell before starting Eclipse or add this two lines to your eclipse.ini:

--launcher.GTK_version
2

Modeled UI

Eclipse 4.x UI layout is more flexible and removes some restrictions 3.x Eclipse had. Now one can place editors and views in the same stack and move editors outside of the main window. FWIW, I personally never used this flexibility, but there are always corner cases where this could be useful.

Flexible UI

Unfortunately, with flexibility comes also complexity and bugs. So migration from 3.x workspace to 4.x with opened editors results in editors without close buttons and close menus (bug 509712). First time user who don't know this are surprised and are helpless to find out how to close the editor in the new world. Another bug (511798) is also not nice: if you have two editors in the split screen mode (like in example above), you will see an ugly white bar over them.

Quick access <Ctrl+3>

One shortcut every Eclipse user should learn is <Ctrl+3>, or "Quick Access". You can open views, start commands etc, very handy. To make it more prominent for new users, a permanent text box was added in the top right corner in Eclipse 4.x. Unfortunately, this changed the location and size of the resulting dialog, which a step backwards compared to 3.x. Instead to open in front of user and have appropriate size and location, it opens somewhere far right, with a small size where nothing really fits into.

Crippled Quick Assist in 4.x
Fortunately, there is a workaround which allows to restore 3.x L&F. One has to right click on the thin text box border and if one has luck, one will be able to click on the "Hide" menu:
Hide that ugly box!

and voila, the old good quick assist appears at the expected location and with size where everything fits:

Welcome back, quick assist with 3.x L&F!

Open resource <Ctrl+Shift+R>

Open Resource dialog got some love. It can now filter duplicated resources, show or hide derived resources, show only files from specific working set. Additionally, files can be either opened with a default editor or user can choose which editor should be used to open them.




Split editor

Sometimes one want to see code from two functions at same time - in a large file this is of course not possible, therefore there is now a new Window > Editor > Toggle Split Editor menu:

Split editor vertical

Word wrap <Alt+Shift+Y>

Believe or not, it took only 12 years for Eclipse to implement soft wrapping in text editors. But better later then never, we have now a button on the toolbar and a shortcut <Alt+Shift+Y> to toggle word wrapping in the current editor:
Word wrap!


Configure left and right sides in Compare editors

Another one change we waited about 10 years finally quietly made into Eclipse 4.6.2 release: one can configure Eclipse to show the new changes on the right side of the diff editor! Unbelievable, but differently to the rest of the world, Eclipse always has shown local changes not on the right but on the left side, which was and is quite surprising for everyone.

Since the old way was there for a decade, by default, the compare editor still shows the local changes on the left side, but the user finally can change this! There are two ways to do so: a new "swap left and right view" button in the compare editor toolbar:
Local changes on the right side!

and the Window > Preferences > General > Compare / Patch > Text Compare > Swap left and right:
Preference to see local changes on the right side

Console improvements

Word wrap button is also added to all I/O consoles, where it enables soft word wrapping for long output. Beside this, I/O consoles got "automatic scroll lock" mode, which is automatically enabled by scrolling up in the Console view using keys, mouse wheel, or scroll bar. When you scroll down to the end of the console, the scroll lock is automatically released again.

Console with word wrap and scroll lock

Root of all evil

Don't drink and drive Don't run Eclipse as root! This happens seldom, but if it happens, it will you make busy for the next few hours. Finally, Eclipse helps us and allows prevent to start it with root rights via new command line option: -protect root. This option will make sure Eclipse don't start if you have root rights on Linux.

Show in system explorer

Right click on any file or folder in Eclipse and say Show In > System Explorer. This will open system default "Explorer" and highlight the selected file or folder. In case the system default "Explorer" doesn't open (Linux), the command line to launch it can be configured under Window > Preferences > General > Workspace > Command for launching system explorer.

Show In System Explorer

Improved Open With ... Other dialog

The Open With > Other... dialog now has:
Open With... extended
  • a filter field
  • remembers last used choice
  • options to remember the selected editor as default for the selected file name or type.

Tabs "Close..." menus

The context menu of editor and view tabs now offer Close Tabs to the Left and Close Tabs to the Right menu:
Tabs menu

MRU or automatic editor shuffling

In classic 2.x versions of Eclipse the editors tab placement strategy was simple: they were shown in exact the order they were opened by the user. This is how all tools in the universe work. Then, in Eclipse 3.0 this simple universal standard was changed to show the most recently used tabs (MRU) first, and automatically reorder tabs to always show few last used if there is not enough place to show all. This change was highly controversial, see lengthy discussions in bug 68684. Finally, via bug 461736 the tab visibility strategy has has been turned into a separate preference, so everyone can decide if MRU should be turned on or off.

The new preference can be found under Window > Preferences > General > Appearance > Visible Tabs on overflow > Show most recently used tabs:

MRU off!

UI responsiveness monitoring

This feature is might be uninteresting for the end user, but it greatly helps IDE developers to recognize misbehaved code which causes UI freezes. UI responsiveness monitoring can be turned on via Window > Preferences > General > UI Responsiveness Monitoring.

UI responsiveness preferences
Please enable monitoring and please report UI freezes (they are reported to the Eclipse error log) to bugzilla.

Copy/paste for files improved

<Ctrl+C > / <Ctrl+V> of a files in same folder in explorer views to create a copy automatically proposes now just the old name followed by the digit 2 (or 3, etc., if that name is already taken). This is really handy if one wants create few file duplicates in same folder.

Shortcut for Skip All Breakpoints  

A very handy Ctrl+Alt+B has been added as the shortcut for Skip All Breakpoints:

Zoom font in editors <Ctrl++> and <Ctrl+->

In text editors, you can now use Zoom In <Ctrl++> or <Ctrl+=> and Zoom Out <Ctrl+-> commands to increase and decrease the font size. Like a change in the Window > General > Appearance > Colors and Fonts preference page, the commands persistently change the font size in all editors of the same type. If the editor type's font is configured to use a default font, then that default font will be zoomed.

Automatic save of dirty editors

Auto-save of dirty editors is now available in Eclipse. The autosave option is disabled by default. A new autosave preference page (Window > Preferences > General > Editors > Autosave) is available and allows to enable/disable the autosave and change the interval of autosave. The countdown is reset on keyboard activity, mouse click, or when a popup is displayed (e.g. content assist, preference page, ...).
Autosave preferences

Workspace selection dialog

The workspace selection dialog now allows you to start a previously selected workspace directly via a link. The path to the workspace is shortened. The full path is available if you hover over the link. You can remove existing entries via the context menu.

Workspace selection dialog

Screen space tweaks

Main toolbar can be hidden (Window > Appearance > Hide Toolbar), and Eclipse window can be put in the "Full Screen" mode without title bar (Window > Appearance > Toggle Full Screen). In 4.7 there will be another tweak: Window > Appearance > Hide Status Bar. Guess what it will do :-)

Print button is hidden

Yep, the global toolbar does not show "Print" button by default, to save space. It turned out, no one actually uses this function, so why should it be on the main toolbar?

Default text editor for unknown files

Since ever Eclipse tried to open a system editor for files which did not have a dedicated editor in Eclipse. In 4.x there is a possibility to stop this and to chose to always use default text editor from Eclipse instead.

On the Window > Preferences > General > Editors > File Association page, you can now define an editor selection strategy for unassociated file types. Three strategies are proposed out-of-the-box:
  • System Editor; if none: Text Editor (default) will open the system editor associated with the file, if available. If no system editor is associated with the given file, fall back to the Eclipse Text Editor
  • Text Editor will always open Eclipse's Text Editor on unassociated file types
  • Ask via pop-up will open the same dialog as using Open With > Other... on a file and let you choose which editor to use (inside or outside the IDE)
Keep in mind that in any case, it's possible to assign an editor for an unassociated file type either via this same preference page, or via the Open With > Other... context-menu on the file

Eclipse sources are in Git

Along with 4.x transition, all Eclipse sources were moved to Git (from CVS). This opened a really nice path for contributions. If you are interested in Eclipse hacking, or just want to fix this nasty XYZ bug - please consider to contribute back to the community: https://wiki.eclipse.org/Platform_UI/How_to_Contribute.

by Andrey Loskutov (noreply@blogger.com) at February 19, 2017 09:39 PM

Combine Xcore, Xtend, Ecore, and Maven

by Niko Stotz at February 18, 2017 06:00 PM

Lots of thanks to Christian for figuring this out together.

The complete example is available on github.

Also, we included all the files as Listings at the end of the article. They are heavily commented.

Objective

Inside an Eclipse plugin, we have EMF models defined in both Xcore and Ecore, using types from each other. Also, we have a Helper Xtend class that’s called from Xcore and uses types from the same model. We want to build the Eclipse Plugin with Maven. We also don’t want to commit any generated sources (from Xtend, Xcore, or Ecore).

Issue

Usually, we would use xtend-maven-plugin to build the Xtend classes, xtext-maven-plugin to build the Xcore model, and MWE2 to build the Ecore model.

However, we have a cyclic compile-time dependency between AllGreetings calling GreetingsHelper.compileAllGreetings() which receives a parameter of type AllGreetings.

Solution

Java (and Xtend) can solve such cycles in general, but only if they process all members at the same time. Thus, we need to make sure both Xtend and Xcore are generated within the same Maven plugin.

We didn’t find a way to include the regular Ecore generator in the same step, so we keep this in a separate MWE2-based Maven plugin.

For generating persons.ecore, we call an MWE2 workflow from Maven via exec-maven-plugin. The workflow itself gets a bit more complicated, as we use INamedElement from base.xcore as a supertype to IPerson inside persons.ecore. Thus, we need to ensure that base.xcore is loaded, available, and can be understood by the Ecore generator.

Afterwards, we use xtext-maven-plugin to generate both Xtend and the two Xcore models. To do this, we need to include all the required languages and dependencies into one single plugin in our maven pom.

Missing Bits

The workaround of using MWE2 to build Ecore models has (presumably) the side effect that we cannot refer to Ecore contents within Xtend. The respective parts are commented in GreetingsHelper.compileAllPersons() and drawn grey in the diagram above.

Remarks

  • We developed this using Eclipse Mars.2.
  • The example project should be free of errors and warnings, and builds in all of Eclipse, MWE2, and Maven.

    In Maven, you might see some warnings due to an Xtext bug. It should not have any negative impact.

  • When creating the Ecore file, make sure only to use built-in types (like EString) from http://www.eclipse.org/emf/2002/Ecore. They may be listed several times.
  • In our genmodel file, Eclipse tends to replace this way of referring to platform:/resource/org.eclipse.emf.ecore/model/Ecore.genmodel#//ecore by something like ../../org.eclipse.emf.ecore/model/Ecore.genmodel#//ecore. This would lead to ConcurrentModificationException in xtext-maven-plugin or MWE2, or “The referenced packages ”{0}” and ”{1}” have the same namespace URI and cannot be checked at the same time.” when opening the GenModel editor.

    In this case, open the genmodel file with a text editor and use the platform:/resource/org.eclipse.emf.ecore/model/Ecore.genmodel#//ecore form in the genmodel:GenModel#usedGenPackages attribute. Sadly, this needs to be fixed every time the Genmodel Editor saves the file.

  • The Xcore builder inside Eclipse automatically picks up the latest EMF complianceLevel, leading to Java generics support in generated code. The maven plugin does not use the latest complianceLevel, thus we need to set it explicitly.
  • The modelDirectory setting in both Xcore and Ecore seem to be highly sensitive to leading or trailing slashes. We found it safest not to have them at all.
  • Using all the involved generators (MWE2, Xcore, Xtend, …) requires quite a few dependencies for our plugin. As a neat trick, we can define them in build.properties rather than MANIFEST.MF. This way, they are available at build time, but do not clog our run-time classpath. As we can see on the right, they are also listed separately in the Eclipse dependency editor.
  • maven-clean-plugin seems to be quite sensitive how its filesets are described. Even when disregarding the .dummy.txt entries in our pom, the *-gen directories were only cleaned if we listed them in separate fileset entries.
  • The workflow should reside within an Eclipse source folder. To separate it from real sources, we created a new source folder named workflow.

Listings

Project Layout

GreetingsHelper.xtend

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package de.nikostotz.xtendxcoremaven.greetings.helper

import de.nikostotz.xtendxcoremaven.greetings.AllGreetings

class GreetingsHelper {
// This method is called from greetings.xcore and has AllGreetings as parameter type,
// thus creating a dependency circle
def static String compileAllGreetings(AllGreetings it) {
var totalSize = 0
// We access the AllGreetings.getGreetings() method in two different ways
// (for-each-loop and map) to demonstrate different error messages if we omit
// 'complianceLevel="8.0"' in greetings.xcore
for (greeting : it.getGreetings()) {
totalSize = totalSize + greeting.getMessage().length
}

'''
Greetings:
«it.getGreetings().map[greeting | greeting.getMessage()].join(", ")»
'
''
}

// This does not work currently with Maven. I didn't figure out why yet, but have some clues:
// AllGreetings.getPersons() refers to type IPerson, which is defined in Ecore.
// This might not be generated yet when the Xtend generator runs in Maven.
// def static String compileAllPersons(AllGreetings it) {
// '''
// Hello Humans:
// «it.getPersons().map[person | person.describeMyself()].join(", ")»
// '''
// }
}

base.xcore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@GenModel(
// This sets the target directory where to put the generated classes.
// Make sure NOT to start or end with a slash!
// Doing so would lead to issues either with Eclipse builder, MWE2 launch, or Maven
modelDirectory="de.nikostotz.xtendxcoremaven/xcore-gen",

// required to fix an issue with xcore (see https://www.eclipse.org/forums/index.php/t/367588/)
operationReflection="false"
)
package de.nikostotz.xtendxcoremaven.base

// This enables usage of the @GenModel annotation above. The annotation would work without
// this line in Eclipse, but Maven would fail.
// (WorkflowInterruptedException: Validation problems: GenModel cannot be resolved.)
annotation "http://www.eclipse.org/emf/2002/GenModel" as GenModel

interface INamedElement {
String name
}

persons

persons.ecore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
< ?xml version="1.0" encoding="UTF-8"?>
<ecore:epackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="persons" nsURI="de.nikostotz.xtendxcoremaven.persons" nsPrefix="persons">
  <eclassifiers xsi:type="ecore:EClass" name="IPerson" abstract="true" interface="true"
     eSuperTypes="base.xcore#/EPackage/INamedElement">
    <eoperations name="describeMyself" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"></eoperations>
  </eclassifiers>
  <eclassifiers xsi:type="ecore:EClass" name="Human" eSuperTypes="#//IPerson">
    <estructuralfeatures xsi:type="ecore:EAttribute" name="knownHumanLanguages" upperBound="-1"
       eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"></estructuralfeatures>
  </eclassifiers>
  <eclassifiers xsi:type="ecore:EClass" name="Developer" eSuperTypes="#//IPerson">
    <estructuralfeatures xsi:type="ecore:EAttribute" name="knownProgrammingLanguages"
       upperBound="-1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"></estructuralfeatures>
  </eclassifiers>
</ecore:epackage>

persons.genmodel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
< ?xml version="1.0" encoding="UTF-8"?>
<genmodel:genmodel xmi:version="2.0"
    xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
    xmlns:genmodel="http://www.eclipse.org/emf/2002/GenModel"
    modelDirectory="de.nikostotz.xtendxcoremaven/emf-gen" modelName="Persons"
    importerID="org.eclipse.emf.importer.ecore" complianceLevel="8.0"
    copyrightFields="false" importOrganizing="true"
    usedGenPackages="base.xcore#/1/base platform:/resource/org.eclipse.emf.ecore/model/Ecore.genmodel#//ecore">
    <!-- Eclipse tends to replace this way of referring to the Ecore genmodel
        by something like "../../org.eclipse.emf.ecore/model/Ecore.genmodel#//ecore".
        This would lead to ConcurrentModificationException in xtext-maven-plugin
        or MWE2, or "The referenced packages ''{0}'' and ''{1}'' have the same namespace
        URI and cannot be checked at the same time." when opening the GenModel editor. -->

    <foreignmodel>persons.ecore</foreignmodel>
    <genpackages prefix="Persons" basePackage="de.nikostotz.xtendxcoremaven.persons"
        disposableProviderFactory="true" ecorePackage="persons.ecore#/">
        <genclasses image="false" ecoreClass="persons.ecore#//IPerson">
            <genoperations ecoreOperation="persons.ecore#//IPerson/describeMyself"></genoperations>
        </genclasses>
        <genclasses ecoreClass="persons.ecore#//Human">
            <genfeatures createChild="false"
                ecoreFeature="ecore:EAttribute persons.ecore#//Human/knownHumanLanguages"></genfeatures>
        </genclasses>
        <genclasses ecoreClass="persons.ecore#//Developer">
            <genfeatures createChild="false"
                ecoreFeature="ecore:EAttribute persons.ecore#//Developer/knownProgrammingLanguages"></genfeatures>
        </genclasses>
    </genpackages>
</genmodel:genmodel>

greetings.xcore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@GenModel(
modelDirectory="de.nikostotz.xtendxcoremaven/xcore-gen",
operationReflection="false",

// This enables Java generics support in EMF (starting with version 6.0).
// If omitted, we'd get a "Validation Problem: The method or field message is undefined" in Maven
// because AllGreetings.getGreetings() would return an EList instead of an EList, thus
// we cannot know about the types of the list elements and whether they have a 'message' property.
// In other cases, this leads to error messages like "Cannot cast Object to Greeting".
complianceLevel="8.0"
)

package de.nikostotz.xtendxcoremaven.greetings

// referring to Ecore
import de.nikostotz.xtendxcoremaven.persons.persons.IPerson

// referring to Xtend
import de.nikostotz.xtendxcoremaven.greetings.helper.GreetingsHelper

annotation "http://www.eclipse.org/emf/2002/GenModel" as GenModel

class AllGreetings {
contains IPerson[] persons
contains Greeting[] greetings

op String compileAllGreetings() {
// calling Xtend inside Xcore
GreetingsHelper.compileAllGreetings(this)
}
}

class Greeting {
String message
refers IPerson person
}

MANIFEST.MF

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: de.nikostotz.xtendxcoremaven;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-ClassPath: .
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Bundle-Activator: de.nikostotz.xtendxcoremaven.XtendXcoreMavenActivator
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.emf.ecore;visibility:=reexport,
org.eclipse.xtext.xbase.lib,
org.eclipse.emf.ecore.xcore.lib
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: de.nikostotz.xtendxcoremaven.greetings.impl,
de.nikostotz.xtendxcoremaven.greetings.util,
de.nikostotz.xtendxcoremaven.base,
de.nikostotz.xtendxcoremaven.base.impl,
de.nikostotz.xtendxcoremaven.base.util,
de.nikostotz.xtendxcoremaven.persons.persons,
de.nikostotz.xtendxcoremaven.persons.persons.impl,
de.nikostotz.xtendxcoremaven.persons.persons.util
Bundle-ActivationPolicy: lazy

build.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#

bin.includes = .,\
model/,\
META-INF/,\
plugin.xml,\
plugin.properties
jars.compile.order = .
source.. = src/,\
emf-gen/,\
xcore-gen/,\
xtend-gen/
src.excludes = workflow/
output.. = bin/
# These work the same as entries in MANIFEST.MF#Require-Bundle, but only at build time, not run-time
additional.bundles = org.eclipse.emf.mwe2.launch,\
org.apache.log4j,\
org.apache.commons.logging,\
org.eclipse.xtext.ecore,\
org.eclipse.emf.codegen.ecore.xtext,\
org.eclipse.emf.ecore.xcore,\
org.eclipse.xtend.core,\
org.eclipse.emf.codegen.ecore,\
org.eclipse.emf.mwe.core,\
org.eclipse.emf.mwe.utils,\
org.eclipse.emf.mwe2.lib

generateGenModel.mwe2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
module GenerateGenModel

var projectName = "de.nikostotz.xtendxcoremaven"
var rootPath = ".."

Workflow {
// This configures the supported model types for EcoreGenerator.
// Order is important.
// Should be the same list as in Reader below.
bean = org.eclipse.emf.ecore.xcore.XcoreStandaloneSetup {}
bean = org.eclipse.xtend.core.XtendStandaloneSetup {}
bean = org.eclipse.xtext.ecore.EcoreSupport {}
bean = org.eclipse.emf.codegen.ecore.xtext.GenModelSupport {}

bean = org.eclipse.emf.mwe.utils.StandaloneSetup {
// Required for finding the platform contents (Ecore.ecore, Ecore.genmodel, ...) under all circumstances
platformUri = "${rootPath}"

// Required for finding above mentioned models inside their Eclipse plugins
scanClassPath = true
}

// As persons.ecore refers to a type inside base.xcore (IPerson extends INamedElement),
// we need to load base.xcore before we can generate persons.ecore.
component = org.eclipse.xtext.mwe.Reader {
// This configures the supported model types for this Reader.
// Order is important.
// Should be the same list as beans above.
register = org.eclipse.emf.ecore.xcore.XcoreStandaloneSetup {}
register = org.eclipse.xtend.core.XtendStandaloneSetup {}
register = org.eclipse.xtext.ecore.EcoreSupport {}
register = org.eclipse.emf.codegen.ecore.xtext.GenModelSupport {}

// This asks the Reader to read all models it understands from these directories (and sub-directories).
path = "model"
path = "src"

// Put the models inside a ResourceSet that's accessible by the EcoreGenerator.
loadFromResourceSet = {}
}

// Generate persons.ecore (via persons.genmodel).
component = org.eclipse.emf.mwe2.ecore.EcoreGenerator {
genModel = "platform:/resource/${projectName}/model/persons.genmodel"
srcPath = "platform:/resource/${projectName}/emf-gen"
}
}

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
<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>de.nikostotz.xtendxcoremaven</groupid>
    <version>1.0.0-SNAPSHOT</version>
    <artifactid>de.nikostotz.xtendxcoremaven</artifactid>

    <properties>
        <project .build.sourceEncoding>UTF-8</project>

        <!-- Java version, will be honored by Xcore / Xtend -->
        <maven .compiler.source>1.8</maven>
        <maven .compiler.target>1.8</maven>

        <!-- Xtend / Xcore -->
        <core -resources-version>3.7.100</core>
        <eclipse -text-version>3.5.101</eclipse>
        <emf -version>2.12.0</emf>
        <emf -common-version>2.12.0</emf>
        <emf -codegen-version>2.11.0</emf>
        <xtext -version>2.10.0</xtext>
        <ecore -xtext-version>1.2.0</ecore>
        <ecore -xcore-version>1.3.1</ecore>
        <ecore -xcore-lib-version>1.1.100</ecore>
        <emf -mwe2-launch-version>2.8.3</emf>
    </properties>

    <dependencies>
        <dependency>
            <groupid>org.eclipse.emf</groupid>
            <artifactid>org.eclipse.emf.common</artifactid>
            <version>${emf-common-version}</version>
        </dependency>
        <dependency>
            <groupid>org.eclipse.emf</groupid>
            <artifactid>org.eclipse.emf.ecore</artifactid>
            <version>${emf-version}</version>
        </dependency>
        <dependency>
            <groupid>org.eclipse.emf</groupid>
            <artifactid>org.eclipse.emf.ecore.xcore.lib</artifactid>
            <version>${ecore-xcore-lib-version}</version>
        </dependency>
        <dependency>
            <groupid>org.eclipse.xtext</groupid>
            <artifactid>org.eclipse.xtext.xbase.lib</artifactid>
            <version>${xtext-version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupid>org.apache.maven.plugins</groupid>
                <artifactid>maven-compiler-plugin</artifactid>
                <version>3.3</version>
            </plugin>

            <plugin>
                <artifactid>maven-clean-plugin</artifactid>
                <version>2.6.1</version>
                <configuration>
                    <filesets>
                        <fileset>
                            <excludes>
                                <exclude>.dummy.txt</exclude>
                            </excludes>
                            <directory>emf-gen</directory>
                        </fileset>
                        <fileset>
                            <excludes>
                                <exclude>.dummy.txt</exclude>
                            </excludes>
                            <directory>xtend-gen</directory>
                        </fileset>
                        <fileset>
                            <excludes>
                                <exclude>.dummy.txt</exclude>
                            </excludes>
                            <directory>xcore-gen</directory>
                        </fileset>
                    </filesets>
                </configuration>
            </plugin>

            <!-- Adds the generated sources to the compiler input -->
            <plugin>
                <groupid>org.codehaus.mojo</groupid>
                <artifactid>build-helper-maven-plugin</artifactid>
                <version>1.9.1</version>
                <executions>
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <!-- This should be in sync with xtext-maven-plugin//source-roots,
                                except for /model directory -->
                            <sources>
                                <source />${basedir}/emf-gen
                                <source />${basedir}/xcore-gen
                                <source />${basedir}/xtend-gen
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <!-- Generates the Ecore model via MWE2 -->
            <plugin>
                <groupid>org.codehaus.mojo</groupid>
                <artifactid>exec-maven-plugin</artifactid>
                <version>1.4.0</version>
                <executions>
                    <execution>
                        <id>mwe2Launcher</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainclass>org.eclipse.emf.mwe2.launch.runtime.Mwe2Launcher</mainclass>
                    <arguments>
                        <argument>${project.basedir}/workflow/generateGenModel.mwe2</argument>
                        <argument>-p</argument>
                        <argument>rootPath=${project.basedir}/..</argument>
                    </arguments>
                    <classpathscope>compile</classpathscope>
                    <includeplugindependencies>true</includeplugindependencies>
                    <cleanupdaemonthreads>false</cleanupdaemonthreads><!-- see https://bugs.eclipse.org/bugs/show_bug.cgi?id=475098#c3 -->
                </configuration>
                <dependencies>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.mwe2.launch</artifactid>
                        <version>${emf-mwe2-launch-version}</version>
                    </dependency>

                    <dependency>
                        <groupid>org.eclipse.xtext</groupid>
                        <artifactid>org.eclipse.xtext.xtext</artifactid>
                        <version>${xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.text</groupid>
                        <artifactid>org.eclipse.text</artifactid>
                        <version>${eclipse-text-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.core</groupid>
                        <artifactid>org.eclipse.core.resources</artifactid>
                        <version>${core-resources-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.xtend</groupid>
                        <artifactid>org.eclipse.xtend.core</artifactid>
                        <version>${xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.xtext</groupid>
                        <artifactid>org.eclipse.xtext.ecore</artifactid>
                        <version>${xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.xtext</groupid>
                        <artifactid>org.eclipse.xtext.xbase</artifactid>
                        <version>${xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.codegen.ecore.xtext</artifactid>
                        <version>${ecore-xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.common</artifactid>
                        <version>${emf-common-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.ecore</artifactid>
                        <version>${emf-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.ecore.xmi</artifactid>
                        <version>${emf-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.codegen</artifactid>
                        <version>${emf-codegen-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.codegen.ecore</artifactid>
                        <version>${emf-codegen-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.ecore.xcore</artifactid>
                        <version>${ecore-xcore-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.ecore.xcore.lib</artifactid>
                        <version>${ecore-xcore-lib-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.text</groupid>
                        <artifactid>org.eclipse.text</artifactid>
                        <version>${eclipse-text-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.core</groupid>
                        <artifactid>org.eclipse.core.resources</artifactid>
                        <version>${core-resources-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.xtend</groupid>
                        <artifactid>org.eclipse.xtend.core</artifactid>
                        <version>${xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.xtext</groupid>
                        <artifactid>org.eclipse.xtext.ecore</artifactid>
                        <version>${xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.xtext</groupid>
                        <artifactid>org.eclipse.xtext.xbase</artifactid>
                        <version>${xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.codegen.ecore.xtext</artifactid>
                        <version>${ecore-xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.common</artifactid>
                        <version>${emf-common-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.ecore</artifactid>
                        <version>${emf-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.ecore.xmi</artifactid>
                        <version>${emf-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.codegen</artifactid>
                        <version>${emf-codegen-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.codegen.ecore</artifactid>
                        <version>${emf-codegen-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.ecore.xcore</artifactid>
                        <version>${ecore-xcore-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.ecore.xcore.lib</artifactid>
                        <version>${ecore-xcore-lib-version}</version>
                    </dependency>
                </dependencies>
            </plugin>

            <!-- Generates the Xtend and Xcore models -->
            <plugin>
                <groupid>org.eclipse.xtext</groupid>
                <artifactid>xtext-maven-plugin</artifactid>
                <version>${xtext-version}</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <languages>
                        <language>
                            <setup>org.eclipse.xtext.ecore.EcoreSupport</setup>
                        </language>
                        <language>
                            <setup>org.eclipse.emf.codegen.ecore.xtext.GenModelSupport</setup>
                        </language>
                        <language>
                            <setup>org.eclipse.xtend.core.XtendStandaloneSetup</setup>
                            <outputconfigurations>
                                <outputconfiguration>
                                    <outputdirectory>${project.basedir}/xtend-gen</outputdirectory>
                                </outputconfiguration>
                            </outputconfigurations>
                        </language>
                        <language>
                            <setup>org.eclipse.emf.ecore.xcore.XcoreStandaloneSetup</setup>
                            <outputconfigurations>
                                <outputconfiguration>
                                    <outputdirectory>${project.basedir}/xcore-gen</outputdirectory>
                                </outputconfiguration>
                            </outputconfigurations>

                        </language>
                    </languages>
                    <!-- This should be in sync with build-helper-maven-plugin//sources,
                        except for /model directory -->
                    <sourceroots>
                        <root>${basedir}/src</root>
                        <root>${basedir}/emf-gen</root>
                        <!-- Note that we include the /model path here although it's not part
                            of the source directories in Eclipse or Maven -->
                        <root>${basedir}/model</root>
                    </sourceroots>
                    <!-- This does not work currently, as we can see by the missing lambda
                        in generated code for GreetingsHelper.compileAllGreetings(). It does work,
                        however, for xtend-maven-plugin. (see https://github.com/eclipse/xtext-maven/issues/11)-->
                    <javasourceversion>1.8</javasourceversion>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupid>org.eclipse.text</groupid>
                        <artifactid>org.eclipse.text</artifactid>
                        <version>${eclipse-text-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.core</groupid>
                        <artifactid>org.eclipse.core.resources</artifactid>
                        <version>${core-resources-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.xtend</groupid>
                        <artifactid>org.eclipse.xtend.core</artifactid>
                        <version>${xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.xtext</groupid>
                        <artifactid>org.eclipse.xtext.ecore</artifactid>
                        <version>${xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.xtext</groupid>
                        <artifactid>org.eclipse.xtext.xbase</artifactid>
                        <version>${xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.codegen.ecore.xtext</artifactid>
                        <version>${ecore-xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.common</artifactid>
                        <version>${emf-common-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.ecore</artifactid>
                        <version>${emf-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.ecore.xmi</artifactid>
                        <version>${emf-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.codegen</artifactid>
                        <version>${emf-codegen-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.codegen.ecore</artifactid>
                        <version>${emf-codegen-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.ecore.xcore</artifactid>
                        <version>${ecore-xcore-version}</version>
                    </dependency>
                    <dependency>
                        <groupid>org.eclipse.emf</groupid>
                        <artifactid>org.eclipse.emf.ecore.xcore.lib</artifactid>
                        <version>${ecore-xcore-lib-version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
</project>

.gitignore

1
2
3
4
5
bin/*
target
emf-gen/*
xcore-gen/*
xtend-gen/*

by Niko Stotz at February 18, 2017 06:00 PM

Eclipse Newsletter - Top Eclipse Marketplace Plugins

February 17, 2017 04:52 PM

What are the top Eclipse Marketplace plugins? How can you benefit from them? Find out!

February 17, 2017 04:52 PM

Eclipse Newsletter - Top Eclipse Marketplace Plugins

February 17, 2017 04:52 PM

What are the top Eclipse Marketplace plugins? How can you benefit from them? Find out!

February 17, 2017 04:52 PM

Prerequisite Dependencies

by waynebeaton at February 17, 2017 06:34 AM

All third party content must be taken through the Eclipse Foundation’s Intellectual Property (IP) Due Diligence Process before being used by an open source project hosted by the Eclipse Foundation. This includes all third party content that is incorporated into project code, included in builds, or otherwise required by the project code to provide functionality.

The Eclipse Foundation’s Guidelines for the Review of Third Party Dependencies defines various classifications of third party content and how project teams should engage in the IP process. The classification of third party content most commonly used is the so-called prerequisite dependency: a prerequisite dependency is third party content that the project either needs to distribute along with the project code, or otherwise have present in order to function.

Third party content is likely a prerequisite dependency if:

  • project code accesses APIs;
  • project code includes an import statement for a package from a library;
  • project code uses reflection or other means to reference a library’s APIs and implementation;
  • the Java/OSGi manifest for a project bundles makes a direct reference; or
  • project code invokes a command line tool to access the functionality.

This list is not intended to be exhaustive, but rather to provide common examples. Fundamentally, if project code makes some kind of use of third-party content, then that content is likely a prerequisite. The guidelines provide for so-called works with and exempt prerequisite dependencies, but I’ll save that discussion for a future post.

Project committers can engage in the IP Due Diligence process by creating a contribution questionnaire (CQ) in the Eclipse Foundation’s IPZilla system.

The term contribution questionnaire is a bit misleading when it comes to third party content. Third party content is not a really a contribution to the project, but since the requirements for tracking project code and third party content is very similar, the same mechanism is used for both.

The workflow looks a little something like this:

prereq

screenshot-from-2017-02-08-13-25-01

Committer Tools

There’s an entry point that project committers can use to Create a Contribution Questionnaire in the Committer Tools block that is on every project’s information page (see the image on the right).

In the first step, the committer creates the CQ record with essential information about the third party content and then attaches the source code for that content (this currently happens in two separate steps). The corresponding Project Management Committee (PMC) must sign-off on the CQ before any further processing occurs.

As a general rule, a CQ should be created for each separate library. The process permits for some flexibility with regard to the definition of library. Content that has source in a single source repository that is distributed as multiple JAR files can very likely be regarded as a single library. There has also been cases where the IP Team has accepted a single CQ to do license certification for a collection of many different JavaScript sources. If you’re not sure, check with the IP Team.

License scanning software will be engaged for third party content that’s to be reviewed for license certification (type A). As we roll out this new type of IP due diligence, the IP Team is engaging the tool manually, evaluating the output, and making a determination. Our plan is to automate the invocation of the tool and make a determination automatically where possible (e.g. in cases where the licenses are clearly indicated in the content) and have the IP Team investigate further when necessary.

For requests to perform the more thorough IP due diligence process (type B), the workflow is different. For content that qualifies for parallel IP processing, the IP Team will do a cursory review and—assuming that the content passes muster—grant check in, meaning that the content can be pushed into the project’s source code repository and included in builds. The full due diligence review includes verification of the content’s provenance and a scan for all kinds of other anomalies (more on this in future posts). This process is a lot work that can take quite a lot of time to complete, and very often requires interaction with the committer. When the IP team completes a full review with a successful outcome, they’ll mark the CQ as approved.

All third party content must be either license certified or approved before an project can issue an official release. Any release that includes license certified content must be marked as a type A. A type A release may include type B content; A type B release, however, cannot include type A content.

I’ve thrown out a few concepts in this post without providing explanations. I’ll try and fill in the gaps in future posts, which will all be grouped in the intellectual property category.



by waynebeaton at February 17, 2017 06:34 AM

What is Two? Much more than yet another Eclipse IDE

by Doug Schaefer at February 16, 2017 07:19 PM

It’s been a wild few weeks on the journey I now simply call “Two”. (Until it becomes an Eclipse project, I can’t call it one. And rightly so). The feedback I’ve received, especially as it hit the presses, was fantastic. It’s driven a lot of traffic to my github repo. I’ve even received a few pull requests from people cleaning up my mess as I plow through it. At the very least, people are intrigued by idea of an IDE built with Web UI technologies running locally under Electron.

As I work through the vision, I don’t think it’s fair to simply call it yet another Eclipse IDE. It’s much grander than that. For me, Two is about that vision. It’s more than a code editor. It’s more than just taking the existing Eclipse IDE and implement it in HTML5 running locally. It’s about a whole new way for developers to work with their tools and access the resources available to them on the web.

Developers today have access to many powerful web services. Github is a huge one. At Eclipse we use Bugzilla for bug tracking. A lot of companies use JIRA. People may be using Gitlab as their private Github. You may be using Gerrit for code reviews. I notice LLVM is using Phabricator for code reviews. And there’s the venerable Review Board still active today. Jenkins for continuous integration. And don’t tell me you don’t cut and paste error messages into Google searches to find others who’ve seen the same problem and worked out a solution. The Web is a critical tool in the developers belt.

I was intrigued by an article written by the creators of a tool called Ship. It’s a Mac native, i.e. Cocoa, app that integrates with the Github issue tracker. This quote hit me:

“A point of pride for us is that many people we have shown Ship 2.0 haven’t been able to tell where the web-based content ends and the native Cocoa stuff begins.”

That’s exactly it. If we can say the same for Two, where you can’t tell where the web ends and integration with local tools begin, then we’ve hit a home run.

Integrated Development Environments provide the most value when they have integrations between tools, which the developer has had to do manually for years. The IDE’s role is to automate workflows that transgress all the tools the developer has to use, where the workflow becomes the key, not the individual tools themselves. This focus makes it much easier for them to accomplish their objectives, so they don’t have to learn all the intricacies of underlying environments, but provide a unified language.

And that’s what Two needs to be, a tools integrator that includes not only the tools the user has installed locally, but also integrates with these super powerful web resources in seamless workflows.

The other important factor with IDEs that so many forget, is that experienced developers will always have a bit of mistrust in their IDE no matter how good it is. They need to be able to get close to the iron and run the underlying tools manually at a place where their trust is higher. An IDE that hides that, or makes those tools hard to get to, will struggle being universal. That’s why I’m not a fan of Cloud or Docker hosted tools. In making deployment easy for the provider, they make it hard for the user to touch the bits they’re creating.

The main reason I don’t want to call this Eclipse Two is that this isn’t just about a next generation Eclipse IDE. That IDE was my One, the first IDE that I’ve had a hand in creating. I want to rethink the whole developer experience and create an IDE that works well in the modern world, now almost 20 years after One. This is Two.


by Doug Schaefer at February 16, 2017 07:19 PM

Tutorial – Eclipse Marketplace & Favourites List

by Antoine THOMAS at February 16, 2017 08:00 AM

A few months ago we introduced the Eclipse Marketplace Favourites List. To explain how it works I created a video tutorial. This article will be a more classic tutorial to explain what Eclipse Marketplace is and how you can use the Favourite Lists to your advantage.

What is Eclipse Marketplace?

The Eclipse Marketplace is a place to discover, share, and install relevant Eclipse plugins and solutions. Think of it like an app store for Eclipse solutions.

One of it’s main uses is to add plugins to your Eclipse installation. You will also find applications based on Eclipse Platform, tooling for IoT and other solutions and services. In this article you’ll find out how to do so – you might even learn a few new tricks along the way.

Favourite list online

One of the great features of the Eclipse Marketplace is the possibility to create and share a list of plugins. This is very helpful if you have many Eclipse installations, and want to find and install your favourites one quickly. How can you do this on the Eclipse website?

How to do this on the website?

  1. Go to https://marketplace.eclipse.org/ and sign up. Or create an account if you don’t have one yet.
  2. Search for your favourite solution
  3. Click on the white star below the logo to add a plugin to your Favourites list.

Visual Example

In this example, Darkest Dark Theme will be added to my favourites plugins list. Once a plugin has been “starred” it is automatically added to your list.

To view it, simply go to “My Marketplace”:

And there it is, in your list of favorites!

Marketplace Client in Eclipse

Manage plugins

Did you know? You can install plugins from your Eclipse IDEs using the Marketplace Client. To launch it:

  1. Click on the “Help” tab in the menu.
  2. Click on “Eclipse Marketplace”.

You can also launch it using the Quick Access Bar at the top right of your Eclipse workspace.

  1. Click “Alt + 3” (Windows) or “Command + 3” (Mac) to launch the Quick Access search bar
  2. Type “Eclipse Marketplace”
  3. Hit “Enter” and voila – you’re there!

You can display and manage your favorites here too:

You can off course add, remove, and install plugins. The Eclipse Marketplace Client and the website store your favorites with your eclipse.org account, so they are synchronised.

Copying Another User’s Favourite List

If you want to install plugins in the list of someone else, say, a colleague, or another contributor to a project, this is also possible.  You can import a favourites list from an other Community users, and then select the plugin you want.

It’s also possible to install plugins from someone else’s list , say, a colleague, or another project contributor. To import a favourites list from an other Community users in your workspace Marketplace client:

  1. Click on “Import Favourites List”
  2. Copy/paste the link to someone’s favorites lists.
  3. All plugins are automatically selected. Unselect any plugins you don’t want by unchecking the checkboxes to the left of each individual plugin.
  4. Click import.

Here is an example with Lars Vogel‘s plugins.

Share

Long story short, to save time or to share your favourite plugins quickly and easily with someone else, you can add plugins to your favourites list. Sharing is simple, all you need is the link to your list. You can find this link on your user profile:

Here are a few Favourites Lists that I would like to share with you. You can import them directly by copying and pasting the link in Eclipse Marketplace Client:

Do not hesitate to share your favourite list on social networks. You can use #EclipseMarketplace on Twitter.

Feedback welcome

As usual, feedback is welcome and discussion is open. Do not hesitate to comment this article or to open an bug.


by Antoine THOMAS at February 16, 2017 08:00 AM

Announcing Availability of Free Error Reporting Service for Eclipse Plugin Developers

by Content Master at February 15, 2017 03:26 PM

What annoys software developers most? Probably when the tools they use Just Don’t Work. And it doesn’t matter what kind of software it is; or whether it’s open-source, or commercial. If it fails, it sucks. Users don’t show mercy. The same holds for the Eclipse IDE. In recent years, many users complained that Eclipse was way too buggy and moved on to the competition. To stop that trend, we started the Automated Error Reporting Initiative for Eclipse. Our main objectives were (i) to make reporting problems with Eclipse as easy as possible and (ii) to make Eclipse committers aware which parts […]

The post Announcing Availability of Free Error Reporting Service for Eclipse Plugin Developers appeared first on Ctrlflow Blog.


by Content Master at February 15, 2017 03:26 PM

Eclipse IoT Announces Support for OMA LightweightM2M 1.0 Device Management Standard

February 15, 2017 02:11 PM

We are pleased to announce the Eclipse Leshan project will support OMA's newly ratified LwM2M 1.0 standard.

February 15, 2017 02:11 PM

Upcoming IoT Events in March 2017

by Roxanne on IoT at February 15, 2017 11:07 AM

It’s no surprise that there are many, MANY, Internet of Things (IoT) events happening all over the world every month. But, there are a few…


by Roxanne on IoT at February 15, 2017 11:07 AM

Why we need industrial consortiums for open source projects!

by tevirselrahc at February 15, 2017 09:00 AM

On Friday, February 17th at 16:00 CET , 15:00 (GMT), and 10:00 EST, the Papyrus Industry Consortium’s (a.k.a. Papyrus-IC or, as I prefer, Me-IC 😉 Research and Academia committee will host their second webinar of the year:

Industrial usage of open source solutions – Why do we need industrial consortiums?

Ericsson’s Francis Bordeleau, who is also the Me-IC’s chairperson will be presenting this very interesting topic.

I must say that, as an open source project myself, I have profited from the creation of the Papyrus IC and I certainly owe some of my growth to its members!

If you are curious as to how open source project can grow and become more palatable for usage in an industrial setting, then you must attend this webinar!

You can find information on how to connect from the Me-IC Research and Academia webinar page!

See you there!


Filed under: Papyrus IC, Research and Academia, webinar Tagged: community, industry, Industry consortium, open-source, PIC

by tevirselrahc at February 15, 2017 09:00 AM

Getting Started With Eclipse Che on Windows 10

by Tracy M at February 14, 2017 01:29 PM

chewindows

Over the last year or so there has been a reasonable amount of evolution of the best way to get Eclipse Che running on Windows. The latest set of instructions are reasonably straightforward though not a complete no-brainer. This post records my snapshot of the step-by-step install process for Eclipse Che 5.2.2 including Docker install, dead ends & false starts.

  1. The aim is to set up a local install of pre-built Che on Windows 10 Home Edition. Starting point, scan documentation at https://www.eclipse.org/che/docs/setup/getting-started/
  2. Install prerequisite Docker. Download & install ‘Docker for Windows’. Helpful error message redirects me to use Docker Toolbox. dockerforwindows
  3. Download Docker Toolbox for Windows. Run installer. Requires 77.6M, and also wants to install Git.  The reason it needs to install a full source control system is merely down to the fact that the Git install comes with a nicely packaged bash & terminal implementation. Nevertheless I already have git installed so no need to here.
  4. Install completes, use shortcut ‘Docker Quickstart Terminal’ doesn’t work as it can’t find bash.exe (The shortcut expects Git to be in a certain default location).
  5. Update shortcut to point at my installed version of Git’s bash.exe (after another false start trying to use Git’s bash directly, fiddling with running things as Admin, etc).
  6. Success & I can run docker run hello-worldhelloworlddocker
  7. Now to the actual Eclipse Che part, try default command line
    docker run -it eclipse/che start

    Not so hasty there, a helpful error message tells me I’m missing a mandatory parameter.cherun1

  8. Add in missing parameter, try again
    docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock \
        eclipse/che start

    Get another useful message about needing to mount a directory to save data:cherun2

  9.  Create a temporary directory and rerun the command specifying a data directory. Get a warning about data folder needing to be in %userprofile% (now you tell me). cherun3
  10. Make a different directory and run command again
    docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock \
        -v /c/Users/tracy/tmp:/data eclipse/che start

    Success!cherun4

  11. Launch up browser, point at http://192.168.99.100:8080, Eclipse Che is up and running.chewindows


by Tracy M at February 14, 2017 01:29 PM

MultiPageEditor with Xtext

February 14, 2017 12:34 PM

Domain specific languages are a great tool when we want to give our users control over complex aspects in our applications; and in most cases, experienced uses can learn syntax and semantics of a well-designed DSL quickly. But on the other hand, there are also inexperienced users, who usually struggle with DSLs and do not want to deal with textual input. Instead, they are used to graphical user interfaces which help them to grasp the structure of information and to enter new data.

Last week, I had a project, in which I needed to provide both groups of users with a suitable user interface. In other words, I needed to create an editor, which provides both an Xtext source editor for my DSL, and a GUI editor for the model behind the DSL.

I started to search the Internet for some hints on how to do this but I did not find a complete example. Basically, to combine multiple editors into a single one, we have to subclass and implement an org.eclipse.ui.part.MultiPageEditorPart. But I did not find more than hints about how to share the model between an Xtext editor and another editor. So, I started experimenting and after some time I was successful, and I wanted to let you participate in my results. Maybe this helps someone who is looking for an example as well.

For the rest of this post, I will use the state machine example that comes with the Xtext distribution as a starting point. To demonstrate the solution I will add a GUI editor for events to the generated Xtext editor. For brevity, I will only show the relevant parts. The full modified example source code is available on GitHub.

Step 1: Setup

To get started, we create the State Machine Example (File > New… > Xtext > Xtext State-Machine Example) in our workspace. The example code is a bit old; to be able to use Java 8 features, we need to switch the Execution Environment, Java Compiler Settings and Java Library Path to Java 1.8.

Step 2: Create the MultiPageEditor

Inside the UI bundle, I have created a new package org.eclipse.xtext.example.fowlerdsl.ui.editor for my editor code. In there, I have created the class StatemachineMultiPageEditor as follows:

public class StatemachineMultiPageEditor extends MultiPageEditorPart
{
  // get the default XtextEditor injected to use as a page
  @Inject
  private XtextEditor sourceEditor;

  private int sourcePageIndex;

  // create and name our editor page
  // The instance is already injected. We only have to add it to the MultiPageEditorPart
  @Override
  protected void createPages()
  {
    try
    {
      this.sourcePageIndex = addPage(this.sourceEditor, getEditorInput());
      setPageText(this.sourcePageIndex, "Source");
    }
    catch (PartInitException e)
    {
      throw new IllegalStateException("Failed to add Xtext editor", e);
    }
  }

  // there are a few abstract methods, we need to implement. 
  // Because the XtextEditor is the master regarding model management, we just delegate every call there 
  @Override
  public void doSave(final IProgressMonitor monitor)
  {
    this.sourceEditor.doSave(monitor);
  }

  // ... other methods likewise
}

This implementation more or less just wraps the Xtext editor. To enable it in the runtime application, we can edit the plugin.xml and replace the XtextEditor which is configured by Xtext with our own implementation:

<extension
        point="org.eclipse.ui.editors">
    <editor
        class="org.eclipse.xtext.example.fowlerdsl.ui.StatemachineExecutableExtensionFactory:org.eclipse.xtext.example.fowlerdsl.ui.editor.StatemachineMultiPageEditor"
        contributorClass="org.eclipse.ui.editors.text.TextEditorActionContributor"
        default="true"
        extensions="statemachine"
        id="org.eclipse.xtext.example.fowlerdsl.Statemachine"
        name="Statemachine Editor">
    </editor>
</extension>

When we start the runtime application, we should be able to create a state machine file (see README in the example project for instructions) and when opening it, we should see that it opens in our own StatemachineMultiPageEditor, which has a single tab called “Source”.

Step 3: Create the UI editor

Now comes the interesting part. To implement our own editor, we need a suitable editor input which provides our editor with access to the XtextEditor model, which is the XtextDocument. So, I decided to wrap the IXtextDocument in an IEditorInput for our own editor:

public class XtextDocumentBasedEditorInput implements IEditorInput
{
  private IXtextDocument document;
  private IFile file;

  public XtextDocumentBasedEditorInput(final IXtextDocument document)
  {
    this.document = document;
    this.file = document.getAdapter(IFile.class);
  }

  public IXtextDocument getDocument()
  {
    return this.document;
  }

  @Override
  public boolean exists()
  {
    return this.file.exists();
  }

  @Override
  public ImageDescriptor getImageDescriptor()
  {
    return this.file.getAdapter(IWorkbenchAdapter.class).getImageDescriptor(this.file);
  }
  
  // the other methods delegate similarly 
  // ...
}

Based on this, we can implement the GUI editor. For this simple example, we will just have a ListViewer showing the list of Events and three buttons (add, edit, delete).

public class EventEditor extends EditorPart
{
  private XtextDocumentBasedEditorInput xtextEditorInput;
  private ListViewer listViewer;
  
  // <irrelevant methods omitted>

  @Override
  public void createPartControl(final Composite parent)
  {
    // <some GUI code omitted>
    
    // create the list viewer
    this.listViewer = new ListViewer(mainComposite, SWT.BORDER);
    this.listViewer.getControl().setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
    this.listViewer.setContentProvider(new ArrayContentProvider());
    this.listViewer.setLabelProvider(new LabelProvider()
    {
      @Override
      public String getText(final Object element)
      {
        if (element instanceof Event)
        {
          Event event = (Event) element;
          return event.getName() + " [" + event.getCode() + "]";
        }
        return super.getText(element);
      }
    });

    // create the buttons
    Composite buttonComposite = new Composite(mainComposite, SWT.NONE);
    buttonComposite.setLayout(new FillLayout(SWT.VERTICAL));
    buttonComposite.setLayoutData(GridDataFactory.swtDefaults().create());
    Button addButton = new Button(buttonComposite, SWT.PUSH);
    addButton.setText("Add");
    addButton.addListener(SWT.Selection, e -> addEvent());

    // <edit and remove button likewise>

    // Synchonize the list viewer input with the Xtext document
    refreshInput();
  }

  /**
   * Recalculates the input to the list viewer, so it is in sync with the source in the Xtext editor.
   * 
   * This is called - when the page becomes visible - after performing an edit operation
   * 
   */
  public void refreshInput()
  {
    IXtextDocument doc = this.xtextEditorInput.getDocument();
    Collection<Event> events = doc.readOnly(res -> EcoreUtil.copyAll(((Statemachine) res.getContents().get(0)).getEvents()));
    this.listViewer.setInput(events.toArray());
  }

  /**
   * Add a new event.
   * 
   * This initializes a new Event object, opens the dialog to let the user specify the event information and if the user closes the dialog by clicking ok, the
   * new event is added to the Xtext document.
   */
  protected void addEvent()
  {
    Event event = StatemachineFactory.eINSTANCE.createEvent();
    event.setName("newEvent");
    event.setCode("CODE");

    boolean result = EditEventDialog.editEvent(getSite().getShell(), event);
    if (result)
    {
      IXtextDocument doc = this.xtextEditorInput.getDocument();
      doc.modify(res -> ((Statemachine) res.getContents().get(0)).getEvents().add(event));
    }

    refreshInput();
  }
  
  // <event handlers for edit and remove button omitted>
}

The interesting methods here are refreshInput() and addEvent(). They use the XtextDocument to access the model in its (dirty) state and/or to manipulate it. It is important to note that the custom code should not hold on to the EMF instances retrieved this way, because when the text is reparsed, Xtext usually throws away old EObject instances and create new ones. Likewise, when modifying the model, make sure that you use the XtextResource and own copies of the information to navigate to the desired model element(s), instead of using previously retrieved EObjects etc.

Step 4: Add the UI editor as a page to the MultiPageEditor

Now we need to add our EventEditor to the StatemachineMultiPageEditor. We let Guice inject our editor just like the XtextEditor. Then we create the editor input and add a second page with our new EventEditor.

Finally, we need to take care of the synchronization between the editors. We could have our editor install a listener on the XtextDocument, so that we get notified on any change. But I decided that it should be enough (and is simpler) to refresh the GUI whenever the user switches the page and the EventEditor becomes visible. To do this, we override the method pageChange().

The resulting changes to the StatemachineMultiPageEditor look like this:

public class StatemachineMultiPageEditor extends MultiPageEditorPart
{
  // ...
  @Inject
  private EventEditor formEditor;
  private int formPageIndex;

  @Override
  protected void createPages()
  {
    // ...
    try
    {
      this.formPageIndex = addPage(this.formEditor, new XtextDocumentBasedEditorInput(this.sourceEditor.getDocument()));
      setPageText(this.formPageIndex, "States");
    }
    catch (PartInitException e)
    {
      throw new IllegalStateException("Failed to add State editor", e);
    }
  }

  @Override
  protected void pageChange(final int newPageIndex)
  {
    if (newPageIndex == this.formPageIndex)
    {
      // when the GUI editor becomes visible, synchronize with the Xtext document
      this.formEditor.refreshInput();
    }
    super.pageChange(newPageIndex);
  }
}

And here is a small demo of the running editor:

 Editor in Action

Odds and Ends

Of course, this example is only a proof of concept and not fully implemented in all detail. For example, validation in the GUI is completely missing. So far, I have not found a good way to include Xtext validation in the GUI (it would be nice to have a name or code checked against the DSL syntax instead of writing an own validator). Also, some additional cases must be handled (for example, what happens if the list of events becomes empty or if there are events with the same name etc.)

Additionally, to have a good interoperability between DSL source and GUI, you have to customize the formatter so that generated model elements are serialized nicely (not like in my example). Also keep in mind that hidden tokens (such as comments) are not represented in the model itself and could be deleted by accident in model modification operations.

{jcomments on}


February 14, 2017 12:34 PM

Introduction to WireframeSketcher

by Antoine THOMAS at February 14, 2017 11:00 AM

WireframeSketcher is based on Eclipse platform. I use it a lot to create mockups for websites and applications. It helps to focus on content, usability and features, instead of design. When your mockup is tested with future end users and documented for developers, it’s time think about design.

Overview

Eclipse users will not be disappointed, the workbench is quite the same, but in the middle, you draw instead of writing code. Also, instead of just drawing basic shape, there is a style added so everything looks like it has been done on paper with a pen. This way, in the mind of people looking at the mockup, you are sure they think about it as a mockup, and not as a definitive design.

You can also add annotations for documentation purpose.

And you can create links on items to other screens, in order to create a live mockup. You can play the live mockup in Wireframesketcher, and also export in HTML to share it.

First project

Menu: File / New / Wireframe project

You can select different type of project, from web to smartphone app, …

Assets

You might want to build a mockup using elements you already have: logo, screenshots or pictures, icons, … You can add them to the “assets” folder of WireframeSketcher folder. They will be available on the right column. When possible add SVG files, so that the software can apply the “hand style”.

WireframeSketcher provides Stencils, it is libraries of screens, icons, mockups, ready to use. You can find them on their website:
http://wireframesketcher.com/mockups/index.html

Icons

You can add an icon alone or with a label, by adding the “Icon” element from the palette.

It is also possible to add icons in some content (text) or attached to an item (button, input, …). To attach an icon to an item, you can click on the properties on the left sidebar, and you can browse the different icon librairies available. With text, you can start to type the name of an icon in { } and use ctrl+space to display some help.

Links

Draw at least 2 screens. You can add links to another screen on elements like buttons, but also on text. Text must be between [ ] to be considered as link. You can’t add links to external resource.

In a screen, select the element. On the left sidebar, next to “Properties”, select “Links”. You will find a list of possible links, just click on the one you want and select the screen to open. That’s all. You will notice the link on the mockup with a special small yellow icon on the item.

The most difficult part of it is to think about the structure, all the links between all the pages. On a live demo, you can highlight links, so testers can easily find the clickable areas.

Annotations

On the right column you will find annotations elements. You can of course change the colour. If you need to use an other element (a square, a round, …), and make it an annotation, you can do that in the menu: Object / Mark as annotation.

During export, you can choose if you want to see them, or hide them.

Storyboard

A storyboard is what will allow you to run the mockup. Put in it all the screens. Be careful about the order of the screens, so the user starts the mockups at the good place. Once done, you can run or export your live mockup.

During a live demo, users will be able to click on the links, or to use left and right keyboard arrows.

Missing features

IMHO, there are two issues with the current version of Wireframesketcher:

  1. You can’t hide annotation while working on the screen, so if you have stuff below, you can not select them. It’s really bad for productivity. There should be at least a layer management system, so one can put all the annotations in one layer and hide them. This is really a missing feature. I already discussed about it on the user forum, the solution they propose is not really useful. And there is no workaround.
  2. There are a lot of text styling options, but no equivalent of the “pre” html tag. It means there is no way to add monotype text.  Let say you want to show how command line or code should look in a design, with fixed characters size, this is not possible. If you are interested too, do not hesitate to tell the developers on the forum.

Conclusion

Despite a few missing features, I really appreciate WireframeSketcher to work on features and UX. I use it at the moment mainly for web stuff. However, I really think that would be awesome to have Eclipse Platform stencils. This way, Eclipse developers could use that to work on their UI/UX before starting to code, collect end user feedback. And also, very important thing, this would be great to share best practice and have a more consistant UI across different Eclipse plugins, applications, tools, …


by Antoine THOMAS at February 14, 2017 11:00 AM

EMF Support for Che – Day 1: Run Che and Import existing EMF project

by Maximilian Koegel and Jonas Helming at February 14, 2017 08:28 AM

In this blog series, we share our experience with extending Eclipse Che and describe how we have built initial EMF support for the Eclipse Che IDE. In the last blog post, we have described our overall goals and the use case.

In this blog post, we describe the first steps in getting started with Che. Before we start to extend Che, let’s run it and see what’s already there. To get started, let us explore the simplest way to get an existing modeling project into a Che workspace. The modeling project is not yet created by Che, but by an Eclipse Modeling Tools IDE. By importing this existing project, we can see what features are already there and what we are going to need to extend later.
As a template project, we will be using the existing “Make it happen!” model (see more details here). This example model is also shipped with every Eclipse Modeling Tools IDE (don’t confuse the desktop IDE with Eclipse Che here), you can instantiate it with New => Example => “Make it happen: Example Model”. The template project already contains generated code. As we will later want to do this directly in Che, we created a version of the “Make it happen!” model without the generated code (“makeinhappen_blank”), which is available here: https://github.com/eclipsesource/emfforms-makeithappen-blank

As a preparation, we have just downloaded and execute Che as described here. So for now, we will use the released and unextended version.

When launching Che and opening it in your browser, you will first see the “Dashboard”. It enables you to create “Workspaces”, but not projects. Che starts a separate runtime for each workspace. Each can be defined as a single Docker container or a group of containers with a composed recipe. However, the default is one container per workspace.
The source code and the corresponding runtime (i.e. a JDK or any other arbitrary tools) are encapsulated in that container and can therefore be shared easily. As you can see in the dashboard, there are a variety of pre-defined workspaces to chose from (also called stacks). The “Java” stack serves as a good basis to begin with.

image04

After we have selected the workspace, Che will launch it for us. Again, technically, a docker container is launched which is pretty similar to  a server-site virtual machine, we will do our development in.

After the workspace has been started, the browser IDE connected to that workspace will be shown (currently empty).
So let us get an existing modeling project into our fresh workspace.
To import a project select Workspace -> Import Project. The default is to use a GIT repository, which is what we use in this example. All you need to do is paste the repository url https://github.com/eclipsesource/emfforms-makeithappen-blank and click “Import”.

image05

Now that we have a fully configured template project in our workspace, we can already have a look at the artifacts. As we have no custom editors yet, all files would be handled as plain text. However, we can open them and have a look:

image00

Of course modifying plain XML is not sufficient, we will have a look at creating custom editors later in this series.
Another interesting thing to see at this point is that the project has been added to the underlying workspace. The console in the lower area of the Che IDE provides us direct access to it. So by typing  

vi /projects/makeithappen/org.eclipse.emf.ecp.makeithappen.model/model/task.ecore

we can look at our Ecore on the console, too:

image09

This means, any command-line based tool can also access our projects artifacts. This is an interesting extension mechanism, that we will use later in our project.

For now, as we have a simple and reproducible way of creating a template project for testing, and we can begin to look at the next requirements for EMF support in Che. It would be obvious to next create a project wizard, a custom modeling project, or a custom editor for Ecore. However, in the next part of this series, we will first enable code generation. This is mainly for risk mitigation. We believe that it is possible with some effort to create our own UI extensions for the Che IDE.

However, for the code generation, we want to use the existing code generator already provided by EMF. So is there a way to integrate existing Eclipse features into Che without much effort? Stay tuned for the next part of this series!

If you are interested in learning more about the prototype for EMF support, if you want to contribute or sponsor its further development, or if you want support for creating your own extension for Che, please get in contact with us.


TwitterGoogle+LinkedInFacebook

2 Comments. Tagged with che, eclipse, che, eclipse


by Maximilian Koegel and Jonas Helming at February 14, 2017 08:28 AM

Connecting your Angular 2 App to your Java EE Backend

by Brian Fernandes at February 13, 2017 08:32 PM

Connecting your Angular 2 App to your Java EE BackendYou’ve been developing in Java EE all this time, but you’re tired of using JSF, or perhaps even Struts, and want to move to something more modern for your front end? Angular 2 is a perfect fit, and with the recent release of Angular 2 GA, […]

The post Connecting your Angular 2 App to your Java EE Backend appeared first on Genuitec.


by Brian Fernandes at February 13, 2017 08:32 PM

Angular Who?

by Wanda Muriy at February 13, 2017 03:31 PM

Staying true to the Angular dynasty.When you are in a serious relationship, you want your partner to have it all… So when someone more attractive comes along, it’s hard to resist the temptation, isn’t it? That’s true for those who started their love story with Angular (or should we say “AngularJS” or “Angular 1”?), have […]

The post Angular Who? appeared first on Genuitec.


by Wanda Muriy at February 13, 2017 03:31 PM

Control OSGi DS Component Instances

by Dirk Fauth at February 13, 2017 07:31 AM

I recently came across some use cases where a more fine grained control is needed for component instance creation. I spent some time in investigating how this is done with OSGi Declarative Services in detail. It turned out that it is easier as it seems, mainly because of missing or misleading tutorials. Therefore I decided to write a new blog post about that topic as part of my OSGi Declarative Service blog post series.

For the start you need to know that by default there is only one component configuration created and activated in the OSGi runtime at the same time. This means that every bundle is sharing the same component instance. So you have a singleton instance for every service. Note: singleton instance in terms of “one single instance” not “Singleton Pattern”!

If you think about multi-threading or context dependent services, you may need multiple instances of a service. In an OSGi environment there are basically the following categories:

  • one service instance per runtime
  • one service instance per bundle
  • one service instance per component/requestor
  • one service instance per request

Instance creation control can only be done for service components. So ensure to specify the service annotation type element in @Component if the implementation does not implement an interface.

To control the instance creation you can use the following mechanisms:

  • DS 1.2 – servicefactory annotation type element of @Component
  • DS 1.3 – scope annotation type element of @Component to specify the service scope
  • DS 1.2 / DS 1.3 – Create a factory component by using the factory annotation type element of @Component

Preparation

For some hands on this topic, we first create some bundles to play with.

Note:
I don’t want to explain every step for creating services in detail in this blog post. If you don’t know how to perform the necessary steps, please refer to my Getting Started with OSGi Declarative Services blog post.

  1. Create an API bundle org.fipro.oneshot.api with a service interface OneShot
    public interface OneShot {
    
        void shoot(String target);
    
    }
  2. Create a provider bundle org.fipro.oneshot.provider with a service implementation Hitman
    @Component
    public class Hitman implements OneShot {
    
        private static AtomicInteger instanceCounter =
                new AtomicInteger(); 
    
        private final int instanceNo;
    
        public Hitman() {
            instanceNo = instanceCounter.incrementAndGet();
        }
    
        @Override
        public void shoot(String target) {
            System.out.println("BAM! I am hitman #"
                + instanceNo + ". And I killed " + target);
        }
    
    }

    This implementation will count the number of instances in a static field and remembers it in a member variable, so we can identify the created instance when the service is called.

  3. Create a command bundle org.fipro.oneshot.command with a console command to call the service
    @Component(
        property= {
            "osgi.command.scope=fipro",
            "osgi.command.function=kill"},
        service=KillCommand.class
    )
    public class KillCommand {
    
        private OneShot killer;
    
        @Reference
        void setOneShot(OneShot oneShot) {
            this.killer = oneShot;
        }
    
        public void kill(String target) {
            killer.shoot(target);
        }
    }
  4. Create a command bundle org.fipro.oneshot.assassinate with two different console commands that call the service
    @Component(
        property= {
            "osgi.command.scope=fipro",
            "osgi.command.function=assassinate"},
        service=AssassinateCommand.class
    )
    public class AssassinateCommand {
    
        private OneShot hitman;
    
        @Reference
        void setOneShot(OneShot oneShot) {
            this.hitman = oneShot;
        }
    
        public void assassinate(String target) {
            hitman.shoot(target);
        }
    }
    @Component(
        property= {
            "osgi.command.scope=fipro",
            "osgi.command.function=eliminate"},
        service=EliminateCommand.class
    )
    public class EliminateCommand {
    
        private ComponentContext context;
        private ServiceReference<OneShot> sr;
    
        @Activate
        void activate(ComponentContext context) {
            this.context = context;
        }
    
        @Reference(name="hitman")
        void setOneShotReference(ServiceReference<OneShot> sr) {
            this.sr = sr;
        }
    
        public void eliminate(String target) {
            OneShot hitman =
                (OneShot) this.context.locateService("hitman", sr);
            hitman.shoot(target);
        }
    }

The EliminateCommand uses the Lookup Strategy to lazily activate the referenced component. In this example probably quite useless, but I wanted to show that this also works fine.

Note:
I am using the DS 1.2 notation here to make it easier to follow the example in both worlds. In the DS 1.3 only examples later in this blog post, you will see the modified version of the components using DS 1.3 annotations.

The sources for this blog post can be found on GitHub:

One instance per runtime

There is not much to say about this. This is the default behavior if you do not specify something else. There is only one component configuration created and activated. Therefore only one component instance is created and shared between all bundles.

In DS 1.2 a singleton instance can be explicitly configured on the component like this:

@Component(servicefactory=false)
public class Hitman implements OneShot {

In DS 1.3 a singleton instance can be explicitly configured on the component like this:

@Component(scope=ServiceScope.SINGLETON)
public class Hitman implements OneShot {

Note:
For Immediate Components and Factory Components it is not allowed to use other values for servicefactory or scope!

If you launch an OSGi application with the necessary bundles (org.apache.felix.scr, org.apache.felix.gogo.*, org.fipro.oneshot.*) and call the commands one after the other, you should get an output similar to this (on a Felix console):

g! kill Dirk
BAM! I am hitman #1. And I killed Dirk
g! assassinate Dirk
BAM! I am hitman #1. And I killed Dirk
g! eliminate Dirk
BAM! I am hitman #1. And I killed Dirk

Every command has a reference to the same Hitman instance, as can be seen by the instance counter in the output.

One instance per bundle

There are use cases where it is useful to have one component configuration created and activated per bundle. For example if the component configuration contains special bundle related configurations.

In DS 1.2 a bundle scope service can be configured on the component like this:

@Component(servicefactory=true)
public class Hitman implements OneShot {

In DS 1.3 a bundle scope service can be configured on the component like this:

@Component(scope=ServiceScope.BUNDLE)
public class Hitman implements OneShot {

When launching the OSGi application and calling the commands one after the other, you should get an output similar to this (on a Felix console):

g! kill Dirk
BAM! I am hitman #1. And I killed Dirk
g! assassinate Dirk
BAM! I am hitman #2. And I killed Dirk
g! eliminate Dirk
BAM! I am hitman #2. And I killed Dirk
g! kill Dirk
BAM! I am hitman #1. And I killed Dirk

You can see that the kill command has a reference to the Hitman instance #1, while the assassinate and the eliminate command both have a reference to the Hitman instance #2, as both reside in the same bundle.

One instance per requestor

There are some use cases where every consumer needs its own instance of a service. With DS 1.2 you could achieve this by creating a Factory Component. As this is basically the same as getting a service instance per request, I will explain the Factory Component in the following chapter. For now I will focus on the DS 1.3 variant to create and use a service instance per requestor.

In DS 1.3 the PROTOTYPE scope was introduced for this scenario.

@Component(scope=ServiceScope.PROTOTYPE)
public class Hitman implements OneShot {

Setting the scope of the service component to PROTOTYPE does not mean that every consumer gets a distinct service instance automatically. By default the result will be the same as with using the BUNDLE scope. So if you start the application with the updated Hitman service, you will get the same result as before.

The reason for this is the reference scope that was also introduced with DS 1.3. It is configured on the consumer side via @Reference and specifies how the service reference should be resolved. There are three possible values:

  • BUNDLE
    All component instances in a bundle will use the same service object. (default)
  • PROTOTYPE
    Every component instance in a bundle may use a distinct service object.
  • PROTOTYPE_REQUIRED
    Every component instance in a bundle must use a distinct service object.

As the default of the reference scope is BUNDLE, we see the same behavior for service scope PROTOTYPE as we saw for service scope BUNDLE. That means the consumer components need to be modified to achieve that every one gets its own service instance.

@Component(
    property= {
        "osgi.command.scope=fipro",
        "osgi.command.function=assassinate"},
    service=AssassinateCommand.class
)
public class AssassinateCommand {

    @Reference(scope=ReferenceScope.PROTOTYPE_REQUIRED)
    private OneShot hitman;

    public void assassinate(String target) {
        hitman.shoot(target);
    }
}
@Component(
    property= {
        "osgi.command.scope=fipro",
        "osgi.command.function=eliminate"},
    service=EliminateCommand.class,
    reference=@Reference(
            name="hitman",
            service=OneShot.class,
            scope=ReferenceScope.PROTOTYPE_REQUIRED
    )
)
public class EliminateCommand {

    private ComponentContext context;

    @Activate
    void activate(ComponentContext context) {
        this.context = context;
    }

    public void eliminate(String target) {
        OneShot hitman =
            (OneShot) this.context.locateService("hitman");
        hitman.shoot(target);
    }
}

Note:
The above examples are showing the DS 1.3 version of the command services. You should recognize the usage of the field strategy and the DS 1.3 lookup strategy, which makes the code more compact.

Note:
In the example I have chosen to use the reference scope PROTOTYPE_REQUIRED. In the given scenario also PROTOTYPE would be sufficient, as the concrete service implementation uses the PROTOTYPE service scope. But IMHO it is better to specify directly which reference scope to use, instead of having a weak rule.

When launching the OSGi application and calling the commands one after the other, you should get an output similar to this (on a Felix console):

g! kill Dirk
BAM! I am hitman #1. And I killed Dirk
g! assassinate Dirk
BAM! I am hitman #2. And I killed Dirk
g! eliminate Dirk
BAM! I am hitman #3. And I killed Dirk
g! kill Dirk
BAM! I am hitman #1. And I killed Dirk

You can see that every command gets its own service instance.

One instance per request

In some use cases it is required to have a distinct service instance per request. This is for example needed for web requests, where it is required that services are created and destroyed in every request, or for multi-threading where services can be executed in parallel (hopefully without side-effects).

With DS 1.2 a Factory Component needs to be used. With DS 1.3 again the PROTOTYPE scope helps in solving that requirement. In both cases some OSGi DS API needs to be used to create (and destroy) the service instances.

First lets have a look at the DS 1.3 approach using PROTOTYPE scoped services and the newly introduced ComponentServiceObjects interface. The implementation of the ComponentServiceObjects is a factory that allows to create and destroy service instances on demand. The following example shows the usage. Create it in the org.fipro.oneshot.command bundle.

@Component(
    property= {
        "osgi.command.scope=fipro",
        "osgi.command.function=terminate"},
    service=TerminateCommand.class
)
public class TerminateCommand {

    // get a factory for creating prototype scoped service instances
    @Reference(scope=ReferenceScope.PROTOTYPE_REQUIRED)
    private ComponentServiceObjects<OneShot> oneShotFactory;

    public void terminate(String target) {
        // create a new service instance
        OneShot oneShot = oneShotFactory.getService();
        try {
            oneShot.shoot(target);
        } finally {
            // destroy the service instance
            oneShotFactory.ungetService(oneShot);
        }
    }
}

Note:
There is no special modification needed in the component configuration of the provider. It simply needs to be configured with a PROTOTYPE service scope as shown before. The consumer needs to decide what instance should be referenced, the same as every service in the bundle, a new one for every component or a new one for each request.

Executing the terminate command multiple times will show that for each call a new Hitman instance is created. Mixing it with the previous commands will show that the other services keep a fixed instance, while terminate constantly will create and use a new instance per execution.

g! kill Dirk
BAM! I am hitman #1. And I killed Dirk
g! terminate Dirk
BAM! I am hitman #2. And I killed Dirk
g! terminate Dirk
BAM! I am hitman #3. And I killed Dirk
g! terminate Dirk
BAM! I am hitman #4. And I killed Dirk
g! kill Dirk
BAM! I am hitman #1. And I killed Dirk

Factory Component

With DS 1.2 you need to create a Factory Component to create a service instance per consumer or per request. The Factory Component is the third type of components specified by the OSGi Compendium Specification, next to the Immediate Component and the Delayed Component. It therefore also has its own lifecycle, which can be seen in the following diagram.

factory_lifecycle

When the component configuration is satisfied, a ComponentFactory is registered. This can be used to activate a new component instance, which is destroyed once it is disposed or the component configuration is not satisfied anymore.

While this looks quite complicated on first sight, it is a lot easier when using DS annotations. You only need to specify the factory annotation type element on @Component. The following snippet shows this for a new OneShot implementation. For the exercise add it to the org.fipro.oneshot.provider bundle.

@Component(factory="fipro.oneshot.factory")
public class Shooter implements OneShot {

    private static AtomicInteger instanceCounter =
        new AtomicInteger(); 

    private final int instanceNo;

    public Shooter() {
        instanceNo = instanceCounter.incrementAndGet();
    }

    @Override
    public void shoot(String target) {
        System.out.println("PEW PEW! I am shooter #"
            + instanceNo + ". And I hit " + target);
    }

}

As explained above, the SCR will register a ComponentFactory that can be used to create and activate new component configurations on demand. On the consumer side this means it is not possible to get a Shooter service instance via @Reference, as it is not registered as a Delayed Component. You need to reference a ComponentFactory instance by specifying the correct target property. The target property needs to be specified for the key component.factory and the value of the factory annotation type element on the @Component annotation of the Factory Component.

The following snippet shows the consumer of a Factory Component. Create it in the org.fipro.oneshot.command bundle.

@Component(
    property= {
        "osgi.command.scope=fipro",
        "osgi.command.function=shoot"},
    service=ShootCommand.class
)
public class ShootCommand {

    @Reference(target = "(component.factory=fipro.oneshot.factory)")
    private ComponentFactory factory;

    public void shoot(String target) {
        // create a new service instance
        ComponentInstance instance = this.factory.newInstance(null);
        OneShot shooter = (OneShot) instance.getInstance();
        try {
            shooter.shoot(target);
        } finally {
            // destroy the service instance
            instance.dispose();
        }
    }
}

Comparing the Factory Component with the PROTOTYPE scoped service, the following differences can be seen:

  • A PROTOTYPE scoped service is a Delayed Component, while the Factory Component is a different component type with its own lifecycle.
  • A Factory Component can only be consumed by getting the ComponentFactory injected, while a PROTOTYPE scoped service can be created and consumed in different ways.
  • component configuration needs to be provided when creating the component instance via ComponentFactory. A PROTOTYPE scoped service can simply use the configuration mechanisms provided in combination with the Configuration Admin.
  • ComponentServiceObjects is type-safe. The result of ComponentInstance#getInstance() needs to be cast to the desired type.

Compared to creating the service instance by using the constructor, the nice thing on using a Factory Component or a PROTOTPYE scoped service is that the configured service references are resolved by the SCR. You could verify this for example by adding a reference to the StringInverter service from my previous blog post.

Note:
To create an instance per requestor by using a Factory Component, you would simply create the instance in the @Activate method, and dispose it on @Deactivate.

Component Instance cleanup

When Peter Kirschner (Twitter: @peterkir) and I prepared our tutorial for the EclipseCon Europe 2016, we noticed a runtime difference between Equinox DS and Felix SCR. In the Console Exercise we also talked about the lifecycle methods and wanted to show them. So we added the @Activate and the @Deactivate method to the StringInverterImpl and the StringInverterCommand. Running the example on Equinox and executing the console command showed a console output for activating the service and the command. But both never were deactivated. Running the example with Felix SCR the StringInverterCommand was activated, executed and deactivated right after the execution. We wondered about that different behavior, but were busy with other topics, so we didn’t search further for the cause.

Note:
The tutorial sources and slides can be found on GitHub.

I recently learned what causes this different behavior and how it can be adjusted.

For Delayed Components the OSGi Compendium Specification says:
If the service registered by a component configuration becomes unused because there are no more bundles using it, then SCR should deactivate that component configuration.

Should is a quite weak statement, so it is easy to have a different understanding of this part of the specification. Apache Felix SCR is taking that statement very serious and deactivates and destroys the component once the last consumer that references the component instance is done with it. Equinox DS on the other hand keeps the instance. At least this is the default behavior in those SCR implementations. But both can be configured via system properties to behave differently.

To configure Equinox DS to dispose component instances that are no longer used (like the Felix SCR default behavior), use the following JVM parameter (see Equinox DS Runtime Options):

-Dequinox.scr.dontDisposeInstances=false

To configure Felix SCR to keep component instances and not dispose them once they are no longer used (like the Equinox DS default behavior), use the following Framework property, e.g. by setting it as JVM parameter (see Felix SCR Configuration):

-Dds.delayed.keepInstances=true

To get some more insight on this you might also want to look at the ticket in the Felix bug tracker where this was discussed.

To experiment with that you can modify for example Hitman and KillCommand and add methods for @Activate and @Deactivate.

@Activate
void activate() {
    System.out.println(
        getClass().getSimpleName() + " activated");
}

@Deactivate
void deactivate() {
    System.out.println(
        getClass().getSimpleName() + " deactivated");
}

Add the JVM arguments for the runtime you are experimenting with and check the results.


by Dirk Fauth at February 13, 2017 07:31 AM