SlideShare une entreprise Scribd logo
1  sur  164
Télécharger pour lire hors ligne
e(fx)clipse APIs
Tom Schindl <tom.schindl@bestsolution.at>
Twitter: @tomsontom
Blog: http://tomsondev.bestsolution.at
Website: http://www.bestsolution.at
Matthew Elliot <matthew.elliot@360t.com>
Website: http://www.360t.com
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
About Tom
‣ CTO BestSolution.at Systemhaus GmbH
‣ Eclipse Committer
‣ e4
‣ Platform
‣ EMF
‣ Project lead
‣ e(fx)clipse
‣ Twitter: @tomsontom
‣ Blog: tomsondev.bestsolution.at
‣ Corporate: http://bestsolution.at
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
About Matt
‣ Software Team Lead @ 360T (Deutsche Börse Group)
‣ Focus on OTC Trading Applications
‣ Product Owner for IAF @ 360T
‣ Eclipse RCP 4
‣ JavaFX
‣ e(fx)clipse
‣ E-Mail: matthew.elliot@360t.com
‣ Company: http://www.360t.com
‣ LinkedIn: https://de.linkedin.com/pub/matthew-elliot/
24/43a/61
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
RCP / JavaFX / e(fx)clipse for Trading 

applications
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Common / Difficult Requirement Set
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Common / Difficult Requirement Set
• Requirements
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Common / Difficult Requirement Set
• Requirements
– Plugin architecture to support growing number of trading, reporting, and
pricing tools
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Common / Difficult Requirement Set
• Requirements
– Plugin architecture to support growing number of trading, reporting, and
pricing tools
– Flexibility in managing screen space, multiple monitor set ups, and
ability for user to customise their layout and tool set
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Common / Difficult Requirement Set
• Requirements
– Plugin architecture to support growing number of trading, reporting, and
pricing tools
– Flexibility in managing screen space, multiple monitor set ups, and
ability for user to customise their layout and tool set
– More flexibility in design and customisation for our customers
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Common / Difficult Requirement Set
• Requirements
– Plugin architecture to support growing number of trading, reporting, and
pricing tools
– Flexibility in managing screen space, multiple monitor set ups, and
ability for user to customise their layout and tool set
– More flexibility in design and customisation for our customers
– Multiple language support
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Common / Difficult Requirement Set
• Requirements
– Plugin architecture to support growing number of trading, reporting, and
pricing tools
– Flexibility in managing screen space, multiple monitor set ups, and
ability for user to customise their layout and tool set
– More flexibility in design and customisation for our customers
– Multiple language support
– Support for integration with 3rd parties at a visual level
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Common / Difficult Requirement Set
• Requirements
– Plugin architecture to support growing number of trading, reporting, and
pricing tools
– Flexibility in managing screen space, multiple monitor set ups, and
ability for user to customise their layout and tool set
– More flexibility in design and customisation for our customers
– Multiple language support
– Support for integration with 3rd parties at a visual level
– Next 5, 10, 15 years, support, evolution, flexibility
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Common / Difficult Requirement Set
• Requirements
– Plugin architecture to support growing number of trading, reporting, and
pricing tools
– Flexibility in managing screen space, multiple monitor set ups, and
ability for user to customise their layout and tool set
– More flexibility in design and customisation for our customers
– Multiple language support
– Support for integration with 3rd parties at a visual level
– Next 5, 10, 15 years, support, evolution, flexibility
• Two main options
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Common / Difficult Requirement Set
• Requirements
– Plugin architecture to support growing number of trading, reporting, and
pricing tools
– Flexibility in managing screen space, multiple monitor set ups, and
ability for user to customise their layout and tool set
– More flexibility in design and customisation for our customers
– Multiple language support
– Support for integration with 3rd parties at a visual level
– Next 5, 10, 15 years, support, evolution, flexibility
• Two main options
– JavaFX
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Common / Difficult Requirement Set
• Requirements
– Plugin architecture to support growing number of trading, reporting, and
pricing tools
– Flexibility in managing screen space, multiple monitor set ups, and
ability for user to customise their layout and tool set
– More flexibility in design and customisation for our customers
– Multiple language support
– Support for integration with 3rd parties at a visual level
– Next 5, 10, 15 years, support, evolution, flexibility
• Two main options
– JavaFX
– HTML 5
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
UX Concept for Visual Integration
Framework
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
UX Concept for Visual Integration
Framework
‣ Core components
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
UX Concept for Visual Integration
Framework
‣ Core components
‣ Tabbed views with flexible layouts; built up like Tetris with
different plugins acting as ‘building blocks’
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
UX Concept for Visual Integration
Framework
‣ Core components
‣ Tabbed views with flexible layouts; built up like Tetris with
different plugins acting as ‘building blocks’
‣ Advanced controls for managing trading activity across multiple
monitors
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
UX Concept for Visual Integration
Framework
‣ Core components
‣ Tabbed views with flexible layouts; built up like Tetris with
different plugins acting as ‘building blocks’
‣ Advanced controls for managing trading activity across multiple
monitors
‣ Modern / flat design line / 360T of the future
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
UX Concept for Visual Integration
Framework
‣ Core components
‣ Tabbed views with flexible layouts; built up like Tetris with
different plugins acting as ‘building blocks’
‣ Advanced controls for managing trading activity across multiple
monitors
‣ Modern / flat design line / 360T of the future
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‚The Leap‘ - A Technology Stack to
Support an Enterprise
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‚The Leap‘ - A Technology Stack to
Support an Enterprise
‣ 2012-14 – Stalled, JavaFX?, HTML5?, Java8?, AppStore?
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‚The Leap‘ - A Technology Stack to
Support an Enterprise
‣ 2012-14 – Stalled, JavaFX?, HTML5?, Java8?, AppStore?
‣ 2014 – Preliminary Investigations into EclipseRCP with
JavaFX
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‚The Leap‘ - A Technology Stack to
Support an Enterprise
‣ 2012-14 – Stalled, JavaFX?, HTML5?, Java8?, AppStore?
‣ 2014 – Preliminary Investigations into EclipseRCP with
JavaFX
‣ 2015 (Q1) – Prototype Phase with JavaFX / Eclipse RCP (can
it support our requirements?) / Best Solution engaged for
experience
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‚The Leap‘ - A Technology Stack to
Support an Enterprise
‣ 2012-14 – Stalled, JavaFX?, HTML5?, Java8?, AppStore?
‣ 2014 – Preliminary Investigations into EclipseRCP with
JavaFX
‣ 2015 (Q1) – Prototype Phase with JavaFX / Eclipse RCP (can
it support our requirements?) / Best Solution engaged for
experience
‣ 2015 (Q3) – Successful development of first concrete
application
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‚The Leap‘ - A Technology Stack to
Support an Enterprise
‣ 2012-14 – Stalled, JavaFX?, HTML5?, Java8?, AppStore?
‣ 2014 – Preliminary Investigations into EclipseRCP with
JavaFX
‣ 2015 (Q1) – Prototype Phase with JavaFX / Eclipse RCP (can
it support our requirements?) / Best Solution engaged for
experience
‣ 2015 (Q3) – Successful development of first concrete
application
‣ 2016 – Well I can’t give away our strategic roadmap…
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
BestSolution as ‚Sparring Partner‘
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
BestSolution as ‚Sparring Partner‘
‣ Trading applications can’t look like my IDE… what else is
possible?
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
BestSolution as ‚Sparring Partner‘
‣ Trading applications can’t look like my IDE… what else is
possible?
‣ How hard is it to customize Eclipse RCP…?
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
BestSolution as ‚Sparring Partner‘
‣ Trading applications can’t look like my IDE… what else is
possible?
‣ How hard is it to customize Eclipse RCP…?
‣ What about ‘insert grand UX design’…?
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
BestSolution as ‚Sparring Partner‘
‣ Trading applications can’t look like my IDE… what else is
possible?
‣ How hard is it to customize Eclipse RCP…?
‣ What about ‘insert grand UX design’…?
‣ What about performance…?
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
BestSolution as ‚Sparring Partner‘
‣ Trading applications can’t look like my IDE… what else is
possible?
‣ How hard is it to customize Eclipse RCP…?
‣ What about ‘insert grand UX design’…?
‣ What about performance…?
‣ What about OSGi? / what about Dependency Injection?
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Demo
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Eclipse RCP <-> 360T Mappings
360T UX Concept Eclipse RCP
Screen TrimmedWindow
Tab Container / Tab
View
PartStack
Feature Part
Menu Main Menu
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Boring code
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
(e4)App-Architecture
‣ Services
‣ Everything is designed as a service in e4
‣ Everything in your app SHOULD be designed as service
‣ Dependencies
‣ NEVER create a (OSGi/e4) framework API dependency in
your business code you can NOT mock easily or
reimplement in other ENVs - watch out for transitive
dependencies!
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Some Helpers
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Useful Base-APIs
‣ Lookup Services (if you are outside the DI-Container)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Useful Base-APIs
‣ Lookup Services (if you are outside the DI-Container)
Bundle bundle = FrameworkUtil.getBundle(ServiceSample.class);
BundleContext btx = bundle.getBundleContext();
if( btx == null ) {
return;
}
ServiceReference<FilesystemService> ref = btx.getServiceReference(FilesystemService.class);
if( ref == null ) {
return;
}
FilesystemService service = btx.getService(ref);
service.observePath(Paths.get("/tmp"), (k,p) -> {
// Handle Path change
});
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Util.getService(ServiceSample.class, FilesystemService.class).ifPresent( service -> {
service.observePath(Paths.get("/tmp"), (k,p) -> {
// Handle Path change
});
});
‣ Lookup Services (if you are outside the DI-Container)
Useful Base-APIs
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ Work with APIs with exceptions
Useful Base-APIs
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ Work with APIs with exceptions
Useful Base-APIs
class EJDTSourceFileInput {

private ICompilationUnit compilationUnit;
// ...
protected void doDispose() {
if( compilationUnit != null ) {
try {
compilationUnit.restore();
} catch (JavaModelException e) {
// Log the exception
}
try {
compilationUnit.discardWorkingCopy();
} catch (JavaModelException e) {
// Log the exception
}
}
// ...
}

}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ Work with APIs with exceptions
Useful Base-APIs
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ Work with APIs with exceptions
Useful Base-APIs
public interface ExRunnable {
public void wrappedRun() throws Throwable;
}
public final class ExExecutor {
// …
// many other wrappers for Supplier, Function
public static void executeRunnable(ExRunnable r) {
// super secrete code

}
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ Work with APIs with exceptions
class EJDTSourceFileInput {

private ICompilationUnit compilationUnit;
// ...
protected void doDispose() {
ExExecutor.executeRunnable(compilationUnit::restore);
ExExecutor.executeRunnable(compilationUnit::discardWorkingCopy);
// ...
}

}
Useful Base-APIs
public interface ExRunnable {
public void wrappedRun() throws Throwable;
}
public final class ExExecutor {
// …
// many other wrappers for Supplier, Function
public static void executeRunnable(ExRunnable r) {
// super secrete code

}
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Update
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ p2 API is powerful but soooo low-level
Update
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ p2 API is powerful but soooo low-level
class UpdateHandler {


public void update(UpdateService u) {
u.checkUpdate(ProgressReporter.NULLPROGRESS_REPORTER).onComplete(this::checkComplete);
}
private void checkComplete(Optional<UpdatePlan> op) {
op.ifPresent( p -> p.runUpdate( ProgressReporter.NULLPROGRESS_REPORTER ) );
}

}
Update
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Command Execution
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Command Execution
‣ e4 defines ECommandService and EHandlerService in
org.eclipse.e4.core.service
‣ exposes us to org.eclipse.core.commands
‣ isn’t as simple to use as it could be
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Command Execution
‣ e4 defines ECommandService and EHandlerService in
org.eclipse.e4.core.service
‣ exposes us to org.eclipse.core.commands
‣ isn’t as simple to use as it could be
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.e4.core.commands.ECommandService;
import org.eclipse.e4.core.commands.EHandlerService;
@Inject
public CommandSample(ECommandService c, EHandlerService h) {
ParameterizedCommand cmd = c.createCommand("my.command.id", Collections.emptyMap() );
String rv = h.executeHandler(cmd);
if( rv != null ) {
rv = "Default";
}
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Command Execution
‣ e4 defines ECommandService and EHandlerService in
org.eclipse.e4.core.service
‣ exposes us to org.eclipse.core.commands
‣ isn’t as simple to use as it could be
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.e4.core.commands.ECommandService;
import org.eclipse.e4.core.commands.EHandlerService;
@Inject
public CommandSample(ECommandService c, EHandlerService h) {
ParameterizedCommand cmd = c.createCommand("my.command.id", Collections.emptyMap() );
String rv = h.executeHandler(cmd);
if( rv != null ) {
rv = "Default";
}
}
Disapproved by Tom
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Command Execution
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ fx.core defines a CommandService
‣ who is simple to use
‣ does not expose you to any complex APIs
Command Execution
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ fx.core defines a CommandService
‣ who is simple to use
‣ does not expose you to any complex APIs
Command Execution
import org.eclipse.fx.core.command.CommandService;
@Inject
public CommandSample(CommandService c) {
Optional<String> rv = c.execute("my.command.id", Collections.emptyMap());
String v = rv.orElse("Default");
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Logging
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Logging the efxclipse way
‣ e4 Log API is not in acceptable state
‣ wanted our framework to not depend on a concrete logging
API (not even SLF4J but in most minimal env we run on
Java-Util-Logging)
‣ we wanted a modern log API who eg accepts lambdas, printf-
formats, …
‣ framework users need to have an easy way to reconfigure
and log EVERYTHING with their preferred framework
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Logging
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Logging
private final Logger logger;
@Inject
public MyComponent(@Log Logger logger) {
this.logger = logger;
}
void method() {
logger.debugf("Duke's Birthday: %1$tm %1$te,%1$tY", Calendar.getInstance());
logger.debug(() -> "This data is very complex to calculate");
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Logging
private final Logger logger;
@Inject
public MyComponent(@Log Logger logger) {
this.logger = logger;
}
void method() {
logger.debugf("Duke's Birthday: %1$tm %1$te,%1$tY", Calendar.getInstance());
logger.debug(() -> "This data is very complex to calculate");
}
@Component
public class MyComponent {
private LoggerFactory factory;
private Logger logger;
@Reference
void setLoggerFactory(LoggerFactory factory) {
this.factory = factory;
this.logger = factory.createLogger(MyComponent.class.getName());
}
void unsetLoggerFactory(LoggerFactory factory) {
// clean up
}
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Events
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEventBroker
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEventBroker
‣ VERSIONED package level imports are not possible
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEventBroker
‣ VERSIONED package level imports are not possible
‣ Service definition has only 4 methods
‣ 2 for publishing: expose String and Object
‣ 2 for subscribing: expose String and EventHandler
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEventBroker
‣ VERSIONED package level imports are not possible
‣ Service definition has only 4 methods
‣ 2 for publishing: expose String and Object
‣ 2 for subscribing: expose String and EventHandler
‣ org.osgi.service.event.EventHandler exposes o.o.s.e.Event
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEventBroker
‣ VERSIONED package level imports are not possible
‣ Service definition has only 4 methods
‣ 2 for publishing: expose String and Object
‣ 2 for subscribing: expose String and EventHandler
‣ org.osgi.service.event.EventHandler exposes o.o.s.e.Event
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEventBroker
‣ VERSIONED package level imports are not possible
‣ Service definition has only 4 methods
‣ 2 for publishing: expose String and Object
‣ 2 for subscribing: expose String and EventHandler
‣ org.osgi.service.event.EventHandler exposes o.o.s.e.Event
Disapproved by Tom
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
EventBus
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
EventBus
‣ VERSIONED package imports possible
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
EventBus
‣ VERSIONED package imports possible
‣ Simple interface who does not expose ANY OSGi-APIs
‣ 2 publish methods
‣ 1 subscribe methods
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
EventBus
‣ VERSIONED package imports possible
‣ Simple interface who does not expose ANY OSGi-APIs
‣ 2 publish methods
‣ 1 subscribe methods
‣ Enhanced type safety
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
EventBus
‣ VERSIONED package imports possible
‣ Simple interface who does not expose ANY OSGi-APIs
‣ 2 publish methods
‣ 1 subscribe methods
‣ Enhanced type safety
‣ Non OSGi-Version based upon Guava EventBus is available
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
public class MyComponent {
private static final String TOPIC = "my/topic";
@Inject
public MyComponent(IEventBroker eventBroker) {
eventBroker.subscribe(TOPIC, this::handleEvent);
eventBroker.send(TOPIC, "Hello World");
eventBroker.unsubscribe(this::handleEvent);
}
private void handleEvent(Event event) {
handle((Long) event.getProperty(IEventBroker.DATA));
}
private void handle(Long data) {
System.err.println("The data is" + data);
}
}
EventBus: From e4 to efx
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
public class MyComponent {
private static final Topic<Long> TOPIC = new Topic<>("my/topic");
@Inject
public MyComponent(EventBus eventBroker) {
eventBroker.subscribe(TOPIC, this::handleEvent);
eventBroker.send(TOPIC, "Hello World");
eventBroker.unsubscribe(this::handleEvent);
}
private void handleEvent(Event event) {
handle(event.getData());
}
private void handle(Long data) {
System.err.println("The data is" + data);
}
}
EventBus: From e4 to efx
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
public class MyComponent {
private static final Topic<Long> TOPIC = new Topic<>("my/topic");
@Inject
public MyComponent(EventBus eventBroker) {
Subscription s = eventBroker.subscribe(TOPIC, this::handleEvent);
eventBroker.publish(TOPIC, "Hello World",true);
s.dispose();
}
private void handleEvent(Event<Long> event) {
handle(event.getData());
}
private void handle(Long data) {
System.err.println("The data is" + data);
}
}
EventBus: From e4 to efx
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
public class MyComponent {
private static final Topic<Long> TOPIC = new Topic<>("my/topic");
@Inject
public MyComponent(EventBus eventBroker) {
Subscription s = eventBroker.subscribe(TOPIC, this::handleEvent);
eventBroker.publish(TOPIC, "Hello World",true);
s.dispose();
}
private void handleEvent(Event<Long> event) {
handle(event.getData());
}
private void handle(Long data) {
System.err.println("The data is" + data);
}
}
Compiler Error
EventBus: From e4 to efx
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
public class MyComponent {
private static final Topic<Long> TOPIC = new Topic<>("my/topic");
@Inject
public MyComponent(EventBus eventBroker) {
Subscription s = eventBroker.subscribe(TOPIC, this::handleEvent);
eventBroker.publish(TOPIC, 1l,true);
s.dispose();
}
private void handleEvent(Event<Long> event) {
handle(event.getData());
}
private void handle(Long data) {
System.err.println("The data is" + data);
}
}
EventBus: From e4 to efx
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
import static org.eclipse.fx.core.event.EventBus.*;
public class MyComponent {
private static final Topic<Long> TOPIC = new Topic<>("my/topic");
@Inject
public MyComponent(EventBus eventBroker) {
Subscription s = eventBroker.subscribe(TOPIC, data(this::handle));
eventBroker.publish(TOPIC, 1l,true);
s.dispose();
}
private void handleEvent(Event<Long> event) {
handle(event.getData());
}
private void handle(Long data) {
System.err.println("The data is" + data);
}
}
EventBus: From e4 to efx
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
IEclipseContext
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEclipseContext
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEclipseContext
‣ Retrieval is easy just use @Inject
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEclipseContext
‣ Retrieval is easy just use @Inject
‣ Publishing is hard
‣ The publisher needs to know where the value has to go.
Is the perspective-, window- or the application-context
the target?
‣ Your code gets a dependency on Eclipse 4 APIs
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEclipseContext
‣ Retrieval is easy just use @Inject
‣ Publishing is hard
‣ The publisher needs to know where the value has to go.
Is the perspective-, window- or the application-context
the target?
‣ Your code gets a dependency on Eclipse 4 APIs
Disapproved by Tom
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEclipseContext
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEclipseContext
‣ Stop thinking about the IEclipseContext as a Map of key-
value-pairs
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEclipseContext
‣ Stop thinking about the IEclipseContext as a Map of key-
value-pairs
‣ Start treating each key-value-slot in IEclipseContext as
an Observable-Value
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEclipseContext
‣ Stop thinking about the IEclipseContext as a Map of key-
value-pairs
‣ Start treating each key-value-slot in IEclipseContext as
an Observable-Value
public interface ContextBoundValue<T> extends Adaptable {
public T getValue();
public void publish(T value);
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEclipseContext
‣ Stop thinking about the IEclipseContext as a Map of key-
value-pairs
‣ Start treating each key-value-slot in IEclipseContext as
an Observable-Value
public interface ContextBoundValue<T> extends Adaptable {
public T getValue();
public void publish(T value);
}
public static class SimpleInject {
@Inject
@ContextValue("simpleValue")
public ContextBoundValue<String> value;
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
The IEclipseContext
‣ Stop thinking about the IEclipseContext as a Map of key-
value-pairs
‣ Start treating each key-value-slot in IEclipseContext as
an Observable-Value
public interface ContextBoundValue<T> extends Adaptable {
public T getValue();
public void publish(T value);
}
public static class SimpleInject {
@Inject
@ContextValue("simpleValue")
public ContextBoundValue<String> value;
}
public static class SimpleInject {
@Inject
@ContextValue("simpleValue")
public IObservableValue<String> value;
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Preference & UI-
State
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Preferences and UI-State
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ Preference-Store:
Used for none UI
states
Preferences and UI-State
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ Preference-Store:
Used for none UI
states
‣ MApplicationElement
#persistedState:
Map<String,String>:
To be used for UI
states
Preferences and UI-State
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ Preference-Store:
Used for none UI
states
‣ MApplicationElement
#persistedState:
Map<String,String>:
To be used for UI
states
Preferences and UI-State
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ Preference-Store:
Used for none UI
states
‣ MApplicationElement
#persistedState:
Map<String,String>:
To be used for UI
states
Preferences and UI-State
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ Preference-Store:
Used for none UI
states
‣ MApplicationElement
#persistedState:
Map<String,String>:
To be used for UI
states
Preferences and UI-State
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
State persistence (e4)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ @Preference
State persistence (e4)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ @Preference
‣ Supports only simple values (int, String, …)
State persistence (e4)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ @Preference
‣ Supports only simple values (int, String, …)
‣ Our application code gets a dependency on
org.eclipse.core.runtime.preferences.IEclipsePreference
State persistence (e4)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ @Preference
‣ Supports only simple values (int, String, …)
‣ Our application code gets a dependency on
org.eclipse.core.runtime.preferences.IEclipsePreference
State persistence (e4)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ @Preference
‣ Supports only simple values (int, String, …)
‣ Our application code gets a dependency on
org.eclipse.core.runtime.preferences.IEclipsePreference
State persistence (e4)
Disapproved by Tom
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
State persistence (e4)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ MApplicationElement#persistedState : Map<String,String>
State persistence (e4)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ MApplicationElement#persistedState : Map<String,String>
‣ Supports only storage of String
State persistence (e4)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ MApplicationElement#persistedState : Map<String,String>
‣ Supports only storage of String
‣ Your code gets a dependency on e4 application model and
transitiv on EMF
State persistence (e4)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ MApplicationElement#persistedState : Map<String,String>
‣ Supports only storage of String
‣ Your code gets a dependency on e4 application model and
transitiv on EMF
State persistence (e4)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ MApplicationElement#persistedState : Map<String,String>
‣ Supports only storage of String
‣ Your code gets a dependency on e4 application model and
transitiv on EMF
State persistence (e4)
Disapproved by Tom
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
State persistence (efx)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
State persistence (efx)
‣ @Preference from e(fx)clipse
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
State persistence (efx)
‣ @Preference from e(fx)clipse
‣ Supports (pluggable) storage of complex values (by
default JAXB is used/available)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
State persistence (efx)
‣ @Preference from e(fx)clipse
‣ Supports (pluggable) storage of complex values (by
default JAXB is used/available)
‣ Supports (pluggable) storage of most „value“ types in
java (eg BigDecimal, Date, Instant, …)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
State persistence (efx)
‣ @Preference from e(fx)clipse
‣ Supports (pluggable) storage of complex values (by
default JAXB is used/available)
‣ Supports (pluggable) storage of most „value“ types in
java (eg BigDecimal, Date, Instant, …)
‣ Injects a simple placeholder (…preference.Value) for
the preference slot in question
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
State persistence (efx)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ org.eclipse.fx.Memento-Interface
State persistence (efx)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ org.eclipse.fx.Memento-Interface
‣ Small interface with no external dependencies
State persistence (efx)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ org.eclipse.fx.Memento-Interface
‣ Small interface with no external dependencies
‣ Allows (pluggable) storage of complex values
State persistence (efx)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Preference
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Preference: From e4 to efx
public class MyStateSample {
private final IEclipsePreferences pref;
@Inject
public MyStateSample(@Preference("rootDirs") IEclipsePreferences pref) {
this.pref = pref;
}
private void rememberRootDirs(List<String> rootDirs)
throws BackingStoreException {
String string = rootDirs.stream().collect(Collectors.joining("##-##"));
this.pref.put("rootDirs", string);
this.pref.flush();
}
@Inject
void setRootDirs(@Preference("rootDirs") String rootDirs) {
String[] dirs = rootDirs.split("##-##");
}
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Preference: From e4 to efx
public class MyStateSample {
private final IEclipsePreferences pref;
@Inject
public MyStateSample(@Preference("rootDirs") IEclipsePreferences pref) {
this.pref = pref;
}
private void rememberRootDirs(List<String> rootDirs)
throws BackingStoreException {
String string = rootDirs.stream().collect(Collectors.joining("##-##"));
this.pref.put("rootDirs", string);
this.pref.flush();
}
@Inject
void setRootDirs(@Preference("rootDirs") String rootDirs) {
String[] dirs = rootDirs.split("##-##");
}
}
NPE Ahead!!!
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Preference: From e4 to efx
public class MyStateSample {
private final Value<String> pref;
@Inject
public MyStateSample(@Preference(key="rootDirs") Value<String> pref) {
this.pref = pref;
}
private void rememberRootDirs(List<String> rootDirs)
throws BackingStoreException {
String string = rootDirs.stream().collect(Collectors.joining("##-##"));
this.pref.put("rootDirs", string);
this.pref.flush();
}
@Inject
void setRootDirs(@Preference("rootDirs") String rootDirs) {
String[] dirs = rootDirs.split("##-##");
}
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Preference: From e4 to efx
public class MyStateSample {
private final Value<String> pref;
@Inject
public MyStateSample(@Preference(key="rootDirs") Value<String> pref) {
this.pref = pref;
}
private void rememberRootDirs(List<String> rootDirs) {
String string = rootDirs.stream().collect(Collectors.joining("##-##"));
this.pref.publish(string);
}
@Inject
void setRootDirs(@Preference("rootDirs") String rootDirs) {
String[] dirs = rootDirs.split("##-##");
}
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Preference: From e4 to efx
public class MyStateSample {
private final Value<String> pref;
@Inject
public MyStateSample(@Preference(key="rootDirs") Value<String> pref) {
this.pref = pref;
}
private void rememberRootDirs(List<String> rootDirs) {
String string = rootDirs.stream().collect(Collectors.joining("##-##"));
this.pref.publish(string);
}
@Inject
void setRootDirs(@Preference(key="rootDirs",defaultValue="") String rootDirs) {
String[] dirs = rootDirs.split("##-##");
}
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Preference: From e4 to efx
public class MyStateSample {
private final Value<List<String>> pref;
@Inject
public MyStateSample(@Preference(key="rootDirs") Value<String> pref) {
this.pref = pref;
}
private void rememberRootDirs(List<String> rootDirs) {
this.pref.publish(rootDirs);
}
@Inject
void setRootDirs(@Preference(key="rootDirs",factory=EmptyListFactory.class)
List<String> rootDirs) {
}
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
UI State
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
UI-State: From e4 to efx
public class MyStateSample {
private final MPart part;
@Inject
public MyStateSample(MPart part) {
this.part = part;
String string = this.part.getPersistedState().get("selectionList");
String[] selection = string.split("##-##");
}
private void rememberSelection(List<String> selectionList) {
String string = selectionList.stream().collect(Collectors.joining("##-##"));
this.part.getPersistedState().put("selectionList", string);
}
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
UI-State: From e4 to efx
public class MyStateSample {
private final MPart part;
@Inject
public MyStateSample(MPart part) {
this.part = part;
String string = this.part.getPersistedState().get("selectionList");
String[] selection = string.split("##-##");
}
private void rememberSelection(List<String> selectionList) {
String string = selectionList.stream().collect(Collectors.joining("##-##"));
this.part.getPersistedState().put("selectionList", string);
}
}
NPE Ahead!!!
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
UI-State: From e4 to efx
public class MyStateSample {
private final Memento memento;
@Inject
public MyStateSample(Memento memento) {
this.memento = memento;
String string = this.memento.get("selectionList","");
String[] selection = string.split("##-##");
}
private void rememberSelection(List<String> selectionList) {
String string = selectionList.stream().collect(Collectors.joining("##-##"));
this.part.getPersistedState().put("selectionList", string);
}
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
UI-State: From e4 to efx
public class MyStateSample {
private final Memento part;
@Inject
public MyStateSample(Memento part) {
this.part = part;
String string = this.part.get("selectionList","");
String[] selection = string.split("##-##");
}
private void rememberSelection(List<String> selectionList) {
String string = selectionList.stream().collect(Collectors.joining("##-##"));
this.part.put("selectionList", string);
}
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
UI-State: From e4 to efx
public class MyStateSample {
private final Memento part;
@Inject
public MyStateSample(Memento part) {
this.part = part;
List<String> selection = this.part.get("selectionList",List.class,
new ArrayList<>());
}
private void rememberSelection(List<String> selectionList) {
this.part.put("selectionList", selectionList,
ObjectSerializer.JAXB_SERIALIZER);
}
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Dialogs in FX
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Lightweight Dialogs
‣ New Service to open lightweight dialogs
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Lightweight Dialogs
‣ New Service to open lightweight dialogs
import org.eclipse.fx.ui.controls.stage.Frame;
public interface LightWeightDialogService {
public enum ModalityScope {
WINDOW,
PERSPECTIVE,
PART
}
public <T extends Node & Frame> T openDialog(Class<T> dialogClass, ModalityScope scope);
public <T extends Node & Frame> void openDialog(T dialog, ModalityScope scope);
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Lightweight Dialogs
‣ New Service to open lightweight dialogs
import org.eclipse.fx.ui.controls.stage.Frame;
public interface LightWeightDialogService {
public enum ModalityScope {
WINDOW,
PERSPECTIVE,
PART
}
public <T extends Node & Frame> T openDialog(Class<T> dialogClass, ModalityScope scope);
public <T extends Node & Frame> void openDialog(T dialog, ModalityScope scope);
}
‣ Usage
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
Lightweight Dialogs
‣ New Service to open lightweight dialogs
import org.eclipse.fx.ui.controls.stage.Frame;
public interface LightWeightDialogService {
public enum ModalityScope {
WINDOW,
PERSPECTIVE,
PART
}
public <T extends Node & Frame> T openDialog(Class<T> dialogClass, ModalityScope scope);
public <T extends Node & Frame> void openDialog(T dialog, ModalityScope scope);
}
public class NewProjectDialogHandler {
@Execute
public void createProject(LightWeightDialogService dialogService) {
dialogService.openDialog(NewProjectDialog.class, ModalityScope.WINDOW);
}
}
‣ Usage
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
DI & OSGi
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
DI and OSGi-Services
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
DI and OSGi-Services
‣ Eclipse DI supports OSGi-Service injection BUT
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
DI and OSGi-Services
‣ Eclipse DI supports OSGi-Service injection BUT
‣ it misses the dynamics of OSGi
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
DI and OSGi-Services
‣ Eclipse DI supports OSGi-Service injection BUT
‣ it misses the dynamics of OSGi
‣ You can only inject the highest ranked service
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@Service
‣ @Service annotation
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@Service
‣ @Service annotation
public class OSGiService {
@Inject
@Service
FilesystemService fs;
@Inject
@Service
List<FilesystemService> filesystemServiceList;
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@Service
‣ @Service annotation
public class OSGiService {
@Inject
@Service
FilesystemService fs;
@Inject
@Service
List<FilesystemService> filesystemServiceList;
}
public Class<?> getCollectionType(java.lang.reflect.Type t) {
if( t instanceof java.lang.reflect.ParameterizedType ) {
java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) t;
return (Class<?>) pt.getRawType();
}
return (Class<?>) t;
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@LocalInstance
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@LocalInstance
if( container != null ) {
part = modelService.createModelElement(MPart.class);
part.setCloseable(true);
part.setLabel(URI.create(uri).lastSegment());
String editorBundleURI = editorUrlProvider
.stream()
.filter( e -> e.test(uri)).findFirst()
.map( e -> e.getBundleClassURI(uri))
.orElse("bundleclass://org.eclipse.fx.code.editor.fx/org.eclipse.fx.code.editor.fx.TextEditor");
part.setContributionURI(editorBundleURI);
String iconUri = fileIconProvider
.stream()
.filter( f -> f.test(uri))
.findFirst()
.map( f -> f.getFileIconUri(uri))
.orElse("platform:/plugin/org.eclipse.fx.code.editor.fx.e4/icons/file_16.png");
part.setIconURI(iconUri);
part.getPersistedState().put(Constants.DOCUMENT_URL, uri);
part.getTags().add(EPartService.REMOVE_ON_HIDE_TAG);
container.getChildren().add(part);
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@LocalInstance
if( container != null ) {
part = modelService.createModelElement(MPart.class);
part.setCloseable(true);
part.setLabel(URI.create(uri).lastSegment());
String editorBundleURI = editorUrlProvider
.stream()
.filter( e -> e.test(uri)).findFirst()
.map( e -> e.getBundleClassURI(uri))
.orElse("bundleclass://org.eclipse.fx.code.editor.fx/org.eclipse.fx.code.editor.fx.TextEditor");
part.setContributionURI(editorBundleURI);
String iconUri = fileIconProvider
.stream()
.filter( f -> f.test(uri))
.findFirst()
.map( f -> f.getFileIconUri(uri))
.orElse("platform:/plugin/org.eclipse.fx.code.editor.fx.e4/icons/file_16.png");
part.setIconURI(iconUri);
part.getPersistedState().put(Constants.DOCUMENT_URL, uri);
part.getTags().add(EPartService.REMOVE_ON_HIDE_TAG);
container.getChildren().add(part);
}
What’s wrong here?
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@LocalInstance
if( container != null ) {
part = modelService.createModelElement(MPart.class);
part.setCloseable(true);
part.setLabel(URI.create(uri).lastSegment());
String editorBundleURI = editorUrlProvider
.stream()
.filter( e -> e.test(uri)).findFirst()
.map( e -> e.getBundleClassURI(uri))
.orElse("bundleclass://org.eclipse.fx.code.editor.fx/org.eclipse.fx.code.editor.fx.TextEditor");
part.setContributionURI(editorBundleURI);
part.setContributorURI("platform:/plugin/org.eclipse.fx.code.editor.fx.e4");
String iconUri = fileIconProvider
.stream()
.filter( f -> f.test(uri))
.findFirst()
.map( f -> f.getFileIconUri(uri))
.orElse("platform:/plugin/org.eclipse.fx.code.editor.fx.e4/icons/file_16.png");
part.setIconURI(iconUri);
part.getPersistedState().put(Constants.DOCUMENT_URL, uri);
part.getTags().add(EPartService.REMOVE_ON_HIDE_TAG);
container.getChildren().add(part);
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ A first fix: enhance EModelService with
@LocalInstance
public <T extends MApplicationElement> T createModelElement(
Class<?> caller,
Class<T> elementType);
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ A first fix: enhance EModelService with
@LocalInstance
public <T extends MApplicationElement> T createModelElement(
Class<?> caller,
Class<T> elementType);
‣ Another fix: Provide a factory service
public interface ModelElementFactoryService {
ModelElementFactory createFactory(Class<?> caller);
}
public interface ModelElementFactory {

<T extends MApplicationElement> T createElement(Class<T> elementType);
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ A first fix: enhance EModelService with
@LocalInstance
public <T extends MApplicationElement> T createModelElement(
Class<?> caller,
Class<T> elementType);
‣ Another fix: Provide a factory service
public interface ModelElementFactoryService {
ModelElementFactory createFactory(Class<?> caller);
}
public interface ModelElementFactory {

<T extends MApplicationElement> T createElement(Class<T> elementType);
}
private ModelElementFactory f;
@Inject
public LocalInstanceSample(ModelElementFactoryService s) {
this.f = s.createFactory(getClass());
}
public void init() {

// ...
part = f.createModelElement(MPart.class);
// ...
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@LocalInstance
‣ Is there a more generic solution to create DI-Instance
values with knowledge about the target (eg classloader,
bundle, …)?
‣ Since 2.1 there a basic TypeProvider API in fx.core
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@LocalInstance
‣ Is there a more generic solution to create DI-Instance
values with knowledge about the target (eg classloader,
bundle, …)?
‣ Since 2.1 there a basic TypeProvider API in fx.core
/**
* A service who provides a type based upon selector value
*
* @param <S>
* the selector value type
* @param <T>
* the type
* @since 2.1
*/
public interface TypeProviderService<S, T> extends Predicate<S> {
@Override
boolean test(S t);
public Class<? extends T> getType(S s);
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ Upon the basic interface there are a specialized ones eg
@LocalInstance
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
‣ Upon the basic interface there are a specialized ones eg
@LocalInstance
/**
* Service who provides a real type for an interface/abstract type
*
* @param <T>
* the type
*/
public interface TypeTypeProviderService<T>
extends TypeProviderService<java.lang.reflect.Type, T> {
/**
* If used with dependency injection and @LocalInstance
*/
public static final String DI_KEY = "localInstanceOwnerType"; //$NON-NLS-1$
}
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@LocalInstance
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@Component
class TypeProviderImpl implements TypeTypeProviderService<ModelElementFactory> {
@Override
public Class<? extends ModelElementFactory> getType(Type s) {
return ModelElementFactoryImpl.class;
}
@Override
public boolean test(Type t) {
return t == ModelElementFactory.class;
}
public static class ModelElementFactoryImpl implements ModelElementFactory {
@NonNull
private final EModelService modelService;
@Inject
public ModelElementFactoryImpl(@NonNull EModelService modelService,
@Named(TypeTypeProviderService.DI_KEY) @NonNull Class<?> ownerType) {
this.modelService = modelService;
}
}
}
@LocalInstance
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@Inject
private EModelService modelService;
public void init() {

// ...
part = modelService.createModelElement(MPart.class);
// ...
}
@LocalInstance
‣ The original code
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@Inject
private EModelService modelService;
public void init() {

// ...
part = modelService.createModelElement(MPart.class);
// ...
}
@LocalInstance
‣ The original code
@Inject
@LocalInstance
private ModelElementFactory modelFactory;
public void init() {

// ...
part = modelFactory.createModelElement(MPart.class);
// ...
}
‣ Gets to
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@Inject
private EModelService modelService;
public void init() {

// ...
part = modelService.createModelElement(MPart.class);
// ...
}
@LocalInstance
‣ The original code
@Inject
@LocalInstance
private ModelElementFactory modelFactory;
public void init() {

// ...
part = modelFactory.createModelElement(MPart.class);
// ...
}
‣ Gets to
LocalInstanceObjectSupplier
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@Inject
private EModelService modelService;
public void init() {

// ...
part = modelService.createModelElement(MPart.class);
// ...
}
@LocalInstance
‣ The original code
@Inject
@LocalInstance
private ModelElementFactory modelFactory;
public void init() {

// ...
part = modelFactory.createModelElement(MPart.class);
// ...
}
‣ Gets to
LocalInstanceObjectSupplier
TypeTypeProviderService
test(ModelElementFactory.class)
(c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
@Inject
private EModelService modelService;
public void init() {

// ...
part = modelService.createModelElement(MPart.class);
// ...
}
@LocalInstance
‣ The original code
@Inject
@LocalInstance
private ModelElementFactory modelFactory;
public void init() {

// ...
part = modelFactory.createModelElement(MPart.class);
// ...
}
‣ Gets to
LocalInstanceObjectSupplier
TypeTypeProviderService
test(ModelElementFactory.class)

Contenu connexe

Tendances

D22 portlet development with open source frameworks
D22 portlet development with open source frameworksD22 portlet development with open source frameworks
D22 portlet development with open source frameworks
Sunil Patil
 
Apache Aries: A blueprint for developing with OSGi and JEE
Apache Aries: A blueprint for developing with OSGi and JEEApache Aries: A blueprint for developing with OSGi and JEE
Apache Aries: A blueprint for developing with OSGi and JEE
mahrwald
 

Tendances (12)

[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
 
Introducing Spring Cloud Gateway and API Hub for VMware Tanzu
Introducing Spring Cloud Gateway and API Hub for VMware TanzuIntroducing Spring Cloud Gateway and API Hub for VMware Tanzu
Introducing Spring Cloud Gateway and API Hub for VMware Tanzu
 
Ajax Swing Flash Jazoon07
Ajax Swing Flash Jazoon07Ajax Swing Flash Jazoon07
Ajax Swing Flash Jazoon07
 
VMware Studio & vAPP-s
VMware Studio & vAPP-sVMware Studio & vAPP-s
VMware Studio & vAPP-s
 
D22 portlet development with open source frameworks
D22 portlet development with open source frameworksD22 portlet development with open source frameworks
D22 portlet development with open source frameworks
 
Apache Aries: A blueprint for developing with OSGi and JEE
Apache Aries: A blueprint for developing with OSGi and JEEApache Aries: A blueprint for developing with OSGi and JEE
Apache Aries: A blueprint for developing with OSGi and JEE
 
Simplifying RCP Update and Install
Simplifying RCP Update and InstallSimplifying RCP Update and Install
Simplifying RCP Update and Install
 
JAX London 2015: Java vs Nodejs
JAX London 2015: Java vs NodejsJAX London 2015: Java vs Nodejs
JAX London 2015: Java vs Nodejs
 
190 959
190 959190 959
190 959
 
Building A Simple Web Service With CXF
Building A Simple Web Service With CXFBuilding A Simple Web Service With CXF
Building A Simple Web Service With CXF
 
Rewriting a Plugin Architecture 3 Times to Harness the API Economy
Rewriting a Plugin Architecture 3 Times to Harness the API EconomyRewriting a Plugin Architecture 3 Times to Harness the API Economy
Rewriting a Plugin Architecture 3 Times to Harness the API Economy
 
New and cool in OSGi R7 - David Bosschaert & Carsten Ziegeler
New and cool in OSGi R7 - David Bosschaert & Carsten ZiegelerNew and cool in OSGi R7 - David Bosschaert & Carsten Ziegeler
New and cool in OSGi R7 - David Bosschaert & Carsten Ziegeler
 

En vedette (7)

The JavaFX Ecosystem
The JavaFX EcosystemThe JavaFX Ecosystem
The JavaFX Ecosystem
 
JavaFX Enterprise (JavaOne 2014)
JavaFX Enterprise (JavaOne 2014)JavaFX Enterprise (JavaOne 2014)
JavaFX Enterprise (JavaOne 2014)
 
Java fx on raspberry pi gerrit grunwald
Java fx on raspberry pi   gerrit grunwaldJava fx on raspberry pi   gerrit grunwald
Java fx on raspberry pi gerrit grunwald
 
Building Java Desktop Apps with JavaFX 8 and Java EE 7
Building Java Desktop Apps with JavaFX 8 and Java EE 7Building Java Desktop Apps with JavaFX 8 and Java EE 7
Building Java Desktop Apps with JavaFX 8 and Java EE 7
 
Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFX
 
JavaFX – 10 things I love about you
JavaFX – 10 things I love about youJavaFX – 10 things I love about you
JavaFX – 10 things I love about you
 
JavaFX Pitfalls
JavaFX PitfallsJavaFX Pitfalls
JavaFX Pitfalls
 

Similaire à Java fx ap is

Similaire à Java fx ap is (20)

Developer Secure Containers for the Cyberspace Battlefield
Developer Secure Containers for the Cyberspace BattlefieldDeveloper Secure Containers for the Cyberspace Battlefield
Developer Secure Containers for the Cyberspace Battlefield
 
Theater Management Software - Features & technology
Theater Management Software - Features & technologyTheater Management Software - Features & technology
Theater Management Software - Features & technology
 
Anypoint Tools and MuleSoft Automation (DRAFT).pptx
Anypoint Tools and MuleSoft Automation (DRAFT).pptxAnypoint Tools and MuleSoft Automation (DRAFT).pptx
Anypoint Tools and MuleSoft Automation (DRAFT).pptx
 
MuleSoft Meetup #9 - Anypoint Tools and MuleSoft Automation (FINAL).pptx
MuleSoft Meetup #9 - Anypoint Tools and MuleSoft Automation (FINAL).pptxMuleSoft Meetup #9 - Anypoint Tools and MuleSoft Automation (FINAL).pptx
MuleSoft Meetup #9 - Anypoint Tools and MuleSoft Automation (FINAL).pptx
 
2016 Streaming Media West: Transitioning from Flash to HTML5
2016 Streaming Media West: Transitioning from Flash to HTML52016 Streaming Media West: Transitioning from Flash to HTML5
2016 Streaming Media West: Transitioning from Flash to HTML5
 
Ppt0000000
Ppt0000000Ppt0000000
Ppt0000000
 
Overview
OverviewOverview
Overview
 
Techcello at a glance
Techcello at a glanceTechcello at a glance
Techcello at a glance
 
Questions Log: Installing Cognos BI 10.2.2
Questions Log: Installing Cognos BI 10.2.2Questions Log: Installing Cognos BI 10.2.2
Questions Log: Installing Cognos BI 10.2.2
 
Cloud Foundry Services on PKS with No Extra Code, "We Bosh So You Don’t Have ...
Cloud Foundry Services on PKS with No Extra Code, "We Bosh So You Don’t Have ...Cloud Foundry Services on PKS with No Extra Code, "We Bosh So You Don’t Have ...
Cloud Foundry Services on PKS with No Extra Code, "We Bosh So You Don’t Have ...
 
Connecting All Abstractions with Istio
Connecting All Abstractions with IstioConnecting All Abstractions with Istio
Connecting All Abstractions with Istio
 
How to Build Your OTT Platform in 2023_ A Step-By-Step Guide.pdf
How to Build Your OTT Platform in 2023_ A Step-By-Step Guide.pdfHow to Build Your OTT Platform in 2023_ A Step-By-Step Guide.pdf
How to Build Your OTT Platform in 2023_ A Step-By-Step Guide.pdf
 
Rendering Innovation and Exemplary End-user Experiences with Product and Plat...
Rendering Innovation and Exemplary End-user Experiences with Product and Plat...Rendering Innovation and Exemplary End-user Experiences with Product and Plat...
Rendering Innovation and Exemplary End-user Experiences with Product and Plat...
 
Extend Agile and DevOps Practices Across Hybrid IT
Extend Agile and DevOps Practices Across Hybrid ITExtend Agile and DevOps Practices Across Hybrid IT
Extend Agile and DevOps Practices Across Hybrid IT
 
What We're Learning Adopting Spring Boot and PCF for Dell.com's eCommerce
What We're Learning Adopting Spring Boot and PCF for Dell.com's eCommerceWhat We're Learning Adopting Spring Boot and PCF for Dell.com's eCommerce
What We're Learning Adopting Spring Boot and PCF for Dell.com's eCommerce
 
Automation and Culture Changes for 40M Subscriber Platform Operation
Automation and Culture Changes for 40M Subscriber Platform OperationAutomation and Culture Changes for 40M Subscriber Platform Operation
Automation and Culture Changes for 40M Subscriber Platform Operation
 
Damodar_TIBCO
Damodar_TIBCODamodar_TIBCO
Damodar_TIBCO
 
Building Volkswagen Group's Digital Ecosystem (AMT304) - AWS re:Invent 2018
Building Volkswagen Group's Digital Ecosystem (AMT304) - AWS re:Invent 2018Building Volkswagen Group's Digital Ecosystem (AMT304) - AWS re:Invent 2018
Building Volkswagen Group's Digital Ecosystem (AMT304) - AWS re:Invent 2018
 
branch_architecture
branch_architecturebranch_architecture
branch_architecture
 
2016 Federal User Group Conference - TeamForge Capabilities and Directions
2016 Federal User Group Conference - TeamForge Capabilities and Directions2016 Federal User Group Conference - TeamForge Capabilities and Directions
2016 Federal User Group Conference - TeamForge Capabilities and Directions
 

Dernier

+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
VishalKumarJha10
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 

Dernier (20)

Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
Pharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodologyPharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodology
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 

Java fx ap is

  • 1. e(fx)clipse APIs Tom Schindl <tom.schindl@bestsolution.at> Twitter: @tomsontom Blog: http://tomsondev.bestsolution.at Website: http://www.bestsolution.at Matthew Elliot <matthew.elliot@360t.com> Website: http://www.360t.com
  • 2. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 About Tom ‣ CTO BestSolution.at Systemhaus GmbH ‣ Eclipse Committer ‣ e4 ‣ Platform ‣ EMF ‣ Project lead ‣ e(fx)clipse ‣ Twitter: @tomsontom ‣ Blog: tomsondev.bestsolution.at ‣ Corporate: http://bestsolution.at
  • 3. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 About Matt ‣ Software Team Lead @ 360T (Deutsche Börse Group) ‣ Focus on OTC Trading Applications ‣ Product Owner for IAF @ 360T ‣ Eclipse RCP 4 ‣ JavaFX ‣ e(fx)clipse ‣ E-Mail: matthew.elliot@360t.com ‣ Company: http://www.360t.com ‣ LinkedIn: https://de.linkedin.com/pub/matthew-elliot/ 24/43a/61
  • 4. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 RCP / JavaFX / e(fx)clipse for Trading 
 applications
  • 5. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Common / Difficult Requirement Set
  • 6. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Common / Difficult Requirement Set • Requirements
  • 7. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Common / Difficult Requirement Set • Requirements – Plugin architecture to support growing number of trading, reporting, and pricing tools
  • 8. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Common / Difficult Requirement Set • Requirements – Plugin architecture to support growing number of trading, reporting, and pricing tools – Flexibility in managing screen space, multiple monitor set ups, and ability for user to customise their layout and tool set
  • 9. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Common / Difficult Requirement Set • Requirements – Plugin architecture to support growing number of trading, reporting, and pricing tools – Flexibility in managing screen space, multiple monitor set ups, and ability for user to customise their layout and tool set – More flexibility in design and customisation for our customers
  • 10. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Common / Difficult Requirement Set • Requirements – Plugin architecture to support growing number of trading, reporting, and pricing tools – Flexibility in managing screen space, multiple monitor set ups, and ability for user to customise their layout and tool set – More flexibility in design and customisation for our customers – Multiple language support
  • 11. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Common / Difficult Requirement Set • Requirements – Plugin architecture to support growing number of trading, reporting, and pricing tools – Flexibility in managing screen space, multiple monitor set ups, and ability for user to customise their layout and tool set – More flexibility in design and customisation for our customers – Multiple language support – Support for integration with 3rd parties at a visual level
  • 12. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Common / Difficult Requirement Set • Requirements – Plugin architecture to support growing number of trading, reporting, and pricing tools – Flexibility in managing screen space, multiple monitor set ups, and ability for user to customise their layout and tool set – More flexibility in design and customisation for our customers – Multiple language support – Support for integration with 3rd parties at a visual level – Next 5, 10, 15 years, support, evolution, flexibility
  • 13. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Common / Difficult Requirement Set • Requirements – Plugin architecture to support growing number of trading, reporting, and pricing tools – Flexibility in managing screen space, multiple monitor set ups, and ability for user to customise their layout and tool set – More flexibility in design and customisation for our customers – Multiple language support – Support for integration with 3rd parties at a visual level – Next 5, 10, 15 years, support, evolution, flexibility • Two main options
  • 14. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Common / Difficult Requirement Set • Requirements – Plugin architecture to support growing number of trading, reporting, and pricing tools – Flexibility in managing screen space, multiple monitor set ups, and ability for user to customise their layout and tool set – More flexibility in design and customisation for our customers – Multiple language support – Support for integration with 3rd parties at a visual level – Next 5, 10, 15 years, support, evolution, flexibility • Two main options – JavaFX
  • 15. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Common / Difficult Requirement Set • Requirements – Plugin architecture to support growing number of trading, reporting, and pricing tools – Flexibility in managing screen space, multiple monitor set ups, and ability for user to customise their layout and tool set – More flexibility in design and customisation for our customers – Multiple language support – Support for integration with 3rd parties at a visual level – Next 5, 10, 15 years, support, evolution, flexibility • Two main options – JavaFX – HTML 5
  • 16. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 UX Concept for Visual Integration Framework
  • 17. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 UX Concept for Visual Integration Framework ‣ Core components
  • 18. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 UX Concept for Visual Integration Framework ‣ Core components ‣ Tabbed views with flexible layouts; built up like Tetris with different plugins acting as ‘building blocks’
  • 19. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 UX Concept for Visual Integration Framework ‣ Core components ‣ Tabbed views with flexible layouts; built up like Tetris with different plugins acting as ‘building blocks’ ‣ Advanced controls for managing trading activity across multiple monitors
  • 20. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 UX Concept for Visual Integration Framework ‣ Core components ‣ Tabbed views with flexible layouts; built up like Tetris with different plugins acting as ‘building blocks’ ‣ Advanced controls for managing trading activity across multiple monitors ‣ Modern / flat design line / 360T of the future
  • 21. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 UX Concept for Visual Integration Framework ‣ Core components ‣ Tabbed views with flexible layouts; built up like Tetris with different plugins acting as ‘building blocks’ ‣ Advanced controls for managing trading activity across multiple monitors ‣ Modern / flat design line / 360T of the future
  • 22. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‚The Leap‘ - A Technology Stack to Support an Enterprise
  • 23. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‚The Leap‘ - A Technology Stack to Support an Enterprise ‣ 2012-14 – Stalled, JavaFX?, HTML5?, Java8?, AppStore?
  • 24. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‚The Leap‘ - A Technology Stack to Support an Enterprise ‣ 2012-14 – Stalled, JavaFX?, HTML5?, Java8?, AppStore? ‣ 2014 – Preliminary Investigations into EclipseRCP with JavaFX
  • 25. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‚The Leap‘ - A Technology Stack to Support an Enterprise ‣ 2012-14 – Stalled, JavaFX?, HTML5?, Java8?, AppStore? ‣ 2014 – Preliminary Investigations into EclipseRCP with JavaFX ‣ 2015 (Q1) – Prototype Phase with JavaFX / Eclipse RCP (can it support our requirements?) / Best Solution engaged for experience
  • 26. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‚The Leap‘ - A Technology Stack to Support an Enterprise ‣ 2012-14 – Stalled, JavaFX?, HTML5?, Java8?, AppStore? ‣ 2014 – Preliminary Investigations into EclipseRCP with JavaFX ‣ 2015 (Q1) – Prototype Phase with JavaFX / Eclipse RCP (can it support our requirements?) / Best Solution engaged for experience ‣ 2015 (Q3) – Successful development of first concrete application
  • 27. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‚The Leap‘ - A Technology Stack to Support an Enterprise ‣ 2012-14 – Stalled, JavaFX?, HTML5?, Java8?, AppStore? ‣ 2014 – Preliminary Investigations into EclipseRCP with JavaFX ‣ 2015 (Q1) – Prototype Phase with JavaFX / Eclipse RCP (can it support our requirements?) / Best Solution engaged for experience ‣ 2015 (Q3) – Successful development of first concrete application ‣ 2016 – Well I can’t give away our strategic roadmap…
  • 28. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 BestSolution as ‚Sparring Partner‘
  • 29. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 BestSolution as ‚Sparring Partner‘ ‣ Trading applications can’t look like my IDE… what else is possible?
  • 30. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 BestSolution as ‚Sparring Partner‘ ‣ Trading applications can’t look like my IDE… what else is possible? ‣ How hard is it to customize Eclipse RCP…?
  • 31. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 BestSolution as ‚Sparring Partner‘ ‣ Trading applications can’t look like my IDE… what else is possible? ‣ How hard is it to customize Eclipse RCP…? ‣ What about ‘insert grand UX design’…?
  • 32. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 BestSolution as ‚Sparring Partner‘ ‣ Trading applications can’t look like my IDE… what else is possible? ‣ How hard is it to customize Eclipse RCP…? ‣ What about ‘insert grand UX design’…? ‣ What about performance…?
  • 33. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 BestSolution as ‚Sparring Partner‘ ‣ Trading applications can’t look like my IDE… what else is possible? ‣ How hard is it to customize Eclipse RCP…? ‣ What about ‘insert grand UX design’…? ‣ What about performance…? ‣ What about OSGi? / what about Dependency Injection?
  • 34. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Demo
  • 35. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Eclipse RCP <-> 360T Mappings 360T UX Concept Eclipse RCP Screen TrimmedWindow Tab Container / Tab View PartStack Feature Part Menu Main Menu
  • 36. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Boring code
  • 37. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 (e4)App-Architecture ‣ Services ‣ Everything is designed as a service in e4 ‣ Everything in your app SHOULD be designed as service ‣ Dependencies ‣ NEVER create a (OSGi/e4) framework API dependency in your business code you can NOT mock easily or reimplement in other ENVs - watch out for transitive dependencies!
  • 38. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Some Helpers
  • 39. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Useful Base-APIs ‣ Lookup Services (if you are outside the DI-Container)
  • 40. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Useful Base-APIs ‣ Lookup Services (if you are outside the DI-Container) Bundle bundle = FrameworkUtil.getBundle(ServiceSample.class); BundleContext btx = bundle.getBundleContext(); if( btx == null ) { return; } ServiceReference<FilesystemService> ref = btx.getServiceReference(FilesystemService.class); if( ref == null ) { return; } FilesystemService service = btx.getService(ref); service.observePath(Paths.get("/tmp"), (k,p) -> { // Handle Path change });
  • 41. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Util.getService(ServiceSample.class, FilesystemService.class).ifPresent( service -> { service.observePath(Paths.get("/tmp"), (k,p) -> { // Handle Path change }); }); ‣ Lookup Services (if you are outside the DI-Container) Useful Base-APIs
  • 42. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ Work with APIs with exceptions Useful Base-APIs
  • 43. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ Work with APIs with exceptions Useful Base-APIs class EJDTSourceFileInput {
 private ICompilationUnit compilationUnit; // ... protected void doDispose() { if( compilationUnit != null ) { try { compilationUnit.restore(); } catch (JavaModelException e) { // Log the exception } try { compilationUnit.discardWorkingCopy(); } catch (JavaModelException e) { // Log the exception } } // ... }
 }
  • 44. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ Work with APIs with exceptions Useful Base-APIs
  • 45. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ Work with APIs with exceptions Useful Base-APIs public interface ExRunnable { public void wrappedRun() throws Throwable; } public final class ExExecutor { // … // many other wrappers for Supplier, Function public static void executeRunnable(ExRunnable r) { // super secrete code
 } }
  • 46. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ Work with APIs with exceptions class EJDTSourceFileInput {
 private ICompilationUnit compilationUnit; // ... protected void doDispose() { ExExecutor.executeRunnable(compilationUnit::restore); ExExecutor.executeRunnable(compilationUnit::discardWorkingCopy); // ... }
 } Useful Base-APIs public interface ExRunnable { public void wrappedRun() throws Throwable; } public final class ExExecutor { // … // many other wrappers for Supplier, Function public static void executeRunnable(ExRunnable r) { // super secrete code
 } }
  • 47. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Update
  • 48. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ p2 API is powerful but soooo low-level Update
  • 49. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ p2 API is powerful but soooo low-level class UpdateHandler { 
 public void update(UpdateService u) { u.checkUpdate(ProgressReporter.NULLPROGRESS_REPORTER).onComplete(this::checkComplete); } private void checkComplete(Optional<UpdatePlan> op) { op.ifPresent( p -> p.runUpdate( ProgressReporter.NULLPROGRESS_REPORTER ) ); }
 } Update
  • 50. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Command Execution
  • 51. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Command Execution ‣ e4 defines ECommandService and EHandlerService in org.eclipse.e4.core.service ‣ exposes us to org.eclipse.core.commands ‣ isn’t as simple to use as it could be
  • 52. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Command Execution ‣ e4 defines ECommandService and EHandlerService in org.eclipse.e4.core.service ‣ exposes us to org.eclipse.core.commands ‣ isn’t as simple to use as it could be import org.eclipse.core.commands.ParameterizedCommand; import org.eclipse.e4.core.commands.ECommandService; import org.eclipse.e4.core.commands.EHandlerService; @Inject public CommandSample(ECommandService c, EHandlerService h) { ParameterizedCommand cmd = c.createCommand("my.command.id", Collections.emptyMap() ); String rv = h.executeHandler(cmd); if( rv != null ) { rv = "Default"; } }
  • 53. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Command Execution ‣ e4 defines ECommandService and EHandlerService in org.eclipse.e4.core.service ‣ exposes us to org.eclipse.core.commands ‣ isn’t as simple to use as it could be import org.eclipse.core.commands.ParameterizedCommand; import org.eclipse.e4.core.commands.ECommandService; import org.eclipse.e4.core.commands.EHandlerService; @Inject public CommandSample(ECommandService c, EHandlerService h) { ParameterizedCommand cmd = c.createCommand("my.command.id", Collections.emptyMap() ); String rv = h.executeHandler(cmd); if( rv != null ) { rv = "Default"; } } Disapproved by Tom
  • 54. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Command Execution
  • 55. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ fx.core defines a CommandService ‣ who is simple to use ‣ does not expose you to any complex APIs Command Execution
  • 56. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ fx.core defines a CommandService ‣ who is simple to use ‣ does not expose you to any complex APIs Command Execution import org.eclipse.fx.core.command.CommandService; @Inject public CommandSample(CommandService c) { Optional<String> rv = c.execute("my.command.id", Collections.emptyMap()); String v = rv.orElse("Default"); }
  • 57. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Logging
  • 58. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Logging the efxclipse way ‣ e4 Log API is not in acceptable state ‣ wanted our framework to not depend on a concrete logging API (not even SLF4J but in most minimal env we run on Java-Util-Logging) ‣ we wanted a modern log API who eg accepts lambdas, printf- formats, … ‣ framework users need to have an easy way to reconfigure and log EVERYTHING with their preferred framework
  • 59. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Logging
  • 60. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Logging private final Logger logger; @Inject public MyComponent(@Log Logger logger) { this.logger = logger; } void method() { logger.debugf("Duke's Birthday: %1$tm %1$te,%1$tY", Calendar.getInstance()); logger.debug(() -> "This data is very complex to calculate"); }
  • 61. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Logging private final Logger logger; @Inject public MyComponent(@Log Logger logger) { this.logger = logger; } void method() { logger.debugf("Duke's Birthday: %1$tm %1$te,%1$tY", Calendar.getInstance()); logger.debug(() -> "This data is very complex to calculate"); } @Component public class MyComponent { private LoggerFactory factory; private Logger logger; @Reference void setLoggerFactory(LoggerFactory factory) { this.factory = factory; this.logger = factory.createLogger(MyComponent.class.getName()); } void unsetLoggerFactory(LoggerFactory factory) { // clean up } }
  • 62. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Events
  • 63. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEventBroker
  • 64. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEventBroker ‣ VERSIONED package level imports are not possible
  • 65. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEventBroker ‣ VERSIONED package level imports are not possible ‣ Service definition has only 4 methods ‣ 2 for publishing: expose String and Object ‣ 2 for subscribing: expose String and EventHandler
  • 66. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEventBroker ‣ VERSIONED package level imports are not possible ‣ Service definition has only 4 methods ‣ 2 for publishing: expose String and Object ‣ 2 for subscribing: expose String and EventHandler ‣ org.osgi.service.event.EventHandler exposes o.o.s.e.Event
  • 67. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEventBroker ‣ VERSIONED package level imports are not possible ‣ Service definition has only 4 methods ‣ 2 for publishing: expose String and Object ‣ 2 for subscribing: expose String and EventHandler ‣ org.osgi.service.event.EventHandler exposes o.o.s.e.Event
  • 68. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEventBroker ‣ VERSIONED package level imports are not possible ‣ Service definition has only 4 methods ‣ 2 for publishing: expose String and Object ‣ 2 for subscribing: expose String and EventHandler ‣ org.osgi.service.event.EventHandler exposes o.o.s.e.Event Disapproved by Tom
  • 69. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 EventBus
  • 70. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 EventBus ‣ VERSIONED package imports possible
  • 71. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 EventBus ‣ VERSIONED package imports possible ‣ Simple interface who does not expose ANY OSGi-APIs ‣ 2 publish methods ‣ 1 subscribe methods
  • 72. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 EventBus ‣ VERSIONED package imports possible ‣ Simple interface who does not expose ANY OSGi-APIs ‣ 2 publish methods ‣ 1 subscribe methods ‣ Enhanced type safety
  • 73. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 EventBus ‣ VERSIONED package imports possible ‣ Simple interface who does not expose ANY OSGi-APIs ‣ 2 publish methods ‣ 1 subscribe methods ‣ Enhanced type safety ‣ Non OSGi-Version based upon Guava EventBus is available
  • 74. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 public class MyComponent { private static final String TOPIC = "my/topic"; @Inject public MyComponent(IEventBroker eventBroker) { eventBroker.subscribe(TOPIC, this::handleEvent); eventBroker.send(TOPIC, "Hello World"); eventBroker.unsubscribe(this::handleEvent); } private void handleEvent(Event event) { handle((Long) event.getProperty(IEventBroker.DATA)); } private void handle(Long data) { System.err.println("The data is" + data); } } EventBus: From e4 to efx
  • 75. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 public class MyComponent { private static final Topic<Long> TOPIC = new Topic<>("my/topic"); @Inject public MyComponent(EventBus eventBroker) { eventBroker.subscribe(TOPIC, this::handleEvent); eventBroker.send(TOPIC, "Hello World"); eventBroker.unsubscribe(this::handleEvent); } private void handleEvent(Event event) { handle(event.getData()); } private void handle(Long data) { System.err.println("The data is" + data); } } EventBus: From e4 to efx
  • 76. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 public class MyComponent { private static final Topic<Long> TOPIC = new Topic<>("my/topic"); @Inject public MyComponent(EventBus eventBroker) { Subscription s = eventBroker.subscribe(TOPIC, this::handleEvent); eventBroker.publish(TOPIC, "Hello World",true); s.dispose(); } private void handleEvent(Event<Long> event) { handle(event.getData()); } private void handle(Long data) { System.err.println("The data is" + data); } } EventBus: From e4 to efx
  • 77. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 public class MyComponent { private static final Topic<Long> TOPIC = new Topic<>("my/topic"); @Inject public MyComponent(EventBus eventBroker) { Subscription s = eventBroker.subscribe(TOPIC, this::handleEvent); eventBroker.publish(TOPIC, "Hello World",true); s.dispose(); } private void handleEvent(Event<Long> event) { handle(event.getData()); } private void handle(Long data) { System.err.println("The data is" + data); } } Compiler Error EventBus: From e4 to efx
  • 78. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 public class MyComponent { private static final Topic<Long> TOPIC = new Topic<>("my/topic"); @Inject public MyComponent(EventBus eventBroker) { Subscription s = eventBroker.subscribe(TOPIC, this::handleEvent); eventBroker.publish(TOPIC, 1l,true); s.dispose(); } private void handleEvent(Event<Long> event) { handle(event.getData()); } private void handle(Long data) { System.err.println("The data is" + data); } } EventBus: From e4 to efx
  • 79. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 import static org.eclipse.fx.core.event.EventBus.*; public class MyComponent { private static final Topic<Long> TOPIC = new Topic<>("my/topic"); @Inject public MyComponent(EventBus eventBroker) { Subscription s = eventBroker.subscribe(TOPIC, data(this::handle)); eventBroker.publish(TOPIC, 1l,true); s.dispose(); } private void handleEvent(Event<Long> event) { handle(event.getData()); } private void handle(Long data) { System.err.println("The data is" + data); } } EventBus: From e4 to efx
  • 80. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 IEclipseContext
  • 81. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEclipseContext
  • 82. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEclipseContext ‣ Retrieval is easy just use @Inject
  • 83. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEclipseContext ‣ Retrieval is easy just use @Inject ‣ Publishing is hard ‣ The publisher needs to know where the value has to go. Is the perspective-, window- or the application-context the target? ‣ Your code gets a dependency on Eclipse 4 APIs
  • 84. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEclipseContext ‣ Retrieval is easy just use @Inject ‣ Publishing is hard ‣ The publisher needs to know where the value has to go. Is the perspective-, window- or the application-context the target? ‣ Your code gets a dependency on Eclipse 4 APIs Disapproved by Tom
  • 85. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEclipseContext
  • 86. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEclipseContext ‣ Stop thinking about the IEclipseContext as a Map of key- value-pairs
  • 87. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEclipseContext ‣ Stop thinking about the IEclipseContext as a Map of key- value-pairs ‣ Start treating each key-value-slot in IEclipseContext as an Observable-Value
  • 88. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEclipseContext ‣ Stop thinking about the IEclipseContext as a Map of key- value-pairs ‣ Start treating each key-value-slot in IEclipseContext as an Observable-Value public interface ContextBoundValue<T> extends Adaptable { public T getValue(); public void publish(T value); }
  • 89. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEclipseContext ‣ Stop thinking about the IEclipseContext as a Map of key- value-pairs ‣ Start treating each key-value-slot in IEclipseContext as an Observable-Value public interface ContextBoundValue<T> extends Adaptable { public T getValue(); public void publish(T value); } public static class SimpleInject { @Inject @ContextValue("simpleValue") public ContextBoundValue<String> value; }
  • 90. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 The IEclipseContext ‣ Stop thinking about the IEclipseContext as a Map of key- value-pairs ‣ Start treating each key-value-slot in IEclipseContext as an Observable-Value public interface ContextBoundValue<T> extends Adaptable { public T getValue(); public void publish(T value); } public static class SimpleInject { @Inject @ContextValue("simpleValue") public ContextBoundValue<String> value; } public static class SimpleInject { @Inject @ContextValue("simpleValue") public IObservableValue<String> value; }
  • 91. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Preference & UI- State
  • 92. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Preferences and UI-State
  • 93. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ Preference-Store: Used for none UI states Preferences and UI-State
  • 94. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ Preference-Store: Used for none UI states ‣ MApplicationElement #persistedState: Map<String,String>: To be used for UI states Preferences and UI-State
  • 95. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ Preference-Store: Used for none UI states ‣ MApplicationElement #persistedState: Map<String,String>: To be used for UI states Preferences and UI-State
  • 96. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ Preference-Store: Used for none UI states ‣ MApplicationElement #persistedState: Map<String,String>: To be used for UI states Preferences and UI-State
  • 97. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ Preference-Store: Used for none UI states ‣ MApplicationElement #persistedState: Map<String,String>: To be used for UI states Preferences and UI-State
  • 98. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 State persistence (e4)
  • 99. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ @Preference State persistence (e4)
  • 100. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ @Preference ‣ Supports only simple values (int, String, …) State persistence (e4)
  • 101. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ @Preference ‣ Supports only simple values (int, String, …) ‣ Our application code gets a dependency on org.eclipse.core.runtime.preferences.IEclipsePreference State persistence (e4)
  • 102. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ @Preference ‣ Supports only simple values (int, String, …) ‣ Our application code gets a dependency on org.eclipse.core.runtime.preferences.IEclipsePreference State persistence (e4)
  • 103. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ @Preference ‣ Supports only simple values (int, String, …) ‣ Our application code gets a dependency on org.eclipse.core.runtime.preferences.IEclipsePreference State persistence (e4) Disapproved by Tom
  • 104. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 State persistence (e4)
  • 105. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ MApplicationElement#persistedState : Map<String,String> State persistence (e4)
  • 106. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ MApplicationElement#persistedState : Map<String,String> ‣ Supports only storage of String State persistence (e4)
  • 107. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ MApplicationElement#persistedState : Map<String,String> ‣ Supports only storage of String ‣ Your code gets a dependency on e4 application model and transitiv on EMF State persistence (e4)
  • 108. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ MApplicationElement#persistedState : Map<String,String> ‣ Supports only storage of String ‣ Your code gets a dependency on e4 application model and transitiv on EMF State persistence (e4)
  • 109. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ MApplicationElement#persistedState : Map<String,String> ‣ Supports only storage of String ‣ Your code gets a dependency on e4 application model and transitiv on EMF State persistence (e4) Disapproved by Tom
  • 110. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 State persistence (efx)
  • 111. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 State persistence (efx) ‣ @Preference from e(fx)clipse
  • 112. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 State persistence (efx) ‣ @Preference from e(fx)clipse ‣ Supports (pluggable) storage of complex values (by default JAXB is used/available)
  • 113. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 State persistence (efx) ‣ @Preference from e(fx)clipse ‣ Supports (pluggable) storage of complex values (by default JAXB is used/available) ‣ Supports (pluggable) storage of most „value“ types in java (eg BigDecimal, Date, Instant, …)
  • 114. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 State persistence (efx) ‣ @Preference from e(fx)clipse ‣ Supports (pluggable) storage of complex values (by default JAXB is used/available) ‣ Supports (pluggable) storage of most „value“ types in java (eg BigDecimal, Date, Instant, …) ‣ Injects a simple placeholder (…preference.Value) for the preference slot in question
  • 115. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 State persistence (efx)
  • 116. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ org.eclipse.fx.Memento-Interface State persistence (efx)
  • 117. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ org.eclipse.fx.Memento-Interface ‣ Small interface with no external dependencies State persistence (efx)
  • 118. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ org.eclipse.fx.Memento-Interface ‣ Small interface with no external dependencies ‣ Allows (pluggable) storage of complex values State persistence (efx)
  • 119. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Preference
  • 120. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Preference: From e4 to efx public class MyStateSample { private final IEclipsePreferences pref; @Inject public MyStateSample(@Preference("rootDirs") IEclipsePreferences pref) { this.pref = pref; } private void rememberRootDirs(List<String> rootDirs) throws BackingStoreException { String string = rootDirs.stream().collect(Collectors.joining("##-##")); this.pref.put("rootDirs", string); this.pref.flush(); } @Inject void setRootDirs(@Preference("rootDirs") String rootDirs) { String[] dirs = rootDirs.split("##-##"); } }
  • 121. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Preference: From e4 to efx public class MyStateSample { private final IEclipsePreferences pref; @Inject public MyStateSample(@Preference("rootDirs") IEclipsePreferences pref) { this.pref = pref; } private void rememberRootDirs(List<String> rootDirs) throws BackingStoreException { String string = rootDirs.stream().collect(Collectors.joining("##-##")); this.pref.put("rootDirs", string); this.pref.flush(); } @Inject void setRootDirs(@Preference("rootDirs") String rootDirs) { String[] dirs = rootDirs.split("##-##"); } } NPE Ahead!!!
  • 122. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Preference: From e4 to efx public class MyStateSample { private final Value<String> pref; @Inject public MyStateSample(@Preference(key="rootDirs") Value<String> pref) { this.pref = pref; } private void rememberRootDirs(List<String> rootDirs) throws BackingStoreException { String string = rootDirs.stream().collect(Collectors.joining("##-##")); this.pref.put("rootDirs", string); this.pref.flush(); } @Inject void setRootDirs(@Preference("rootDirs") String rootDirs) { String[] dirs = rootDirs.split("##-##"); } }
  • 123. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Preference: From e4 to efx public class MyStateSample { private final Value<String> pref; @Inject public MyStateSample(@Preference(key="rootDirs") Value<String> pref) { this.pref = pref; } private void rememberRootDirs(List<String> rootDirs) { String string = rootDirs.stream().collect(Collectors.joining("##-##")); this.pref.publish(string); } @Inject void setRootDirs(@Preference("rootDirs") String rootDirs) { String[] dirs = rootDirs.split("##-##"); } }
  • 124. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Preference: From e4 to efx public class MyStateSample { private final Value<String> pref; @Inject public MyStateSample(@Preference(key="rootDirs") Value<String> pref) { this.pref = pref; } private void rememberRootDirs(List<String> rootDirs) { String string = rootDirs.stream().collect(Collectors.joining("##-##")); this.pref.publish(string); } @Inject void setRootDirs(@Preference(key="rootDirs",defaultValue="") String rootDirs) { String[] dirs = rootDirs.split("##-##"); } }
  • 125. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Preference: From e4 to efx public class MyStateSample { private final Value<List<String>> pref; @Inject public MyStateSample(@Preference(key="rootDirs") Value<String> pref) { this.pref = pref; } private void rememberRootDirs(List<String> rootDirs) { this.pref.publish(rootDirs); } @Inject void setRootDirs(@Preference(key="rootDirs",factory=EmptyListFactory.class) List<String> rootDirs) { } }
  • 126. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 UI State
  • 127. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 UI-State: From e4 to efx public class MyStateSample { private final MPart part; @Inject public MyStateSample(MPart part) { this.part = part; String string = this.part.getPersistedState().get("selectionList"); String[] selection = string.split("##-##"); } private void rememberSelection(List<String> selectionList) { String string = selectionList.stream().collect(Collectors.joining("##-##")); this.part.getPersistedState().put("selectionList", string); } }
  • 128. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 UI-State: From e4 to efx public class MyStateSample { private final MPart part; @Inject public MyStateSample(MPart part) { this.part = part; String string = this.part.getPersistedState().get("selectionList"); String[] selection = string.split("##-##"); } private void rememberSelection(List<String> selectionList) { String string = selectionList.stream().collect(Collectors.joining("##-##")); this.part.getPersistedState().put("selectionList", string); } } NPE Ahead!!!
  • 129. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 UI-State: From e4 to efx public class MyStateSample { private final Memento memento; @Inject public MyStateSample(Memento memento) { this.memento = memento; String string = this.memento.get("selectionList",""); String[] selection = string.split("##-##"); } private void rememberSelection(List<String> selectionList) { String string = selectionList.stream().collect(Collectors.joining("##-##")); this.part.getPersistedState().put("selectionList", string); } }
  • 130. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 UI-State: From e4 to efx public class MyStateSample { private final Memento part; @Inject public MyStateSample(Memento part) { this.part = part; String string = this.part.get("selectionList",""); String[] selection = string.split("##-##"); } private void rememberSelection(List<String> selectionList) { String string = selectionList.stream().collect(Collectors.joining("##-##")); this.part.put("selectionList", string); } }
  • 131. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 UI-State: From e4 to efx public class MyStateSample { private final Memento part; @Inject public MyStateSample(Memento part) { this.part = part; List<String> selection = this.part.get("selectionList",List.class, new ArrayList<>()); } private void rememberSelection(List<String> selectionList) { this.part.put("selectionList", selectionList, ObjectSerializer.JAXB_SERIALIZER); } }
  • 132. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Dialogs in FX
  • 133. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Lightweight Dialogs ‣ New Service to open lightweight dialogs
  • 134. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Lightweight Dialogs ‣ New Service to open lightweight dialogs import org.eclipse.fx.ui.controls.stage.Frame; public interface LightWeightDialogService { public enum ModalityScope { WINDOW, PERSPECTIVE, PART } public <T extends Node & Frame> T openDialog(Class<T> dialogClass, ModalityScope scope); public <T extends Node & Frame> void openDialog(T dialog, ModalityScope scope); }
  • 135. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Lightweight Dialogs ‣ New Service to open lightweight dialogs import org.eclipse.fx.ui.controls.stage.Frame; public interface LightWeightDialogService { public enum ModalityScope { WINDOW, PERSPECTIVE, PART } public <T extends Node & Frame> T openDialog(Class<T> dialogClass, ModalityScope scope); public <T extends Node & Frame> void openDialog(T dialog, ModalityScope scope); } ‣ Usage
  • 136. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Lightweight Dialogs ‣ New Service to open lightweight dialogs import org.eclipse.fx.ui.controls.stage.Frame; public interface LightWeightDialogService { public enum ModalityScope { WINDOW, PERSPECTIVE, PART } public <T extends Node & Frame> T openDialog(Class<T> dialogClass, ModalityScope scope); public <T extends Node & Frame> void openDialog(T dialog, ModalityScope scope); } public class NewProjectDialogHandler { @Execute public void createProject(LightWeightDialogService dialogService) { dialogService.openDialog(NewProjectDialog.class, ModalityScope.WINDOW); } } ‣ Usage
  • 137. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
  • 138. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0
  • 139. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 DI & OSGi
  • 140. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 DI and OSGi-Services
  • 141. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 DI and OSGi-Services ‣ Eclipse DI supports OSGi-Service injection BUT
  • 142. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 DI and OSGi-Services ‣ Eclipse DI supports OSGi-Service injection BUT ‣ it misses the dynamics of OSGi
  • 143. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 DI and OSGi-Services ‣ Eclipse DI supports OSGi-Service injection BUT ‣ it misses the dynamics of OSGi ‣ You can only inject the highest ranked service
  • 144. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @Service ‣ @Service annotation
  • 145. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @Service ‣ @Service annotation public class OSGiService { @Inject @Service FilesystemService fs; @Inject @Service List<FilesystemService> filesystemServiceList; }
  • 146. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @Service ‣ @Service annotation public class OSGiService { @Inject @Service FilesystemService fs; @Inject @Service List<FilesystemService> filesystemServiceList; } public Class<?> getCollectionType(java.lang.reflect.Type t) { if( t instanceof java.lang.reflect.ParameterizedType ) { java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) t; return (Class<?>) pt.getRawType(); } return (Class<?>) t; }
  • 147. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @LocalInstance
  • 148. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @LocalInstance if( container != null ) { part = modelService.createModelElement(MPart.class); part.setCloseable(true); part.setLabel(URI.create(uri).lastSegment()); String editorBundleURI = editorUrlProvider .stream() .filter( e -> e.test(uri)).findFirst() .map( e -> e.getBundleClassURI(uri)) .orElse("bundleclass://org.eclipse.fx.code.editor.fx/org.eclipse.fx.code.editor.fx.TextEditor"); part.setContributionURI(editorBundleURI); String iconUri = fileIconProvider .stream() .filter( f -> f.test(uri)) .findFirst() .map( f -> f.getFileIconUri(uri)) .orElse("platform:/plugin/org.eclipse.fx.code.editor.fx.e4/icons/file_16.png"); part.setIconURI(iconUri); part.getPersistedState().put(Constants.DOCUMENT_URL, uri); part.getTags().add(EPartService.REMOVE_ON_HIDE_TAG); container.getChildren().add(part); }
  • 149. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @LocalInstance if( container != null ) { part = modelService.createModelElement(MPart.class); part.setCloseable(true); part.setLabel(URI.create(uri).lastSegment()); String editorBundleURI = editorUrlProvider .stream() .filter( e -> e.test(uri)).findFirst() .map( e -> e.getBundleClassURI(uri)) .orElse("bundleclass://org.eclipse.fx.code.editor.fx/org.eclipse.fx.code.editor.fx.TextEditor"); part.setContributionURI(editorBundleURI); String iconUri = fileIconProvider .stream() .filter( f -> f.test(uri)) .findFirst() .map( f -> f.getFileIconUri(uri)) .orElse("platform:/plugin/org.eclipse.fx.code.editor.fx.e4/icons/file_16.png"); part.setIconURI(iconUri); part.getPersistedState().put(Constants.DOCUMENT_URL, uri); part.getTags().add(EPartService.REMOVE_ON_HIDE_TAG); container.getChildren().add(part); } What’s wrong here?
  • 150. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @LocalInstance if( container != null ) { part = modelService.createModelElement(MPart.class); part.setCloseable(true); part.setLabel(URI.create(uri).lastSegment()); String editorBundleURI = editorUrlProvider .stream() .filter( e -> e.test(uri)).findFirst() .map( e -> e.getBundleClassURI(uri)) .orElse("bundleclass://org.eclipse.fx.code.editor.fx/org.eclipse.fx.code.editor.fx.TextEditor"); part.setContributionURI(editorBundleURI); part.setContributorURI("platform:/plugin/org.eclipse.fx.code.editor.fx.e4"); String iconUri = fileIconProvider .stream() .filter( f -> f.test(uri)) .findFirst() .map( f -> f.getFileIconUri(uri)) .orElse("platform:/plugin/org.eclipse.fx.code.editor.fx.e4/icons/file_16.png"); part.setIconURI(iconUri); part.getPersistedState().put(Constants.DOCUMENT_URL, uri); part.getTags().add(EPartService.REMOVE_ON_HIDE_TAG); container.getChildren().add(part); }
  • 151. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ A first fix: enhance EModelService with @LocalInstance public <T extends MApplicationElement> T createModelElement( Class<?> caller, Class<T> elementType);
  • 152. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ A first fix: enhance EModelService with @LocalInstance public <T extends MApplicationElement> T createModelElement( Class<?> caller, Class<T> elementType); ‣ Another fix: Provide a factory service public interface ModelElementFactoryService { ModelElementFactory createFactory(Class<?> caller); } public interface ModelElementFactory {
 <T extends MApplicationElement> T createElement(Class<T> elementType); }
  • 153. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ A first fix: enhance EModelService with @LocalInstance public <T extends MApplicationElement> T createModelElement( Class<?> caller, Class<T> elementType); ‣ Another fix: Provide a factory service public interface ModelElementFactoryService { ModelElementFactory createFactory(Class<?> caller); } public interface ModelElementFactory {
 <T extends MApplicationElement> T createElement(Class<T> elementType); } private ModelElementFactory f; @Inject public LocalInstanceSample(ModelElementFactoryService s) { this.f = s.createFactory(getClass()); } public void init() {
 // ... part = f.createModelElement(MPart.class); // ... }
  • 154. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @LocalInstance ‣ Is there a more generic solution to create DI-Instance values with knowledge about the target (eg classloader, bundle, …)? ‣ Since 2.1 there a basic TypeProvider API in fx.core
  • 155. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @LocalInstance ‣ Is there a more generic solution to create DI-Instance values with knowledge about the target (eg classloader, bundle, …)? ‣ Since 2.1 there a basic TypeProvider API in fx.core /** * A service who provides a type based upon selector value * * @param <S> * the selector value type * @param <T> * the type * @since 2.1 */ public interface TypeProviderService<S, T> extends Predicate<S> { @Override boolean test(S t); public Class<? extends T> getType(S s); }
  • 156. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ Upon the basic interface there are a specialized ones eg @LocalInstance
  • 157. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 ‣ Upon the basic interface there are a specialized ones eg @LocalInstance /** * Service who provides a real type for an interface/abstract type * * @param <T> * the type */ public interface TypeTypeProviderService<T> extends TypeProviderService<java.lang.reflect.Type, T> { /** * If used with dependency injection and @LocalInstance */ public static final String DI_KEY = "localInstanceOwnerType"; //$NON-NLS-1$ }
  • 158. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @LocalInstance
  • 159. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @Component class TypeProviderImpl implements TypeTypeProviderService<ModelElementFactory> { @Override public Class<? extends ModelElementFactory> getType(Type s) { return ModelElementFactoryImpl.class; } @Override public boolean test(Type t) { return t == ModelElementFactory.class; } public static class ModelElementFactoryImpl implements ModelElementFactory { @NonNull private final EModelService modelService; @Inject public ModelElementFactoryImpl(@NonNull EModelService modelService, @Named(TypeTypeProviderService.DI_KEY) @NonNull Class<?> ownerType) { this.modelService = modelService; } } } @LocalInstance
  • 160. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @Inject private EModelService modelService; public void init() {
 // ... part = modelService.createModelElement(MPart.class); // ... } @LocalInstance ‣ The original code
  • 161. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @Inject private EModelService modelService; public void init() {
 // ... part = modelService.createModelElement(MPart.class); // ... } @LocalInstance ‣ The original code @Inject @LocalInstance private ModelElementFactory modelFactory; public void init() {
 // ... part = modelFactory.createModelElement(MPart.class); // ... } ‣ Gets to
  • 162. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @Inject private EModelService modelService; public void init() {
 // ... part = modelService.createModelElement(MPart.class); // ... } @LocalInstance ‣ The original code @Inject @LocalInstance private ModelElementFactory modelFactory; public void init() {
 // ... part = modelFactory.createModelElement(MPart.class); // ... } ‣ Gets to LocalInstanceObjectSupplier
  • 163. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @Inject private EModelService modelService; public void init() {
 // ... part = modelService.createModelElement(MPart.class); // ... } @LocalInstance ‣ The original code @Inject @LocalInstance private ModelElementFactory modelFactory; public void init() {
 // ... part = modelFactory.createModelElement(MPart.class); // ... } ‣ Gets to LocalInstanceObjectSupplier TypeTypeProviderService test(ModelElementFactory.class)
  • 164. (c) BestSolution.at - Licensed under Creative Commons Attribution-NonCommerical-ShareAlike 3.0 @Inject private EModelService modelService; public void init() {
 // ... part = modelService.createModelElement(MPart.class); // ... } @LocalInstance ‣ The original code @Inject @LocalInstance private ModelElementFactory modelFactory; public void init() {
 // ... part = modelFactory.createModelElement(MPart.class); // ... } ‣ Gets to LocalInstanceObjectSupplier TypeTypeProviderService test(ModelElementFactory.class)