Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Guice setup in multi-plug-in setups
Guice setup in multi-plug-in setups [message #881639] Tue, 05 June 2012 00:59 Go to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1828
Registered: July 2009
Senior Member
I keep running into situations that all might be related to some bogus setup of my Guice modules, so let me ask: does anyone have a good strategy how to do initialization in a setup where multiple plug-ins all contribute to one integrated tool set?

Specifically, I have a bunch of plug-ins:
- Model
- Dsl1
-- contains a grammar, parser creates elements to subset of Model
-- file extension is .ex1
- Dsl2
-- similar to Dsl1, grammar imports that of Dsl1
-- file extension is .ex2
- Dsl1.ui
-- contains an Activator to initialize Guice for Dsl1
- Dsl2.ui
-- contains an Activator to initialize Guice for Dsl2
- Generator
-- contains several implementations of IGenerator
--- one of these generators creates HTML
- Servlet
-- an Eclipse application
-- defines a servlet that invokes the HTML generator from "Generator"
-- cannot depend on any ui plug-ins

After lots of good stuff is pre-generated by Xtext, in the last plug-in, I'm on my own. As my main reference I followed the advice from http://kthoms.wordpress.com/2011/09/28/moving-an-xtend-generator-into-its-own-plugin/

Let's assume the servlet is supposed to handle ".ex1" and ".ex2" files. How many injectors do I need?


One, because everybody keeps saying I should never create a second injector, and also because the servlet itself should be created via an ExtensionFactory which can only delegate to one injector.

Two, because each (sub-) language binds it own parser, and merging both modules into one injector makes the selection of the parser non-deterministic.

But when I need an XtextResourceSetProvider to bootstrap loading of XtextResources. Which injector should I obtain this from? Is it safe to load resources from multiple DSLs via the same ResourceSet?

When would I need to mix-in the SharedStateModule()?

I'm using snippets like this:
Registry.INSTANCE.getExtensionToFactoryMap().put("ex1", resourceFactory);
IResourceServiceProvider.Registry.INSTANCE.getExtensionToFactoryMap().put("ex1", serviceProvider);

When exactly, is that needed / can this be omitted? I saw such code in Activators generated into a UI plug-in, but what if I need to process my languages in a headless environment?

As I have several generators I need the option to explicitly instantiate one of them. Is there anything unsafe about doing so and then passing it into:
Activator.getInstance().getInjector().injectMembers(generator);

?

From the above list of plug-ins, could anyone derive a recipe for initializing guice modules for various scenarios like: headless servlet, IDE with editors, menu actions that invoke some generator, invoking a generator via maven/fornax, working with an Eclipse workspace / without etc.? I'm not asking for a full design, just whether any strategy concerning guice can possibly serve this range of applications, and how that setup should be designed.

thanks,
Stephan

PS: This post originally had triple the length because I was explaining some really weird effects, like the same code (an Eclipse application) would work when launched within Eclipse, but fail when exported and launched outside Eclipse. The above is the result of days of trial and error and surfing the net and more trial and more error. While the help document clearly says "In Xtext, you should never instantiate the injector of your language yourself" I ran into several situations, where I simply cannot access a pre-configured injector that has everything I need.

So, I was forced to understand more about how Xtext uses guice modules than I had planned for. I think it would be great if we had more articles about why guice modules have to be configured this way or that way, so that people can indeed mix and match many building blocks into one cool integrated tool, rather than being tied to what Xtext generates for them, which naturally is based on some simplifying assumptions.
Re: Guice setup in multi-plug-in setups [message #881803 is a reply to message #881639] Tue, 05 June 2012 09:24 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian ZarnekowFriend
Messages: 3108
Registered: July 2009
Senior Member
Hi Stephan,

generally speacking, you may create as many injectors as you want (after
all, that's what we do: one per language). However, you should never try
to use the very same module (runtime, ui) to create a new injector since
the module configuration will cause side effects on EMFs global
singleton registries. You may want to look into the shared services
(org.eclipse.xtext.ui.shared.Access) where we provide instances as
singletons for LangA'S injector that were created by a global injector.
A similar pattern should work for you use case.

Please keep in mind that instances, that are configured by other
plugins, usually use extension points to collect their configuration.

See below.

Am 05.06.12 02:59, schrieb Stephan Herrmann:
> I keep running into situations that all might be related to some bogus
> setup of my Guice modules, so let me ask: does anyone have a good
> strategy how to do initialization in a setup where multiple plug-ins all
> contribute to one integrated tool set?
>
> Specifically, I have a bunch of plug-ins:
> - Model
> - Dsl1 -- contains a grammar, parser creates elements to subset of Model
> -- file extension is .ex1
> - Dsl2
> -- similar to Dsl1, grammar imports that of Dsl1
> -- file extension is .ex2
> - Dsl1.ui
> -- contains an Activator to initialize Guice for Dsl1
> - Dsl2.ui
> -- contains an Activator to initialize Guice for Dsl2
> - Generator
> -- contains several implementations of IGenerator
> --- one of these generators creates HTML
> - Servlet
> -- an Eclipse application
> -- defines a servlet that invokes the HTML generator from "Generator"
> -- cannot depend on any ui plug-ins
>
> After lots of good stuff is pre-generated by Xtext, in the last plug-in,
> I'm on my own. As my main reference I followed the advice from
> http://kthoms.wordpress.com/2011/09/28/moving-an-xtend-generator-into-its-own-plugin/
>
>
> Let's assume the servlet is supposed to handle ".ex1" and ".ex2" files.
> How many injectors do I need?
>

One for the lang with ex1, another for ex2, a third for the servlet.

>
> One, because everybody keeps saying I should never create a second
> injector, and also because the servlet itself should be created via an
> ExtensionFactory which can only delegate to one injector.

The Servlet injector should use its own module configuration / bindings.
See xtext.ui.shared.


>
> Two, because each (sub-) language binds it own parser, and merging both
> modules into one injector makes the selection of the parser
> non-deterministic.
>

Right, you should not try to do that.


> But when I need an XtextResourceSetProvider to bootstrap loading of
> XtextResources. Which injector should I obtain this from? Is it safe to
> load resources from multiple DSLs via the same ResourceSet?

It is save to use a resource set that was provided by the servlet's
injector as long as you are sure that the other injects did their job
and the EMF registries are properly initialized (by equinox or manually
-> see your XXXStandaloneSetup). E.g. the XtextBuilder uses a language
independent resource set.

>
> When would I need to mix-in the SharedStateModule()?

If you want to access global singletons like the workbench, the
Storage2URIMapper or others.

>
> I'm using snippets like this:
> Registry.INSTANCE.getExtensionToFactoryMap().put("ex1", resourceFactory);
> IResourceServiceProvider.Registry.INSTANCE.getExtensionToFactoryMap().put("ex1",
> serviceProvider);

Where do you do so? I hope not in a running Eclipse? Modifying global
singletons is not a good idea at all. A cleaner approach would be to use
the resource factory registry that is local to a specific resource set.

> When exactly, is that needed / can this be omitted?

This is only necessary in a standalone environment where no extensions
are loaded by equinox.

> I saw such code in
> Activators generated into a UI plug-in, but what if I need to process my
> languages in a headless environment?

Where did you see such code?

>
> As I have several generators I need the option to explicitly instantiate
> one of them. Is there anything unsafe about doing so and then passing it
> into:
> Activator.getInstance().getInjector().injectMembers(generator);
> ?
>

It is ok to do so but a cleaner approach would inject a
Provider<SpecificGenerator> which could havce been provided by some sort
of Access implementation or by means of equinox extensions.

Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com

> From the above list of plug-ins, could anyone derive a recipe for
> initializing guice modules for various scenarios like: headless servlet,
> IDE with editors, menu actions that invoke some generator, invoking a
> generator via maven/fornax, working with an Eclipse workspace / without
> etc.? I'm not asking for a full design, just whether any strategy
> concerning guice can possibly serve this range of applications, and how
> that setup should be designed.
>
> thanks,
> Stephan
>
> PS: This post originally had triple the length because I was explaining
> some really weird effects, like the same code (an Eclipse application)
> would work when launched within Eclipse, but fail when exported and
> launched outside Eclipse. The above is the result of days of trial and
> error and surfing the net and more trial and more error. While the help
> document clearly says "In Xtext, you should never instantiate the
> injector of your language yourself" I ran into several situations, where
> I simply cannot access a pre-configured injector that has everything I
> need.
>
> So, I was forced to understand more about how Xtext uses guice modules
> than I had planned for. I think it would be great if we had more
> articles about why guice modules have to be configured this way or that
> way, so that people can indeed mix and match many building blocks into
> one cool integrated tool, rather than being tied to what Xtext generates
> for them, which naturally is based on some simplifying assumptions.
>
Re: Guice setup in multi-plug-in setups [message #882456 is a reply to message #881803] Wed, 06 June 2012 13:51 Go to previous message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1828
Registered: July 2009
Senior Member
Hi Sebastian,

Sebastian Zarnekow wrote on Tue, 05 June 2012 11:24
...generally speacking, you may create as many injectors as you want ... However, you should never try
to use the very same module (runtime, ui) to create a new injector ...


OK, good to know, but I never tried that, so one less worries.

Quote:
You may want to look into the shared services
(org.eclipse.xtext.ui.shared.Access) where we provide instances as
singletons for LangA'S injector that were created by a global injector.
A similar pattern should work for you use case.


Admittedly, I don't fully understand what problem is solved here. If it's just how to provide global singletons, than this doesn't appear to be my problem - so far.

Quote:

Please keep in mind that instances, that are configured by other
plugins, usually use extension points to collect their configuration.


This got me to notice an important detail I missed so far:

The EMF registration seems to happen from the generated plugin.xml of the UI plug-in (via extension points org.eclipse.emf.ecore.extension_parser and org.eclipse.xtext.extension_resourceServiceProvider).

Since my Servlet doesn't use the UI-plugin I ended up with a language that was not registered with EMF!

Question: wouldn't it be a good idea to generate this extension into the grammar plug-in, instead of the UI plug-in? How is this UI related? or: how can I use the language (in an Equinox context) without this extension? Excuse me if this sounds naive, but this seems to be the core reason for most of my confusion in this field.

When trying this, I see that this would require to have an Activator and an ExtensionFactory in the grammar plug-in, too. At this point, it gets tricky how an Activator in the grammar plug-in can create an injector, while the UI plug-in should only add its UIModule to that injector. Is this why injector creation only happens in the UI plug-in, not the grammar plug-in?

Actually, looking at my Generator project, which operates on both languages (just like the Servlet), it looks like I never triggered creating the injector for one of the languages, still the generator worked. Oops?

Let me explicitly ask: depending on a grammar plug-in is not sufficient for ensuring that a suitable injector has been created and registered with EMF, right?

Quote:

One for the lang with ex1, another for ex2, a third for the servlet.


And then I only need to ensure that those injectors have all I need for the respective language. Besides the two extension points mentioned above, could there be more that I'm missing when running without the UI plug-in?

Quote:

The Servlet injector should use its own module configuration / bindings.
See xtext.ui.shared.


I'm not sure what you are suggesting here? Copy code to create a similar structure? Should I register an overridingGuiceModule extension (do you have examples that show when this is useful)?

Quote:

> I'm using snippets like this:
> Registry.INSTANCE.getExtensionToFactoryMap().put("ex1", resourceFactory);
> IResourceServiceProvider.Registry.INSTANCE.getExtensionToFactoryMap().put("ex1",
> serviceProvider);

Where do you do so? I hope not in a running Eclipse? Modifying global
singletons is not a good idea at all. A cleaner approach would be to use
the resource factory registry that is local to a specific resource set.


I found it in a StandaloneSetup (not the UI Activator as I claimed, sorry). Used it in the Servlet's Activator.start(), which works like a charm, but seems to be superceded by the two extension points mentioned above, right?

Quote:

> As I have several generators I need the option to explicitly instantiate
> one of them. Is there anything unsafe about doing so and then passing it
> into:
> Activator.getInstance().getInjector().injectMembers(generator);
> ?

It is ok to do so but a cleaner approach would inject a
Provider<SpecificGenerator> which could havce been provided by some sort
of Access implementation or by means of equinox extensions.


If it's OK, I'll keep that pattern, because I'm not keen to introduce more indirections for a single "new" statement where everything is statically known Smile

thanks, I feel I'm getting closer to actually understanding what happens Smile
Stephan
Previous Topic:Custom Activator in UI plug-in?
Next Topic:use the importURI mechanism to incude an ecore model
Goto Forum:
  


Current Time: Sat Oct 31 14:30:07 GMT 2020

Powered by FUDForum. Page generated in 0.07548 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top