|
Re: e4 Best Practice to avoid extension points [message #1716235 is a reply to message #1716232] |
Wed, 02 December 2015 11:55 |
Thomas Schindl Messages: 6651 Registered: July 2009 |
Senior Member |
|
|
Hi,
I'm certainly biased because I'm on my "Get rid of all Framework stuff
in my business code trip" and Extension Points don't have a place there
because:
* to read them you need to use Equinox APIs
* it is an Equinox only API (although in theory it can be used on other
OSGi-Container I think nobody really tried that)
In contrast to that DS is subject to injection (you can even let the
framework inject you a list of OSGi-Services but that requires an
extension not shipped as part of plain e4)
In the e4 framework we introduced 2 extension points and looking back I
totally regret that and I'd like to get rid of them (in reality they'll
never go away but will get deprecated).
I would definately use DS eg in e(fx)clipse we are registering CSS-Files
through DS and with the help of @Component annotations this even easier
than with extension points.
Tom
On 02.12.15 12:27, Hauke Fuhrmann wrote:
> Hi there,
>
> I quite often have the use case to register some resources in my
> application, where I use custom extension points of E3. I might store
> some meta-information with the resources such my client can load and use
> the resources in some way.
>
> What is the best-practice to work with such information in E4? I
> understand that to register Java Classes, the best way is to use
> OSGi-services, which I successfully do. However, for any other arbitrary
> resources, it would be too much to create an OSGi-Service that publishes
> the file by means of Java code.
>
> Is there some other mechanism? E.g. has the e4 Application model some
> storage for arbitrary data which I can contribute in some fragment? Or
> is there some mechanism in the Manifest?
> Or is the e3-extension-mechanism still the main way to do it, even in a
> pure E4-Application?
>
> Cheers,
> Hauke
|
|
|
|
|
|
|
|
Re: e4 Best Practice to avoid extension points [message #1716405 is a reply to message #1716384] |
Thu, 03 December 2015 14:11 |
Thomas Schindl Messages: 6651 Registered: July 2009 |
Senior Member |
|
|
No no activator is required (or if you ask me violates a good design),
but you use DS.
@Component
public class ParserComponent {
private List<Parser> parserList = new ArrayList<>();
@Reference(cardinality=ReferenceCardinality.MULTIPLE,
policyOption=ReferencePolicyOption.GREEDY)
public void registerParser(Parser parser) {
synchronized(parserList) {
parserList.add(parser);
}
}
public void unregisterParser(Parser parser) {
synchronized(parserList) {
parserList.remove(parser);
}
}
public Optional<DomainObject> parseFile(String file) {
Optional<Parser> parser
synchronized(parserList) {
parser = parserList.stream()
.filter( p -> p.test(file) ).findFirst();
}
return parser.map( p -> p.parse(file) );
}
}
In your code you write:
public class MyUI() {
@Inject
ParserComponent component;
void bla() {
component.parseFile( "helloworld.xml" ).ifPresent(
this::updateUI );
}
void updateUI(DomainObject o) {
}
}
Just to sum this up there's even cooler stuff you can do with the Help
of context functions, ... but this is hard to explain in newsgroup
postings and even blogs and you'd have to invite me to your company for
a workshop ;-)
I've some slideware uploaded from my latest presentations on e4 architecture
*
https://www.eclipsecon.org/europe2015/sites/default/files/slides/JavaFX%20APIs_0.pdf
*
https://www.eclipsecon.org/europe2015/sites/default/files/slides/JavaFX%20Smart%20Code%20Econ_0.pdf
Where the 2nd one present the so called TypeProvider infrastructure who
even supports the usage of DI in your service layer but once more
describing how you implement and use this kind of thing is out-of-scope
in none face to face discussion.
Tom
On 03.12.15 13:21, Gernot Krause wrote:
> Hi!
>
> I have a general question: If I replace extension points by services how
> do I manage that a plugin registers a functionality at the service?
>
> In my case for example I have an RCP application with a base plugin A.
> Here I want to load and parse data from different files into my
> application. I can define a IParseDataService and let it be injected
> into my LoadDataFileHandler. Whenever the user selects a file the file
> is passed to the service and the service should then select the right
> parser based on the file's type or file extension.
>
> The parsers for each file type are provided by other plugins (B,C,D,
> ...). Using a service that selects the right parser requires that each
> plugin B, C, D, ... registers its specific parser at the service. But
> which class of the plugins is responsible for this? I am looking for
> something like an Activator. Is it done by a model processor or a model
> addon in E4? I mean whenever one of the plugins is loaded (or one of its
> classes) the parser needs to be registered, doesn't it? And removed when
> plugin is stopped.
>
> Is this reasonable?
>
> Thanks,
> Gernot.
>
|
|
|
Re: e4 Best Practice to avoid extension points [message #1716406 is a reply to message #1716405] |
Thu, 03 December 2015 14:14 |
Thomas Schindl Messages: 6651 Registered: July 2009 |
Senior Member |
|
|
Oh and the guy responsible for getting all that up and running is
org.eclipse.equinox.ds which implements the Extender Pattern.
What this OSGi-Bundle does is that it observes all bundles that come and
go, looks at their MANIFEST.MF (search there for the
ServiceComponent-Header) files and registers all of them in the
OSGi-Service registry.
Tom
On 03.12.15 15:11, Tom Schindl wrote:
> No no activator is required (or if you ask me violates a good design),
> but you use DS.
>
> @Component
> public class ParserComponent {
> private List<Parser> parserList = new ArrayList<>();
>
> @Reference(cardinality=ReferenceCardinality.MULTIPLE,
> policyOption=ReferencePolicyOption.GREEDY)
> public void registerParser(Parser parser) {
> synchronized(parserList) {
> parserList.add(parser);
> }
> }
>
> public void unregisterParser(Parser parser) {
> synchronized(parserList) {
> parserList.remove(parser);
> }
> }
>
>
> public Optional<DomainObject> parseFile(String file) {
> Optional<Parser> parser
> synchronized(parserList) {
> parser = parserList.stream()
> .filter( p -> p.test(file) ).findFirst();
> }
> return parser.map( p -> p.parse(file) );
> }
> }
>
> In your code you write:
>
> public class MyUI() {
> @Inject
> ParserComponent component;
>
> void bla() {
> component.parseFile( "helloworld.xml" ).ifPresent(
> this::updateUI );
> }
>
> void updateUI(DomainObject o) {
> }
> }
>
>
> Just to sum this up there's even cooler stuff you can do with the Help
> of context functions, ... but this is hard to explain in newsgroup
> postings and even blogs and you'd have to invite me to your company for
> a workshop ;-)
>
> I've some slideware uploaded from my latest presentations on e4 architecture
> *
> https://www.eclipsecon.org/europe2015/sites/default/files/slides/JavaFX%20APIs_0.pdf
> *
> https://www.eclipsecon.org/europe2015/sites/default/files/slides/JavaFX%20Smart%20Code%20Econ_0.pdf
>
> Where the 2nd one present the so called TypeProvider infrastructure who
> even supports the usage of DI in your service layer but once more
> describing how you implement and use this kind of thing is out-of-scope
> in none face to face discussion.
>
> Tom
>
> On 03.12.15 13:21, Gernot Krause wrote:
>> Hi!
>>
>> I have a general question: If I replace extension points by services how
>> do I manage that a plugin registers a functionality at the service?
>>
>> In my case for example I have an RCP application with a base plugin A.
>> Here I want to load and parse data from different files into my
>> application. I can define a IParseDataService and let it be injected
>> into my LoadDataFileHandler. Whenever the user selects a file the file
>> is passed to the service and the service should then select the right
>> parser based on the file's type or file extension.
>>
>> The parsers for each file type are provided by other plugins (B,C,D,
>> ...). Using a service that selects the right parser requires that each
>> plugin B, C, D, ... registers its specific parser at the service. But
>> which class of the plugins is responsible for this? I am looking for
>> something like an Activator. Is it done by a model processor or a model
>> addon in E4? I mean whenever one of the plugins is loaded (or one of its
>> classes) the parser needs to be registered, doesn't it? And removed when
>> plugin is stopped.
>>
>> Is this reasonable?
>>
>> Thanks,
>> Gernot.
>>
>
|
|
|
Re: e4 Best Practice to avoid extension points [message #1716416 is a reply to message #1716406] |
Thu, 03 December 2015 15:14 |
Eclipse User |
|
|
|
I'm late to the game, but contrary to Tom and Dirk, I love extension points. Extension points are declarative, non-executable data and are great for separating the producers from consumers.
To deal with Tom's concern on extension points, separate your configuration code (how things are wired together based on the data from the extensions) from your "business" code / behaviour. You want to do that for good testing purposes anyways. Don't embed knowledge of the registry within your business.
Brian.
|
|
|
Powered by
FUDForum. Page generated in 0.04671 seconds